/**
 * @file landing.css
 * @author Jouni Miikki
 * SPDX-License-Identifier: MIT
 * @description Logged-out landing + pricing pages (ld- prefix). Theme tokens only;
 *   path cards stack on mobile, ticker truncates to one line.
 * @version-history
 *   v2.2.1 -- 2026-09-27 -- The contact card's rules (.ld-contact*) leave with components/ContactCard.js
 *     under its own names (css/components/contact-card.css, a move).
 *   2026-09-13 -- Compose shared aside cuts; normalize one-off geometry under brief 10.7.
 *   v2.2.0 -- 2026-09-13 -- V2: the wall search composes its shared poster frame.
 *   v2.1.2 — 2026-08-29 — The pricing code block reads var(--font-mono) instead of a Consolas stack.
 *   v2.1.1 — 2026-08-29 — The business hero's shadow is the sun (with the front page), and the "why it
 *     improves this fast" label on the sun band is ink rather than coral on yellow.
 *   v2.1.0 — 2026-08-29 — The index pages join the showroom (design canvas "AIMEAT Index Pages"): the
 *       hero, the explainer cards, the proof block, the business hero, the cases, the group titles,
 *       the ink and sun bands (.ld-band--ink / .ld-band--sun) and the contact box on the front page's
 *       shapes. The app wall's cards stand straight; nothing tilts any more.
 *   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.
 *   v2.0.0 — 2026-08-28 — The showroom. The page widens to 1280; the wish box, the wall cards, the
 *       counters (now one dark strip) and the change log (now the yellow band with the "built with
 *       itself" claim) wear the showroom face: Bungee, 3px ink borders, solid offset shadows. The
 *       pricing page's .ld-pricing / .ld-tier rules are gone with the page. The six new blocks have
 *       their own file, landing-showroom.css.
 */
/* 1280 rather than 980 since the showroom (2026-08-28): its bands and its four-up wall want the
   width, and the older blocks an operator may put back centre themselves inside it anyway. */
.ld { max-width: 1280px; margin: 0 auto; padding: 0 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; }
/* The index pages' hero (how it works, business, transparency) in the showroom face: the sentence as
   a headline in the display face, the line under it in bold Archivo, left-aligned. */
.ld-hero { display: flex; flex-direction: column; align-items: flex-start; gap: 1.4rem; text-align: left; padding: 2.75rem 0 .5rem; max-width: 1040px; }
.ld-h1 { margin: 0; font-family: var(--font-showroom); font-weight: 400; text-transform: uppercase; font-size: clamp(2rem, 3.6vw, 2.9rem); line-height: 1.04; letter-spacing: .01em; color: var(--text); }
.ld-hero-sub { margin: 0; font-family: var(--font-showroom-body); font-size: 1.25rem; line-height: 1.5; font-weight: 600; color: var(--text); max-width: 56rem; }
/* "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; }
/* The proof block: a claim line in the display face and the examples under it, each with its door.
   With the picture (how it works) it is two columns, the picture framed and shadowed on the left. */
