/* TheTin — prototype design system. All pages use these tokens/components.
   Page-scoped <style> may extend but must reuse the variables. */

:root {
  --ink: #221f1a;
  --ink-soft: #5c564c;
  --paper: #faf6ee;
  --card: #ffffff;
  --line: #e7e0d2;
  --accent: #b45309;        /* default: amber (Jack / brand) */
  --accent-ink: #ffffff;
  --accent-soft: #fdf1e3;
  --danger: #b3261e;
  --ok: #256d3a;
  --radius: 14px;
  --shadow: 0 1px 2px rgba(34,31,26,.06), 0 8px 24px rgba(34,31,26,.08);
  /* Sticky top bar height + small gap — used so #section anchors clear the bar */
  --site-sticky-offset: 6.75rem;
}
/* Curated palettes (REQUIREMENTS §4: structured customization).

   A page's look is two independent axes, and every palette may be worn by every
   layout. The rule that keeps that matrix from exploding is narrow and exact:

     A STYLE sets surface treatment — colour, radius, border, shadow, typeface.
     It must never move, resize or reorder a block: no position, display,
     grid-template, flex-direction, order, float, width, height, margin,
     padding or gap.

     A LAYOUT sets arrangement — what goes where, at what size. It must never
     set a colour or a typeface, and never touches the palette tokens.

   `tests/unit/tin-css-axes.test.mjs` enforces both halves. If a change needs to
   break one of them, the axes are wrong — fix the axes, not the test. */
