);
}
diff --git a/src/components/Map/markerManager.js b/src/components/Map/markerManager.js
index cff2c63..0eba557 100644
--- a/src/components/Map/markerManager.js
+++ b/src/components/Map/markerManager.js
@@ -2,17 +2,17 @@ import maplibregl from "maplibre-gl";
import React from "react";
import { createRoot } from "react-dom/client";
-import TemplateMarkerCard from "./TemplateMarkerCard";
-import { getDefaultTemplateCached } from "../../api/templates";
+import CardRenderer from "../Cards/CardRenderer";
+import { cardTokens } from "../../theme/cardTokens";
+import { getTemplateSpecForPost, adaptPostToTemplateData } from "./templateSpecs";
export function clearAllMarkers(markersRef, expandedElRef) {
if (markersRef.current) {
for (const m of markersRef.current) {
try {
- if (m?.el && m.el.__reactRoot) {
- try { m.el.__reactRoot.unmount(); } catch {}
- m.el.__reactRoot = null;
- }
+ if (m?.el && m.el.__swUnmount) m.el.__swUnmount();
+ } catch {}
+ try {
m.marker.remove();
} catch {}
}
@@ -72,29 +72,30 @@ export function clearOcclusion(markersRef) {
}
}
-function escapeHtml(str) {
- return String(str)
- .replace(/&/g, "&")
- .replace(//g, ">")
- .replace(/"/g, """);
+function mountCard(container, spec, data, theme) {
+ const root = createRoot(container);
+ const tokens = cardTokens?.[theme] || cardTokens.blue;
+
+ root.render(
+ React.createElement(CardRenderer, {
+ spec,
+ data,
+ themeTokens: tokens,
+ onAction: (action, value) => {
+ if (action?.type === "open_url" && value) {
+ try { window.open(value, "_blank"); } catch {}
+ }
+ },
+ className: "",
+ })
+ );
+
+ return () => {
+ try { root.unmount(); } catch {}
+ };
}
-function currentTheme() {
- try {
- const t = document?.body?.getAttribute("data-theme") || "dark";
- if (t === "dark" || t === "blue" || t === "light") return t;
- } catch {}
- return "dark";
-}
-
-function ensureReactRoot(el) {
- if (el.__reactRoot) return el.__reactRoot;
- el.__reactRoot = createRoot(el);
- return el.__reactRoot;
-}
-
-export function createMarkerForPost(post, mapRef, markersRef, expandedElRef) {
+export function createMarkerForPost(post, mapRef, markersRef, expandedElRef, theme = "blue") {
const map = mapRef.current;
if (!map) return;
@@ -117,65 +118,98 @@ export function createMarkerForPost(post, mapRef, markersRef, expandedElRef) {
return;
}
- const title = (post.title || "").trim() || "Untitled";
-
const root = document.createElement("div");
root.className = "post-pin post-pin--compact";
root.style.zIndex = "1";
+ function unmountIfAny() {
+ if (root.__swUnmount) {
+ try { root.__swUnmount(); } catch {}
+ root.__swUnmount = null;
+ }
+ }
+
function renderCompact() {
+ unmountIfAny();
root.className = "post-pin post-pin--compact";
root.style.zIndex = "1";
+ // pointer stays: .post-pin-pointer-small (UNCHANGED)
root.innerHTML = `
-
`;
- if (root.__reactRoot) {
- try { root.__reactRoot.unmount(); } catch {}
- root.__reactRoot = null;
+ const wrap = root.querySelector(".sw-template-mini-wrap");
+ if (wrap) {
+ const spec = getTemplateSpecForPost(post, "mini");
+ const data = adaptPostToTemplateData(post);
+ root.__swUnmount = mountCard(wrap, spec, data, theme);
}
clearOcclusion(markersRef);
}
- async function renderExpanded() {
+ function renderExpanded() {
+ unmountIfAny();
root.className = "post-pin post-pin--expanded";
root.style.zIndex = "999999";
+ // pointer stays: .post-card-pointer (UNCHANGED)
+ const headline = escapeHtml(post?.title || "Untitled");
+
root.innerHTML = `
-
-
Loading template…
+
+
+
+
+
+
Watching
+
+
+
☑ Kim / CNN
— Blah blah blah
+
+
+
+
+
+
+
+
${headline}
+
The news here (generated)
+
+
+
+
+
`;
- const cardEl = root.querySelector(".post-card");
- if (!cardEl) return;
-
- const theme = currentTheme();
-
- try {
- const tpl = await getDefaultTemplateCached("news");
-
- const rr = ensureReactRoot(cardEl);
- rr.render(
- React.createElement(TemplateMarkerCard, {
- post,
- template: tpl,
- theme,
- mode: "full",
- })
- );
- } catch (e) {
- cardEl.innerHTML = `
-
${escapeHtml(title)}
-
(template load failed)
- `;
+ const wrap = root.querySelector(".sw-template-full-wrap");
+ if (wrap) {
+ const spec = getTemplateSpecForPost(post, "full");
+ const data = adaptPostToTemplateData(post);
+ root.__swUnmount = mountCard(wrap, spec, data, theme);
}
requestAnimationFrame(() => {
@@ -210,3 +244,11 @@ export function createMarkerForPost(post, mapRef, markersRef, expandedElRef) {
}
});
}
+
+function escapeHtml(str) {
+ return String(str ?? "")
+ .replace(/&/g, "&")
+ .replace(//g, ">")
+ .replace(/"/g, """);
+}
diff --git a/src/components/Map/templateSpecs.js b/src/components/Map/templateSpecs.js
new file mode 100644
index 0000000..0ad7d57
--- /dev/null
+++ b/src/components/Map/templateSpecs.js
@@ -0,0 +1,71 @@
+/**
+ * Frontend-only template specs (no DB changes).
+ * Keep pointers as-is:
+ * - compact triangle: .post-pin-pointer-small
+ * - expanded triangle: .post-card-pointer
+ */
+
+export const TEMPLATE_SPECS = {
+ news: {
+ mini_spec: {
+ size: { w: 280, h: 110 },
+ background: { type: "gradient", value: "newsBlue" },
+ radius: 18,
+ layers: [
+ { id: "badge", type: "chip", x: 14, y: 12, text: "NEWS", style: "chip.news" },
+ { id: "title", type: "text", x: 14, y: 40, w: 252, h: 44, bind: "data.headline", style: "text.title", maxLines: 2 },
+ { id: "meta", type: "text", x: 14, y: 88, w: 252, h: 16, bind: "data.source", style: "text.meta", maxLines: 1 }
+ ],
+ },
+ full_spec: {
+ size: { w: 360, h: 520 },
+ background: { type: "solid", value: "surface" },
+ radius: 22,
+ layers: [
+ { id: "hero", type: "image", x: 0, y: 0, w: 360, h: 220, bind: "data.image" },
+ { id: "badge", type: "chip", x: 16, y: 16, text: "NEWS", style: "chip.news" },
+ { id: "title", type: "text", x: 16, y: 240, w: 328, h: 78, bind: "data.headline", style: "text.h1", maxLines: 3 },
+ { id: "summary", type: "text", x: 16, y: 325, w: 328, h: 110, bind: "data.summary", style: "text.body", maxLines: 5 },
+ {
+ id: "cta",
+ type: "button",
+ x: 16, y: 450, w: 328, h: 48,
+ text: "Open source",
+ style: "button.primary",
+ action: { type: "open_url", bind: "data.url" }
+ }
+ ],
+ },
+ },
+};
+
+function normCat(post) {
+ const c = (post?.category || "").toString().toUpperCase();
+ if (c === "NEWS") return "news";
+ if (c === "EVENT") return "news";
+ if (c === "FRIENDS") return "news";
+ if (c === "MARKET") return "news";
+ return "news";
+}
+
+export function getTemplateKeyForPost(post) {
+ // Future mapping: if (post.template_id === 101) return "news";
+ return normCat(post);
+}
+
+export function getTemplateSpecForPost(post, variant /* "mini"|"full" */) {
+ const key = getTemplateKeyForPost(post);
+ const t = TEMPLATE_SPECS[key] || TEMPLATE_SPECS.news;
+ return variant === "full" ? t.full_spec : t.mini_spec;
+}
+
+export function adaptPostToTemplateData(post) {
+ const headline = post?.title || "Untitled";
+ const author = post?.author ? `by ${post.author}` : "";
+ const sub = post?.sub_category ? String(post.sub_category) : "";
+ const source = author || sub || "";
+ const summary = post?.snippet || post?.body || "";
+ const url = post?.url || "";
+ const image = post?.image_large || post?.image_small || post?.image || post?.media_url || "";
+ return { headline, source, summary, url, image };
+}
diff --git a/src/components/Posts/PostCard.jsx b/src/components/Posts/PostCard.jsx
index 0a2d5a4..96172e7 100644
--- a/src/components/Posts/PostCard.jsx
+++ b/src/components/Posts/PostCard.jsx
@@ -1,24 +1,28 @@
import React from "react";
-
-function getKmFromPost(post) {
- return post.km ?? post.distance_km ?? post.distanceKm ?? post.dist_km ?? null;
-}
+import CardRenderer from "../Cards/CardRenderer";
+import { cardTokens } from "../../theme/cardTokens";
+import { getTemplateSpecForPost, adaptPostToTemplateData } from "../Map/templateSpecs";
export default function PostCard({ post, selected, onSelect }) {
- const title = post.title || post.name || "Post";
- const fullBody = post.body || post.content || post.text || "";
- const body = fullBody.length > 80 ? fullBody.slice(0, 77) + "..." : fullBody;
- const km = getKmFromPost(post);
-
- function handleClick() {
- if (onSelect) onSelect(post);
- }
+ const spec = getTemplateSpecForPost(post, "mini");
+ const data = adaptPostToTemplateData(post);
return (
-
- {title}
- {body}
- {km != null && {km} km}
+ onSelect && onSelect(post)}
+ style={{ padding: 6 }}
+ >
+
+ {
+ if (action?.type === "open_url" && value) window.open(value, "_blank");
+ }}
+ />
+
);
}
diff --git a/src/styles/layout.css b/src/styles/layout.css
index aa6e899..4510a6b 100644
--- a/src/styles/layout.css
+++ b/src/styles/layout.css
@@ -1,3 +1,5 @@
-.app-root { height: 100vh; display: flex; flex-direction: column; }
-.main-shell { flex: 1; display: flex; padding: 0; }
-.map-shell { position: relative; flex: 1; border-radius: 0; overflow: hidden; border: none; background: #020617; }
+.app-root{ min-height:100vh; display:flex; flex-direction:column; }
+
+/* IMPORTANT: allow scrolling under the map */
+.main-shell{ flex: 0 0 auto; display:block; padding:0; }
+.map-shell{ position:relative; width:100%; height:62vh; border-radius:0; overflow:hidden; border:none; background:#020617; }
diff --git a/src/styles/map.css b/src/styles/map.css
index 2860dc8..7fbb292 100644
--- a/src/styles/map.css
+++ b/src/styles/map.css
@@ -1,5 +1,19 @@
-.map-view { position: relative; width: 100%; height: 100%; }
-.map-container, .maplibre-container { position: absolute; inset: 0; width: 100%; height: 100%; }
+.map-page { display: flex; flex-direction: column; }
+
+/* Map stage (visible first). Then you scroll down for the wall. */
+.map-stage {
+ position: relative;
+ width: 100%;
+ height: clamp(520px, 72vh, 860px);
+}
+
+.map-container, .maplibre-container {
+ position: absolute;
+ inset: 0;
+ width: 100%;
+ height: 100%;
+}
+
.map-status {
position: absolute;
left: 0.5rem;
@@ -8,4 +22,21 @@
padding: 0.2rem 0.4rem;
background: rgba(0, 0, 0, 0.6);
border-radius: 0.5rem;
+ z-index: 30;
+}
+
+/* Below map area */
+.below-stage{
+ padding: 0.25rem 0.7rem 1.0rem;
+}
+.below-row{
+ display:flex;
+ gap:.6rem;
+ align-items:stretch;
+}
+
+/* Mobile: stack */
+@media (max-width: 640px){
+ .map-stage{ height: clamp(520px, 78vh, 900px); }
+ .below-row{ flex-direction: column; }
}
diff --git a/src/styles/mapMarkers.css b/src/styles/mapMarkers.css
index c64bfdb..41a7962 100644
--- a/src/styles/mapMarkers.css
+++ b/src/styles/mapMarkers.css
@@ -88,3 +88,548 @@
border-top:11px solid rgba(8, 20, 40, 0.97);
filter: drop-shadow(0 2px 4px rgba(0,0,0,.8));
}
+
+/* ===== Template marker wrappers (pointers stay the same classes) ===== */
+.sw-template-mini-wrap{
+ position: absolute;
+ left: 0;
+ top: 0;
+ transform: translate(-50%, calc(-100% - 12px));
+}
+
+.sw-expanded-shell{
+ padding: 10px 12px;
+}
+
+.sw-expanded-top{
+ display:flex;
+ gap:10px;
+ align-items:flex-start;
+}
+
+.sw-expanded-left{
+ flex: 1;
+}
+
+.sw-expanded-right{
+ width: 150px;
+ min-width: 140px;
+ display:flex;
+ flex-direction:column;
+ gap:8px;
+ padding-top: 4px;
+}
+
+.sw-watch-title{
+ font-size: 11px;
+ font-weight: 800;
+ color:#bfdbfe;
+ text-transform: uppercase;
+ letter-spacing: .06em;
+}
+
+.sw-watch-list{
+ display:flex;
+ flex-direction:column;
+ gap:6px;
+}
+
+.sw-watch-item{
+ font-size: 11px;
+ color:#e8f5ff;
+ background: rgba(3, 14, 32, 0.75);
+ border: 1px solid rgba(90, 190, 255, 0.35);
+ border-radius: 10px;
+ padding: 6px 8px;
+}
+
+.sw-watch-msg{
+ opacity:.85;
+ margin-top:2px;
+ font-size: 10px;
+ color:#c7e3ff;
+}
+
+.sw-add-feed-btn{
+ margin-top: 2px;
+ border: 1px solid rgba(148,163,184,.7);
+ border-radius: 10px;
+ padding: 8px 10px;
+ background: rgba(5, 35, 70, 0.85);
+ color:#e8f5ff;
+ font-weight: 900;
+ font-size: 11px;
+ cursor:pointer;
+}
+
+.sw-news-generated{
+ margin-top: 10px;
+ padding: 8px 10px;
+ border-radius: 12px;
+ background: rgba(3, 14, 32, 0.75);
+ border: 1px solid rgba(90, 190, 255, 0.35);
+}
+
+.sw-news-title{
+ font-size: 12px;
+ font-weight: 900;
+ color:#e8f5ff;
+ margin-bottom: 2px;
+}
+
+.sw-news-sub{
+ font-size: 10px;
+ color:#9eb7ff;
+}
+
+.sw-actions-row{
+ margin-top: 8px;
+}
+
+.sw-livechat{
+ margin-top: 8px;
+}
+
+.sw-livechat-title{
+ font-weight: 800;
+ letter-spacing:.04em;
+ margin-bottom: 6px;
+}
+
+.sw-livechat-body{
+ display:flex;
+ flex-direction:column;
+ gap:3px;
+ margin-bottom: 8px;
+ opacity:.95;
+}
+
+.sw-chat-line{
+ font-size: 10px;
+ color:#c7e3ff;
+}
+
+.sw-livechat-inputrow{
+ display:flex;
+ gap:8px;
+ align-items:center;
+}
+
+.sw-livechat-input{
+ flex:1;
+ border-radius: 999px;
+ border: 1px solid rgba(90, 190, 255, 0.35);
+ background: rgba(3, 14, 32, 0.75);
+ color:#e8f5ff;
+ padding: 8px 10px;
+ font-size: 11px;
+ outline: none;
+}
+
+.sw-livechat-post{
+ border:none;
+ border-radius: 10px;
+ padding: 8px 12px;
+ background: rgba(56,189,248,0.22);
+ color:#e8f5ff;
+ font-weight: 900;
+ font-size: 11px;
+ cursor:pointer;
+}
+
+/* ===== Template marker wrappers (pointers stay the same classes) ===== */
+.sw-template-mini-wrap{
+ position: absolute;
+ left: 0;
+ top: 0;
+ transform: translate(-50%, calc(-100% - 12px));
+}
+
+.sw-expanded-shell{
+ padding: 10px 12px;
+}
+
+.sw-expanded-top{
+ display:flex;
+ gap:10px;
+ align-items:flex-start;
+}
+
+.sw-expanded-left{
+ flex: 1;
+}
+
+.sw-expanded-right{
+ width: 150px;
+ min-width: 140px;
+ display:flex;
+ flex-direction:column;
+ gap:8px;
+ padding-top: 4px;
+}
+
+.sw-watch-title{
+ font-size: 11px;
+ font-weight: 800;
+ color:#bfdbfe;
+ text-transform: uppercase;
+ letter-spacing: .06em;
+}
+
+.sw-watch-list{
+ display:flex;
+ flex-direction:column;
+ gap:6px;
+}
+
+.sw-watch-item{
+ font-size: 11px;
+ color:#e8f5ff;
+ background: rgba(3, 14, 32, 0.75);
+ border: 1px solid rgba(90, 190, 255, 0.35);
+ border-radius: 10px;
+ padding: 6px 8px;
+}
+
+.sw-watch-msg{
+ opacity:.85;
+ margin-top:2px;
+ font-size: 10px;
+ color:#c7e3ff;
+}
+
+.sw-add-feed-btn{
+ margin-top: 2px;
+ border: 1px solid rgba(148,163,184,.7);
+ border-radius: 10px;
+ padding: 8px 10px;
+ background: rgba(5, 35, 70, 0.85);
+ color:#e8f5ff;
+ font-weight: 900;
+ font-size: 11px;
+ cursor:pointer;
+}
+
+.sw-news-generated{
+ margin-top: 10px;
+ padding: 8px 10px;
+ border-radius: 12px;
+ background: rgba(3, 14, 32, 0.75);
+ border: 1px solid rgba(90, 190, 255, 0.35);
+}
+
+.sw-news-title{
+ font-size: 12px;
+ font-weight: 900;
+ color:#e8f5ff;
+ margin-bottom: 2px;
+}
+
+.sw-news-sub{
+ font-size: 10px;
+ color:#9eb7ff;
+}
+
+.sw-actions-row{
+ margin-top: 8px;
+}
+
+.sw-livechat{
+ margin-top: 8px;
+}
+
+.sw-livechat-title{
+ font-weight: 800;
+ letter-spacing:.04em;
+ margin-bottom: 6px;
+}
+
+.sw-livechat-body{
+ display:flex;
+ flex-direction:column;
+ gap:3px;
+ margin-bottom: 8px;
+ opacity:.95;
+}
+
+.sw-chat-line{
+ font-size: 10px;
+ color:#c7e3ff;
+}
+
+.sw-livechat-inputrow{
+ display:flex;
+ gap:8px;
+ align-items:center;
+}
+
+.sw-livechat-input{
+ flex:1;
+ border-radius: 999px;
+ border: 1px solid rgba(90, 190, 255, 0.35);
+ background: rgba(3, 14, 32, 0.75);
+ color:#e8f5ff;
+ padding: 8px 10px;
+ font-size: 11px;
+ outline: none;
+}
+
+.sw-livechat-post{
+ border:none;
+ border-radius: 10px;
+ padding: 8px 12px;
+ background: rgba(56,189,248,0.22);
+ color:#e8f5ff;
+ font-weight: 900;
+ font-size: 11px;
+ cursor:pointer;
+}
+
+/* ===== Template marker wrappers (pointers stay the same classes) ===== */
+.sw-template-mini-wrap{
+ position: absolute;
+ left: 0;
+ top: 0;
+ transform: translate(-50%, calc(-100% - 12px));
+}
+
+.sw-expanded-shell{ padding: 10px 12px; }
+
+.sw-expanded-top{
+ display:flex;
+ gap:10px;
+ align-items:flex-start;
+}
+
+.sw-expanded-left{ flex: 1; }
+
+.sw-expanded-right{
+ width: 150px;
+ min-width: 140px;
+ display:flex;
+ flex-direction:column;
+ gap:8px;
+ padding-top: 4px;
+}
+
+.sw-watch-title{
+ font-size: 11px;
+ font-weight: 800;
+ color:#bfdbfe;
+ text-transform: uppercase;
+ letter-spacing: .06em;
+}
+
+.sw-watch-list{ display:flex; flex-direction:column; gap:6px; }
+
+.sw-watch-item{
+ font-size: 11px;
+ color:#e8f5ff;
+ background: rgba(3, 14, 32, 0.75);
+ border: 1px solid rgba(90, 190, 255, 0.35);
+ border-radius: 10px;
+ padding: 6px 8px;
+}
+
+.sw-watch-msg{
+ opacity:.85;
+ margin-top:2px;
+ font-size: 10px;
+ color:#c7e3ff;
+}
+
+.sw-add-feed-btn{
+ margin-top: 2px;
+ border: 1px solid rgba(148,163,184,.7);
+ border-radius: 10px;
+ padding: 8px 10px;
+ background: rgba(5, 35, 70, 0.85);
+ color:#e8f5ff;
+ font-weight: 900;
+ font-size: 11px;
+ cursor:pointer;
+}
+
+.sw-news-generated{
+ margin-top: 10px;
+ padding: 8px 10px;
+ border-radius: 12px;
+ background: rgba(3, 14, 32, 0.75);
+ border: 1px solid rgba(90, 190, 255, 0.35);
+}
+
+.sw-news-title{
+ font-size: 12px;
+ font-weight: 900;
+ color:#e8f5ff;
+ margin-bottom: 2px;
+}
+
+.sw-news-sub{ font-size: 10px; color:#9eb7ff; }
+
+.sw-actions-row{ margin-top: 8px; }
+
+.sw-livechat{ margin-top: 8px; }
+
+.sw-livechat-title{
+ font-weight: 800;
+ letter-spacing:.04em;
+ margin-bottom: 6px;
+}
+
+.sw-livechat-body{
+ display:flex;
+ flex-direction:column;
+ gap:3px;
+ margin-bottom: 8px;
+ opacity:.95;
+}
+
+.sw-chat-line{ font-size: 10px; color:#c7e3ff; }
+
+.sw-livechat-inputrow{ display:flex; gap:8px; align-items:center; }
+
+.sw-livechat-input{
+ flex:1;
+ border-radius: 999px;
+ border: 1px solid rgba(90, 190, 255, 0.35);
+ background: rgba(3, 14, 32, 0.75);
+ color:#e8f5ff;
+ padding: 8px 10px;
+ font-size: 11px;
+ outline: none;
+}
+
+.sw-livechat-post{
+ border:none;
+ border-radius: 10px;
+ padding: 8px 12px;
+ background: rgba(56,189,248,0.22);
+ color:#e8f5ff;
+ font-weight: 900;
+ font-size: 11px;
+ cursor:pointer;
+}
+
+/* =========================================================
+ RESPONSIVE SIZING FIX
+ - Mini markers were too big (280x110 real size)
+ - Expanded card was overflowing on mobile
+ ========================================================= */
+
+/* Mini template wrapper: keep pointer EXACTLY as-is, only scale the card */
+.sw-template-mini-wrap{
+ /* was: translate(-50%, calc(-100% - 12px)) */
+ transform: translate(-50%, calc(-100% - 12px)) scale(var(--sw-mini-scale, 0.72));
+ transform-origin: bottom center;
+ will-change: transform;
+}
+
+/* Expanded card: make it fit phone screens nicely */
+.post-pin--expanded .post-card{
+ max-width: min(92vw, 380px);
+ width: auto;
+ max-height: min(72vh, 640px);
+ overflow: auto;
+ -webkit-overflow-scrolling: touch;
+}
+
+/* Layout in expanded sketch area */
+.sw-expanded-top{
+ gap: 10px;
+}
+
+/* Mobile tweaks */
+@media (max-width: 640px){
+ /* Shrink mini markers even more on phones */
+ .sw-template-mini-wrap{
+ --sw-mini-scale: 0.58;
+ }
+
+ /* Expanded: stack instead of side-by-side */
+ .sw-expanded-top{
+ flex-direction: column;
+ }
+
+ /* Right panel becomes horizontal strip (or you can hide it if you prefer) */
+ .sw-expanded-right{
+ width: 100%;
+ min-width: 0;
+ flex-direction: row;
+ gap: 8px;
+ align-items: center;
+ overflow-x: auto;
+ padding-top: 0;
+ }
+
+ .sw-watch-title{
+ white-space: nowrap;
+ margin-right: 6px;
+ }
+
+ .sw-watch-list{
+ flex-direction: row;
+ gap: 8px;
+ }
+
+ .sw-watch-item{
+ min-width: 180px;
+ flex: 0 0 auto;
+ }
+
+ .sw-add-feed-btn{
+ flex: 0 0 auto;
+ white-space: nowrap;
+ }
+}
+
+
+/* SW_EXPANDED_OFFSET_FIX: lower expanded cards on phones (keep pointers unchanged) */
+@media (max-width: 640px){
+ .post-pin--expanded .post-card{
+ transform: translate(-50%, calc(-100% - 6px));
+ }
+}
+
+
+/* SW_MOBILE_EXPANDED_TIGHTEN: make expanded marker card less tall on phones (no pointer change) */
+@media (max-width: 640px){
+ .post-pin--expanded .post-card{
+ padding: 8px 10px;
+ max-width: 300px;
+ }
+ .post-pin--expanded .post-card-main{ gap: 6px; margin-bottom: 6px; }
+ .post-pin--expanded .post-card-media{ width: 56px; height: 56px; border-radius: 10px; }
+ .post-pin--expanded .post-card-title{ font-size: 12px; line-height: 15px; }
+ .post-pin--expanded .post-card-body{ font-size: 11px; max-height: 56px; }
+}
+
+/* SW_TEMPLATE_FULL_TIGHTEN: make template-full card less tall on phones */
+@media (max-width: 640px){
+ .sw-template-full{
+ transform: translate(-50%, calc(-100% - 14px)) scale(0.88);
+ transform-origin: bottom center;
+ }
+}
+
+/* ===== MOBILE TUNING: expanded marker popup (template OR classic) ===== */
+@media (max-width: 640px){
+ /* shrink the whole expanded marker a bit */
+ .post-pin--expanded{
+ transform: translate3d(0,0,0) scale(0.86);
+ transform-origin: bottom center;
+ }
+
+ /* keep it inside screen */
+ .post-pin--expanded .post-card{
+ max-width: min(92vw, 340px) !important;
+ }
+
+ /* title/body: prevent giant blocks */
+ .post-pin--expanded .post-card-title{ font-size: 12px !important; line-height: 15px !important; }
+ .post-pin--expanded .post-card-body{ font-size: 11px !important; line-height: 14px !important; max-height: 54px !important; }
+
+ /* buttons/footer area: tighter */
+ .post-pin--expanded .post-card-footer{ gap: 5px !important; }
+ .post-pin--expanded .post-card-btn{ font-size: 10px !important; padding: 3px 7px !important; }
+}
diff --git a/src/styles/posts.css b/src/styles/posts.css
index 704a732..39bf383 100644
--- a/src/styles/posts.css
+++ b/src/styles/posts.css
@@ -1,34 +1,39 @@
-.map-overlay-wall {
- position:absolute;
- left:.7rem; right:.7rem; bottom:.6rem;
- display:flex; gap:.6rem; align-items:stretch;
- pointer-events:none; z-index:10;
+/* Sociowall + Chat BELOW the map */
+.below-row{
+ display:flex;
+ gap:.6rem;
+ align-items:stretch;
}
-.map-overlay-wall * { pointer-events:auto; }
.sociowall-panel {
- flex: 1.5;
- min-height: 80px;
- max-height: 150px;
+ flex: 1.8;
+ min-height: 160px;
background: rgba(15, 23, 42, 0.96);
border-radius: 14px;
border: 1px solid rgba(148, 163, 184, 0.9);
box-shadow: 0 10px 28px rgba(0,0,0,.9), 0 0 18px rgba(56,189,248,.45);
padding: .45rem .55rem;
- display:flex; flex-direction:column;
-}
-.sociowall-header {
- font-size: .78rem; font-weight: 600;
- letter-spacing: .06em; text-transform: uppercase;
- color:#bfdbfe; margin-bottom:.25rem;
+ display:flex;
+ flex-direction:column;
}
-.post-list { flex:1; overflow-y:auto; padding-right:.15rem; }
-.post-list-header { display:flex; align-items:center; gap:.5rem; margin-bottom:.2rem; font-size:.7rem; color:#cbd5f5; }
-.km-filter input[type="range"] { width:130px; }
+.sociowall-header {
+ font-size: .78rem;
+ font-weight: 700;
+ letter-spacing: .06em;
+ text-transform: uppercase;
+ color:#bfdbfe;
+ margin-bottom:.25rem;
+}
+
+.post-list { flex: 1; overflow-y: auto; padding-right: .15rem; max-height: 44vh; }
+.post-list-header { display:flex; align-items:center; gap:.5rem; margin-bottom:.25rem; font-size:.7rem; color:#cbd5f5; }
+.km-filter input[type="range"] { width:160px; }
+
.status-text { font-size:.72rem; opacity:.85; margin:.15rem 0; }
.status-error { color:#fecaca; }
+/* list items compact */
.post-card {
border-radius:10px;
border:1px solid rgba(55, 65, 81, 0.9);
@@ -53,28 +58,41 @@
.post-card h3 { margin:0 0 .12rem 0; font-size:.8rem; }
.post-card p { margin:0; font-size:.72rem; opacity:.9; }
-.post-km {
- display:inline-block; margin-top:.12rem; font-size:.68rem;
- padding:.05rem .35rem; border-radius:999px;
- background: rgba(15, 118, 110, 0.2);
- border: 1px solid rgba(45, 212, 191, 0.7);
- color: #a5f3fc;
-}
-
.chat-panel {
- width:150px; min-width:130px;
- max-height:150px;
+ width: 170px;
+ min-width: 170px;
background: rgba(15, 23, 42, 0.96);
border-radius: 14px;
border: 1px solid rgba(148, 163, 184, 0.9);
box-shadow: 0 10px 28px rgba(0,0,0,.9), 0 0 18px rgba(56,189,248,.45);
padding:.4rem .45rem;
- display:flex; flex-direction:column;
+ display:flex;
+ flex-direction:column;
+
+ /* stays visible beside wall while scrolling inside the list */
+ position: sticky;
+ top: 10px;
+ align-self: flex-start;
}
+
.chat-header {
- font-size:.78rem; font-weight:600; letter-spacing:.06em; text-transform:uppercase;
- color:#bfdbfe; margin-bottom:.2rem;
+ font-size:.78rem;
+ font-weight:700;
+ letter-spacing:.06em;
+ text-transform:uppercase;
+ color:#bfdbfe;
+ margin-bottom:.2rem;
}
.chat-users { list-style:none; padding:0; margin:0; font-size:.76rem; }
.chat-users li { display:flex; align-items:center; gap:.3rem; padding:.18rem .1rem; }
.chat-users li::before { content:"👤"; font-size:.72rem; opacity:.9; }
+
+/* Mobile: stack */
+@media (max-width: 640px){
+ .below-row{ flex-direction: column; }
+ .chat-panel{ width: 100%; min-width: 0; position: static; }
+ .post-list{ max-height: 46vh; }
+}
+
+/* Guard: never render Sociowall overlay on top of the map */
+.map-overlay-wall{ display:none !important; }