.ld-stats { margin: 4rem 0 0; padding: 0; border: 0; background: none; text-align: center; display: flex; flex-direction: column; gap: 1.25rem; align-items: center; }
.ld-stats-line { font-family: var(--font-showroom-body); font-size: 1.25rem; font-weight: 600; line-height: 1.5; }
.ld-stats-own { margin: 0; color: var(--text); font-family: var(--font-showroom-body); font-size: .95rem; line-height: 1.6; }
.ld-stats-cta { display: inline-block; margin-left: .35rem; color: var(--text); font-weight: 800; text-decoration: none; border-bottom: 3px solid var(--accent); }
.ld-stats-cta:hover { color: var(--accent); text-decoration: none; }
.ld-stats--withimg { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: 1.25rem 3.5rem; align-items: center; text-align: left; }
.ld-stats--withimg .ld-example-img { grid-column: 1; grid-row: 1 / span 4; align-self: center; }
.ld-stats--withimg .ld-stats-line, .ld-stats--withimg .ld-stats-own { grid-column: 2; }
.ld-stats--withimg .ld-stats-line { font-family: var(--font-showroom); font-weight: 400; text-transform: uppercase; font-size: clamp(1.4rem, 2.2vw, 1.75rem); line-height: 1.05; letter-spacing: .01em; }
.ld-stats--withimg .ld-stats-own { display: flex; flex-direction: column; gap: .5rem; align-items: flex-start; }
.ld-stats--withimg .ld-stats-cta { margin-left: 0; }
@media (max-width: 900px) {
  .ld-stats--withimg { grid-template-columns: 1fr; }
  .ld-stats--withimg .ld-example-img { grid-row: auto; }
  .ld-stats--withimg .ld-stats-line, .ld-stats--withimg .ld-stats-own { grid-column: 1; }
}
/* The explainer cards: an ink frame and a solid shadow whose colour turns down the row. */
.ld-paths { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.75rem; margin: 4rem 0 0; }
@media (max-width: 760px) { .ld-paths { grid-template-columns: 1fr; } }
.ld-path { border: 3px solid var(--text); border-radius: 0; background: var(--card-bg); padding: 1.1rem 1.25rem; display: flex; flex-direction: column; gap: .6rem; box-shadow: 6px 6px 0 var(--accent); }
.ld-path:nth-child(3n+2) { box-shadow: 6px 6px 0 var(--text); }
.ld-path:nth-child(3n+3) { box-shadow: 6px 6px 0 var(--sun); }
.ld-path--hot { border-color: var(--text); border-width: 3px; }
.ld-path h3 { margin: 0; font-family: var(--font-showroom); font-weight: 400; text-transform: uppercase; font-size: 1.25rem; line-height: 1.1; letter-spacing: .01em; }
.ld-path p { margin: 0; color: var(--text); font-family: var(--font-showroom-body); font-size: .95rem; line-height: 1.6; 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: 1rem 0 2rem; }
/* The wall's heading wears the showroom face; the older blocks that reuse .ld-h2 (the prompts,
   the folded builder) wear it too, which is the point: one page, one voice. */
.ld-h2 { font-family: var(--font-showroom); font-weight: 400; text-transform: uppercase; font-size: clamp(1.3rem, 2.4vw, 1.8rem); line-height: 1.1; margin: 0 0 1rem; }
.ld-wall-search { width: 100%; max-width: 360px; margin: 0 0 1rem; padding: .6rem .8rem; color: var(--text); font-size: .9rem; font-family: var(--font-showroom-body); }
.ld-wall-search:focus { outline: none; box-shadow: 4px 4px 0 var(--accent); }
/* Four up since the showroom: the page is wider and the cards are the proof, so more of them
   fit above the store. Three on a laptop, two on a tablet, one on a phone. */
.ld-gallery { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.25rem; padding: 6px; }
@media (max-width: 1100px) { .ld-gallery { grid-template-columns: repeat(3, 1fr); } }
@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. The showroom card: a 3px ink border and a solid offset shadow
   whose colour rotates down the row (coral, ink, yellow, coral), two of every four tilted half a
   degree, so the wall reads as stickers on a board rather than as a table. */
.ld-app-card {
  display: flex; flex-direction: column; border: 3px solid var(--text);
  background: var(--card-bg); padding: 1rem 1.1rem; text-decoration: none; color: var(--text); cursor: pointer;
  box-shadow: 6px 6px 0 var(--accent);
  transition: transform 120ms ease, box-shadow 120ms ease;
}
.ld-app-card:nth-child(4n+2) { box-shadow: 6px 6px 0 var(--text); }
.ld-app-card:nth-child(4n+3) { box-shadow: 6px 6px 0 var(--sun); }
.ld-app-card:hover, .ld-app-card:focus-visible { transform: translate(2px, 2px); box-shadow: 2px 2px 0 var(--text); outline: none; }
/* 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: 2px solid var(--text); 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. */
/* The pricing page's rules (.ld-pricing, .ld-tiers, .ld-tier*) left with the page on 2026-08-28:
   the store is its own AIMEAT instance and the one place a price exists. */

