Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions apps/web/src/app/(site)/[locale]/p/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import type { Metadata } from "next";
import { notFound } from "next/navigation";
import { PrototypeView } from "@/components/PrototypeView";
import { getDict, isLocale, type Locale } from "@/lib/i18n";
import "../../../../prototype.css";
import "../../../../share.css";

// A shared preview, kept out of search.
export const metadata: Metadata = { robots: { index: false, follow: false } };
Expand All @@ -17,9 +19,15 @@ export default async function PrototypeSharePage({
const d = getDict(locale);

return (
<main className="wrap" style={{ padding: "32px 24px 64px" }}>
<h1 style={{ fontSize: "1.4rem" }}>{d.proto.shareTitle}</h1>
<PrototypeView id={id} locale={locale} d={d} />
<main className="sh">
<div className="pp-band sh-band">
<div className="wrap">
<h1>{d.proto.shareTitle}</h1>
</div>
</div>
<div className="wrap sh-body">
<PrototypeView id={id} locale={locale} d={d} />
</div>
</main>
);
}
82 changes: 82 additions & 0 deletions apps/web/src/app/share.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/* The share page (/[locale]/p/[id]): the built prototype, or where its build is.
Builds on prototype.css (band, inputs, buttons); everything here is scoped under `.sh`. */

.sh { padding-bottom: 80px; }
.sh p { margin: 0; }
.sh .wrap { max-width: 1200px; }
.sh-band { padding: 36px 0 84px; }
.sh-band h1 { font-size: clamp(1.8rem, 3vw, 2.4rem); letter-spacing: -0.035em; margin: 0; }
.sh-body { margin-top: -56px; }

/* ---------- Status: waiting, building, failed, expired ---------- */
.sh-status { max-width: 620px; margin: 0 auto; background: #fff; border: 1px solid var(--border); border-radius: 20px; padding: 32px; box-shadow: 0 30px 70px rgba(15, 23, 42, 0.1); display: grid; gap: 14px; justify-items: start; }
.sh-status h2 { font-size: 1.3rem; margin: 0; }
.sh-status > p { color: var(--ink-soft); font-size: 0.95rem; line-height: 1.55; }
.sh-status-ico { width: 48px; height: 48px; border-radius: 14px; display: grid; place-items: center; background: var(--accent-soft); color: var(--accent); }
.sh-status-bad .sh-status-ico { background: #fef2f2; color: #b91c1c; }
.sh-status .btn { margin-top: 4px; }
.sh-meta { font-size: 0.85rem; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.sh-bar { width: 100%; height: 8px; border-radius: 99px; background: #e2e8f0; overflow: hidden; }
.sh-bar span { display: block; height: 100%; border-radius: inherit; background: linear-gradient(90deg, var(--accent), var(--violet)); transition: width 1s linear; }

.sh-steps { list-style: none; margin: 4px 0 0; padding: 0; display: grid; gap: 12px; width: 100%; }
.sh-steps li { display: flex; gap: 12px; align-items: flex-start; font-size: 0.95rem; color: var(--ink-soft); }
.sh-steps small { display: block; font-size: 0.84rem; font-weight: 400; color: var(--ink-soft); margin-top: 2px; line-height: 1.45; }
.sh-dot { flex: none; width: 22px; height: 22px; border-radius: 50%; border: 2px solid #cbd5e1; display: grid; place-items: center; font-size: 0.7rem; font-weight: 800; color: #fff; margin-top: 1px; }
.sh-steps li[data-state="done"] { color: var(--ink); }
.sh-steps li[data-state="done"] .sh-dot { background: var(--valid); border-color: var(--valid); }
.sh-steps li[data-state="now"] { color: var(--ink); font-weight: 600; }
.sh-steps li[data-state="now"] .sh-dot { border-color: var(--accent); box-shadow: inset 0 0 0 4px #fff; background: var(--accent); animation: sh-pulse 1.4s ease-in-out infinite; }
.sh-steps li[data-state="failed"] .sh-dot { background: #dc2626; border-color: #dc2626; }
.sh-steps li[data-state="todo"] { opacity: 0.55; }
@keyframes sh-pulse { 50% { box-shadow: inset 0 0 0 4px #fff, 0 0 0 5px rgba(29, 78, 216, 0.15); } }
@media (prefers-reduced-motion: reduce) { .sh-steps li[data-state="now"] .sh-dot { animation: none; } }

/* ---------- Ready: toolbar, then the prototype ---------- */
.sh-toolbar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 14px 24px; background: #fff; border: 1px solid var(--border); border-radius: 18px; padding: 18px 22px; box-shadow: 0 20px 50px rgba(15, 23, 42, 0.08); margin-bottom: 20px; }
.sh-toolbar > p { flex: 1 1 320px; font-size: 0.92rem; color: var(--ink-soft); line-height: 1.5; max-width: 560px; }
.sh-actions { display: flex; flex-wrap: wrap; gap: 10px; }
.sh .btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; }
.sh-ghost { background: #fff; color: var(--ink); border-color: var(--border); }
.sh-ghost:hover { border-color: #c7d2fe; color: var(--accent-hover); }

.sh-frame { border: 1px solid var(--border); border-radius: 18px; overflow: hidden; box-shadow: 0 30px 70px rgba(15, 23, 42, 0.12); background: #fff; }
.sh-frame iframe { display: block; width: 100%; height: 80vh; border: 0; }
.sh .sh-credit { font-size: 0.8rem; color: var(--ink-soft); margin-top: 10px; }
.sh-credit-center { text-align: center; }

/* Campaign parts */
.sh-tabs { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 16px; }
.sh-tab { padding: 9px 16px; border: 1px solid var(--border); border-radius: 99px; background: #fff; font: 600 0.9rem var(--font-body); color: var(--ink-soft); cursor: pointer; }
.sh-tab:hover { border-color: #c7d2fe; color: var(--ink); }
.sh-tab[aria-selected="true"] { background: var(--accent); border-color: var(--accent); color: #fff; }
.sh-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.sh-tabs + .sh-status { margin: 0; }

/* ---------- The one free change ---------- */
.sh-revise { max-width: 680px; margin-top: 24px; background: #fff; border: 1px solid var(--border); border-radius: 18px; padding: 22px 24px; box-shadow: var(--shadow); display: grid; gap: 14px; }
.sh-revise-head { display: flex; gap: 14px; align-items: flex-start; }
.sh-revise-head h2 { font-size: 1.1rem; margin: 0 0 4px; }
.sh-revise-head p, .sh-revise > p { font-size: 0.9rem; color: var(--ink-soft); line-height: 1.5; }
.sh-revise-ico { flex: none; width: 40px; height: 40px; border-radius: 12px; display: grid; place-items: center; background: var(--accent-soft); color: var(--accent); }
.sh-revise-ico .ico { width: 20px; height: 20px; }
.sh-revise-text { min-height: 96px; }
.sh-revise .pp-submit { justify-self: start; }
.sh-inline { display: flex; flex-wrap: wrap; gap: 10px; }
.sh-inline .pp-input { flex: 1 1 240px; width: auto; }
.sh-sent { background: #ecfdf3; color: #166534; border-radius: 12px; padding: 12px 14px; font-size: 0.92rem; }
.sh .sh-note { font-size: 0.88rem; color: var(--ink-soft); margin-top: 16px; }

/* Owner panels under a campaign (landing page, report, ads): same card as the rest. */
.sh .card { margin-top: 24px !important; border-radius: 18px; padding: 22px 24px; box-shadow: var(--shadow); }

@media (max-width: 640px) {
.sh-band { padding: 26px 0 72px; }
.sh-status { padding: 24px 20px; }
.sh-toolbar { padding: 16px; }
.sh-actions, .sh-actions .btn { width: 100%; }
.sh-actions .btn { padding: 13px 14px; font-size: 0.95rem; }
.sh-frame iframe { height: 72vh; }
.sh-revise { padding: 18px; }
.sh-revise .pp-submit, .sh-inline .pp-submit { width: 100%; }
}
Loading
Loading