This commit is contained in:
108
apps/web/pages/campaign/demo.vue
Normal file
108
apps/web/pages/campaign/demo.vue
Normal file
File diff suppressed because one or more lines are too long
36
apps/web/pages/dashboard.vue
Normal file
36
apps/web/pages/dashboard.vue
Normal file
@@ -0,0 +1,36 @@
|
||||
<script setup lang="ts">
|
||||
const { worlds } = useDemo()
|
||||
const filter = ref<'all' | 'active' | 'drafts'>('all')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AppShell section="COMMAND DECK">
|
||||
<div class="dash-wrap noise">
|
||||
<section class="dash-head">
|
||||
<div><p class="kicker">WELCOME BACK, MARA</p><h1>YOUR UNIVERSES<span>.</span></h1><p>Every world remembers where you left it.</p></div>
|
||||
<NuxtLink to="/worlds/new" class="create-button"><span>+</span> CREATE A UNIVERSE</NuxtLink>
|
||||
</section>
|
||||
|
||||
<div class="filter-row">
|
||||
<button v-for="item in ['all','active','drafts']" :key="item" :class="{active:filter===item}" @click="filter=item as typeof filter">{{ item }}</button>
|
||||
<span>1 / 5 ALPHA WORLDS</span>
|
||||
</div>
|
||||
|
||||
<section class="world-grid">
|
||||
<NuxtLink v-for="world in worlds" :key="world.title" to="/campaign/demo" class="world-card active-world">
|
||||
<div class="world-art"><div class="eclipse" /><span>ACTIVE CAMPAIGN</span></div>
|
||||
<div class="world-info"><small>{{ world.genre }}</small><h2>{{ world.title }}</h2><p>{{ world.premise }}</p><div><b>ROUND 03</b><span>2 PARTY MEMBERS</span></div></div>
|
||||
</NuxtLink>
|
||||
<NuxtLink to="/worlds/new" class="world-card new-card">
|
||||
<span class="plus">+</span><h2>MAKE THE NEXT<br>IMPOSSIBLE PLACE</h2><p>Begin with a sentence. The coauthor will ask the rest.</p>
|
||||
</NuxtLink>
|
||||
</section>
|
||||
|
||||
<section class="system-strip"><span><i /> OPENROUTER ADAPTER READY</span><span>SERVER DICE <b>ONLINE</b></span><span>PRIVATE BY DEFAULT</span></section>
|
||||
</div>
|
||||
</AppShell>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.dash-wrap{min-height:calc(100vh - 76px);padding:clamp(42px,6vw,86px) clamp(20px,6vw,88px)}.dash-head{display:flex;align-items:end;justify-content:space-between;gap:30px}.kicker{font:500 9px var(--mono);letter-spacing:.2em;color:var(--acid)}.dash-head h1{margin:14px 0 10px;font:600 clamp(44px,6vw,82px)/1 var(--display);letter-spacing:-.06em}.dash-head h1 span{color:var(--acid)}.dash-head p{color:var(--muted)}.create-button{display:flex;align-items:center;gap:18px;padding:18px 22px;background:var(--acid);color:#090909;text-decoration:none;font:600 10px var(--mono);letter-spacing:.12em}.create-button span{font-size:20px}.filter-row{display:flex;align-items:center;gap:10px;margin:58px 0 24px;border-bottom:1px solid var(--line)}.filter-row button{padding:0 4px 16px;background:none;border:0;color:var(--muted);font:500 9px var(--mono);text-transform:uppercase;letter-spacing:.14em;margin-right:18px}.filter-row button.active{color:var(--ink);border-bottom:2px solid var(--acid)}.filter-row>span{margin-left:auto;padding-bottom:16px;font:500 8px var(--mono);color:var(--muted)}.world-grid{display:grid;grid-template-columns:1.35fr .65fr;gap:18px}.world-card{min-height:420px;border:1px solid var(--line);color:var(--ink);text-decoration:none;background:#0e0e0d;transition:.25s ease}.world-card:hover{border-color:#65655e;transform:translateY(-3px)}.active-world{display:grid;grid-template-columns:.9fr 1.1fr}.world-art{position:relative;overflow:hidden;display:grid;place-items:center;background:radial-gradient(circle at 50% 60%,#7d8240 0 2%,#303018 4%,#0b0b0a 36%,#030303 72%)}.world-art:before{content:"";position:absolute;width:320px;height:320px;border:1px solid #38382d;border-radius:50%;box-shadow:0 0 0 34px #111,0 0 0 35px #26261d}.eclipse{position:absolute;width:126px;height:126px;border-radius:50%;background:#020202;box-shadow:0 0 50px var(--acid-dim)}.world-art span{position:absolute;left:20px;top:20px;padding:9px 11px;background:var(--acid);color:#0a0a0a;font:600 8px var(--mono);letter-spacing:.12em}.world-info{padding:42px;display:flex;flex-direction:column}.world-info small{font:500 8px var(--mono);letter-spacing:.14em;color:var(--acid);text-transform:uppercase}.world-info h2,.new-card h2{font:600 clamp(25px,3vw,42px)/1.05 var(--display);letter-spacing:-.05em;margin:22px 0}.world-info p,.new-card p{color:var(--muted);font-size:13px;line-height:1.7}.world-info div{margin-top:auto;padding-top:26px;border-top:1px solid var(--line);display:flex;justify-content:space-between;font:500 8px var(--mono);color:var(--muted)}.world-info b{color:var(--acid)}.new-card{padding:48px;display:flex;flex-direction:column;justify-content:flex-end;background:linear-gradient(145deg,#121211,#090909)}.new-card .plus{margin-bottom:auto;font:300 42px var(--body);color:var(--acid)}.system-strip{margin-top:32px;padding:18px 0;border-top:1px solid var(--line);display:flex;justify-content:space-between;font:500 8px var(--mono);letter-spacing:.12em;color:var(--muted)}.system-strip i{display:inline-block;width:6px;height:6px;background:var(--acid);border-radius:50%;margin-right:8px}.system-strip b{color:var(--acid)}@media(max-width:850px){.dash-head{align-items:start;flex-direction:column}.world-grid{grid-template-columns:1fr}.active-world{grid-template-columns:1fr}.world-art{min-height:280px}.system-strip{gap:16px;flex-wrap:wrap}}@media(max-width:520px){.filter-row>span{display:none}.world-info,.new-card{padding:28px}.active-world{min-height:580px}}
|
||||
</style>
|
||||
61
apps/web/pages/index.vue
Normal file
61
apps/web/pages/index.vue
Normal file
@@ -0,0 +1,61 @@
|
||||
<script setup lang="ts">
|
||||
const { signedIn } = useDemo()
|
||||
const email = ref('founder@example.com')
|
||||
const notice = ref('')
|
||||
|
||||
function enterDemo() {
|
||||
signedIn.value = true
|
||||
navigateTo('/dashboard')
|
||||
}
|
||||
|
||||
function requestAccess() {
|
||||
notice.value = `Invite request saved for ${email.value}. Demo access is available now.`
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="landing noise">
|
||||
<header class="landing-nav">
|
||||
<AppMark />
|
||||
<span class="alpha-tag">INVITE-ONLY ALPHA</span>
|
||||
</header>
|
||||
|
||||
<main class="hero">
|
||||
<section class="hero-copy">
|
||||
<p class="eyebrow"><span /> ASYNC AI-POWERED TTRPG</p>
|
||||
<h1>STORIES THAT<br><em>WAIT FOR NO ONE.</em></h1>
|
||||
<p class="lede">Build an original universe with an AI coauthor. Gather real players and persistent AI companions. Take your turn when life allows—the Groundkeeper remembers everything.</p>
|
||||
<div class="hero-actions">
|
||||
<button class="btn btn-acid" @click="enterDemo">ENTER THE ALPHA <span>↗</span></button>
|
||||
<a href="#how" class="btn btn-ghost">SEE HOW IT WORKS</a>
|
||||
</div>
|
||||
<div class="trust-row">
|
||||
<span>PRIVATE WORLDS</span><i />
|
||||
<span>SERVER-OWNED DICE</span><i />
|
||||
<span>13+ ADVENTURES</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="signal-card" aria-label="Live campaign preview">
|
||||
<div class="signal-top"><span>LIVE SIGNAL / CAMPAIGN 04</span><b>ROUND 17</b></div>
|
||||
<div class="orbit" aria-hidden="true"><i /><i /><i /><span>D&G</span></div>
|
||||
<div class="transmission">
|
||||
<small>GROUNDKEEPER</small>
|
||||
<p>“The voice in the relay is yours—three days from now. It tells you not to open the archive.”</p>
|
||||
</div>
|
||||
<div class="party-status"><span><b>3</b> HUMANS READY</span><span><b>1</b> AI COMPANION THINKING</span></div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<section id="how" class="how-grid">
|
||||
<article><b>01</b><h2>DESCRIBE THE IMPOSSIBLE</h2><p>A coauthor asks sharp questions, then turns your idea into a playable private world.</p></article>
|
||||
<article><b>02</b><h2>ASSEMBLE YOUR PARTY</h2><p>Invite friends, add AI companions, and decide who can step in when someone is away.</p></article>
|
||||
<article><b>03</b><h2>ACT ON YOUR TIME</h2><p>The Groundkeeper resolves each shared round only when the party is ready.</p></article>
|
||||
<form @submit.prevent="requestAccess"><label for="email">REQUEST AN INVITE</label><div><input id="email" v-model="email" type="email" required><button>→</button></div><small>{{ notice || 'We only email about alpha access.' }}</small></form>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.landing{min-height:100vh;overflow:hidden}.landing-nav{height:90px;padding:0 clamp(22px,6vw,90px);display:flex;justify-content:space-between;align-items:center;border-bottom:1px solid var(--line)}.alpha-tag{font:500 9px var(--mono);letter-spacing:.18em;border:1px solid var(--line);padding:10px 14px;color:var(--muted)}.hero{min-height:680px;padding:72px clamp(22px,6vw,90px) 60px;display:grid;grid-template-columns:minmax(0,1.15fr) minmax(360px,.85fr);gap:7vw;align-items:center}.eyebrow{font:500 10px var(--mono);letter-spacing:.22em;color:var(--muted)}.eyebrow span{display:inline-block;width:26px;height:1px;background:var(--acid);vertical-align:middle;margin-right:10px}.hero h1{margin:22px 0 28px;font:600 clamp(52px,6.6vw,108px)/.91 var(--display);letter-spacing:-.07em}.hero h1 em{font-style:normal;color:transparent;-webkit-text-stroke:1px var(--acid)}.lede{max-width:650px;font-size:clamp(16px,1.5vw,20px);line-height:1.7;color:#b9b9b2}.hero-actions{display:flex;gap:12px;margin-top:38px}.btn{min-height:52px;padding:0 22px;border:1px solid var(--line);font:600 10px var(--mono);letter-spacing:.13em;text-decoration:none;display:inline-flex;align-items:center;justify-content:center;gap:20px}.btn-acid{border-color:var(--acid);background:var(--acid);color:#080808}.btn-ghost{color:var(--ink);background:transparent}.trust-row{display:flex;align-items:center;gap:14px;margin-top:42px;font:500 8px var(--mono);letter-spacing:.16em;color:var(--muted)}.trust-row i{width:3px;height:3px;background:var(--acid);border-radius:50%}.signal-card{position:relative;min-height:510px;border:1px solid var(--line);background:linear-gradient(145deg,#111 0%,#090909 60%);box-shadow:0 40px 120px #000;padding:22px;clip-path:polygon(0 0,calc(100% - 20px) 0,100% 20px,100% 100%,20px 100%,0 calc(100% - 20px))}.signal-top,.party-status{display:flex;justify-content:space-between;font:500 8px var(--mono);letter-spacing:.13em;color:var(--muted)}.signal-top b{color:var(--acid)}.orbit{position:relative;width:245px;height:245px;margin:48px auto 30px;border:1px solid #2b2b29;border-radius:50%;display:grid;place-items:center}.orbit:before,.orbit:after{content:"";position:absolute;border:1px solid #262624;border-radius:50%;inset:28px}.orbit:after{inset:61px;border-color:var(--acid-dim)}.orbit i{position:absolute;width:7px;height:7px;border-radius:50%;background:var(--acid);box-shadow:0 0 18px var(--acid)}.orbit i:nth-child(1){top:23px;left:52px}.orbit i:nth-child(2){right:-3px;top:113px}.orbit i:nth-child(3){bottom:20px;left:85px}.orbit span{font:600 28px var(--display);color:var(--acid)}.transmission{border-left:2px solid var(--acid);padding:8px 18px;margin:0 12px 34px}.transmission small{font:500 8px var(--mono);letter-spacing:.18em;color:var(--acid)}.transmission p{font:500 15px/1.6 var(--body);color:#d6d6d0}.party-status{padding:18px 12px 0;border-top:1px solid var(--line)}.party-status b{color:var(--acid)}.how-grid{display:grid;grid-template-columns:repeat(3,1fr) 1.2fr;border-top:1px solid var(--line)}.how-grid article,.how-grid form{min-height:215px;padding:34px;border-right:1px solid var(--line)}.how-grid article>b{font:500 9px var(--mono);color:var(--acid)}.how-grid h2{margin:34px 0 12px;font:600 13px var(--display);letter-spacing:-.03em}.how-grid p,.how-grid small{font-size:12px;line-height:1.6;color:var(--muted)}.how-grid label{font:600 10px var(--mono);letter-spacing:.12em}.how-grid form div{display:flex;margin:35px 0 12px}.how-grid input{width:100%;background:#10100f;border:1px solid var(--line);padding:14px;color:var(--ink)}.how-grid form button{width:50px;border:0;background:var(--acid);font-size:20px}@media(max-width:950px){.hero{grid-template-columns:1fr}.signal-card{max-width:620px}.how-grid{grid-template-columns:1fr 1fr}}@media(max-width:620px){.alpha-tag{display:none}.hero{padding-top:50px}.hero h1{font-size:48px}.hero-actions{flex-direction:column}.trust-row{flex-wrap:wrap}.signal-card{min-height:470px}.how-grid{grid-template-columns:1fr}.how-grid article,.how-grid form{border-bottom:1px solid var(--line)}}
|
||||
</style>
|
||||
100
apps/web/pages/worlds/new.vue
Normal file
100
apps/web/pages/worlds/new.vue
Normal file
@@ -0,0 +1,100 @@
|
||||
<script setup lang="ts">
|
||||
import type { WorldStarter } from '@dng/shared'
|
||||
|
||||
const { worlds, activeWorld } = useDemo()
|
||||
const step = ref<'chat' | 'generating' | 'preview'>('chat')
|
||||
const input = ref('A science-fiction mystery about a dead relay sending messages from the future.')
|
||||
const answers = reactive({ tone: '', conflict: '', role: '' })
|
||||
const questionIndex = ref(0)
|
||||
const questions = [
|
||||
{ key: 'tone', label: 'What should the story feel like?', options: ['Tense & uncanny', 'Bold & adventurous', 'Melancholy & intimate'] },
|
||||
{ key: 'conflict', label: 'What pressure drives the opening?', options: ['A ticking clock', 'A fragile alliance', 'A dangerous discovery'] },
|
||||
{ key: 'role', label: 'Who are the players in this world?', options: ['A freelance crew', 'Reluctant investigators', 'Agents of a fading power'] },
|
||||
]
|
||||
const draft = ref<WorldStarter | null>(null)
|
||||
|
||||
function answerFor(key: string) {
|
||||
return answers[key as keyof typeof answers]
|
||||
}
|
||||
|
||||
function begin() {
|
||||
if (!input.value.trim()) return
|
||||
questionIndex.value = 1
|
||||
}
|
||||
|
||||
function choose(key: string, value: string) {
|
||||
;(answers as Record<string, string>)[key] = value
|
||||
if (questionIndex.value < questions.length) questionIndex.value += 1
|
||||
}
|
||||
|
||||
async function generate() {
|
||||
step.value = 'generating'
|
||||
try {
|
||||
draft.value = await $fetch<WorldStarter>('/api/worlds/generate', { method: 'POST', body: { prompt: input.value, answers } })
|
||||
} catch {
|
||||
draft.value = structuredClone(activeWorld.value)
|
||||
}
|
||||
await new Promise(resolve => setTimeout(resolve, 700))
|
||||
step.value = 'preview'
|
||||
}
|
||||
|
||||
function confirm() {
|
||||
if (!draft.value) return
|
||||
activeWorld.value = draft.value
|
||||
if (!worlds.value.some(world => world.title === draft.value!.title)) worlds.value.unshift(draft.value)
|
||||
navigateTo('/campaign/demo')
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AppShell section="WORLD FORGE">
|
||||
<div class="forge noise">
|
||||
<aside>
|
||||
<p class="step-label">CREATION PROTOCOL</p>
|
||||
<ol>
|
||||
<li :class="{ active: step==='chat' }"><b>01</b><span>Seed idea<small>Say what cannot exist yet.</small></span></li>
|
||||
<li :class="{ active: questionIndex>0 && step==='chat' }"><b>02</b><span>Shape the signal<small>Tone, pressure, player role.</small></span></li>
|
||||
<li :class="{ active: step==='generating' }"><b>03</b><span>Generate structure<small>A playable starting kit.</small></span></li>
|
||||
<li :class="{ active: step==='preview' }"><b>04</b><span>Review & launch<small>You remain the final author.</small></span></li>
|
||||
</ol>
|
||||
<div class="boundary"><span>13+ BOUNDARY</span><p>Dark themes are welcome. Explicit sexual content and extreme graphic violence are not.</p></div>
|
||||
</aside>
|
||||
|
||||
<main v-if="step==='chat'" class="coauthor">
|
||||
<p class="kicker">COAUTHOR / SESSION 01</p>
|
||||
<h1>WHAT SHOULD<br>WE BUILD<span>?</span></h1>
|
||||
<div class="chat-line ai"><small>COAUTHOR</small><p>Give me the first impossible sentence. I’ll help turn it into a world your party can enter tonight.</p></div>
|
||||
<form class="seed" @submit.prevent="begin"><textarea v-model="input" aria-label="World idea" rows="3"/><button>BEGIN <span>→</span></button></form>
|
||||
|
||||
<div v-for="(question, index) in questions" v-show="questionIndex > index" :key="question.key" class="question-block">
|
||||
<div class="chat-line ai"><small>COAUTHOR · {{ String(index+2).padStart(2,'0') }}</small><p>{{ question.label }}</p></div>
|
||||
<div class="choices">
|
||||
<button v-for="option in question.options" :key="option" :class="{selected:answerFor(question.key)===option}" @click="choose(question.key, option)">{{ option }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<button v-if="Object.values(answers).every(Boolean)" class="generate" @click="generate">GENERATE STARTING WORLD <span>↗</span></button>
|
||||
</main>
|
||||
|
||||
<main v-else-if="step==='generating'" class="generating">
|
||||
<div class="scanner"><i/><i/><i/><span>D&G</span></div><p>ASSEMBLING A PLAYABLE WORLD</p><small>Premise · Location · 3 NPCs · 2 factions · Hidden pressure</small>
|
||||
</main>
|
||||
|
||||
<main v-else-if="draft" class="preview">
|
||||
<div class="preview-top"><div><p class="kicker">GENERATED STARTING KIT</p><input v-model="draft.title" aria-label="World title"></div><button @click="step='chat'">← REVISE INPUT</button></div>
|
||||
<div class="preview-grid">
|
||||
<section class="premise"><label>PREMISE</label><textarea v-model="draft.premise" rows="6"/><div><span>{{ draft.genre }}</span><span>{{ draft.tone }}</span></div></section>
|
||||
<section><label>STARTING LOCATION</label><h2>{{ draft.startingLocation.name }}</h2><p>{{ draft.startingLocation.summary }}</p></section>
|
||||
<section class="wide"><label>KEY PEOPLE</label><div class="entity-row"><article v-for="npc in draft.npcs" :key="npc.id"><small>NPC</small><h3>{{ npc.name }}</h3><p>{{ npc.summary }}</p></article></div></section>
|
||||
<section class="wide"><label>FACTIONS</label><div class="entity-row factions"><article v-for="faction in draft.factions" :key="faction.id"><small>FACTION</small><h3>{{ faction.name }}</h3><p>{{ faction.summary }}</p></article></div></section>
|
||||
<section><label>OPENING HOOK</label><p>{{ draft.hook }}</p></section>
|
||||
<section><label>CONTENT BOUNDARIES</label><ul><li v-for="boundary in draft.contentBoundaries" :key="boundary">{{ boundary }}</li></ul></section>
|
||||
</div>
|
||||
<div class="confirm-bar"><p><b>PRIVATE WORLD</b><span>Only invited campaign members can see it.</span></p><button @click="confirm">CONFIRM & ENTER WORLD <span>→</span></button></div>
|
||||
</main>
|
||||
</div>
|
||||
</AppShell>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.forge{min-height:calc(100vh - 76px);display:grid;grid-template-columns:300px 1fr}.forge>aside{padding:50px 34px;border-right:1px solid var(--line);display:flex;flex-direction:column}.step-label,.kicker{font:500 9px var(--mono);letter-spacing:.18em;color:var(--acid)}ol{list-style:none;padding:28px 0;margin:0}li{display:flex;gap:18px;padding:20px 0;color:#4d4d48}li>b{font:500 9px var(--mono)}li span{font:600 10px var(--display);letter-spacing:.04em}li small{display:block;margin-top:7px;font:400 10px/1.4 var(--body);color:#55554f}li.active{color:var(--ink)}li.active b{color:var(--acid)}li.active small{color:var(--muted)}.boundary{margin-top:auto;padding:18px;border:1px solid var(--line)}.boundary span{font:600 8px var(--mono);color:var(--acid)}.boundary p{font-size:10px;line-height:1.5;color:var(--muted)}.coauthor,.preview{padding:clamp(44px,6vw,82px);max-width:1100px;width:100%}.coauthor h1{font:600 clamp(42px,5vw,72px)/.95 var(--display);letter-spacing:-.06em;margin:16px 0 54px}.coauthor h1 span{color:var(--acid)}.chat-line{max-width:680px;border-left:2px solid var(--acid);padding:3px 20px;margin:26px 0 18px}.chat-line small{font:500 8px var(--mono);letter-spacing:.15em;color:var(--acid)}.chat-line p{font-size:15px;line-height:1.65;color:#d0d0ca}.seed{display:flex;align-items:stretch;max-width:760px}.seed textarea,.preview textarea,.preview input{width:100%;resize:none;background:#10100f;border:1px solid var(--line);color:var(--ink);padding:18px;font:500 14px/1.6 var(--body)}.seed button,.generate,.confirm-bar button{border:0;background:var(--acid);color:#080808;padding:0 24px;font:600 9px var(--mono);letter-spacing:.12em}.choices{display:flex;gap:9px;flex-wrap:wrap;margin-left:20px}.choices button{padding:12px 14px;border:1px solid var(--line);background:#10100f;color:var(--muted);font:500 9px var(--mono)}.choices button.selected{border-color:var(--acid);color:var(--acid)}.generate{margin-top:42px;min-height:52px}.generating{display:grid;place-content:center;text-align:center}.scanner{position:relative;width:250px;height:250px;border:1px solid var(--line);border-radius:50%;display:grid;place-items:center;margin:0 auto 34px;animation:rotate 8s linear infinite}.scanner:after{content:"";position:absolute;inset:35px;border:1px dashed var(--acid-dim);border-radius:50%}.scanner i{position:absolute;width:7px;height:7px;background:var(--acid);border-radius:50%}.scanner i:nth-child(1){top:10px}.scanner i:nth-child(2){left:20px;bottom:55px}.scanner i:nth-child(3){right:5px;top:90px}.scanner span{font:600 26px var(--display);color:var(--acid)}.generating p{font:600 11px var(--mono);letter-spacing:.16em}.generating small{color:var(--muted)}@keyframes rotate{to{transform:rotate(360deg)}}.preview{max-width:1300px}.preview-top{display:flex;justify-content:space-between;align-items:end;gap:20px;margin-bottom:34px}.preview-top input{border:0;border-bottom:1px solid var(--line);font:600 clamp(30px,4vw,54px) var(--display);letter-spacing:-.05em;padding:12px 0;background:transparent}.preview-top button{background:transparent;color:var(--muted);border:0;font:500 8px var(--mono)}.preview-grid{display:grid;grid-template-columns:1fr 1fr;border-top:1px solid var(--line);border-left:1px solid var(--line)}.preview-grid>section{padding:28px;border-right:1px solid var(--line);border-bottom:1px solid var(--line)}.preview-grid .wide{grid-column:1/-1}.preview-grid label{font:600 8px var(--mono);letter-spacing:.15em;color:var(--acid)}.preview-grid h2{font:600 22px var(--display);margin:20px 0 12px}.preview-grid p{font-size:12px;line-height:1.7;color:var(--muted)}.premise div{display:flex;gap:8px;margin-top:14px}.premise div span{padding:7px 9px;border:1px solid var(--line);font:500 8px var(--mono);color:var(--muted)}.entity-row{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;background:var(--line);margin-top:22px}.entity-row article{background:#0d0d0c;padding:20px}.entity-row small{font:500 7px var(--mono);color:var(--acid)}.entity-row h3{font:600 13px var(--display)}.factions{grid-template-columns:1fr 1fr}.preview-grid ul{padding-left:18px;color:var(--muted);font-size:12px}.confirm-bar{position:sticky;bottom:0;display:flex;justify-content:space-between;align-items:center;padding:18px 22px;background:#11110f;border:1px solid var(--line);margin-top:24px}.confirm-bar p{margin:0;display:flex;flex-direction:column;font:600 8px var(--mono);color:var(--acid)}.confirm-bar p span{margin-top:5px;color:var(--muted);font-weight:400}.confirm-bar button{min-height:48px}@media(max-width:850px){.forge{grid-template-columns:1fr}.forge>aside{display:none}.coauthor,.preview{padding:40px 20px}.preview-grid{grid-template-columns:1fr}.preview-grid .wide{grid-column:auto}.entity-row,.factions{grid-template-columns:1fr}.confirm-bar{align-items:stretch;flex-direction:column;gap:14px}}
|
||||
</style>
|
||||
Reference in New Issue
Block a user