.theme-amber  { --accent:#b45309; --accent-soft:#fdf1e3; }
.theme-warm   { --accent:#7c5e3c; --accent-soft:#f4ece0; }
.theme-slate  { --accent:#33506d; --accent-soft:#e8eef5; }
.theme-moss   { --accent:#3f6b3f; --accent-soft:#e9f1e6; }

/* Platform-shell directions offered as page palettes an owner can choose.
   Scoped to the body class, never :root — a page palette must not restyle the
   platform around it. The shell that `UI_STYLE` actually names is not offered
   here: see PAGE_THEMES in app/src/db/types.ts. */
.theme-trust {
  --paper:#e9edf2; --card:#ffffff; --ink:#16202c; --ink-soft:#526074;
  --line:#d3dae3; --accent:#146fdb; --accent-soft:#e2edfb; --radius:10px;
}
.theme-trust .btn { border-radius:8px; }

.theme-ink {
  --paper:#ffffff; --card:#ffffff; --ink:#141414; --ink-soft:#555555;
  --line:#141414; --accent:#b8860b; --accent-soft:#f4e8cf;
  --radius:4px; --shadow:none;
}

.theme-ink .card {
  border:none; border-top:3px solid var(--ink); border-bottom:1px solid var(--ink);
  border-radius:0;
}
.theme-ink .btn { border-radius:999px; }
.theme-ink .amounts a { border:1.5px solid var(--ink); border-radius:0; }
.theme-ink .amounts a.sel, .theme-ink .amounts a:hover { border-color:var(--accent); }

@media (prefers-color-scheme: dark) {
  .theme-trust {
    --paper:#0b1320; --card:#141e2c; --ink:#e8eef6; --ink-soft:#8fa1b8;
    --line:#243349; --accent:#1da4f0; --accent-soft:#0f2740; --shadow:none;
  }
  .theme-ink {
    --paper:#0f0f0f; --card:#0f0f0f; --ink:#f2f2f2; --ink-soft:#9a9a9a;
    --accent:#c8901a; --accent-soft:#2a2210;
  }
}

/* Curated layouts. A layout only rearranges blocks the renderer already emits,
   so each one must still read correctly with no cover image, no avatar photo,
   no bio and no links. It sets no colour and no typeface — see the axes rule
   above. layout-card is the default and needs no rules: it is the arrangement
   the components below already describe.

   The three curated layouts below each REORDER the hero, not merely resize
   it — the title moves in front of the photo in every one of them, and each
   treats the photo differently (circle, two-column row, square). `.hero`'s
   children are, in DOM order: {cover} {avatar|avatar-photo} <h1> .handle-pill
   {bio} {links} — the renderer's order never changes (layout-card depends on
   it), only `order`/grid placement does. The give-card that follows keeps its
   one settled internal order — amounts, then custom amount, then the CTA,
   with the trust line and payer privacy notice last — in every layout; only
   the hero rearranges.

   None of the three renders a cover band: `identityCard()` in app/src/index.ts
   only builds `.cover` (and the `hero-with-cover` class) for layout-card, so
   `{cover}` is simply absent from the DOM here — not hidden, never emitted.
   The suppression lives in the renderer rather than in a `.layout-*` CSS rule
   because a layout rule must never set a colour (the axes rule above), and
   `.hero-with-cover`'s own border/padding reset touches `border-top-color`
   alongside width and style. These three always render exactly as if the
   page had no cover, whether or not the owner uploaded one. In every one of
   them, the photo — profile photo, not cover — is the hero. The real page and
   the customize-editor's live preview render the identical `<h1>` for the
   title (customizePage.ts) — there is no second, editor-only tag to key
   these rules off. */

/* ---------------------------------------------------------------------------
   FONT — the third axis. A font rule sets a typeface and NOTHING else: no
   colour, no size, no spacing, no arrangement. tin-css-axes.test.mjs enforces
   that, and it is what keeps four typefaces x six palettes x four layouts
   reviewable instead of ninety-six separate looks.

   Every stack is fonts the reader already has. Nothing here loads a webfont —
   a font file fetched from a third party makes every payer's browser announce
   its IP and referrer to that host. A face that needs a request cannot be
   offered here.
   --------------------------------------------------------------------------- */
/* Each stack ends in a generic family, so a reader missing the named face still
   gets one of the same character — a serif stays a serif. The named face is
   what most readers see; the fallback is what keeps the page from looking
   broken for the rest. */
.font-system { font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; }
.font-arial { font-family: Arial, Helvetica, sans-serif; }
.font-verdana { font-family: Verdana, Geneva, "DejaVu Sans", sans-serif; }
.font-tahoma { font-family: Tahoma, Verdana, Geneva, sans-serif; }
.font-trebuchet { font-family: "Trebuchet MS", "Segoe UI", Tahoma, sans-serif; }
.font-georgia { font-family: Georgia, "Times New Roman", serif; }
.font-times { font-family: "Times New Roman", Times, serif; }
.font-palatino { font-family: Palatino, "Palatino Linotype", "Book Antiqua", Georgia, serif; }
.font-garamond { font-family: Garamond, "EB Garamond", "Palatino Linotype", "Times New Roman", serif; }
.font-courier { font-family: "Courier New", Courier, ui-monospace, monospace; }
.font-comic { font-family: "Comic Sans MS", "Chalkboard SE", "Segoe Print", cursive; }
.font-impact { font-family: Impact, Haettenschweiler, "Arial Narrow Bold", "Arial Black", sans-serif; }

/* Paper: the name leads, then a large circular photo, then the bio — and the
   give button is drawn as a coin, not a bar. Border colour/style/radius are
   surface treatment — the palette's job, not this layout's — so only the
   border's WIDTH is set here; whatever style the page wears still draws its
   own chip shape (theme-ink's square flat corners included). */
.layout-paper .wrap { max-width: 480px; }
.layout-paper .hero { display: flex; flex-direction: column; }
.layout-paper .hero h1 { order: 0; }
.layout-paper .hero .handle-pill { order: 2; align-self: center; }
/* ~40% of the 480px column: the photo is this layout's hero, not a
   supporting thumbnail — noticeably larger than the 96px base avatar. */
.layout-paper .hero .avatar,
.layout-paper .hero .avatar-photo {
  order: 3; width: 190px; height: 190px; font-size: 4.2rem; margin: .9rem auto .7rem;
}
.layout-paper .hero .bio { order: 4; }
.layout-paper .hero .page-links { order: 5; }
.layout-paper .amounts a {
  border-width: 2px;
}
/* A round CTA has to hold cta_label up to 40 chars without breaking: grow
   into a pill (min-height keeps the circle at rest, fit-content lets it widen
   for a long label without overflowing the card, and generous padding plus
   wrapped, tightened line-height keep multi-line text inside the shape)
   rather than clip. The rounding itself is a clip-path, not a border-radius —
   corner shape is arrangement here (round vs. the default rectangle is part
   of what makes this THE round-CTA layout), not a style's surface finish, so
   it stays off the property the axes rule reserves for palettes. */
.layout-paper .give-go {
  display: flex; align-items: center; justify-content: center;
  width: fit-content; max-width: 100%; min-width: 8.5rem; min-height: 8.5rem;
  margin: 1.25rem auto 0; padding: 1rem 1.35rem;
  clip-path: inset(0 round 999px); font-size: 1.05rem; line-height: 1.2;
  white-space: normal; text-align: center; overflow-wrap: break-word;
}
.layout-paper .give-card > .trust,
.layout-paper .give-card > .notice { margin-top: 1.25rem; }

/* Hall: the title spans the top, then a two-column row — the photo on the
   left, the handle/bio/links on the right — then the give card. Below 480px
   wide the row collapses to a single column: two real columns of content do
   not fit a phone screen next to the give card underneath. */
.layout-hall .wrap { max-width: 520px; }
.layout-hall .hero {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-areas:
    "title  title"
    "photo  handle"
    "photo  bio"
    "photo  links";
  column-gap: 1.5rem; row-gap: .35rem;
  align-items: start; text-align: left;
}
.layout-hall .hero h1 { grid-area: title; text-align: center; }
.layout-hall .hero .avatar,
.layout-hall .hero .avatar-photo {
  grid-area: photo; width: 124px; height: 124px; font-size: 3.05rem; margin: 0;
}
.layout-hall .hero .handle-pill { grid-area: handle; justify-self: start; }
.layout-hall .hero .bio { grid-area: bio; margin-top: 0; }
.layout-hall .hero .page-links { grid-area: links; justify-content: flex-start; }
.layout-hall .give-card { border-top-width: 5px; margin-top: 1.6rem; }
@media (max-width: 480px) {
  .layout-hall .hero {
    grid-template-columns: 1fr;
    grid-template-areas: "title" "photo" "handle" "bio" "links";
    justify-items: center; text-align: center;
  }
  .layout-hall .hero .avatar,
  .layout-hall .hero .avatar-photo { margin: 0 auto; }
  .layout-hall .hero .handle-pill { justify-self: center; }
  .layout-hall .hero .page-links { justify-content: center; }
}

/* The thank-you card carries the page's layout so a payer sees one design
   across pay and thanks, but it holds NONE of the identity parts those
   layouts arrange — no handle pill, no bio, no links. Laid out on the
   identity grid its message auto-places into the far column and centres
   itself there, stranding it a column away from the tick. It is a single
   centred column in every layout; only the surface treatment varies. */
.card.hero.thanks-hero {
  display: block;
  text-align: center;
}
.card.hero.thanks-hero .avatar,
.card.hero.thanks-hero .avatar-photo {
  margin: 0 auto .75rem;
}

/* Copper: the name leads, then the photo full-width and SQUARE — this
   layout's defining element — then the bio; clean white space around every
   block, arrangement only; "clean white" is the style's job, not this
   layout's. The give card keeps the one settled money order (amounts, then
   custom amount, then the CTA) like every other layout. */
.layout-copper .wrap { padding-top: 1.75rem; padding-bottom: 3.5rem; }
.layout-copper .hero { display: flex; flex-direction: column; padding-top: 2.2rem; }
.layout-copper .hero h1 { order: 0; }
.layout-copper .hero .handle-pill { order: 2; align-self: center; }
/* The real photo: fills the column, corners square. Shape is arrangement, so
   a layout may set border-radius outright — this is what makes it Copper's
   photo, not a palette choice. */
.layout-copper .hero .avatar-photo {
  order: 3;
  width: 100%; height: auto; aspect-ratio: 1;
  border-radius: 4px; margin: 1rem auto;
}
/* The letter fallback (no photo uploaded) deliberately does NOT inherit the
   full-width square treatment above — a single giant letter stretched across
   the whole column reads as broken, not as this layout's hero. It stays a
   circle, sized up from the 96px base default so the hero spot isn't left
   looking empty, but well short of the real photo's full column width. */
.layout-copper .hero .avatar {
  order: 3;
  width: 190px; height: 190px; font-size: 4.2rem; margin: 1rem auto;
}
.layout-copper .hero .bio { order: 4; }
.layout-copper .hero .page-links { order: 5; }


/* Screen-reader-only: keeps text in the accessibility tree without showing it
   or reserving layout space. Never use display:none for accessible names —
   that removes the node from the tree too. */
.sr-only {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

* { box-sizing: border-box; }
html {
  -webkit-text-size-adjust: 100%;
  /* Native hash / scrollIntoView — keep target below sticky top bar */
  scroll-padding-top: var(--site-sticky-offset);
}
body {
  margin: 0; background: var(--paper); color: var(--ink);
  font: 16px/1.55 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}
h1,h2,h3 { line-height: 1.2; margin: 0 0 .5em; letter-spacing: -.01em; }
h1 { font-size: 1.7rem; } h2 { font-size: 1.25rem; } h3 { font-size: 1.05rem; }
p { margin: .4em 0 .9em; } a { color: var(--accent); }
small, .muted { color: var(--ink-soft); }

/* Demo chip — quiet on tipper path; slightly stronger on portal (still not a lab bar) */
.proto {
  background: transparent; color: var(--ink-soft); font-size: .72rem;
  letter-spacing: .02em; text-align: center; padding: .4rem .75rem .15rem;
  font-weight: 600;
}
.proto::before {
  content: ""; display: inline-block; width: .45rem; height: .45rem;
  border-radius: 50%; background: var(--accent); margin-right: .4rem;
  vertical-align: .05em; opacity: .85;
}
/* Portal / admin: slightly more visible strip (not uppercase PROTOTYPE) */
body:not(.tipper) > .proto {
  background: #f0ebe1; color: var(--ink-soft); border-bottom: 1px solid var(--line);
  padding: .4rem .75rem; margin-bottom: 0;
}
body:not(.tipper) > .proto::before { background: #8a5a13; }
.proto a { color: var(--accent); }

/* Legacy (Sam/Raj): not v1 product story */
.legacy-banner {
  background: #f8e4e2; color: var(--danger); font-size: .82rem; font-weight: 600;
  text-align: center; padding: .55rem .75rem; border-bottom: 1px solid #f0d4d1;
}

/* Layout */
.wrap { max-width: 640px; margin: 0 auto; padding: 1.25rem 1rem 3rem; }
.wrap-wide { max-width: 960px; margin: 0 auto; padding: 1.25rem 1rem 3rem; }
/* Marketing pages (landing): Ko-fi-like wider column */
.wrap-marketing {
  max-width: 1080px;
  margin: 0 auto;
  padding: 0 1.25rem 3.5rem;
}

/*
  Site brand bar — Ko-fi pattern:
  sticky full-width top chrome, logo LEFT, actions RIGHT.
  Not a floating centered favicon mid-column.
*/
header.site {
  position: sticky;
  top: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  width: 100%;
  box-sizing: border-box;
  margin: 0 0 1rem;
  padding: .65rem 0;
  /* Solid page colour — hides scrolling content underneath (not white, not clear) */
  background: var(--paper);
  border-bottom: none;
}
/* When header is a direct body child (marketing), full-bleed bar + inner max-width */
body > header.site,
header.site.topbar {
  width: 100%;
  max-width: none;
  margin: 0;
  padding: 0;
  background: var(--paper);
  border-bottom: none;
  box-shadow: none;
}
/* Marketing paper is slightly warmer; keep bar identical so scroll never bleeds through */
body.marketing > header.site,
body.marketing header.site.topbar {
  background: #faf7f2;
}
header.site .topbar-inner,
body > header.site > .topbar-inner {
  width: 100%;
  max-width: 640px;
  margin: 0 auto;
  padding: .75rem 1.25rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  box-sizing: border-box;
}
/* Header still inside .wrap (portal): full-bleed sticky without leaving wrap.
   Padding inset matches each wrap's half-width so brand stays left-aligned
   with page content (not centred on the viewport). */
.wrap > header.site,
.wrap-wide > header.site {
  width: 100vw;
  max-width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
  margin-bottom: 1rem;
  background: var(--paper);
  box-sizing: border-box;
}
/* .wrap max-width 640px → half = 320 */
.wrap > header.site {
  padding: .75rem max(1rem, calc(50vw - 320px));
}
/* .wrap-wide max-width 960px → half = 480 */
.wrap-wide > header.site {
  padding: .75rem max(1rem, calc(50vw - 480px));
}
/* Authed recipient chrome: brand (+ handle) LEFT · account actions RIGHT */
.topbar-nav {
  display: flex;
  align-items: center;
  gap: .35rem .65rem;
  flex-wrap: wrap;
  justify-content: flex-end;
  margin-left: auto;
  min-width: 0;
}
/* Session Dashboard (injected by brand-home.js when signed in and not already
   on /r/dashboard). Recipient order inside #account-nav:
   Hi name · Dashboard · other actions · Log out */
a.session-dashboard-link {
  flex: none;
  white-space: nowrap;
}
/* Public tip/pay headers with only .topbar-inner (no account-nav): brand left, Dashboard right */
.topbar-inner > a.session-dashboard-link {
  margin-left: auto;
}
/* Standalone header without nav: keep Dashboard on the right */
header.site > a.session-dashboard-link {
  margin-left: auto;
}
.topbar-nav a:not(.btn) {
  color: var(--ink-soft);
  text-decoration: none;
  font-weight: 600;
  font-size: .92rem;
}
.topbar-nav a:not(.btn):hover { color: var(--ink); }
.topbar-nav .btn {
  padding: .5rem .95rem;
  font-size: .9rem;
  border-radius: 999px;
}
.topbar-nav .btn + .btn { margin-left: 0; }
.topbar-nav #logout-btn { flex: none; }
.topbar-nav #logout-btn:disabled { opacity: .65; cursor: wait; }
.topbar-brand {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: .1rem;
  min-width: 0;
  flex: none;
}
.topbar-email {
  display: inline-block;
  max-width: min(16rem, 42vw);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--ink-soft);
  font-weight: 600;
  font-size: .9rem;
  line-height: 1.2;
  text-decoration: none;
}
.topbar-email:hover { color: var(--ink); }
.topbar-handle {
  display: block;
  max-width: min(18rem, 48vw);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--ink-soft);
  font-size: .72rem;
  font-weight: 600;
  line-height: 1.15;
  text-decoration: none;
  opacity: .92;
}
.topbar-handle[hidden] { display: none !important; }
.topbar-handle:hover { color: var(--ink); opacity: 1; }
.topbar-handle code {
  font: inherit;
  font-weight: 700;
  background: transparent;
  padding: 0;
}
@media (max-width: 420px) {
  .topbar-email { max-width: 7.5rem; font-size: .82rem; }
  .topbar-handle { max-width: 7.5rem; font-size: .68rem; }
  .topbar-nav { gap: .25rem .4rem; }
  .topbar-nav .btn { padding: .4rem .7rem; font-size: .85rem; }
}

.logo {
  display:inline-flex; align-items:center; gap:.5rem; font-weight:700;
  font-size:1.05rem; color: var(--ink); text-decoration:none;
}
.logo .coin {
  width:1.5rem; height:1.5rem; border-radius:50%;
  background: radial-gradient(circle at 35% 30%, #f2c66d, var(--accent));
  border: 2px solid var(--ink); flex:none;
}
/* Brand lockup — large mark (tin + gold coin + TheTin on body). Fixed SVG colours. */
.brand-lockup {
  display: inline-flex;
  align-items: center;
  gap: .65rem;
  text-decoration: none;
  color: var(--ink);
  flex: none;
}
.brand-lockup:hover { color: var(--ink); }
.brand-lockup:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
  border-radius: 6px;
}
.brand-lockup img.mark {
  width: 11.25rem;
  height: 4rem;
  flex: none;
  display: block;
  object-fit: contain;
}
/* mark-crop kept as the HTML hook used across shell pages; transparent pass-through */
.brand-lockup .mark-crop {
  width: 3.75rem; height: 3.75rem; flex: none; /* ~60px default */
  display: block;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  padding: 0;
  overflow: visible;
  position: relative;
}
.brand-lockup .mark-crop picture {
  display: block;
  width: 100%;
  height: 100%;
}
.brand-lockup .mark-crop img {
  width: 100%; height: 100%; object-fit: contain; object-position: center;
  display: block;
}
.brand-lockup .wordmark {
  font-weight: 700;
  font-size: 1.4rem;
  letter-spacing: -.03em;
  line-height: 1.05;
  font-feature-settings: "kern" 1, "liga" 1;
}
.brand-lockup .wordmark small {
  display: block;
  font-weight: 500;
  font-size: .68rem;
  letter-spacing: .055em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-top: .14rem;
  line-height: 1.2;
}
/* Top bar: shared brand banner size across all pages */
header.site .brand-lockup { gap: .75rem; }
header.site .brand-lockup .mark-crop {
  width: 11.25rem;
  height: 4rem;
  filter: drop-shadow(0 2px 8px rgba(34, 31, 26, 0.12));
}
header.site .brand-lockup .wordmark { display: none; }
header.site .brand-lockup .wordmark small { font-size: .7rem; }
@media (max-width: 560px) {
  header.site .brand-lockup .mark-crop,
  header.site .brand-lockup img.mark {
    width: 8.75rem;
    height: 3.125rem;
  }
}
/* Dark shell paper ≈ ink tin — lift the mark slightly so silhouette holds.
   Fixed brand colours stay; this is display compensation only. */
@media (prefers-color-scheme: dark) {
  .brand-lockup .mark-crop img,
  .brand-lockup img.mark {
    filter: brightness(1.45) contrast(1.06);
  }
}

/* ---- Marketing landing (Ko-fi layout rhythm) ---- */
body.marketing {
  background: #faf7f2;
  /*
    Fallback offset until JS measures the real sticky bar.
    Must be ≥ bar height or the previous section’s tail peeks under the nav.
  */
  --site-sticky-offset: 11.5rem; /* large welcome tin + wordmark */
}
body.marketing > .proto {
  background: #f0ebe1;
  border-bottom: 1px solid var(--line);
  margin: 0;
}
/* First fold: big type, compact height — next section sits close (no empty vh gap) */
.hero-open {
  text-align: center;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: center;
  min-height: 0;
  padding: 1rem 1rem 1.25rem;
  max-width: 42rem;
  margin: 0 auto;
  box-sizing: border-box;
}
.hero-open .hero-eyebrow {
  display: block;
  font-size: .76rem;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 1rem;
}
.hero-open h1 {
  font-size: clamp(2.6rem, 8.5vw, 4rem);
  line-height: 1.02;
  letter-spacing: -.04em;
  font-weight: 800;
  margin: 0 0 1.15rem;
  color: var(--ink);
  max-width: 14ch;
}
/* One short welcoming line under the H1 — not a product essay */
.hero-open .hero-lede {
  font-size: clamp(1.1rem, 2.4vw, 1.28rem);
  line-height: 1.5;
  color: var(--ink-soft);
  max-width: 26ch;
  margin: 0 auto 1.85rem;
}
.hero-open .hero-lede strong { color: var(--ink); }
.hero-open .hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: .65rem;
  justify-content: center;
  align-items: center;
  margin: 0;
}
.hero-open .hero-actions .btn {
  min-width: 10.5rem;
  border-radius: 999px;
  padding: .85rem 1.45rem;
  font-size: 1.02rem;
}
.hero-open .hero-actions .btn + .btn { margin-left: 0; }
.mkt-section {
  margin: 2.5rem auto 0;
  max-width: 40rem;
  /* Must match/exceed sticky bar — otherwise previous section tail shows under nav */
  scroll-margin-top: var(--site-sticky-offset);
}
.hero-open + .mkt-section {
  margin-top: .5rem;
}
.mkt-section.wide { max-width: 52rem; }
/* Any in-page hash target on the marketing page */
body.marketing [id] {
  scroll-margin-top: var(--site-sticky-offset);
}
.mkt-section .sec-head {
  text-align: center;
  margin-bottom: 1rem;
}
.mkt-section .sec-head h2 {
  font-size: clamp(1.35rem, 3.5vw, 1.7rem);
  letter-spacing: -.02em;
  margin: 0;
}
.mkt-footer {
  text-align: center;
  margin: 2.75rem auto 0;
  max-width: 40rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--line);
  font-size: .9rem;
}
.mkt-footer .legal-links {
  margin-top: 1rem;
  white-space: nowrap;
}
@media (max-width: 480px) {
  /* One line of links cannot grow forever: nowrap plus another item is a
     horizontal scrollbar on a 360px phone, which LANDING-07 pins. Let it
     wrap here; the single line is a wide-screen nicety, not a rule. */
  .mkt-footer .legal-links { white-space: normal; line-height: 1.9; }
}
@media (max-width: 380px) {
  .mkt-footer .legal-links { font-size: .78rem; }
}
/* Homepage How/Fees stay reachable on a phone. Four links plus the wordmark
   do not fit one row at ~360px, so below 480px the site nav wraps under the
   lockup rather than hiding the pricing links. Scoped to body.marketing so
   authed .topbar-nav (dashboard/profile/customize) is untouched. */
@media (max-width: 720px) {
  .topbar-nav a.nav-sec { font-size: .85rem; }
}
@media (max-width: 560px) {
  body.marketing header.site .topbar-nav a:not(.btn) {
    display: inline-flex;
    align-items: center;
    min-height: 24px;
  }
  body.marketing header.site .topbar-nav a.nav-sec {
    font-size: .8rem;
    padding: .2rem .4rem;
  }
  body.marketing { --site-sticky-offset: 8.5rem; }
  .hero-open {
    min-height: 0;
    padding: .75rem .75rem 1rem;
  }
  .hero-open + .mkt-section { margin-top: .35rem; }
  .hero-open .hero-actions { flex-direction: column; width: 100%; }
  .hero-open .hero-actions .btn { width: 100%; max-width: 18rem; }
}
@media (max-width: 480px) {
  body.marketing header.site .topbar-inner {
    flex-wrap: wrap;
    row-gap: .35rem;
  }
  body.marketing header.site .topbar-nav {
    flex: 1 1 100%;
    justify-content: flex-end;
    gap: .25rem .5rem;
  }
  /* Two-row marketing header. JS still measures the real bar; this fallback
     must stay ≥ that height so hash targets clear it. */
  body.marketing { --site-sticky-offset: 10.5rem; }
}

/* Cards */
.card {
  background: var(--card); border:1px solid var(--line); border-radius: var(--radius);
  padding: 1.1rem 1.15rem; box-shadow: var(--shadow); margin: 0 0 1rem;
}
.hero {
  border-top: 4px solid var(--accent);
  text-align:center; padding-top: 1.7rem;
  background:
    radial-gradient(130% 90% at 50% -20%, var(--accent-soft) 0%, rgba(255,255,255,0) 62%),
    var(--card);
}
/* Section rhythm: a quiet eyebrow label above top-level headings gives the page
   structure without another box. */
.eyebrow {
  display: block; font-size: .74rem; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--accent); margin: 0 0 .35rem;
}
.wrap > h2, .wrap-wide > h2 { letter-spacing: -.01em; }
/* Tip page with cover photo — who first, amounts second */
.hero-with-cover {
  border-top: none; padding: 0 0 1.15rem; overflow: hidden; text-align: center;
}
.hero-with-cover .cover {
  height: 7.5rem; background: var(--accent-soft) center/cover no-repeat;
  border-radius: var(--radius) var(--radius) 0 0;
  border-bottom: 1px solid var(--line);
}
.hero-with-cover .avatar,
.hero-with-cover .avatar-photo {
  margin-top: -2.6rem; position: relative; z-index: 1;
}
.hero-with-cover h1 { margin-top: .45rem; margin-bottom: .2em; }
.hero-with-cover .tagline { margin: .1rem 0 .45rem; font-size: .95rem; color: var(--ink-soft); }
.hero-with-cover .bio { margin-top: .55rem; }
.avatar {
  width:88px; height:88px; border-radius:50%; margin:0 auto .6rem;
  background: var(--accent-soft); border: 3px solid var(--accent);
  display:flex; align-items:center; justify-content:center;
  font-size:2.2rem; font-weight:700; color:var(--accent);
}
.avatar-photo {
  width: 96px; height: 96px; border-radius: 50%; margin: 0 auto .55rem;
  border: 3px solid var(--card); box-shadow: 0 0 0 2px var(--accent), var(--shadow);
  object-fit: cover; background: var(--accent-soft); display: block;
}
.handle-pill {
  display:inline-block; font-size:.8rem; color:var(--ink-soft);
  background:var(--accent-soft); border-radius:999px; padding:.15rem .7rem;
}
/* Cover demos (no external image deps) */
.cover-jack {
  background:
    linear-gradient(160deg, rgba(34,31,26,.15), rgba(180,83,9,.35)),
    radial-gradient(ellipse at 30% 40%, #f2c66d 0%, transparent 55%),
    linear-gradient(135deg, #5c3d1e 0%, #b45309 45%, #1a1510 100%);
}
.cover-stmarks {
  background:
    linear-gradient(180deg, rgba(20,30,45,.2), rgba(51,80,109,.45)),
    linear-gradient(135deg, #1e2a3a 0%, #33506d 50%, #0f1720 100%);
  position: relative;
}
.cover-stmarks::after {
  content: ""; position: absolute; inset: 0;
  background: repeating-linear-gradient(
    90deg, transparent, transparent 12%, rgba(255,255,255,.04) 12%, rgba(255,255,255,.04) 13%
  );
  pointer-events: none;
}

/* Buttons */
.btn {
  display:inline-block; text-align:center; text-decoration:none; cursor:pointer;
  border-radius: 12px; border: 1.5px solid var(--ink); background: var(--card);
  color: var(--ink); font: inherit; font-weight: 600; padding: .65rem 1.1rem;
  transition: border-color .15s ease, box-shadow .15s ease, filter .15s ease, transform .05s ease;
}
.btn:hover { border-color: var(--accent); }
.btn:active { transform: translateY(1px); }
.btn-primary {
  background: var(--accent); border-color: var(--accent); color: var(--accent-ink);
  box-shadow: 0 1px 2px rgba(34,31,26,.12);
}
.btn-primary:hover { border-color: var(--accent); filter: brightness(1.06); }
.btn-quiet { border-color: var(--line); font-weight: 500; }
.btn-danger { border-color: var(--danger); color: var(--danger); background: #fff; }
/* Permanent delete — solid danger (disable stays outline) */
.btn-danger-solid {
  border-color: var(--danger); background: var(--danger); color: #fff;
}
.btn-block { display:block; width:100%; }
.btn + .btn { margin-left:.4rem; }
.btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Tip amount row — one line always, up to PRESET_AMOUNTS_MAX (6) chips. Chip
   text is the compact amount ("$5", never "NZ$5.00" — see formatMinorCompact)
   so six chips carry little enough text to read at a legible size; type still
   scales down a little with the viewport for very narrow phones, and a long
   overflow value (should one ever slip past the compact formatter) is clipped
   rather than pushed onto its own line, which would push the CTA below the
   fold. */
.amounts { display:flex; gap:.4rem; margin:.85rem 0; }
.amounts a {
  display:flex; align-items:center; justify-content:center;
  flex: 1 1 0; min-width: 0;
  text-align:center; padding:1.05rem .15rem; border-radius:12px;
  border:1.5px solid var(--line); background:var(--card); color:var(--ink);
  font-weight:800; font-size: clamp(.8rem, 3.6vw, 1.25rem); text-decoration:none;
  font-variant-numeric: tabular-nums; letter-spacing: -.01em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  transition: border-color .12s ease, background .12s ease, transform .05s ease;
}
.amounts a:hover { border-color: var(--accent); }
.amounts a:active { transform: translateY(1px); }
.amounts a.sel {
  border-color: var(--accent); background: var(--accent-soft); color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
}
.custom-amount { display:flex; gap:.6rem; }
.custom-amount input { flex:1; padding:.8rem .75rem; font-size:1.05rem; font-weight:600; }
/* Tipper "give" card — the money moment. Give it a clear accent edge and a
   confident full-width action. */
.give-card { border-top: 3px solid var(--accent); }
.give-card .lede { font-size: .95rem; }
.custom-label {
  display:block; font-weight:600; font-size:.85rem; color:var(--ink-soft);
  margin:.9rem 0 .3rem;
}
.give-go { margin-top:.75rem; font-size:1.05rem; padding:.85rem 1.1rem; }
.give-card .trust {
  display:flex; align-items:center; justify-content:center; gap:.35rem;
  margin-top:1rem; font-size:.82rem;
}
.give-card .trust::before {
  content:""; width:.85rem; height:.85rem; flex:none;
  background: currentColor; opacity:.7;
  -webkit-mask: var(--shield) center/contain no-repeat; mask: var(--shield) center/contain no-repeat;
}
:root { --shield: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2l8 3.5V11c0 5-3.4 9.2-8 11-4.6-1.8-8-6-8-11V5.5L12 2z'/%3E%3C/svg%3E"); }

/* Forms */
label { display:block; font-weight:600; font-size:.9rem; margin:.9rem 0 .25rem; }
input[type=text], input[type=number], input[type=email], select, textarea {
  width:100%; font:inherit; color:var(--ink); background:#fff;
  border:1.5px solid var(--line); border-radius:10px; padding:.55rem .7rem;
}
input:focus, select:focus, textarea:focus { outline:2px solid var(--accent); border-color:var(--accent); }
.hint { font-size:.8rem; color:var(--ink-soft); margin-top:.25rem; }
.field-warn { color: var(--danger); font-size:.85rem; font-weight:600; }
/* Public-page amount clamp + form errors (danger text; never hide via color alone) */
.form-msg { font-size: .9rem; margin: .45rem 0 0; min-height: 1.1em; }
.form-msg.err { color: var(--danger); font-weight: 600; }
.form-msg.ok { color: var(--ok, #256d3a); font-weight: 600; }

/* Status + tables */
.status { display:inline-block; font-size:.75rem; font-weight:700; border-radius:999px; padding:.15rem .6rem; }
.st-live { background:#e5f2e8; color:var(--ok); }
.st-pending { background:#fdf1e3; color:#8a5a13; }
.st-frozen, .st-suspended { background:#f8e4e2; color:var(--danger); }
.st-off { background:#eee7da; color:var(--ink-soft); }
table { width:100%; border-collapse:collapse; font-size:.92rem; }
th, td { text-align:left; padding:.5rem .4rem; border-bottom:1px solid var(--line); }
th { font-size:.78rem; text-transform:uppercase; letter-spacing:.05em; color:var(--ink-soft); }
.num { text-align:right; font-variant-numeric: tabular-nums; }

/* Steps (wizard) */
.steps { display:flex; gap:.4rem; margin:0 0 1rem; font-size:.75rem; color:var(--ink-soft); }
.steps span { flex:1; border-top:4px solid var(--line); padding-top:.3rem; }
.steps .done { border-color: var(--accent); color: var(--ink); font-weight:600; }

/* Notices */
.notice { border-left:4px solid var(--accent); background:var(--accent-soft); border-radius:0 10px 10px 0; padding:.7rem .9rem; margin:.9rem 0; font-size:.92rem; }
.notice-danger { border-color: var(--danger); background:#f8e4e2; }

/* Live payment notifications (REQUIREMENTS §4) — portal-only, simulated in the
   prototype. Content is rule-6 metadata: amount + page + time, never payer identity. */
.toast-region {
  /* Below sticky brand bar (large mark) so toasts never cover the lockup */
  position: fixed; left: 0; right: 0; top: 6rem; z-index: 60;
  display: flex; flex-direction: column; align-items: center; gap: .5rem;
  padding: 0 1rem; pointer-events: none;
}
.toast {
  display: flex; align-items: center; gap: .6rem; width: 100%; max-width: 26rem;
  background: var(--card); color: var(--ink);
  border: 1.5px solid var(--accent); border-left-width: 6px;
  border-radius: 12px; padding: .6rem .9rem; font-size: .95rem;
  box-shadow: var(--shadow), 0 6px 24px rgba(0,0,0,.16);
  animation: toast-in .35s ease-out;
}
.toast .amt { font-weight: 800; font-variant-numeric: tabular-nums; }
.toast .demo-chip {
  margin-left: auto; flex: none; font-size: .66rem; font-weight: 700;
  letter-spacing: .07em; text-transform: uppercase; color: var(--ink-soft);
  border: 1px solid var(--line); border-radius: 999px; padding: .12rem .5rem;
}
@keyframes toast-in { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .toast { animation: none; } }
.notif-row {
  display: flex; gap: .6rem; align-items: baseline;
  padding: .45rem .2rem; border-bottom: 1px solid var(--line); font-size: .92rem;
}
.notif-row:last-child { border-bottom: none; }
.notif-row .amt { font-weight: 700; font-variant-numeric: tabular-nums; }
.notif-row .when { margin-left: auto; color: var(--ink-soft); font-size: .8rem; white-space: nowrap; }
.notif-row.notif-new { background: var(--accent-soft); border-radius: 8px; }
.tip-new td { background: var(--accent-soft); }

/* Save-notification toast — prominent, accessible feedback for a Save action on
   the recipient editors (profile + page customize). Distinct from the payment
   .toast above: this reports the result of pressing Save (in-progress / success
   / error), not an incoming tip. Shared here so both editors look identical. */
.save-toast-region {
  /* Below the sticky brand bar so a toast never covers the lockup */
  position: fixed; left: 0; right: 0; top: 5.75rem; z-index: 70;
  display: flex; flex-direction: column; align-items: center; gap: .5rem;
  padding: 0 1rem; pointer-events: none;
}
.save-toast {
  pointer-events: auto;
  display: flex; align-items: center; gap: .6rem;
  width: 100%; max-width: 30rem;
  border: 1.5px solid; border-left-width: 6px; border-radius: 12px;
  padding: .7rem .9rem; font-size: .95rem; font-weight: 600;
  box-shadow: var(--shadow), 0 8px 28px rgba(34,31,26,.18);
  animation: save-toast-in .28s ease-out;
}
.save-toast-icon {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 1.4rem; height: 1.4rem; border-radius: 50%;
  font-size: .95rem; font-weight: 800; line-height: 1;
}
.save-toast-msg { flex: 1 1 auto; min-width: 0; }
.save-toast-close {
  flex: none; margin-left: .3rem; border: none; background: transparent;
  color: inherit; font-size: 1.35rem; line-height: 1; cursor: pointer;
  padding: 0 .25rem; opacity: .7;
}
.save-toast-close:hover { opacity: 1; }
.save-toast-close:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; border-radius: 4px; }
/* Success — green, auto-dismisses */
.save-toast-ok { background: #e9f5ee; border-color: var(--ok); color: #14512a; }
.save-toast-ok .save-toast-icon { background: var(--ok); color: #fff; }
/* Error — red, persists until dismissed or the next save */
.save-toast-err { background: #fdecea; border-color: var(--danger); color: #7f1a15; }
.save-toast-err .save-toast-icon { background: var(--danger); color: #fff; }
/* In-progress — accent, spinner */
.save-toast-saving { background: var(--accent-soft); border-color: var(--accent); color: var(--ink); }
.save-toast-saving .save-toast-icon {
  background: transparent; border: 2.5px solid var(--accent); border-top-color: transparent;
  animation: save-toast-spin .7s linear infinite;
}
@keyframes save-toast-in { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: none; } }
@keyframes save-toast-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .save-toast { animation: none; }
  .save-toast-saving .save-toast-icon { animation: none; }
}

/* Onboarding map + progress */
.map-list { list-style: none; margin: .4rem 0 0; padding: 0; }
.map-list li {
  display: flex; gap: .75rem; align-items: flex-start;
  padding: .7rem 0; border-bottom: 1px solid var(--line);
}
.map-list li:last-child { border-bottom: none; }
.map-list .n {
  flex: none; width: 1.6rem; height: 1.6rem; border-radius: 50%;
  border: 1.5px solid var(--line); display: flex; align-items: center;
  justify-content: center; font-size: .75rem; font-weight: 700; margin-top: .1rem;
}
.map-list strong { display: block; }
.map-list small { color: var(--ink-soft); }
.demo-label {
  display: inline-block; font-size: .68rem; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: #8a5a13; background: #fdf1e3;
  border: 1px solid #f0dcc0; border-radius: 999px; padding: .12rem .5rem;
  vertical-align: middle;
}
.danger-split { display: grid; gap: .75rem; }
@media (min-width: 480px) { .danger-split { grid-template-columns: 1fr 1fr; } }
.danger-split .opt {
  border: 1.5px solid var(--line); border-radius: var(--radius);
  padding: .9rem; background: var(--card);
}
.danger-split .opt.delete { border-color: #f0d4d1; background: #fdf8f7; }
.danger-split .opt h3 { margin: 0 0 .35rem; font-size: 1rem; }
.danger-split .opt p { margin: 0 0 .75rem; font-size: .88rem; color: var(--ink-soft); }
.danger-split .opt .btn { margin-left: 0; width: 100%; }

/* Handle claim: <canonical host>/[name] - [category] Claim
   Name = who (you / parish); Category = what (church, choir, appeal, …) */
.claim-bar {
  display: flex; flex-wrap: wrap; align-items: stretch; gap: .5rem;
  margin: .85rem 0 .4rem;
}
.claim-bar .claim-prefix {
  display: flex; align-items: center; gap: 0;
  flex: 1 1 14rem; min-width: 0;
  border: 1.5px solid var(--line); border-radius: 12px;
  background: #fff; overflow: hidden;
}
.claim-bar .claim-prefix .host {
  flex: none; padding: .65rem .5rem .65rem .7rem;
  font-weight: 600; font-size: .85rem; color: var(--ink-soft);
  background: var(--paper); border-right: 1px solid var(--line);
  white-space: nowrap;
}
.claim-bar .claim-prefix input {
  border: none; border-radius: 0; flex: 1 1 4rem; min-width: 0;
  width: 0; /* flex grow */
  padding: .65rem .45rem; font-weight: 600; background: transparent;
  text-align: center;
}
.claim-bar .claim-prefix input:first-of-type { text-align: left; padding-left: .55rem; }
.claim-bar .claim-prefix input:last-of-type { text-align: left; padding-right: .55rem; }
.claim-bar .claim-prefix input:focus { outline: none; }
.claim-bar .claim-prefix input::placeholder { font-weight: 500; color: #a89f8f; }
.claim-bar .claim-dash {
  flex: none; font-weight: 800; font-size: 1.15rem; color: var(--ink-soft);
  padding: 0 .05rem; user-select: none; line-height: 1;
}
.claim-bar .claim-prefix:focus-within {
  border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft);
}
.claim-bar .btn-claim {
  flex: none; min-width: 6.5rem; margin-left: 0;
  display: inline-flex; align-items: center; justify-content: center;
}
.claim-parts-labels {
  display: grid; grid-template-columns: 1fr auto 1fr; gap: .35rem;
  align-items: end; margin: 0 0 .25rem;
  font-size: .78rem; font-weight: 600; color: var(--ink-soft);
}
.claim-parts-labels .host-spacer { /* aligns under host when full-width bar */
  font-size: .78rem; visibility: hidden;
}
.claim-field-labels {
  display: flex; flex-wrap: wrap; gap: .35rem 1rem;
  margin: 0 0 .15rem; font-size: .8rem; font-weight: 600; color: var(--ink-soft);
}
.claim-field-labels span strong { color: var(--ink); }
.claim-status {
  font-size: .85rem; min-height: 1.3em; margin: .25rem 0 .5rem;
}
.claim-status.ok { color: var(--ok); font-weight: 600; }
.claim-status.bad { color: var(--danger); font-weight: 600; }
.claim-status.muted { color: var(--ink-soft); }
.claim-examples {
  display: flex; flex-wrap: wrap; gap: .35rem; margin: .35rem 0 .15rem;
  padding: 0; list-style: none; font-size: .8rem;
}
.claim-examples li {
  margin: 0; padding: .2rem .5rem; border-radius: 999px; cursor: pointer;
  background: var(--paper); border: 1px solid var(--line); color: var(--ink-soft);
}
.claim-examples li:hover { border-color: var(--ink-soft); }
.claim-examples code { font-size: .8rem; color: var(--ink); }
.welcome-hero { text-align: center; padding-top: 1.5rem; }
.welcome-hero h1 { margin-bottom: .35em; }
.welcome-hero .lede {
  max-width: 36ch; margin: 0 auto .9rem; color: var(--ink-soft); font-size: 1.02rem;
  line-height: 1.5;
}
.welcome-points {
  text-align: left; list-style: none; margin: 1rem 0 0; padding: 0;
  max-width: 34rem; margin-left: auto; margin-right: auto;
}
.welcome-points li {
  display: flex; gap: .65rem; align-items: flex-start;
  padding: .55rem 0; border-top: 1px solid var(--line);
  font-size: .92rem; color: var(--ink-soft);
}
.welcome-points li:first-child { border-top: none; }
.welcome-points strong { color: var(--ink); display: block; font-size: .95rem; }
.welcome-points .tick {
  flex: none; color: var(--ok); font-weight: 800; width: 1.1rem; text-align: center;
  margin-top: .1rem;
}

/* Poster (print) */
.poster { text-align:center; padding:2rem 1rem; }
.poster .qr { width:220px; height:220px; margin:1rem auto; }
@media print {
  .proto, .no-print { display:none !important; }
  body { background:#fff; }
  .card { box-shadow:none; border:none; }
}

@media (max-width: 420px) {
  .amounts { gap:.4rem; }
  .wrap { padding: .9rem .8rem 2.5rem; }
}

/* Custom page links (up to 3; each has a title + URL). Rendered only when set. */
.page-links {
  display: flex; flex-wrap: wrap; justify-content: center; gap: .5rem;
  margin: .9rem 0 0;
}
.page-link {
  display: inline-flex; align-items: center; gap: .35rem;
  padding: .4rem .8rem; border: 1.5px solid var(--line); border-radius: 999px;
  font-size: .88rem; font-weight: 600; text-decoration: none;
  color: var(--ink); background: var(--card);
}
.page-link:hover, .page-link:focus-visible { border-color: var(--accent); }
.page-link::after { content: "↗"; font-size: .85em; color: var(--ink-soft); }
.mini .page-links { margin-top: .6rem; }
.mini .page-link { font-size: .78rem; padding: .3rem .6rem; pointer-events: none; }