/* ── How it works ── */
.hiw-diagram { margin: 2.75rem 0 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; } }
/* The diagram's words: the box titles in the display face, the lines under them in Archivo. */
.hiw-block-title { font-family: var(--font-showroom); font-weight: 400; text-transform: uppercase; letter-spacing: .01em; }
.hiw-block-line, .hiw-caption { font-family: var(--font-showroom-body); }
.ld-ctarow { display: flex; gap: 2rem; align-items: center; justify-content: center; flex-wrap: wrap; margin: 4rem 0 1rem; }
.ld-ctarow a { text-decoration: none; }

/* ── Business ── */
/* The hero: the night-shift picture framed and shadowed on the left, the headline with the coral
   offset on the right, the demo button under it. */
.ld-bhero { position: relative; display: grid; grid-template-columns: 1fr 1fr; align-items: center; gap: 3.5rem; margin: 2.75rem 0 .5rem; border: 0; border-radius: 0; overflow: visible; background: none; }
.ld-bhero-img { display: block; width: calc(100% - 14px); height: auto; min-height: 0; margin: 0 0 14px 14px; object-fit: cover; border: 4px solid var(--text); box-shadow: -14px 14px 0 var(--text); }
.ld-bhero-text { padding: 0; display: flex; flex-direction: column; gap: 1.4rem; align-items: flex-start; }
.ld-bhero .ld-h1 { font-size: clamp(2.4rem, 4.6vw, 4rem); line-height: .98; text-shadow: .075em .075em 0 var(--sun); }
.ld-bhero--noimg { grid-template-columns: 1fr; }
.ld-bhero--noimg .ld-bhero-text { padding: 1rem 0; }
@media (max-width: 700px) { .ld-bhero { grid-template-columns: 1fr; gap: 1.75rem; } .ld-bhero-img { box-shadow: -8px 8px 0 var(--text); margin-left: 8px; width: calc(100% - 8px); } }
/* The cases: ink-framed cards whose shadow colour turns down the row; the proof is a door, the
   quote and the example note are dashed boxes. */
.ld-cases { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1.9rem 2rem; margin: 1.5rem 0; }
@media (max-width: 760px) { .ld-cases { grid-template-columns: 1fr; } }
.ld-case { border: 3px solid var(--text); border-radius: 0; background: var(--card-bg); padding: 1.1rem 1.25rem; display: flex; flex-direction: column; gap: .7rem; box-shadow: 6px 6px 0 var(--accent); }
.ld-case:nth-child(3n+2) { box-shadow: 6px 6px 0 var(--text); }
.ld-case:nth-child(3n+3) { box-shadow: 6px 6px 0 var(--sun); }
.ld-case-title { margin: 0; font-family: var(--font-showroom-body); font-size: 1.19rem; font-weight: 800; line-height: 1.3; }
.ld-case-text { margin: 0; color: var(--text); font-family: var(--font-showroom-body); font-size: .95rem; line-height: 1.6; flex: 1; }
.ld-case-quote { margin: 0; }
.ld-case-quote footer { color: var(--text-dim); font-size: .85rem; margin-top: .25rem; }
.ld-case-proof { align-self: flex-start; font-family: var(--font-showroom-body); font-size: .95rem; color: var(--text); text-decoration: none; font-weight: 800; border-bottom: 3px solid var(--accent); }
.ld-case-proof:hover { color: var(--accent); text-decoration: none; }
.ld-case-proofnote { font-style: normal; }

/* 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: 4rem 0 0; }
.ld-casegroup-title { margin: 0; font-family: var(--font-showroom); font-weight: 400; text-transform: uppercase; font-size: clamp(1.5rem, 2.6vw, 2rem); line-height: 1.05; letter-spacing: .01em; color: var(--text); }
.ld-casegroup .ld-cases { margin-top: 1.5rem; }

/* Why owning it is the reason to buy — the regulated-buyer argument. Three sections share the
   shape; the first is the ink band and the second the sun band (business.js adds the modifier),
   the third stays on the page. */
