Files
Omair Saleh 056c47581f feat: editorial review dashboard + elite-grade pilot batch (5 SKUs)
Ships the second dashboard surface — a Pattern Library + Preview Theatre — that
presents the 4-section PDP pilot batch back to Umar, compliance, and the board
in an editorial format. Adds the full data layer that drives it: 5 source-backed
per-SKU drafts at QA 100/100, 15 competitor PDP semantic extracts, PubMed
evidence packs, EFSA claims library extension, JV brand voice guide, hand-curated
product FAQs, and the Matrixify-ready CSV exports for Lewis.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-02 18:50:09 +08:00

227 lines
4.8 KiB
Vue

<template>
<div class="shell">
<header class="masthead">
<div class="masthead-inner">
<div class="brand">
<span class="brand-eyebrow">Just Vitamins</span>
<span class="brand-title">Editorial Review</span>
</div>
<nav class="modes" aria-label="View mode">
<router-link
class="mode"
:class="{ 'is-active': isPatterns }"
to="/patterns"
>
<span class="mode-num">01</span>
<span class="mode-label">Pattern Library</span>
</router-link>
<router-link
class="mode"
:class="{ 'is-active': isPreview }"
to="/preview"
>
<span class="mode-num">02</span>
<span class="mode-label">Preview Theatre</span>
</router-link>
</nav>
<div class="masthead-meta">
<span class="meta">Pilot batch · 2 Jun 2026</span>
</div>
</div>
<div class="masthead-rule"></div>
</header>
<main class="content">
<router-view v-slot="{ Component }">
<transition name="fade" mode="out-in">
<component :is="Component" />
</transition>
</router-view>
</main>
<footer class="footer">
<div class="footer-inner">
<span class="meta">5 pilots · 15 references · 100/100 QA</span>
<span class="meta">Hand-set in Fraunces &amp; General Sans</span>
</div>
</footer>
</div>
</template>
<script setup>
import { computed } from 'vue'
import { useRoute } from 'vue-router'
const route = useRoute()
const isPatterns = computed(() => route.path.startsWith('/patterns'))
const isPreview = computed(() => route.path.startsWith('/preview'))
</script>
<style scoped>
.shell {
display: flex;
flex-direction: column;
min-height: 100vh;
}
/* MASTHEAD ------------------------------------------------------------ */
.masthead {
position: sticky;
top: 0;
z-index: 50;
background: var(--bg-paper);
}
.masthead-inner {
display: grid;
grid-template-columns: 1fr auto 1fr;
align-items: end;
gap: var(--s-7);
padding: var(--s-6) var(--s-7) var(--s-4);
max-width: var(--col-full);
margin: 0 auto;
}
.brand {
display: flex;
flex-direction: column;
gap: var(--s-1);
justify-self: start;
}
.brand-eyebrow {
font-family: var(--font-display);
font-style: italic;
font-variation-settings: 'opsz' 24, 'WONK' 1;
font-size: var(--t-sm);
color: var(--ink-soft);
letter-spacing: 0.01em;
}
.brand-title {
font-family: var(--font-display);
font-size: var(--t-2xl);
font-variation-settings: 'opsz' 60, 'SOFT' 30, 'WONK' 0;
letter-spacing: -0.025em;
line-height: 1;
color: var(--ink);
}
/* Mode toggle — large editorial-style nav, not chips */
.modes {
display: flex;
gap: var(--s-7);
align-items: baseline;
justify-self: center;
}
.mode {
position: relative;
text-decoration: none;
display: inline-flex;
align-items: baseline;
gap: var(--s-2);
padding-bottom: var(--s-2);
transition: color var(--dur) var(--ease);
color: var(--ink-muted);
}
.mode-num {
font-family: var(--font-mono);
font-size: 10px;
letter-spacing: 0.1em;
color: inherit;
align-self: center;
margin-top: -2px;
}
.mode-label {
font-family: var(--font-display);
font-style: italic;
font-variation-settings: 'opsz' 36, 'WONK' 1, 'SOFT' 20;
font-size: var(--t-xl);
font-weight: 400;
letter-spacing: -0.01em;
}
.mode::after {
content: '';
position: absolute;
left: 0;
right: 0;
bottom: -2px;
height: 2px;
background: var(--ink);
transform: scaleX(0);
transform-origin: left;
transition: transform var(--dur-slow) var(--ease-out);
}
.mode.is-active {
color: var(--ink);
}
.mode.is-active::after {
transform: scaleX(1);
}
.mode:hover {
color: var(--ink-soft);
}
.masthead-meta {
justify-self: end;
align-self: end;
}
.masthead-rule {
height: 1px;
background: var(--rule);
max-width: var(--col-full);
margin: 0 auto;
}
/* CONTENT ------------------------------------------------------------ */
.content {
flex: 1;
padding: var(--s-8) 0 var(--s-9);
min-height: 60vh;
}
/* FOOTER ------------------------------------------------------------ */
.footer {
padding: var(--s-6) 0;
border-top: 1px solid var(--rule);
margin-top: var(--s-7);
}
.footer-inner {
max-width: var(--col-full);
margin: 0 auto;
padding: 0 var(--s-7);
display: flex;
justify-content: space-between;
gap: var(--s-4);
}
/* Responsive ------------------------------------------------------ */
@media (max-width: 900px) {
.masthead-inner {
grid-template-columns: 1fr;
gap: var(--s-4);
padding: var(--s-5) var(--s-5) var(--s-3);
}
.modes {
justify-self: start;
gap: var(--s-5);
}
.mode-label { font-size: var(--t-lg); }
.masthead-meta { display: none; }
.footer-inner { padding: 0 var(--s-5); flex-wrap: wrap; }
}
</style>