/**
 * @file landing.css
 * @description Logged-out landing + pricing pages (ld- prefix). Theme tokens only;
 *   path cards stack on mobile, ticker truncates to one line.
 * @version-history
 *   v1.0.0 — 2026-06-10 — Initial (landing/portal split).
 *   v1.1.0 — 2026-06-16 — Add public activity feed styles (pa- prefix).
 *   v1.2.0 — 2026-06-16 — Add reward-first Hero v2 styles (ld-hero2-*): newspaper-framed
 *     Sanomat teaser (designed masthead card; real screenshot when one exists), mobile-first, two CTAs.
 *   v1.3.0 — 2026-06-20 — Live wall: .ld-gallery is now a fixed 3-up grid (2-up tablet, 1-up phone)
 *     + .ld-wall-search filter box, for the real published-apps wall.
 *   v1.4.0 — 2026-08-01 — .ld-transline: the single AI-transparency line above the footer
 *     (TARGET-058 Phase 10).
 *   v1.5.0 — 2026-08-08 — .ld-askai-copy became a container rule on .ld-askai-box. .ld-gen-copy renamed
 *       .ld-gen-action: it was never a copy class — step 3's "Register and add your app" anchor
 *       wears it too.
 *   v1.6.0 — 2026-08-16 — .ld-wish: the wish box under the pitch line (input + GO), the front
 *       page's primary action.
 */
.ld { max-width: 980px; margin: 0 auto; padding: 2rem 1.25rem 3rem; color: var(--text); }

/* ── Hero v2 — reward first: a newspaper-framed Sanomat teaser (designed card now, real
   screenshot when one exists) + two CTAs. Mobile-first, no iframe. ── */