.ld-sovereignty { margin: 4rem 0 0; }
.ld-sovereignty .ld-case-text { max-width: 58rem; margin-top: 1rem; font-size: 1.1rem; }
.ld-sovereignty .ld-path-cta { display: inline-block; margin-top: 1rem; }
.ld-sov-list { list-style: none; margin: 1.25rem 0 0; padding: 0; display: grid; gap: .9rem; }
.ld-sov-list li { display: flex; gap: .6rem; color: var(--text); font-family: var(--font-showroom-body); font-size: .95rem; line-height: 1.55; }
.ld-sov-list li::before { content: ''; flex: 0 0 auto; width: 10px; height: 10px; margin-top: .45rem; background: var(--accent); }
.ld-band--ink { margin: 4.5rem -1.25rem 0; padding: 3.5rem 3rem; background: var(--text); color: var(--bg); }
.ld-band--ink .ld-casegroup-title { color: var(--sun); text-align: center; }
.ld-band--ink .ld-sov-list { grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 1.1rem; margin-top: 1.75rem; }
.ld-band--ink .ld-sov-list li { display: block; padding: 1.1rem 1.25rem; border: 2px solid color-mix(in srgb, var(--bg) 28%, transparent); color: var(--bg); font-size: .9rem; }
.ld-band--ink .ld-sov-list li::before { display: none; }
.ld-band--sun { margin: 0 -1.25rem; padding: 3rem; background: var(--sun); color: var(--on-sun); border-bottom: 3px solid var(--text); }
.ld-band--sun .ld-casegroup-title { color: var(--on-sun); }
.ld-band--sun .ld-sov-list { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .9rem 2.5rem; max-width: 1100px; }
.ld-band--sun .ld-sov-list li { color: var(--on-sun); }
.ld-band--sun .ld-sov-list li::before { background: var(--on-sun); }
.ld-band--sun .ld-path-cta { color: var(--on-sun); border-bottom: 3px solid var(--on-sun); font-size: .95rem; }
.ld-band--sun .ld-path-cta:hover { color: var(--accent); border-bottom-color: var(--accent); text-decoration: none; }
@media (max-width: 980px) { .ld-band--ink .ld-sov-list { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 760px) {
  .ld-band--ink, .ld-band--sun { padding: 2rem 1.25rem; }
  .ld-band--ink .ld-sov-list, .ld-band--sun .ld-sov-list { grid-template-columns: 1fr; }
  .ld-band--ink .ld-casegroup-title { text-align: left; }
}

/* The contact card (business + pricing) is the ContactCard component's: css/components/contact-card.css. */
.ld-example-img { display: block; width: calc(100% - 16px); height: auto; max-height: none; object-fit: cover; border-radius: 0; margin: 0 16px 16px 0; border: 4px solid var(--text); box-shadow: 16px 16px 0 var(--accent); }
.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 (nt- prefix) — the showroom's live strip: four figures on one dark band ── */
.nt { margin: 1.5rem 0 0; }
.nt-strip {
  display: flex; justify-content: center; align-items: center; flex-wrap: wrap; gap: .75rem 4rem;
  padding: 1.4rem 1.5rem; background: var(--text); color: var(--bg);
  border-top: 3px solid var(--text); border-bottom: 3px solid var(--text);
}
.nt-figure { display: flex; align-items: baseline; gap: .6rem; }
.nt-value { font-family: var(--font-showroom); font-size: 1.85rem; line-height: 1; font-variant-numeric: tabular-nums; color: var(--sun); }
.nt-label { font-family: var(--font-showroom-body); font-size: 1rem; font-weight: 800; }
/* The one live figure carries a dot; it is the only colour on the strip that is not yellow. */
.nt-dot { width: 12px; height: 12px; border-radius: 999px; background: var(--mint); align-self: center; }
.nt-counting { margin: .4rem 0 0; text-align: center; font-family: var(--font-showroom-body); font-size: .8rem; color: var(--text-muted); }
@media (max-width: 900px) {
  .nt-strip { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .9rem 1rem; padding: 1.25rem; }
  .nt-figure { flex-direction: column; align-items: flex-start; gap: .1rem; }
  .nt-label { font-size: .85rem; }
}

/* ── 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; }
/* The pitch line and the wish box are two blocks now, each one an operator can keep or drop. They
   wear the same frame so they line up, and the second drops its own top margin so the pair reads
   as one unit rather than as two sections that happen to be adjacent. */
.ld-pitch + .ld-pitch { margin-top: 0; }
.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: .9rem; margin: 1rem 0 0; }
/* The showroom's wish box: a 3px ink frame with a coral offset shadow, and the GO slab in Bungee.
   The placeholder is bold italic on purpose: it is the one question the page asks. */
