diff --git a/client/app.js b/client/app.js index b562ea4..18a6302 100644 --- a/client/app.js +++ b/client/app.js @@ -3,49 +3,86 @@ import { encryptString, decryptToString, toBlob } from "./crypto.js"; const els = {}; function $(id){ return document.getElementById(id); } -// Bind after DOM is ready to avoid nulls +// ---- Trusted Types policy & safe HTML setter ---- +const ttPolicy = (() => { + try { + if (window.trustedTypes) { + // Allow only our sanitized HTML chunks (legal pages). Strip scripts & inline handlers. + return window.trustedTypes.createPolicy("gc", { + createHTML: (s) => + s + .replace(/ diff --git a/client/privacy.html b/client/privacy.html new file mode 100644 index 0000000..271032f --- /dev/null +++ b/client/privacy.html @@ -0,0 +1,41 @@ + + +
+ +Effective: 2025-08-22
+ +GreenCoast is a zero-trust, end-to-end encrypted (E2EE) social platform. By default, we do not collect analytics, do not store personal data, and do not maintain server logs that identify users.
+ +If you use Discord/Google/etc., those providers may process your data under their own terms. We cannot vouch for their security.
+ +We use browser storage on your device to keep connection settings and, if you choose, session tokens. You can wipe them with “Panic wipe”.
+ +E2EE for private content, proof-of-possession on mutations, rate-limits, CSP/COOP/COEP, and optional hardware keys via WebAuthn (if enabled on your shard).
+ +Because we do not maintain user identities or server-side profiles, requests to access/correct/erase personal data typically do not apply. For encrypted content, we cannot decrypt it for you.
+ +Email: dsapelli@yahoo.com
+ +This page describes our reference shard. Self-hosted deployments may differ.
+ + + diff --git a/client/styles.css b/client/styles.css index fe5c2d6..e25b851 100644 --- a/client/styles.css +++ b/client/styles.css @@ -1,19 +1,48 @@ -:root{--bg:#0f172a;--surface:#111827;--muted:#8b949e;--text:#e5e7eb;--accent:#22c55e;--card:#0b1222;--border:#1f2937} +:root{ + --bg:#0f172a;--surface:#111827;--muted:#8b949e;--text:#e5e7eb;--accent:#22c55e; + --card:#0b1222;--border:#1f2937;--tab:#0b1222;--tab-active:#1f2937 +} *{box-sizing:border-box} -html,body{margin:0;padding:0;background:var(--bg);color:var(--text);font-family:ui-sans-serif,system-ui,Segoe UI,Roboto,Ubuntu,"Helvetica Neue","Noto Sans",Arial,"Apple Color Emoji","Segoe UI Emoji"} -.topbar{display:flex;align-items:center;justify-content:space-between;padding:.75rem 1rem;border-bottom:1px solid var(--border);background:#0b1222;position:sticky;top:0;z-index:10} -.topbar .brand{font-weight:700} -.topbar .actions button{margin-left:.5rem} -.container{max-width:980px;margin:1rem auto;padding:0 1rem} +html,body{margin:0;padding:0;background:var(--bg);color:var(--text); + font-family:ui-sans-serif,system-ui,Segoe UI,Roboto,Ubuntu,"Helvetica Neue","Noto Sans",Arial} +a{color:#93c5fd;text-decoration:none} +a:hover{text-decoration:underline} + +.topbar{display:flex;align-items:center;justify-content:space-between;padding:.6rem 1rem; + border-bottom:1px solid var(--border);background:#0b1222;position:sticky;top:0;z-index:10} +.brand{font-weight:700} +.actions button{margin-left:.5rem} +button{background:#134e4a;border:1px solid #0f766e;color:white;border-radius:.6rem;padding:.45rem .7rem;cursor:pointer} +button:hover{filter:brightness(1.05)} + +.tabs{display:flex;gap:.25rem;margin:0 .75rem} +.tabs a{padding:.35rem .6rem;border:1px solid var(--border);border-radius:.5rem;background:var(--tab)} +.tabs a.active{background:var(--tab-active);border-color:#334155} + +.banner{background:#1f2937;color:#e5e7eb;border-bottom:1px solid var(--border);padding:.6rem 1rem} + +.shell{max-width:1100px;margin:1rem auto;display:grid;grid-template-columns:280px 1fr 300px;gap:1rem;padding:0 1rem} +.col{min-width:0} .card{background:var(--card);border:1px solid var(--border);border-radius:.75rem;padding:1rem;margin-bottom:1rem} .row{display:flex;gap:.75rem;align-items:center;margin:.5rem 0} .row label{min-width:140px;color:#cbd5e1} -.row input, .row select, textarea{flex:1;background:#0f172a;border:1px solid var(--border);border-radius:.5rem;padding:.6rem .7rem;color:var(--text)} -button{background:#134e4a;border:1px solid #0f766e;color:white;border-radius:.6rem;padding:.5rem .75rem;cursor:pointer} -button:hover{filter:brightness(1.05)} -.muted{color:var(--muted)} +.row input,.row select,textarea{flex:1;background:#0f172a;border:1px solid var(--border);border-radius:.5rem;padding:.55rem .65rem;color:var(--text)} +.muted{color:var(--muted)} .small{font-size:.9rem} .profile{display:flex;align-items:center;gap:1rem} #avatar{border-radius:50%;border:1px solid var(--border);background:#0f172a;image-rendering:pixelated} + .post{border:1px dashed var(--border);border-radius:.5rem;padding:.6rem .7rem;margin-bottom:.6rem} .post .meta{color:var(--muted);font-size:.9rem;margin-bottom:.25rem} .badge{background:var(--surface);border:1px solid var(--border);border-radius:999px;padding:.05rem .5rem;font-size:.75rem;margin-left:.5rem} + +.advanced summary{cursor:pointer;color:#cbd5e1;margin:.25rem 0} +.links{list-style:none;padding:0;margin:0} +.links li{margin:.25rem 0} + +.footer{max-width:1100px;margin:1rem auto 2rem auto;padding:0 1rem;color:#94a3b8} + +@media (max-width: 980px){ + .shell{grid-template-columns:1fr;gap:.75rem} + #left,#right{order:2} + #feed,#page{order:1} +} diff --git a/client/terms.html b/client/terms.html new file mode 100644 index 0000000..2202daf --- /dev/null +++ b/client/terms.html @@ -0,0 +1,33 @@ + + + + +Effective: 2025-08-22
+ +GreenCoast is provided “as-is”, with no warranties. You may self-host under the Unlicense. This reference shard has no paid plans.
+ +You are responsible for content you publish. Do not post illegal content or abuse others. We reserve the right to remove content that violates applicable law.
+ +Device-key and optional SSO are used to prove control of a device. We do not maintain user profiles.
+ +If you connect SSO providers, your use of those services is governed by their terms and privacy policies.
+ +To the fullest extent permitted by law, the operator is not liable for indirect or consequential damages.
+ +We may update these Terms by posting a new version on this page.
+ + + +