.ld-hero2 { text-align: center; padding: 1.75rem 0 1.5rem; }
.ld-hero2-kicker { color: var(--text-dim); font-size: 1rem; font-weight: 600; margin: 0 0 .35rem; }
.ld-hero2-title { font-size: 2.4rem; font-weight: 800; letter-spacing: -0.5px; line-height: 1.1; margin: 0 0 1.1rem; }
@media (max-width: 600px) { .ld-hero2-title { font-size: 1.85rem; } }
.ld-hero2-shot { position: relative; display: block; max-width: 680px; margin: 0 auto; border: 1px solid var(--border); border-radius: 14px; overflow: hidden; background: var(--card); box-shadow: 0 8px 30px rgba(0, 0, 0, .25); text-decoration: none; }
.ld-hero2-shot:hover { border-color: var(--accent); }
.ld-hero2-img { display: block; width: 100%; height: auto; max-height: 440px; object-fit: cover; object-position: top center; }
/* Designed "newspaper" card shown when no real screenshot exists (the default today). */
.ld-hero2-paper { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .7rem; min-height: 240px; padding: 2rem 1.25rem 2.75rem; background: var(--bg-surface, var(--bg-dim)); }
.ld-hero2-masthead { font-family: Georgia, 'Times New Roman', serif; font-size: 2.4rem; font-weight: 800; letter-spacing: -.5px; color: var(--text); text-align: center; }
@media (max-width: 600px) { .ld-hero2-masthead { font-size: 1.9rem; } }
.ld-hero2-paper-rule { width: 64px; height: 2px; background: var(--accent); border-radius: 2px; }
.ld-hero2-paper-line { color: var(--text-dim); font-size: .92rem; text-align: center; }
.ld-hero2-openbar { position: absolute; left: 0; right: 0; bottom: 0; padding: .55rem .8rem; background: linear-gradient(to top, rgba(0, 0, 0, .72), transparent); color: #fff; font-weight: 700; font-size: .95rem; text-align: left; }
.ld-hero2-sub { color: var(--text-dim); font-size: 1rem; max-width: 560px; margin: 1rem auto .25rem; }
.ld-hero2-cta { display: flex; gap: .8rem; justify-content: center; flex-wrap: wrap; margin-top: 1.1rem; }
.ld-hero2-cta a { text-decoration: none; }
.ld-hero2-after { color: var(--text-dim); font-size: .9rem; max-width: 560px; margin: .9rem auto 0; }
.ld-hero2-after a { color: var(--accent); font-weight: 600; }
/* The other paths, one quiet line under the single primary button. Four buttons of equal
   weight asked the visitor to choose before they knew enough to choose. */
.ld-hero2-more { display: flex; gap: 1.2rem; justify-content: center; flex-wrap: wrap; margin-top: .85rem; }
.ld-hero2-more a { color: var(--text-dim); font-size: .88rem; text-decoration: none; }
.ld-hero2-more a:hover { color: var(--accent); text-decoration: underline; }
.ld-hero { text-align: center; padding: 2.5rem 0 1.25rem; }
.ld-h1 { font-size: 2.1rem; font-weight: 800; letter-spacing: -0.5px; margin: 0 0 .6rem; }
.ld-hero-sub { color: var(--text-dim); font-size: 1.05rem; margin: 0; }
/* "Ask your own AI what AIMEAT is" prompt box */
.ld-askai { max-width: 760px; margin: 1.25rem auto 2rem; text-align: center; }
.ld-askai-title { font-size: 1.25rem; font-weight: 700; margin: 0 0 .4rem; }
.ld-askai-sub { color: var(--text-dim); font-size: .92rem; margin: 0 auto 1rem; max-width: 620px; }
.ld-askai-box { border: 1px solid var(--border); border-radius: 12px; background: var(--card); padding: 1rem 1.1rem; text-align: left; }
.ld-askai-prompt { margin: 0; white-space: pre-wrap; word-break: break-word; font-family: var(--font-mono, monospace); font-size: .8rem; line-height: 1.5; color: var(--text); max-height: 260px; overflow-y: auto; }
/* The prompt box's copy button is the shared <CopyButton> (.btn-primary); the gap above it
   belongs to this box, not to a bespoke button class. */
.ld-askai-box .btn-primary { margin-top: .9rem; }
/* "Show the full prompt" sits between the preview and the copy button. */
.ld-askai-more { margin-top: .6rem; display: block; font-size: .82rem; }
.ld-ticker { display: flex; align-items: center; gap: .5rem; justify-content: center; margin: 1rem auto; max-width: 760px; padding: .45rem .9rem; border: 1px solid var(--border); border-radius: 999px; background: var(--card); font-size: .85rem; color: var(--text-dim); white-space: nowrap; overflow: hidden; }
.ld-ticker-text { overflow: hidden; text-overflow: ellipsis; }
.ld-ticker-dot { color: var(--success-fg, #2E9E5B); flex: none; }
.ld-stats { max-width: 760px; margin: 1.25rem auto 2rem; padding: 1rem 1.25rem; border: 1px solid var(--border); border-radius: 12px; background: var(--bg-surface, var(--bg-dim)); text-align: center; }
.ld-stats-line { font-size: 1.05rem; font-weight: 600; }
.ld-stats-own { margin-top: .6rem; color: var(--text-dim); font-size: .95rem; }
.ld-stats-cta { color: var(--accent); font-weight: 700; text-decoration: none; margin-left: .35rem; }
.ld-stats-cta:hover { text-decoration: underline; }
.ld-paths { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; margin: 1.5rem 0; }
@media (max-width: 760px) { .ld-paths { grid-template-columns: 1fr; } }
.ld-path { border: 1px solid var(--border); border-radius: 12px; background: var(--card); padding: 1.1rem 1.2rem; display: flex; flex-direction: column; }
.ld-path--hot { border-color: var(--accent); border-width: 2px; }
.ld-path h3 { margin: 0 0 .4rem; font-size: 1.05rem; }
.ld-path p { margin: 0 0 .9rem; color: var(--text-dim); font-size: .9rem; flex: 1; }
.ld-path-cta { color: var(--accent); font-weight: 700; text-decoration: none; font-size: .92rem; }
.ld-path-cta:hover { text-decoration: underline; }
.ld-loop { display: flex; align-items: center; justify-content: center; gap: .6rem; flex-wrap: wrap; margin: 1.5rem 0 2rem; padding: .8rem 1rem; border: 1px solid var(--border); border-radius: 10px; background: var(--bg-surface, var(--bg-dim)); font-size: .9rem; }
.ld-loop-arrow { color: var(--text-dim); }
.ld-section { margin: 2rem 0; }
.ld-h2 { font-size: 1.3rem; margin: 0 0 1rem; }
.ld-wall-search { width: 100%; max-width: 360px; margin: 0 0 1rem; padding: .55rem .8rem; border: 1px solid var(--border); border-radius: 8px; background: var(--card); color: var(--text); font-size: .9rem; }
.ld-gallery { display: grid; grid-template-columns: repeat(3, 1fr); gap: .9rem; }
@media (max-width: 900px) { .ld-gallery { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .ld-gallery { grid-template-columns: 1fr; } }
/* A column so the footer can be pushed to the bottom edge. Cards in a row are as tall as the
   longest description, and a footer that floated up behind a short one left the ragged gap that
   made the grid look unfinished. */
.ld-app-card {
  display: flex; flex-direction: column; border: 1px solid var(--border); border-radius: 10px;
  background: var(--card); padding: .9rem 1rem; text-decoration: none; color: var(--text); cursor: pointer;
}
.ld-app-card:hover { border-color: var(--accent); }
/* Search and order on one row; the order buttons wrap under the search on a narrow screen. */
.ld-wall-bar { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; margin-bottom: .8rem; }
.ld-wall-bar .ld-wall-search { flex: 1 1 220px; margin-bottom: 0; }
.ld-wall-sort { display: inline-flex; border: 1px solid var(--border); border-radius: 999px; overflow: hidden; background: var(--card); }
.ld-wall-sort-btn {
  border: 0; background: transparent; cursor: pointer; font: inherit; font-size: .78rem;
  color: var(--text-muted); padding: .32rem .8rem;
}
.ld-wall-sort-btn:hover { color: var(--text); }
.ld-wall-sort-btn.is-on { background: var(--accent); color: #fff; }

.ld-app-shot { display: block; width: 100%; aspect-ratio: 16 / 10; object-fit: cover; border-radius: 8px; border: 1px solid var(--border); margin-bottom: .55rem; background: var(--bg-dim); }
.ld-app-name { font-weight: 700; margin-bottom: .25rem; }
.ld-app-desc { font-size: .82rem; color: var(--text-dim); margin-bottom: .55rem; }
.ld-app-meta { font-size: .72rem; color: var(--muted); }
/* One rule, then one line: what the app IS on the left, who made it and when on the right.
   Pills turned four short facts into four boxes and made the card look busier than the app.
   Emphasis carries the version and the counts instead of a border. */
.ld-app-foot {
  margin-top: auto; padding-top: .55rem; border-top: 1px solid var(--border);
  display: flex; align-items: baseline; justify-content: space-between; gap: .5rem .75rem; flex-wrap: wrap;
}
/* The footer is one quiet line, all of it the same grey. The facts were ink and the count was
   accent, which pulled the eye to the corner of every card at once and turned a wall of thirty
   into thirty competing signals. They are there for whoever looks; they do not ask to be looked at. */
.ld-app-facts { font-size: .72rem; color: var(--text-muted); letter-spacing: .01em; display: inline-flex; align-items: center; gap: .3rem; }
.ld-app-sep { color: var(--text-muted); }
.ld-app-opens { display: inline-flex; align-items: center; gap: .22rem; }
.ld-eye { flex: 0 0 auto; }
.ld-app-by { font-size: .7rem; color: var(--text-muted); }
/* One line about AI transparency, above the footer. Quiet on purpose: the claim it makes is small
   and checkable, and the page it links to is where the limits belong. */
.ld-transline { margin: 2rem auto 0; max-width: 62ch; text-align: center; color: var(--text-dim); font-size: .88rem; line-height: 1.6; }
.ld-transline a { color: var(--accent); font-weight: 600; white-space: nowrap; }
/* .ld-footer / .ld-gh / .gh-mark left with the landing's own footer on 2026-08-09: the shell
   renders one .site-footer (theme.css) under every public view instead. */
/* Pricing */
.ld-pricing .ld-h1 { text-align: center; }
.ld-pricing .ld-hero-sub { text-align: center; margin-bottom: 1.5rem; }
.ld-tiers { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 1rem; margin: 1.25rem 0; }
.ld-tier { border: 1px solid var(--border); border-radius: 12px; background: var(--card); padding: 1.1rem 1.2rem; display: flex; flex-direction: column; }
.ld-tier--hot { border-color: var(--accent); border-width: 2px; }
.ld-tier-name { margin: 0 0 .2rem; font-size: 1.05rem; }
.ld-tier-price { font-size: 1.3rem; font-weight: 800; margin-bottom: .6rem; }
.ld-tier-lines { margin: 0 0 1rem; padding-left: 1.1rem; color: var(--text-dim); font-size: .88rem; flex: 1; }
.ld-tier-lines li { margin-bottom: .3rem; }

/* ── How it works ── */
.hiw-diagram { margin: 1.5rem 0; }
.hiw-svg { width: 100%; height: auto; display: block; }
.hiw-svg--tall { display: none; max-width: 360px; margin: 0 auto; }
@media (max-width: 700px) { .hiw-svg--wide { display: none; } .hiw-svg--tall { display: block; } }
.ld-ctarow { display: flex; gap: .9rem; justify-content: center; flex-wrap: wrap; margin: 2rem 0 1rem; }
.ld-ctarow a { text-decoration: none; }

/* ── Business ── */
.ld-bhero { position: relative; display: grid; grid-template-columns: 1fr 1fr; align-items: center; gap: 1.25rem; margin: 1rem 0 2rem; border-radius: 14px; overflow: hidden; background: var(--bg-surface, var(--bg-dim)); border: 1px solid var(--border); }
.ld-bhero-img { width: 100%; height: 100%; object-fit: cover; min-height: 260px; }
.ld-bhero-text { padding: 1.5rem 1.5rem 1.5rem .25rem; }
.ld-bhero--noimg { grid-template-columns: 1fr; text-align: center; }
.ld-bhero--noimg .ld-bhero-text { padding: 2.25rem 1.5rem; }
@media (max-width: 700px) { .ld-bhero { grid-template-columns: 1fr; } .ld-bhero-text { padding: 1.25rem; } .ld-bhero-img { max-height: 220px; } }
.ld-cases { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1rem; margin: 1.5rem 0; }
@media (max-width: 760px) { .ld-cases { grid-template-columns: 1fr; } }
.ld-case { border: 1px solid var(--border); border-radius: 12px; background: var(--card); padding: 1.1rem 1.2rem; display: flex; flex-direction: column; gap: .55rem; }
.ld-case-title { margin: 0; font-size: 1.05rem; }
.ld-case-text { margin: 0; color: var(--text-dim); font-size: .9rem; flex: 1; }
.ld-case-quote { margin: 0; padding: .5rem .8rem; border-left: 3px solid var(--accent); background: var(--bg-surface, var(--bg-dim)); border-radius: 6px; font-size: .88rem; }
.ld-case-quote footer { color: var(--text-dim); font-size: .78rem; margin-top: .25rem; }
.ld-case-proof { font-size: .85rem; color: var(--accent); text-decoration: none; font-weight: 600; }
.ld-case-proof:hover { text-decoration: underline; }
.ld-case-proofnote { font-size: .8rem; color: var(--text-dim); font-style: italic; background: var(--bg-surface, var(--bg-dim)); border-radius: 6px; padding: .45rem .7rem; }

/* Cases grouped by how far up the value ladder they sit: work happens without you →
   the company runs on it → the company earns on it. A group with no cases is dropped in
   JS (Group() returns null), not here — htm leaves whitespace nodes, so :empty never matches. */
.ld-casegroup { margin: 2.5rem 0 0; }
.ld-casegroup-title { font-size: 1.1rem; font-weight: 700; color: var(--accent); margin: 0; }
.ld-casegroup .ld-cases { margin-top: .9rem; }

/* Why owning it is the reason to buy — the regulated-buyer argument. */
.ld-sovereignty { margin: 2.75rem 0 0; }
.ld-sov-list { margin: .9rem 0 0; padding-left: 1.2rem; display: grid; gap: .5rem; }
.ld-sov-list li { color: var(--text-dim); font-size: .9rem; line-height: 1.5; }

/* ── Contact card (business + pricing only) ── */
.ld-contact { max-width: 460px; margin: 2.25rem auto 0; padding: 1.25rem 1.5rem; border: 2px solid var(--accent); border-radius: 14px; background: var(--card); text-align: center; }
.ld-contact-title { font-size: 1.15rem; font-weight: 800; margin-bottom: .4rem; }
/* Two people side by side on a wide screen, stacked on a phone. */
.ld-contact-people { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1rem; margin-bottom: .5rem; }
.ld-contact-person { display: flex; flex-direction: column; gap: .2rem; }
.ld-contact-role { font-size: .8rem; color: var(--text-dim); margin-bottom: .2rem; }
.ld-contact-name { font-weight: 600; margin-bottom: .35rem; }
.ld-contact-person .ld-contact-name { margin-bottom: 0; }
.ld-contact-person .ld-contact-links { flex-direction: column; gap: .15rem; margin-bottom: 0; }
.ld-contact-links { display: flex; gap: 1rem; justify-content: center; flex-wrap: wrap; margin-bottom: .45rem; }
.ld-contact-links a { color: var(--accent); text-decoration: none; font-weight: 600; }
.ld-contact-links a:hover { text-decoration: underline; }
.ld-contact-sub { color: var(--text-dim); font-size: .88rem; }
.ld-example-img { width: 100%; max-height: 260px; object-fit: cover; border-radius: 10px; margin-bottom: .9rem; }
.ld-app-badge { font-size: .68rem; font-weight: 600; color: var(--text-dim); border: 1px solid var(--border); border-radius: 999px; padding: 1px 7px; vertical-align: 2px; }

/* ── Public activity feed (pa- prefix) ── */
.pa { max-width: 760px; margin: 2rem auto; }
.pa-title { font-size: 1.3rem; margin: 0 0 .3rem; }
.pa-sub { color: var(--text-dim); font-size: .9rem; margin: 0 0 1rem; }
.pa-tabs { display: flex; justify-content: center; gap: .4rem; flex-wrap: wrap; margin-bottom: .75rem; }
.pa-tab { position: relative; display: inline-flex; align-items: center; gap: .4rem; padding: .45rem .9rem; border: 1px solid var(--border); border-radius: 999px; background: var(--card); color: var(--text-dim); font-size: .88rem; font-weight: 600; cursor: pointer; }
.pa-tab:hover { border-color: var(--accent); }
.pa-tab--active { background: var(--accent); border-color: var(--accent); color: #fff; }
.pa-tab-icon { font-size: .95rem; }
.pa-badge { display: inline-flex; align-items: center; justify-content: center; min-width: 1.1rem; height: 1.1rem; padding: 0 .3rem; border-radius: 999px; background: var(--accent); color: #fff; font-size: .68rem; font-weight: 700; }
.pa-tab--active .pa-badge { background: #fff; color: var(--accent); }
.pa-panel { border: 1px solid var(--border); border-radius: 12px; background: var(--card); overflow: hidden; }
.pa-empty { padding: 1.5rem 1.25rem; text-align: center; color: var(--text-dim); font-size: .9rem; }
.pa-list { list-style: none; margin: 0; padding: 0; }
.pa-row { border-bottom: 1px solid var(--border); }
.pa-row:last-child { border-bottom: none; }
.pa-row-head { width: 100%; display: flex; align-items: center; gap: .7rem; padding: .65rem .95rem; background: none; border: none; text-align: left; cursor: pointer; color: var(--text); font-size: .9rem; }
.pa-row-head:hover { background: var(--bg-surface, var(--bg-dim)); }
.pa-time { flex: none; font-variant-numeric: tabular-nums; color: var(--text-dim); font-size: .82rem; }
.pa-summary { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pa-caret { flex: none; color: var(--text-dim); font-size: .8rem; }
.pa-detail { padding: 0 .95rem .8rem 3.1rem; }
.pa-detail-text { margin: 0 0 .4rem; color: var(--text-dim); font-size: .85rem; white-space: pre-wrap; word-break: break-word; }
.pa-detail-actor { margin: 0 0 .4rem; color: var(--muted); font-size: .78rem; }
.pa-detail-link { color: var(--accent); font-weight: 700; text-decoration: none; font-size: .85rem; }
.pa-detail-link:hover { text-decoration: underline; }

/* ── Node totals panel (nt- prefix) — cumulative counters replacing the activity feed ── */
.nt-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: .6rem; }
.nt-card { display: flex; flex-direction: column; align-items: center; gap: .15rem; padding: 1rem .75rem; border: 1px solid var(--border); border-radius: 12px; background: var(--card); text-align: center; }
.nt-icon { font-size: 1.4rem; line-height: 1; }
.nt-value { font-size: 1.6rem; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--text); }
.nt-label { font-size: .8rem; color: var(--text-dim); }
.nt-sub { font-size: .72rem; font-weight: 600; color: var(--accent); }

/* ── Build invitation, folded (TARGET-056) ──────────────────────────────────
   The generator used to sit open at the top. Two visitors made a throwaway chat app
   and stopped, while the wall below is what reads as a living place. So the builder is
   one prominent line until someone wants it, and the wall leads. */
/* The one sentence that says what this is, above the first thing that asks for a click.
   It carries the page, so it is set at heading weight without being an <h1> competitor to the
   ownership question further down; the lead-in under it is deliberately quiet, because its
   whole job is to stop the fold from reading as the entire product. */
/* An app that has been opened forty times and revised to v1.2.0 is a different thing from one
   published yesterday and never touched, and the wall showed neither. A zero is omitted rather
   than printed: "0 opens" on a new app reads as a verdict on it. */

.ld-pitch { max-width: 760px; margin: 2rem auto 1rem; text-align: left; }
.ld-pitch-line { font-size: 1.35rem; line-height: 1.4; font-weight: 700; color: var(--text); margin: 0; }
.ld-pitch-lead { font-size: .95rem; color: var(--text-muted); margin: .75rem 0 0; }

/* The wish box: the one field the whole page funnels into. Big on purpose — it is the primary
   action of the front page, and everything below it is evidence that pressing GO works. */
.ld-wish { display: flex; gap: .6rem; margin: 1rem 0 0; }
.ld-wish-input {
  flex: 1 1 auto; min-width: 0;
  font-size: 1.1rem; font-weight: 600;
  padding: .8rem 1rem;
  border: 2px solid var(--border); border-radius: 12px;
  background: var(--card); color: var(--text);
}
.ld-wish-input:focus { outline: none; border-color: var(--accent); }
.ld-wish-input::placeholder { color: var(--text-dim); font-weight: 400; }
.ld-wish-go { flex: 0 0 auto; font-size: 1rem; padding: .8rem 1.6rem; }

.ld-invite { max-width: 760px; margin: 0 auto 2rem; }
.ld-invite .collapsible {
  border: 1px solid var(--border); border-radius: 16px;
  background: var(--card); overflow: hidden;
  box-shadow: 0 8px 40px rgba(0, 0, 0, .06);
}
.ld-invite .collapsible-header { padding: 20px 28px; width: 100%; cursor: pointer; }
/* The header IS the door — it needs to look like one, or the invitation reads as a heading
   with a decorative chevron and nobody opens it. */
.ld-invite .collapsible-header:hover { background: var(--surface); }
.ld-invite .collapsible-header:hover .ld-invite-sub { color: var(--accent); }
.ld-invite .collapsible-title { display: flex; flex-direction: column; gap: .15rem; text-align: left; }
.ld-invite-title { font-size: 1.15rem; font-weight: 800; color: var(--text); }
.ld-invite-sub { font-size: .88rem; color: var(--text-dim); font-weight: 400; }
.ld-invite .collapsible-body { padding: 0 28px 28px; }
/* Inside the fold the loop and the prompt box lose their standalone page margins. */
.ld-invite .ld-loop { margin-top: .25rem; }
.ld-invite .ld-askai { margin-top: 1rem; }

/* The connect door's body: one paragraph of scope, then one action + the account caveat. */
.ld-connect-note { font-size: .9rem; line-height: 1.6; color: var(--text-dim); margin: 0 0 1rem; }
.ld-connect-cta { display: flex; align-items: center; gap: .75rem; flex-wrap: wrap; }
.ld-connect-hint { font-size: .82rem; color: var(--text-dim); }

/* "Show the other N apps" — the wall's first page is short so the two doors above it stay
   reachable on a phone; the rest expands in place rather than sending the visitor elsewhere. */
.ld-wall-more { display: flex; justify-content: center; margin-top: 1.25rem; }

/* ── Node change log — folded, one line until it is wanted ────────────────────────────
   Same door as .ld-invite (one collapsible on the page should not read as two components),
   but quieter: this is a status line, not the page's invitation. Shut it shows the freshest
   entry; open it scrolls its own history instead of pushing the wall off the screen. */
.ld-log { max-width: 760px; margin: 0 auto 1.25rem; }
.ld-log .collapsible {
  border: 1px solid var(--border); border-radius: 14px;
  background: var(--card); overflow: hidden;
}
.ld-log .collapsible-header { padding: 12px 20px; width: 100%; cursor: pointer; }
.ld-log .collapsible-header:hover { background: var(--surface); }
.ld-log .collapsible-title { text-align: left; }
.ld-log-head { display: flex; flex-direction: column; gap: .2rem; }
.ld-log-label { font-size: .78rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--text-muted); }
.ld-log-latest { display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap; }
.ld-log-newest { font-size: .95rem; font-weight: 600; color: var(--text); }
.ld-log-date { font-size: .78rem; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.ld-log-version { font-size: .74rem; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.ld-log-kind {
  font-size: .68rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  padding: 2px 7px; border-radius: 999px; border: 1px solid var(--border); color: var(--text-dim);
  white-space: nowrap;
}
/* Colour carries meaning here and nowhere else in the row: what KIND of change this was. */
.ld-log-kind-feature { color: var(--accent); border-color: var(--accent); }
.ld-log-kind-security { color: var(--danger); border-color: var(--danger); }
/* The open history scrolls inside itself — an unbounded list would bury the app wall. */
.ld-log-list { max-height: 380px; overflow-y: auto; padding: 0 20px 16px; text-align: left; }
.ld-log-item { padding: 14px 0; border-top: 1px solid var(--border); }
.ld-log-item:first-child { border-top: none; padding-top: 4px; }
.ld-log-meta { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; margin-bottom: .3rem; }
.ld-log-title { margin: 0 0 .25rem; font-size: 1rem; font-weight: 700; color: var(--text); }
/* pre-line, because an entry body carries its own paragraph breaks. Without it every blank line in
   changelog.json collapsed into a space and a four-paragraph entry rendered as one wall. Nothing
   parses markdown here, so an entry is written as plain text and its \n\n are the only structure
   it gets. */
.ld-log-body { margin: 0; font-size: .87rem; line-height: 1.55; color: var(--text-dim); white-space: pre-line; }
@media (max-width: 600px) {
  .ld-log .collapsible-header { padding: 12px 14px; }
  .ld-log-list { padding: 0 14px 14px; max-height: 320px; }
}

/* ── Generator — a direct port of the app-catalog's .pb-* rules (TARGET-056) ──────────
   Every value here is the catalog's value, translated only where the two stylesheets name the
   same token differently (--bg-subtle → --bg-dim, --text-muted is shared). Kept literal on
   purpose: a "similar" generator on the front page and in the catalog reads as two products,
   and every private deviation is a place they drift apart again. */
.ld-gen { text-align: left; }
.ld-gen-intro { font-size: .82rem; color: var(--text-muted); line-height: 1.55; margin: 0 0 18px; }
.ld-gen-step { border-top: 1px solid var(--border); padding-top: 16px; margin-bottom: 16px; }
.ld-gen-step:first-of-type { border-top: none; padding-top: 0; }
.ld-gen-head { display: flex; align-items: center; gap: 10px; font-weight: 700; font-size: .98rem; margin-bottom: 12px; }
.ld-gen-num {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; border-radius: 50%; flex: 0 0 auto;
  background: var(--accent); color: #fff; font-size: .82rem; font-weight: 700;
}
.ld-gen-idea {
  width: 100%; box-sizing: border-box; min-height: 60px; max-height: 120px; resize: vertical;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 10px; padding: 10px 14px; color: inherit; font-size: .85rem;
  font-family: inherit; line-height: 1.5; margin-bottom: 14px;
}
.ld-gen-idea:focus { outline: none; border-color: var(--accent); }
.ld-gen-label { display: flex; align-items: center; gap: 8px; font-size: .85rem; margin-bottom: 10px; }
.ld-gen-opt { color: var(--text-muted); }
.ld-gen-select {
  width: 100%; margin-bottom: 8px; font-size: .85rem;
  background: var(--surface); border: 1px solid var(--border); border-radius: 10px;
  padding: 10px 14px; color: inherit;
}
.ld-gen-hint { font-size: .8rem; color: var(--text-muted); line-height: 1.55; margin: 0 0 12px; }
.ld-gen-packs { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.ld-gen-pack {
  display: inline-flex; align-items: center; gap: 6px; padding: 5px 10px;
  border: 1px solid var(--border); border-radius: 999px; background: var(--surface);
  font-size: 13px; cursor: pointer; user-select: none;
}
.ld-gen-pack:hover { border-color: var(--accent); }
.ld-gen-pack input { accent-color: var(--accent); margin: 0; }
.ld-gen-pack:has(input:checked) { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 14%, var(--card)); }
.ld-gen-tier {
  font-size: 10px; text-transform: uppercase; letter-spacing: .03em; padding: 1px 5px;
  border-radius: 999px; background: color-mix(in srgb, var(--text-muted) 15%, transparent);
  color: var(--text-muted); font-weight: 600; cursor: help;
}
.ld-gen-tier.is-frontier { background: color-mix(in srgb, var(--accent) 20%, transparent); color: var(--accent); }
/* What the pack you are pointing at actually does. The name alone told nobody what
   `noste-cortex` is, and the description was hidden in a native tooltip that never appears on a
   phone. Sits under the pills so the grid stays compact. */
.ld-gen-packinfo {
  margin: 10px 0 0; padding: 10px 12px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 10px;
}
.ld-gen-packinfo-line { margin: 0 0 6px; font-size: .8rem; line-height: 1.5; color: var(--text-muted); }
.ld-gen-packinfo-line:last-child { margin-bottom: 0; }
.ld-gen-packinfo-name { font-weight: 700; color: var(--text); }
/* The three badge words are instructions, not statuses, and unexplained they read as warnings. */
.ld-gen-legend { margin: 8px 0 0; font-size: .72rem; line-height: 1.55; color: var(--text-muted); }
.ld-gen-preview-label { font-size: .75rem; text-transform: uppercase; letter-spacing: .1em; color: var(--text-muted); margin-bottom: 6px; }
.ld-gen-preview {
  min-height: 90px; max-height: 150px; overflow-y: auto; margin-bottom: 12px; padding: 12px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 10px; font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
  font-size: .75rem; line-height: 1.5; white-space: pre-wrap; word-break: break-word;
  color: var(--text-muted);
}
/* What the prompt contains, instead of how many characters it is: a count reads as
   complexity, the contents read as the reason it is long. */
.ld-gen-contains { font-size: .8rem; color: var(--text-muted); margin: 0 0 12px; }
/* Full-width step action. Not a copy class despite its old name (.ld-gen-copy): step 3's
   "Register and add your app" anchor wears it too. */
.ld-gen-action { width: 100%; justify-content: center; }
/* Step 3's action is an anchor, not a button — it leaves the page — so it needs the
   button box model spelled out that <button> gets for free. */
.ld-gen-add { display: block; box-sizing: border-box; text-align: center; text-decoration: none; }
.ld-gen-mcp { margin: 10px 0 0; }
