customer-presentation/advisory-board-post/editor.html
2026-06-11 14:19:02 +02:00

362 lines
11 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Board post editor · Fenja AI</title>
<link rel="stylesheet" href="colors_and_type.css" />
<style>
/* ────────── Editor chrome ────────── */
html, body { background: var(--surface-container-low); }
body { margin: 0; min-height: 100vh; font-family: var(--font-sans); color: var(--on-surface); }
.topbar {
position: sticky; top: 0; z-index: 10;
background: rgba(246, 242, 232, 0.92);
backdrop-filter: blur(14px);
-webkit-backdrop-filter: blur(14px);
padding: 20px 48px;
display: flex; align-items: center; justify-content: space-between; gap: 24px;
}
.topbar .brand { display: flex; align-items: center; gap: 14px; }
.topbar .brand img { height: 28px; }
.topbar .brand .title {
font-family: var(--font-serif);
font-size: 20px;
letter-spacing: -0.01em;
}
.topbar .brand .title em { font-style: italic; font-weight: 700; }
.topbar .actions { display: flex; align-items: center; gap: 14px; }
.btn {
font-family: var(--font-sans);
font-weight: 600;
font-size: 14px;
letter-spacing: 0;
padding: 12px 22px;
border-radius: var(--radius-md);
border: none;
cursor: pointer;
transition: background var(--duration-fast) var(--ease-standard),
color var(--duration-fast) var(--ease-standard),
transform var(--duration-fast) var(--ease-standard);
}
.btn-primary { background: var(--secondary); color: var(--on-secondary); }
.btn-primary:hover { background: var(--secondary-dim); }
.btn-primary:active { transform: translateY(1px); }
.btn-primary[disabled] { opacity: 0.5; cursor: not-allowed; }
.btn-ghost {
background: transparent;
color: var(--on-surface-variant);
padding: 12px 14px;
}
.btn-ghost:hover { color: var(--on-surface); }
/* ────────── Workspace ────────── */
.workspace {
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
gap: 56px;
padding: 48px;
max-width: 1640px;
margin: 0 auto;
align-items: start;
}
.form-col h2 {
font-family: var(--font-serif);
font-size: 32px;
letter-spacing: -0.01em;
margin: 0 0 8px;
}
.form-col .col-sub {
font-family: var(--font-serif);
font-style: italic;
color: var(--on-surface-variant);
font-size: 16px;
margin: 0 0 32px;
}
.section {
background: var(--surface-container-lowest);
border-radius: var(--radius-lg);
padding: 32px;
margin-bottom: 24px;
}
.section h3 {
font-family: var(--font-sans);
font-weight: 500;
font-size: 12px;
letter-spacing: 0.14em;
text-transform: uppercase;
color: var(--on-surface-muted);
margin: 0 0 22px;
}
.field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 18px; }
.field:last-child { margin-bottom: 0; }
.field label {
font-family: var(--font-sans);
font-size: 11px;
letter-spacing: 0.14em;
text-transform: uppercase;
color: var(--on-surface-muted);
font-weight: 500;
}
.field input, .field textarea {
font-family: var(--font-sans);
font-size: 16px;
color: var(--on-surface);
background: transparent;
border: 0;
border-bottom: 1px solid rgba(186, 186, 176, 0.4);
padding: 8px 0 10px;
outline: none;
transition: border-color var(--duration-fast) var(--ease-standard);
}
.field input:focus, .field textarea:focus {
border-bottom-color: var(--secondary);
}
.field .hint {
font-family: var(--font-serif);
font-style: italic;
font-size: 13px;
color: var(--on-surface-muted);
}
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 18px 22px; }
/* Member row in the form */
.member-row {
display: grid;
grid-template-columns: 110px 1fr;
gap: 22px;
padding: 22px 0;
align-items: start;
}
.member-row + .member-row {
border-top: 1px solid rgba(186, 186, 176, 0.25);
}
.member-row .number {
font-family: var(--font-serif);
font-style: italic;
font-size: 16px;
color: var(--on-surface-muted);
margin-bottom: 8px;
}
/* Photo dropzone */
.dropzone {
position: relative;
width: 110px; height: 110px;
background: var(--surface-container);
border-radius: 6px;
overflow: hidden;
cursor: pointer;
display: flex; align-items: center; justify-content: center;
transition: background var(--duration-fast) var(--ease-standard);
}
.dropzone:hover { background: var(--surface-container-high); }
.dropzone img { width: 100%; height: 100%; object-fit: cover; display: block; }
.dropzone .ph {
font-family: var(--font-sans);
font-size: 11px;
letter-spacing: 0.12em;
text-transform: uppercase;
color: var(--on-surface-muted);
text-align: center;
padding: 0 8px;
line-height: 1.4;
}
.dropzone input[type=file] {
position: absolute; inset: 0; opacity: 0; cursor: pointer;
}
.dropzone.has-image .ph { display: none; }
.dropzone .clear {
position: absolute; top: 4px; right: 4px;
background: rgba(56,56,49,0.7); color: #fffcf7;
border: 0; border-radius: 999px;
width: 22px; height: 22px;
cursor: pointer;
display: none;
align-items: center; justify-content: center;
font-size: 13px;
line-height: 1;
}
.dropzone.has-image:hover .clear { display: flex; }
.member-fields { display: grid; grid-template-columns: 1fr 1fr; gap: 14px 22px; }
.member-fields .field { margin-bottom: 0; }
.member-fields .field.full { grid-column: 1 / -1; }
/* ────────── Preview column ────────── */
.preview-col {
position: sticky;
top: 88px;
width: 540px;
}
.preview-col h3 {
font-family: var(--font-sans);
font-weight: 500;
font-size: 12px;
letter-spacing: 0.14em;
text-transform: uppercase;
color: var(--on-surface-muted);
margin: 0 0 14px;
display: flex;
align-items: center;
justify-content: space-between;
}
.preview-col .pixel-tag {
font-family: var(--font-mono);
font-size: 11px;
color: var(--on-surface-muted);
letter-spacing: 0;
text-transform: none;
}
.preview-frame {
width: 540px;
height: 540px;
overflow: hidden;
box-shadow: var(--shadow-float);
border-radius: 6px;
background: var(--surface);
}
.preview-frame .stage {
width: 1200px;
height: 1200px;
transform: scale(0.45);
transform-origin: top left;
}
.preview-foot {
margin-top: 18px;
font-family: var(--font-serif);
font-style: italic;
font-size: 14px;
color: var(--on-surface-muted);
line-height: 1.5;
max-width: 540px;
}
/* Hidden off-screen capture target — full size, untransformed. */
.capture-host {
position: fixed;
left: -100000px;
top: 0;
width: 1200px;
height: 1200px;
pointer-events: none;
}
/* ────────── Board post styles — mirrors Variation A in index.html ────────── */
.post, .post *, .post *::before, .post *::after { box-sizing: border-box; }
.post {
position: relative;
width: 1200px;
height: 1200px;
background: var(--surface);
color: var(--on-surface);
overflow: hidden;
font-family: var(--font-sans);
}
.post h1 {
font-family: var(--font-serif);
font-weight: 400;
letter-spacing: -0.02em;
line-height: 1.04;
color: var(--on-surface);
margin: 0;
text-wrap: balance;
}
.post h1 em { font-style: italic; font-weight: 700; }
.post .subtitle {
font-family: var(--font-serif);
font-size: 26px;
color: var(--on-surface-variant);
line-height: 1.35;
margin-top: 18px;
}
.post .member { display: flex; flex-direction: column; }
.post .member .name {
font-family: var(--font-serif);
font-weight: 700;
color: var(--on-surface);
letter-spacing: -0.01em;
line-height: 1.15;
font-size: 22px;
margin-top: 18px;
}
.post .member .title {
font-family: var(--font-sans);
font-weight: 600;
color: var(--on-surface);
line-height: 1.35;
font-size: 16px;
margin-top: 6px;
}
.post .member .company {
font-family: var(--font-sans);
font-weight: 500;
color: var(--on-surface-variant);
line-height: 1.35;
font-size: 17px;
margin-top: 2px;
}
.post .member .portrait {
width: 100%;
height: 210px;
border-radius: 4px;
object-fit: cover;
display: block;
background: var(--surface-container-high);
}
.post .member .portrait-empty {
width: 100%;
height: 210px;
border-radius: 4px;
background: var(--surface-container-high);
display: flex;
align-items: center;
justify-content: center;
color: var(--on-surface-muted);
font-size: 12px;
letter-spacing: 0.14em;
text-transform: uppercase;
font-family: var(--font-sans);
}
.post .a-root { padding: 96px 96px 80px; display: flex; flex-direction: column; height: 100%; }
.post .a-head { max-width: 980px; }
.post .a-head h1 { font-size: 64px; }
.post .a-grid {
margin-top: 64px;
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 36px 28px;
}
.post .a-foot {
margin-top: auto;
display: flex;
align-items: center;
}
.post .mark {
display: flex;
align-items: center;
}
.post .mark img { height: 160px; opacity: 1; display: block; margin-left: -6px; }
</style>
<script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>
<script src="https://unpkg.com/react-dom@18.3.1/umd/react-dom.development.js" integrity="sha384-u6aeetuaXnQ38mYT8rp6sbXaQe3NL9t+IBXmnYxwkUI2Hw4bsp2Wvmx4yRQF1uAm" crossorigin="anonymous"></script>
<script src="https://unpkg.com/@babel/standalone@7.29.0/babel.min.js" integrity="sha384-m08KidiNqLdpJqLq95G/LEi8Qvjl/xUYll3QILypMoQ65QorJ9Lvtp2RXYGBFj1y" crossorigin="anonymous"></script>
<script src="https://unpkg.com/html-to-image@1.11.13/dist/html-to-image.js"></script>
<script type="text/babel" src="editor.jsx"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
const { createRoot } = ReactDOM;
createRoot(document.getElementById('root')).render(<EditorApp />);
</script>
</body>
</html>