.ld-wish-input {
  flex: 1 1 auto; min-width: 0;
  font-family: var(--font-showroom-body); font-size: 1.2rem; font-weight: 800;
  padding: .9rem 1.1rem;
  border: 3px solid var(--text); border-radius: 0;
  background: var(--card-bg); color: var(--text);
  box-shadow: 6px 6px 0 var(--accent);
}
.ld-wish-input:focus { outline: none; box-shadow: 6px 6px 0 var(--text); }
.ld-wish-input::placeholder { color: var(--text-dim); font-weight: 800; font-style: italic; }
.ld-wish-go {
  flex: 0 0 auto; font-family: var(--font-showroom); font-weight: 400; text-transform: uppercase;
  font-size: 1.2rem; padding: .9rem 1.8rem; border: 3px solid var(--text); border-radius: 0;
  background: var(--accent); color: #FFFFFF; box-shadow: 6px 6px 0 var(--text);
  transition: transform 120ms ease, box-shadow 120ms ease;
}
.ld-wish-go:hover { transform: translate(2px, 2px); box-shadow: 3px 3px 0 var(--text); background: var(--accent); }
@media (max-width: 600px) {
  .ld-wish { flex-direction: column; }
  .ld-wish-go { width: 100%; }
}

.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. */
/* Since the showroom (2026-08-28) the log is the yellow band under the two rooms: the "built with
   itself" claim leads it and the folded list is the evidence. */
.ld-log {
  margin: 0; padding: 2rem 3rem; background: var(--sun); color: #1A1A2E;
  border-top: 3px solid var(--text); border-bottom: 3px solid var(--text);
  display: flex; flex-direction: column; gap: 1.25rem;
}
.ld-log-dogfood { margin: 0 auto; max-width: 54rem; text-align: center; font-family: var(--font-showroom-body); font-size: 1.1rem; line-height: 1.6; font-weight: 600; }
/* Ink, not coral: coral on the sun band is 2:1 and the label was the least readable line on the page. */
.ld-log-dogfood-label { font-family: var(--font-showroom); text-transform: uppercase; font-size: .9rem; letter-spacing: .02em; color: var(--on-sun); }
.ld-log .collapsible {
  max-width: 54rem; width: 100%; margin: 0 auto;
  border: 3px solid var(--text); box-shadow: 6px 6px 0 var(--text);
  background: var(--card-bg); color: var(--text); overflow: hidden;
}
@media (max-width: 600px) { .ld-log { padding: 1.5rem 1.25rem; } .ld-log-dogfood { text-align: left; } }
.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;
}
/* The track choice: two cards, one decision, made before anything else (TARGET-074). */
.ld-gen-track { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 14px; }
@media (max-width: 560px) { .ld-gen-track { grid-template-columns: 1fr; } }
.ld-gen-trackcard {
  position: relative; display: block; cursor: pointer;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 10px; padding: 12px 14px;
}
.ld-gen-trackcard.is-on { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.ld-gen-trackcard input { position: absolute; opacity: 0; pointer-events: none; }
.ld-gen-trackcard:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
.ld-gen-trackname { font-weight: 700; font-size: .92rem; margin-right: 6px; }
.ld-gen-tracknew {
  display: inline-block; padding: 1px 8px; border-radius: 999px;
  background: var(--accent); color: #fff; font-size: .7rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .04em; vertical-align: 2px;
}
.ld-gen-trackdesc { display: block; margin-top: 4px; font-size: .8rem; color: var(--text-muted); line-height: 1.45; }

.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: var(--font-mono);
  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; }
