Files
transcript/design/transcript-design-exploration-v2.html
T
evandrodevbr 06aaeeaf79 wip: snapshot das alterações não commitadas (2026-10-20)
Origem: D:/Documents/Github/transcript
Arquivos omitidos (segredos, bancos de dados, logs, >50 MB): 2
2026-10-20 00:50:17 -03:00

1879 lines
59 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="pt-BR">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Transcript — Redesign v2</title>
<style>
@import url("https://fonts.googleapis.com/css2?family=Afacad:wght@400;500;600;700&family=Chivo:wght@400;500;600;700;800&family=Literata:opsz,[email protected],500;7..72,650&family=Recursive:CASL,MONO,[email protected],0..1,400..800&display=swap");
:root {
color-scheme: dark;
--font-ui: "Afacad", "Segoe UI", system-ui, sans-serif;
--font-display: "Chivo", "Afacad", sans-serif;
--font-mono: "Recursive", "SF Mono", ui-monospace, monospace;
--font-editorial: "Literata", Georgia, serif;
--ink: oklch(96% 0.012 62);
--muted: oklch(74% 0.018 62);
--soft: oklch(58% 0.018 62);
--line: oklch(100% 0 0 / 0.105);
--line-strong: oklch(100% 0 0 / 0.18);
--brand: oklch(75% 0.078 62);
--brand-hot: oklch(86% 0.085 62);
--ok: oklch(76% 0.105 150);
--bad: oklch(72% 0.12 29);
--bg: oklch(10% 0.012 62);
--panel: oklch(16% 0.014 62);
--panel-2: oklch(20% 0.016 62);
--ease-out: cubic-bezier(0.16, 1, 0.3, 1);
--ease-toggle: cubic-bezier(0.65, 0, 0.35, 1);
}
* {
box-sizing: border-box;
}
html,
body {
margin: 0;
min-height: 100%;
background: var(--bg);
color: var(--ink);
}
body {
font-family: var(--font-ui);
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
background:
radial-gradient(
circle at 12% 0%,
oklch(68% 0.08 62 / 0.2),
transparent 30rem
),
radial-gradient(
circle at 92% 10%,
oklch(72% 0.09 150 / 0.1),
transparent 34rem
),
linear-gradient(180deg, oklch(13% 0.014 62), oklch(7% 0.01 62));
overflow-x: hidden;
}
body::after {
content: "";
position: fixed;
inset: 0;
pointer-events: none;
opacity: 0.08;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 160 160' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='.55'/%3E%3C/svg%3E");
mix-blend-mode: soft-light;
z-index: 50;
}
button,
textarea,
input {
font: inherit;
color: inherit;
}
button {
border: 0;
background: none;
cursor: pointer;
}
button:focus-visible,
textarea:focus-visible,
input:focus-visible {
outline: 2px solid var(--brand-hot);
outline-offset: 3px;
}
svg.icon {
width: 17px;
height: 17px;
stroke: currentColor;
fill: none;
stroke-width: 1.65;
stroke-linecap: round;
stroke-linejoin: round;
}
.shell {
width: min(1480px, calc(100vw - 40px));
margin: 0 auto;
padding: 34px 0 60px;
}
.masthead {
display: grid;
grid-template-columns: minmax(0, 1.1fr) minmax(320px, 0.9fr);
gap: 32px;
align-items: end;
}
.kicker {
width: max-content;
padding: 7px 11px;
border: 1px solid oklch(85% 0.08 62 / 0.28);
border-radius: 999px;
color: var(--brand-hot);
background: oklch(70% 0.08 62 / 0.08);
font: 700 11px/1 var(--font-mono);
letter-spacing: 0.12em;
text-transform: uppercase;
}
h1 {
margin: 16px 0 12px;
max-width: 920px;
font: 800 clamp(42px, 6vw, 84px)/0.87 var(--font-display);
letter-spacing: -0.075em;
}
.lead {
max-width: 72ch;
margin: 0;
color: var(--muted);
font-size: 17px;
line-height: 1.62;
}
.critique-box {
padding: 18px 20px;
border: 1px solid var(--line);
border-radius: 28px;
background: linear-gradient(
180deg,
oklch(100% 0 0 / 0.07),
oklch(100% 0 0 / 0.032)
);
box-shadow:
inset 0 1px 0 oklch(100% 0 0 / 0.08),
0 28px 90px oklch(0% 0 0 / 0.28);
color: var(--muted);
line-height: 1.55;
}
.critique-box strong {
color: var(--ink);
}
.controls {
position: sticky;
top: 12px;
z-index: 20;
margin: 26px 0;
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
gap: 12px;
padding: 9px;
border-radius: 30px;
border: 1px solid var(--line);
background: oklch(11% 0.012 62 / 0.78);
backdrop-filter: blur(24px) saturate(160%);
box-shadow:
0 24px 80px oklch(0% 0 0 / 0.38),
inset 0 1px 0 oklch(100% 0 0 / 0.08);
}
.tabs,
.states {
display: flex;
gap: 6px;
overflow: auto;
scrollbar-width: none;
}
.tabs::-webkit-scrollbar,
.states::-webkit-scrollbar {
display: none;
}
.tab,
.state {
min-height: 38px;
padding: 0 13px;
border-radius: 999px;
color: var(--muted);
white-space: nowrap;
transition:
transform 150ms var(--ease-out),
background 220ms var(--ease-out),
color 220ms var(--ease-out);
}
.tab:hover,
.state:hover {
background: oklch(100% 0 0 / 0.06);
color: var(--ink);
}
.tab[aria-selected="true"],
.state.active {
background: linear-gradient(
180deg,
oklch(100% 0 0 / 0.13),
oklch(100% 0 0 / 0.055)
);
color: var(--ink);
box-shadow: inset 0 1px 0 oklch(100% 0 0 / 0.12);
}
.states {
padding: 4px;
border-radius: 999px;
border: 1px solid var(--line);
background: oklch(100% 0 0 / 0.04);
}
.state {
min-height: 30px;
font-size: 13px;
}
.state.active {
color: var(--brand-hot);
background: oklch(70% 0.08 62 / 0.13);
}
.workspace {
display: grid;
grid-template-columns: minmax(0, 1fr) 430px;
gap: 30px;
align-items: start;
}
.brief {
min-height: 520px;
padding: 28px;
border-radius: 36px;
border: 1px solid var(--line);
background: linear-gradient(
180deg,
oklch(100% 0 0 / 0.065),
oklch(100% 0 0 / 0.028)
);
box-shadow:
inset 0 1px 0 oklch(100% 0 0 / 0.08),
0 30px 100px oklch(0% 0 0 / 0.32);
}
.brief h2 {
margin: 0 0 12px;
font: 800 clamp(34px, 4.5vw, 64px)/0.91 var(--font-display);
letter-spacing: -0.06em;
}
.brief p {
margin: 0;
color: var(--muted);
font-size: 16px;
line-height: 1.65;
max-width: 76ch;
}
.score-grid {
margin-top: 28px;
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 12px;
}
.score {
padding: 16px;
border-radius: 22px;
background: oklch(0% 0 0 / 0.18);
border: 1px solid var(--line);
}
.score b {
display: block;
color: var(--brand-hot);
font: 700 11px/1 var(--font-mono);
letter-spacing: 0.1em;
text-transform: uppercase;
margin-bottom: 8px;
}
.score span {
color: oklch(80% 0.018 62);
font-size: 14px;
line-height: 1.42;
}
.preview-zone {
position: sticky;
top: 112px;
display: grid;
justify-items: center;
gap: 13px;
}
.frame-wrap {
width: 430px;
min-height: 520px;
display: grid;
place-items: center;
border-radius: 40px;
background:
radial-gradient(
circle at 35% 0%,
oklch(72% 0.08 62 / 0.12),
transparent 18rem
),
oklch(100% 0 0 / 0.035);
border: 1px solid var(--line);
box-shadow: inset 0 1px 0 oklch(100% 0 0 / 0.08);
}
.app-frame {
width: 380px;
height: 460px;
position: relative;
overflow: hidden;
border-radius: 28px;
border: 1px solid oklch(100% 0 0 / 0.14);
background: oklch(9% 0.012 62);
box-shadow:
0 40px 110px oklch(0% 0 0 / 0.56),
0 0 0 10px oklch(100% 0 0 / 0.025);
isolation: isolate;
}
.caption {
color: var(--soft);
font-size: 13px;
}
.view {
display: none;
}
.view.active {
display: contents;
}
.mark {
display: block;
object-fit: contain;
}
.topline {
display: flex;
align-items: center;
justify-content: space-between;
gap: 10px;
}
.brand {
display: flex;
align-items: center;
min-width: 0;
gap: 10px;
}
.brand-name {
margin: 0;
white-space: nowrap;
}
.orb {
display: grid;
place-items: center;
border-radius: 50%;
flex: 0 0 auto;
}
.orb img {
object-fit: contain;
}
.iconbtn {
display: grid;
place-items: center;
min-width: 34px;
min-height: 34px;
border-radius: 12px;
color: inherit;
}
.status {
display: inline-flex;
align-items: center;
gap: 7px;
width: max-content;
border-radius: 999px;
white-space: nowrap;
font: 700 12px/1 var(--font-ui);
}
.status::before {
content: "";
width: 6px;
height: 6px;
border-radius: 50%;
background: currentColor;
box-shadow: 0 0 10px currentColor;
}
.rec-state .status {
color: var(--bad) !important;
}
.overlay-state .status,
.settings-state .status {
color: var(--brand-hot) !important;
}
.primary {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 9px;
min-height: 50px;
border-radius: 999px;
font-weight: 800;
transition:
transform 120ms var(--ease-out),
filter 200ms var(--ease-out);
}
.primary:active {
transform: scale(0.985);
}
.wave {
display: flex;
align-items: center;
gap: 4px;
}
.wave i {
display: block;
width: 4px;
border-radius: 999px;
background: currentColor;
opacity: 0.82;
transform-origin: center;
animation: wave 880ms var(--ease-toggle) infinite;
animation-delay: calc(var(--i) * -56ms);
}
@keyframes wave {
0%,
100% {
transform: scaleY(0.35);
opacity: 0.42;
}
50% {
transform: scaleY(1.85);
opacity: 1;
}
}
/* 00 faithful clone */
.clone {
--c-fg: #f5f3f0;
--c-muted: rgba(245, 243, 240, 0.5);
--c-soft: rgba(245, 243, 240, 0.72);
--c-accent: #d3a784;
--c-accent-strong: #e9be95;
--c-success: #7fc99c;
--c-danger: #e58a82;
height: 100%;
display: flex;
flex-direction: column;
font-family: "Inter var", "Segoe UI", sans-serif;
font-size: 13px;
background:
radial-gradient(
circle at 12% 0%,
rgba(211, 167, 132, 0.14),
transparent 24rem
),
radial-gradient(
circle at 88% 100%,
rgba(127, 201, 156, 0.06),
transparent 28rem
),
linear-gradient(180deg, #0e0d10 0%, #07070a 100%);
}
.clone .bar {
min-height: 48px;
padding: 7px 8px 6px;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid rgba(255, 255, 255, 0.07);
background: linear-gradient(
180deg,
rgba(34, 31, 38, 0.82),
rgba(12, 11, 15, 0.58)
);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06);
}
.clone .drag {
display: flex;
align-items: center;
gap: 8px;
min-width: 0;
padding-left: 6px;
}
.clone .brand-chip {
display: flex;
align-items: center;
gap: 10px;
padding: 4px 10px 4px 5px;
border-radius: 999px;
border: 1px solid rgba(255, 255, 255, 0.08);
background: rgba(255, 255, 255, 0.035);
}
.clone .orb {
width: 32px;
height: 32px;
background:
radial-gradient(
circle at 36% 28%,
rgba(233, 190, 149, 0.22),
transparent 58%
),
linear-gradient(
180deg,
rgba(255, 255, 255, 0.08),
rgba(255, 255, 255, 0.025)
);
border: 1px solid rgba(233, 190, 149, 0.18);
}
.clone .orb img {
width: 23px;
}
.clone h3 {
margin: 0;
font-size: 0.9rem;
font-weight: 720;
letter-spacing: -0.025em;
}
.clone .ctrls {
display: flex;
gap: 2px;
}
.clone .iconbtn {
min-width: 30px;
min-height: 30px;
border-radius: 8px;
color: rgba(245, 243, 240, 0.72);
}
.clone .main {
flex: 1;
margin: 10px;
padding: 10px;
display: flex;
flex-direction: column;
gap: 10px;
border-radius: 22px;
background: rgba(255, 255, 255, 0.035);
border: 1px solid rgba(255, 255, 255, 0.075);
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.055),
0 18px 52px rgba(0, 0, 0, 0.18);
}
.clone .status {
padding: 3px 10px;
background: rgba(127, 201, 156, 0.18);
color: #7fc99c;
font-size: 0.72rem;
}
.clone.rec-state .status {
background: rgba(229, 138, 130, 0.18);
}
.clone .actions {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 6px;
padding: 8px;
border-radius: 18px;
background: rgba(5, 5, 7, 0.24);
border: 1px solid rgba(255, 255, 255, 0.045);
}
.clone .record {
grid-column: span 2;
min-height: 48px;
border-radius: 14px;
background: linear-gradient(
180deg,
rgba(255, 223, 195, 0.98),
rgba(211, 167, 132, 0.98) 45%,
rgba(174, 118, 82, 0.98)
);
color: #1a1108;
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.38),
0 12px 30px rgba(211, 167, 132, 0.22),
0 2px 0 rgba(0, 0, 0, 0.24);
}
.clone.rec-state .record {
background: linear-gradient(180deg, #e58a82, #c46a64);
color: #1a0606;
}
.clone .mini {
min-height: 34px;
border-radius: 12px;
border: 1px solid rgba(255, 255, 255, 0.08);
background: rgba(255, 255, 255, 0.07);
font-size: 0.74rem;
font-weight: 650;
}
.clone .ghost {
background: rgba(255, 255, 255, 0.025);
color: rgba(245, 243, 240, 0.72);
}
.clone .msg {
margin: 0;
color: rgba(245, 243, 240, 0.5);
font-size: 0.74rem;
}
.clone .more {
display: flex;
gap: 6px;
max-height: 0;
opacity: 0;
overflow: hidden;
}
.clone.text-state .more {
max-height: 80px;
opacity: 1;
}
.clone .editor {
max-height: 0;
opacity: 0;
overflow: hidden;
display: grid;
gap: 6px;
}
.clone.text-state .editor {
max-height: 240px;
opacity: 1;
}
.clone label {
font-size: 0.7rem;
color: rgba(245, 243, 240, 0.72);
text-transform: uppercase;
font-weight: 600;
}
.clone textarea {
height: 146px;
resize: none;
border-radius: 8px;
border: 1px solid rgba(255, 255, 255, 0.08);
background: rgba(14, 13, 16, 0.7);
color: #f5f3f0;
padding: 10px 12px;
line-height: 1.5;
}
.clone .details {
margin-top: 4px;
padding-top: 8px;
border-top: 1px solid rgba(255, 255, 255, 0.08);
}
.clone .details span {
display: inline-flex;
padding: 4px 10px;
border-radius: 999px;
border: 1px solid rgba(255, 255, 255, 0.08);
color: rgba(245, 243, 240, 0.5);
font-size: 0.68rem;
text-transform: uppercase;
letter-spacing: 0.06em;
}
.clone .overlay,
.clone .settings {
display: none;
}
.clone.overlay-state .bar,
.clone.overlay-state .main {
display: none;
}
.clone.overlay-state .overlay {
height: 100%;
display: grid;
grid-template-columns: 54px 1fr 118px;
gap: 14px;
align-items: center;
padding: 13px 18px;
border-radius: 26px;
border: 1px solid rgba(255, 255, 255, 0.14);
background:
radial-gradient(
circle at 16% 18%,
rgba(233, 190, 149, 0.14),
transparent 22rem
),
linear-gradient(180deg, rgba(18, 16, 20, 0.88), rgba(7, 7, 10, 0.92));
}
.clone .overlay .orb {
width: 48px;
height: 48px;
}
.clone .overlay .orb img {
width: 34px;
}
.clone .wave {
height: 48px;
color: #d3a784;
justify-content: center;
}
.clone .wave i {
height: 22px;
}
.clone .ov-copy strong {
font-size: 0.82rem;
text-transform: uppercase;
letter-spacing: 0.08em;
}
.clone .ov-copy small {
display: block;
color: rgba(245, 243, 240, 0.5);
font-size: 0.72rem;
line-height: 1.25;
}
.clone.settings-state .settings {
position: absolute;
inset: 0;
display: grid;
place-items: center;
background: rgba(0, 0, 0, 0.55);
backdrop-filter: blur(18px);
}
.clone .modal {
width: 340px;
border-radius: 16px;
border: 1px solid rgba(255, 255, 255, 0.08);
background: rgba(34, 31, 38, 0.86);
box-shadow: 0 24px 80px rgba(0, 0, 0, 0.45);
overflow: hidden;
}
.clone .modal header,
.clone .modal footer {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 16px;
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
.clone .modal footer {
justify-content: flex-end;
gap: 6px;
border-top: 1px solid rgba(255, 255, 255, 0.08);
border-bottom: 0;
}
.clone .modal-body {
display: grid;
gap: 10px;
padding: 12px 16px;
}
.clone input {
width: 100%;
padding: 8px 10px;
border-radius: 8px;
border: 1px solid rgba(255, 255, 255, 0.08);
background: rgba(14, 13, 16, 0.7);
}
/* 01 Native Command — not the same layout */
.native {
padding: 12px;
font-family: var(--font-ui);
background:
radial-gradient(
circle at 18% 8%,
oklch(77% 0.08 62 / 0.18),
transparent 11rem
),
linear-gradient(180deg, oklch(14% 0.014 62), oklch(8% 0.01 62));
}
.native .topline {
height: 42px;
}
.native .orb {
width: 34px;
height: 34px;
border: 1px solid oklch(85% 0.08 62 / 0.22);
background: linear-gradient(
180deg,
oklch(100% 0 0 / 0.1),
oklch(100% 0 0 / 0.03)
);
}
.native .orb img {
width: 24px;
}
.native .brand-name {
font: 800 16px/1 var(--font-display);
letter-spacing: -0.045em;
}
.native .iconbtn {
color: oklch(80% 0.018 62);
background: oklch(100% 0 0 / 0.045);
}
.native .layout {
height: 394px;
display: grid;
grid-template-rows: 74px 1fr 72px;
gap: 10px;
}
.native .header-card {
padding: 14px;
border-radius: 24px;
border: 1px solid var(--line);
background: oklch(100% 0 0 / 0.05);
display: flex;
justify-content: space-between;
align-items: start;
}
.native .status {
padding: 6px 11px;
color: var(--ok);
background: oklch(72% 0.105 150 / 0.12);
}
.native .header-card small {
display: block;
color: var(--soft);
font: 650 11px/1 var(--font-mono);
text-transform: uppercase;
letter-spacing: 0.1em;
margin-bottom: 6px;
}
.native .header-card b {
display: block;
font: 800 20px/0.96 var(--font-display);
letter-spacing: -0.045em;
max-width: 210px;
}
.native .transcript-sheet {
padding: 18px;
border-radius: 26px;
background: oklch(12% 0.014 62);
border: 1px solid var(--line);
box-shadow: inset 0 1px 0 oklch(100% 0 0 / 0.06);
}
.native .transcript-sheet p {
margin: 0;
color: oklch(86% 0.014 62);
font-size: 17px;
line-height: 1.42;
}
.native .transcript-sheet em {
color: var(--soft);
font-style: normal;
}
.native .dock {
display: grid;
grid-template-columns: 1fr 44px 44px 44px;
gap: 8px;
}
.native .primary {
background: linear-gradient(180deg, var(--brand-hot), var(--brand));
color: oklch(13% 0.018 62);
box-shadow: inset 0 1px 0 oklch(100% 0 0 / 0.42);
}
.native .dock .iconbtn {
min-height: 50px;
border-radius: 18px;
}
/* 02 Island Recorder — overlay-first */
.island {
padding: 14px;
background:
radial-gradient(
circle at 50% 42%,
oklch(78% 0.08 62 / 0.18),
transparent 13rem
),
oklch(8% 0.012 62);
font-family: var(--font-ui);
}
.island .topline {
height: 34px;
opacity: 0.85;
}
.island .brand-name {
font: 800 14px/1 var(--font-display);
letter-spacing: -0.04em;
}
.island .orb {
width: 28px;
height: 28px;
background: oklch(100% 0 0 / 0.07);
border: 1px solid var(--line);
}
.island .orb img {
width: 20px;
}
.island .canvas {
height: 398px;
display: grid;
grid-template-rows: 1fr auto;
align-items: center;
}
.island .focus-orb {
width: 196px;
height: 196px;
margin: 0 auto;
border-radius: 50%;
display: grid;
place-items: center;
position: relative;
background: radial-gradient(
circle,
oklch(100% 0 0 / 0.12),
oklch(100% 0 0 / 0.025)
);
border: 1px solid var(--line-strong);
box-shadow:
0 0 0 18px oklch(75% 0.08 62 / 0.035),
0 34px 90px oklch(0% 0 0 / 0.42),
inset 0 1px 0 oklch(100% 0 0 / 0.1);
}
.island .focus-orb::before,
.island .focus-orb::after {
content: "";
position: absolute;
inset: 28px;
border: 1px solid oklch(85% 0.08 62 / 0.18);
border-radius: 50%;
animation: breathe 2200ms var(--ease-toggle) infinite;
}
.island .focus-orb::after {
inset: -14px;
opacity: 0.35;
animation-delay: -800ms;
}
@keyframes breathe {
50% {
transform: scale(1.08);
opacity: 0.5;
}
}
.island .focus-orb img {
width: 84px;
filter: drop-shadow(0 18px 26px oklch(0% 0 0 / 0.42));
}
.island .callout {
margin-top: 24px;
text-align: center;
}
.island .callout h3 {
margin: 0;
font: 800 35px/0.88 var(--font-display);
letter-spacing: -0.075em;
}
.island .callout p {
margin: 8px auto 0;
color: var(--muted);
max-width: 260px;
line-height: 1.35;
}
.island .bottom-island {
display: grid;
grid-template-columns: 1fr auto;
align-items: center;
gap: 12px;
padding: 10px 10px 10px 16px;
border-radius: 999px;
background: oklch(100% 0 0 / 0.075);
border: 1px solid var(--line);
box-shadow: inset 0 1px 0 oklch(100% 0 0 / 0.08);
}
.island .wave {
color: var(--brand-hot);
height: 36px;
}
.island .wave i {
height: 24px;
}
.island .primary {
min-height: 42px;
padding: 0 18px;
background: var(--ink);
color: oklch(11% 0.012 62);
}
/* 03 Editorial Desk */
.desk {
padding: 12px;
background: oklch(91% 0.022 67);
color: oklch(18% 0.018 62);
font-family: var(--font-ui);
}
.desk .paper {
height: 436px;
display: grid;
grid-template-columns: 56px 1fr;
overflow: hidden;
border-radius: 26px;
border: 1px solid oklch(25% 0.02 62 / 0.14);
background: oklch(96% 0.015 67);
box-shadow: 0 34px 80px oklch(18% 0.018 62 / 0.25);
}
.desk .rail {
padding: 10px 8px;
display: grid;
grid-template-rows: auto 1fr auto;
justify-items: center;
background: oklch(18% 0.018 62);
color: oklch(94% 0.02 67);
}
.desk .rail .orb {
width: 36px;
height: 36px;
background: oklch(94% 0.02 67);
}
.desk .rail .orb img {
width: 26px;
}
.desk .rail .rail-word {
writing-mode: vertical-rl;
transform: rotate(180deg);
font: 700 11px/1 var(--font-mono);
letter-spacing: 0.16em;
color: oklch(94% 0.02 67 / 0.62);
}
.desk .body {
padding: 18px;
display: grid;
grid-template-rows: auto auto 1fr auto;
gap: 14px;
}
.desk .topline .brand-name {
font: 650 20px/1 var(--font-editorial);
letter-spacing: -0.035em;
}
.desk .iconbtn {
min-width: 32px;
min-height: 32px;
color: oklch(18% 0.018 62 / 0.58);
}
.desk .status {
padding: 6px 10px;
color: oklch(38% 0.09 145);
background: oklch(84% 0.09 145 / 0.22);
}
.desk h3 {
margin: 0;
font: 650 29px/0.95 var(--font-editorial);
letter-spacing: -0.05em;
}
.desk textarea {
min-height: 0;
resize: none;
border: 0;
border-radius: 20px;
padding: 16px;
color: oklch(22% 0.018 62);
background: oklch(100% 0 0 / 0.72);
box-shadow: inset 0 0 0 1px oklch(20% 0.02 62 / 0.1);
font-size: 16px;
line-height: 1.52;
}
.desk .desk-actions {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 8px;
}
.desk .desk-actions button {
min-height: 40px;
border-radius: 999px;
color: oklch(18% 0.018 62);
background: oklch(18% 0.018 62 / 0.06);
font-weight: 700;
}
.desk .primary {
background: oklch(18% 0.018 62) !important;
color: oklch(96% 0.015 67) !important;
}
/* 04 Engine Map */
.engine {
padding: 12px;
background:
radial-gradient(
circle at 100% 0%,
oklch(74% 0.1 150 / 0.16),
transparent 14rem
),
oklch(9% 0.012 150);
font-family: var(--font-ui);
}
.engine .grid {
height: 436px;
display: grid;
grid-template-rows: 44px 144px 1fr 54px;
gap: 10px;
}
.engine .brand-name {
font: 800 15px/1 var(--font-display);
letter-spacing: -0.04em;
}
.engine .orb {
width: 34px;
height: 34px;
border: 1px solid oklch(80% 0.08 150 / 0.23);
background: oklch(100% 0 0 / 0.055);
}
.engine .orb img {
width: 24px;
}
.engine .iconbtn {
background: oklch(100% 0 0 / 0.04);
color: oklch(82% 0.035 150);
}
.engine .engine-card {
position: relative;
overflow: hidden;
border-radius: 28px;
padding: 16px;
background: linear-gradient(
135deg,
oklch(74% 0.1 150 / 0.14),
oklch(75% 0.08 62 / 0.08)
);
border: 1px solid var(--line);
}
.engine .engine-card::after {
content: "";
position: absolute;
width: 170px;
height: 170px;
right: -70px;
top: -50px;
border-radius: 50%;
border: 1px solid oklch(82% 0.08 150 / 0.17);
box-shadow: inset 0 0 0 28px oklch(82% 0.08 150 / 0.035);
}
.engine .engine-card small {
font: 750 11px/1 var(--font-mono);
text-transform: uppercase;
letter-spacing: 0.13em;
color: oklch(84% 0.1 150);
}
.engine .engine-card h3 {
margin: 10px 0 0;
max-width: 240px;
font: 800 30px/0.9 var(--font-display);
letter-spacing: -0.07em;
}
.engine .timeline {
display: grid;
gap: 8px;
}
.engine .row {
display: grid;
grid-template-columns: 34px 1fr auto;
align-items: center;
gap: 10px;
padding: 9px;
border-radius: 18px;
background: oklch(100% 0 0 / 0.045);
border: 1px solid oklch(100% 0 0 / 0.075);
}
.engine .row b {
font-size: 14px;
}
.engine .row small {
color: var(--soft);
font-size: 12px;
}
.engine .badge {
font: 750 11px/1 var(--font-mono);
color: oklch(85% 0.1 150);
}
.engine .primary {
background: oklch(80% 0.1 150);
color: oklch(10% 0.014 150);
}
/* 05 Radial HUD */
.hud {
padding: 0;
background:
radial-gradient(
circle at 50% 48%,
oklch(75% 0.08 62 / 0.18),
transparent 15rem
),
linear-gradient(180deg, oklch(12% 0.012 62), oklch(7% 0.012 62));
font-family: var(--font-ui);
}
.hud .topline {
position: absolute;
inset: 14px 14px auto;
z-index: 2;
}
.hud .brand-name {
font: 800 14px/1 var(--font-display);
letter-spacing: -0.04em;
}
.hud .orb {
width: 32px;
height: 32px;
background: oklch(100% 0 0 / 0.06);
border: 1px solid var(--line);
}
.hud .orb img {
width: 23px;
}
.hud .radar {
height: 100%;
display: grid;
place-items: center;
}
.hud .dial {
position: relative;
width: 286px;
height: 286px;
border-radius: 50%;
display: grid;
place-items: center;
border: 1px solid oklch(100% 0 0 / 0.08);
background: radial-gradient(
circle,
oklch(100% 0 0 / 0.06),
transparent 58%
);
}
.hud .dial::before {
content: "";
position: absolute;
inset: 34px;
border-radius: 50%;
border: 1px dashed oklch(85% 0.08 62 / 0.2);
animation: spin 14s cubic-bezier(0.45, 0, 0.55, 1) infinite;
}
.hud .dial::after {
content: "";
position: absolute;
inset: 75px;
border-radius: 50%;
border: 1px solid oklch(85% 0.08 62 / 0.16);
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
.hud .center {
z-index: 1;
width: 142px;
height: 142px;
border-radius: 50%;
display: grid;
place-items: center;
background: oklch(100% 0 0 / 0.08);
border: 1px solid var(--line-strong);
box-shadow:
inset 0 1px 0 oklch(100% 0 0 / 0.1),
0 30px 80px oklch(0% 0 0 / 0.36);
}
.hud .center img {
width: 74px;
}
.hud .node {
position: absolute;
z-index: 2;
width: 78px;
min-height: 42px;
border-radius: 999px;
display: grid;
place-items: center;
padding: 0 12px;
background: oklch(100% 0 0 / 0.075);
border: 1px solid var(--line);
font-weight: 750;
font-size: 12px;
}
.hud .node:nth-child(2) {
top: 16px;
}
.hud .node:nth-child(3) {
right: -8px;
top: 120px;
}
.hud .node:nth-child(4) {
bottom: 16px;
}
.hud .node:nth-child(5) {
left: -8px;
top: 120px;
}
.hud .bottom {
position: absolute;
left: 16px;
right: 16px;
bottom: 16px;
display: grid;
grid-template-columns: 1fr auto;
gap: 10px;
align-items: center;
}
.hud .status {
padding: 7px 12px;
color: var(--brand-hot);
background: oklch(100% 0 0 / 0.055);
border: 1px solid var(--line);
}
.hud .primary {
min-height: 44px;
padding: 0 18px;
background: var(--brand-hot);
color: oklch(12% 0.012 62);
}
/* 06 Stack Flow */
.stack {
padding: 14px;
background: linear-gradient(
155deg,
oklch(12% 0.012 62),
oklch(8% 0.014 62)
);
font-family: var(--font-ui);
}
.stack .brand-name {
font: 800 15px/1 var(--font-display);
letter-spacing: -0.04em;
}
.stack .orb {
width: 34px;
height: 34px;
background: oklch(100% 0 0 / 0.055);
border: 1px solid var(--line);
}
.stack .orb img {
width: 24px;
}
.stack .deck {
position: relative;
height: 394px;
margin-top: 12px;
}
.stack .pane {
position: absolute;
border-radius: 28px;
border: 1px solid var(--line);
box-shadow:
0 22px 60px oklch(0% 0 0 / 0.34),
inset 0 1px 0 oklch(100% 0 0 / 0.08);
}
.stack .pane.one {
inset: 0 18px 118px 0;
padding: 18px;
background: oklch(18% 0.014 62);
transform: rotate(-1.7deg);
}
.stack .pane.two {
inset: 122px 0 46px 42px;
padding: 16px;
background: oklch(22% 0.016 62);
transform: rotate(1.4deg);
}
.stack .pane.three {
left: 14px;
right: 26px;
bottom: 0;
height: 74px;
display: grid;
grid-template-columns: 1fr auto;
gap: 10px;
align-items: center;
padding: 12px;
background: oklch(15% 0.014 62);
}
.stack .pane h3 {
margin: 0;
font: 800 31px/0.9 var(--font-display);
letter-spacing: -0.07em;
max-width: 230px;
}
.stack .pane p {
color: var(--muted);
line-height: 1.42;
margin: 10px 0 0;
max-width: 250px;
}
.stack textarea {
width: 100%;
height: 100%;
resize: none;
border: 0;
background: transparent;
color: var(--ink);
line-height: 1.5;
}
.stack .primary {
min-height: 46px;
padding: 0 18px;
background: linear-gradient(180deg, var(--brand-hot), var(--brand));
color: oklch(11% 0.012 62);
}
.stack .quick {
display: flex;
gap: 6px;
color: var(--muted);
font-size: 12px;
}
.stack .quick span {
padding: 6px 9px;
border-radius: 999px;
background: oklch(100% 0 0 / 0.055);
}
.settings-state:not(.clone) .settings-preview {
display: grid !important;
}
.settings-preview {
position: absolute;
inset: 0;
display: none;
place-items: center;
background: oklch(0% 0 0 / 0.52);
backdrop-filter: blur(18px);
z-index: 4;
}
.settings-preview .sheet {
width: 326px;
padding: 16px;
border-radius: 26px;
border: 1px solid var(--line);
background: var(--panel-2);
box-shadow: 0 26px 80px oklch(0% 0 0 / 0.52);
}
.settings-preview h4 {
margin: 0 0 12px;
font: 800 20px/1 var(--font-display);
letter-spacing: -0.04em;
}
.settings-preview label {
display: grid;
gap: 5px;
margin: 10px 0;
color: var(--muted);
font-size: 12px;
}
.settings-preview input {
min-height: 38px;
border: 1px solid var(--line);
border-radius: 12px;
background: oklch(0% 0 0 / 0.2);
padding: 0 10px;
}
.global-overlay {
position: absolute;
inset: 0;
display: none;
place-items: center;
padding: 18px;
background: oklch(0% 0 0 / 0.58);
backdrop-filter: blur(20px);
z-index: 5;
}
.overlay-state:not(.clone) .global-overlay {
display: grid;
}
.global-overlay-card {
width: 100%;
min-height: 132px;
border-radius: 30px;
border: 1px solid var(--line-strong);
background:
radial-gradient(
circle at 20% 18%,
oklch(85% 0.08 62 / 0.18),
transparent 14rem
),
linear-gradient(
180deg,
oklch(18% 0.016 62 / 0.94),
oklch(10% 0.012 62 / 0.96)
);
box-shadow:
0 26px 90px oklch(0% 0 0 / 0.58),
inset 0 1px 0 oklch(100% 0 0 / 0.1);
padding: 16px;
display: grid;
grid-template-columns: 52px 1fr;
gap: 14px;
align-items: center;
}
.global-overlay-card .orb {
width: 52px;
height: 52px;
background: oklch(100% 0 0 / 0.08);
border: 1px solid var(--line-strong);
}
.global-overlay-card .orb img {
width: 36px;
}
.global-overlay-card strong {
display: block;
font: 800 15px/1 var(--font-display);
letter-spacing: -0.025em;
}
.global-overlay-card small {
display: block;
margin-top: 5px;
color: var(--muted);
line-height: 1.25;
}
.global-overlay-card .wave {
grid-column: 1 / -1;
height: 34px;
color: var(--brand-hot);
justify-content: center;
}
@media (max-width: 980px) {
.masthead,
.workspace {
grid-template-columns: 1fr;
}
.preview-zone {
position: static;
}
.frame-wrap {
width: 100%;
}
.controls {
grid-template-columns: 1fr;
}
.score-grid {
grid-template-columns: 1fr;
}
}
@media (max-width: 520px) {
.shell {
width: min(100vw - 20px, 1480px);
padding-top: 20px;
}
.frame-wrap {
border-radius: 28px;
min-height: 500px;
}
.app-frame {
transform: scale(0.92);
}
h1 {
font-size: 42px;
}
}
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
</style>
</head>
<body>
<svg
aria-hidden="true"
style="position: absolute; width: 0; height: 0; overflow: hidden"
>
<symbol id="settings" viewBox="0 0 24 24">
<path d="M12 15.5a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7Z" />
<path
d="M19.2 14.7c.1.4.4.8.8 1l.2.1a2 2 0 0 1-2 3.5l-.2-.1a1.9 1.9 0 0 0-1.3-.2 1.9 1.9 0 0 0-1 .8l-.1.2a2 2 0 0 1-3.5-2v-.2a1.9 1.9 0 0 0-.5-1.2 1.9 1.9 0 0 0-1.2-.5h-.3a2 2 0 0 1 0-4h.3a1.9 1.9 0 0 0 1.2-.5 1.9 1.9 0 0 0 .5-1.2v-.3a2 2 0 0 1 3.5-2l.1.2c.2.4.6.7 1 .8.4.1.9 0 1.3-.2l.2-.1a2 2 0 0 1 2 3.5l-.2.1a1.9 1.9 0 0 0-.8 1c-.1.4-.1.9 0 1.3Z"
/>
</symbol>
<symbol id="x" viewBox="0 0 24 24">
<path d="M18 6 6 18M6 6l12 12" />
</symbol>
<symbol id="minus" viewBox="0 0 24 24"><path d="M5 12h14" /></symbol>
<symbol id="mic" viewBox="0 0 24 24">
<path
d="M12 3.5a3.2 3.2 0 0 0-3.2 3.2v5.6a3.2 3.2 0 0 0 6.4 0V6.7A3.2 3.2 0 0 0 12 3.5Z"
/>
<path d="M19 11.2v1a7 7 0 0 1-14 0v-1M12 19.2V22" />
</symbol>
<symbol id="copy" viewBox="0 0 24 24">
<rect x="8" y="8" width="12" height="12" rx="2.4" />
<path d="M4 15.5V5.8A1.8 1.8 0 0 1 5.8 4h9.7" />
</symbol>
<symbol id="arrow" viewBox="0 0 24 24">
<path d="M5 12h13M13 6l6 6-6 6" />
</symbol>
<symbol id="save" viewBox="0 0 24 24">
<path d="M5 4h11l3 3v13H5Z" />
<path d="M8 4v6h8M8 20v-7h8v7" />
</symbol>
<symbol id="trash" viewBox="0 0 24 24">
<path d="M4 6h16M9 6V4h6v2M18 6l-1 14H7L6 6" />
</symbol>
</svg>
<main class="shell" id="page">
<section class="masthead">
<div>
<div class="kicker">Redesign v2 · Impeccable pass</div>
<h1>
Agora são direções diferentes, não seis skins do mesmo layout.
</h1>
<p class="lead">
O clone fiel continua como baseline. As outras seis propostas foram
reconstruídas em torno de modelos mentais diferentes: comando
nativo, ilha de ditado, mesa editorial, motor local, HUD radial e
pilha física de estados.
</p>
</div>
<aside class="critique-box">
<strong>Correção aplicada:</strong> as variações anteriores
reaproveitavam a mesma composição. Esta versão força diferenças reais
em estrutura, densidade, tipografia, interação e prioridade de
informação, mantendo o logo/mark do aplicativo.
</aside>
</section>
<nav class="controls" aria-label="Exploração de design">
<div class="tabs" role="tablist">
<button
class="tab"
role="tab"
data-target="clone"
aria-selected="true"
>
00 Clone atual
</button>
<button
class="tab"
role="tab"
data-target="native"
aria-selected="false"
>
01 Native Command
</button>
<button
class="tab"
role="tab"
data-target="island"
aria-selected="false"
>
02 Dictation Island
</button>
<button
class="tab"
role="tab"
data-target="desk"
aria-selected="false"
>
03 Editorial Desk
</button>
<button
class="tab"
role="tab"
data-target="engine"
aria-selected="false"
>
04 Local Engine
</button>
<button
class="tab"
role="tab"
data-target="hud"
aria-selected="false"
>
05 Radial HUD
</button>
<button
class="tab"
role="tab"
data-target="stack"
aria-selected="false"
>
06 Stack Flow
</button>
</div>
<div class="states" aria-label="Estados">
<button class="state" data-state="idle">Pronto</button>
<button class="state" data-state="rec">Gravando</button>
<button class="state active" data-state="text">Com texto</button>
<button class="state" data-state="overlay">Overlay</button>
<button class="state" data-state="settings">Config</button>
</div>
</nav>
<section class="workspace">
<article class="brief" id="brief"></article>
<aside class="preview-zone">
<div class="frame-wrap"><div class="app-frame" id="frame"></div></div>
<div class="caption" id="caption">Baseline atual fiel</div>
</aside>
</section>
</main>
<script>
const mark = "../assets/brand/mark.png";
const icon = (id) => `<svg class="icon"><use href="#${id}"></use></svg>`;
const wave = (n = 12) =>
Array.from(
{ length: n },
(_, i) => `<i style="--i:${i};height:${12 + ((i * 17) % 30)}px"></i>`,
).join("");
const settingsPreview = `<section class="settings-preview"><div class="sheet"><h4>Configurações</h4><label>Modelo local<input value="Whisper Base multilingual"></label><label>Atalho global<input value="Ctrl+Shift+Space"></label><label>Fallback API<input value="http://localhost:8022/v1/audio/transcriptions"></label></div></section>`;
const overlayPreview = `<section class="global-overlay"><div class="global-overlay-card"><span class="orb"><img src="${mark}" alt=""></span><div><strong>Ouvindo no app ativo</strong><small>Pressione o atalho novamente para transcrever e inserir.</small></div><div class="wave">${wave(14)}</div></div></section>`;
const stateOverlays = settingsPreview + overlayPreview;
const briefs = {
clone: {
title: "00 · Clone atual fiel.",
intent:
"Baseline preservado para comparação: topbar frameless, botão âmbar, painel translúcido, editor expansível, configurações e overlay conforme o design atual.",
scores: [
"Fidelidade visual ao CSS atual",
"Útil como referência, não como proposta nova",
"Mantém o comportamento compacto 380×460",
"Ponto de comparação para avaliar as outras direções",
],
caption: "Baseline atual fiel",
},
native: {
title: "01 · Native Command.",
intent:
"Direção recomendada para produção: parece um utilitário nativo caro, com hierarquia clara, área de transcrição confortável e dock de ações que não compete com o botão principal.",
scores: [
"Melhor equilíbrio entre novidade e baixo risco",
"Fluxo principal fica legível em 3 zonas",
"Mais premium sem virar peça decorativa",
"Boa base para implementar direto no app atual",
],
caption: "Recomendação: evolução premium segura",
},
island: {
title: "02 · Dictation Island.",
intent:
"O app vira uma experiência de ditado primeiro. A gravação é um objeto central e memorável, com barra inferior para parar/inserir. Ideal se o hotkey global for o principal uso.",
scores: [
"Mais original e memorável",
"Estado de gravação fica impossível de perder",
"Ótima direção para overlay e marketing",
"Menos eficiente para edição longa de texto",
],
caption: "Experiência focada em ditado global",
},
desk: {
title: "03 · Editorial Desk.",
intent:
"Uma opção clara, editorial e orientada a revisão. Ela trata a transcrição como rascunho/documento, não como painel técnico. Boa para textos mais longos.",
scores: [
"Melhor leitura e revisão",
"Diferencia o app dos dark UIs de AI",
"Contraste diurno e aparência de ferramenta autoral",
"Mudança visual maior em relação ao app atual",
],
caption: "Modo editorial claro para revisar texto",
},
engine: {
title: "04 · Local Engine.",
intent:
"Comunica o diferencial offline/local sem virar um cockpit confuso. Mostra modelo, etapas e prontidão do motor de transcrição.",
scores: [
"Excelente para explicar sem Docker/API",
"Reduz incerteza sobre modo local vs API",
"Bom para onboarding e settings",
"Mais informativo; exige controle de densidade",
],
caption: "Offline/local como proposta de valor",
},
hud: {
title: "05 · Radial HUD.",
intent:
"Direção experimental e muito distinta: a interface organiza ações ao redor da marca, como um instrumento de áudio. Não é segura, mas é a mais memorável.",
scores: [
"Mais distinta das seis",
"Forte personalidade visual",
"Boa para modo gravação/overlay",
"Risco alto para uso diário se exagerar",
],
caption: "Instrumento radial de ditado",
},
stack: {
title: "06 · Stack Flow.",
intent:
"Organiza gravação, texto e ações como camadas físicas. Dá sensação de profundidade e deixa estados simultâneos visíveis sem repetir cards iguais.",
scores: [
"Layout realmente diferente do baseline",
"Boa metáfora de estados empilhados",
"Mantém editor e ações acessíveis",
"Precisa de implementação cuidadosa para não parecer torto",
],
caption: "Estados como camadas físicas",
},
};
const templates = {
clone: () =>
`<div class="clone view-root"><header class="bar"><div class="drag"><button class="iconbtn">${icon("settings")}</button><div class="brand-chip"><span class="orb"><img src="${mark}" alt=""></span><h3>Transcript</h3></div></div><div class="ctrls"><button class="iconbtn">${icon("minus")}</button><button class="iconbtn">${icon("x")}</button></div></header><section class="main"><span class="status">Pronto</span><div class="actions"><button class="primary record">${icon("mic")}<span class="record-label">Gravar</span><small>Ctrl+Shift+Space</small></button><button class="mini">${icon("copy")}Copiar</button><button class="mini">${icon("arrow")}Inserir</button><button class="mini ghost">${icon("save")}Salvar</button><button class="mini ghost">${icon("trash")}Limpar</button><p class="msg">Transcrição local concluída.</p><div class="more"><button class="mini">Continuar</button><button class="mini ghost">Regravar</button><button class="mini ghost">Expandir</button></div></div><div class="editor"><label>Texto transcrito</label><textarea>Esta é uma prévia do texto transcrito. O campo expande somente quando há conteúdo.</textarea></div><div class="details"><span>› Detalhes</span></div></section><section class="overlay"><span class="orb"><img src="${mark}" alt=""></span><div class="wave">${wave(12)}</div><div class="ov-copy"><strong>Ouvindo</strong><small>Pressione o atalho de novo para inserir</small></div></section><section class="settings"><div class="modal"><header><h3>Configurações</h3><button class="iconbtn">${icon("x")}</button></header><div class="modal-body"><input value="http://localhost:8022/v1/audio/transcriptions"><input value="Whisper Base multilingual"><input value="Ctrl+Shift+Space"></div><footer><button class="mini ghost">Cancelar</button><button class="mini">Salvar</button></footer></div></section></div>`,
native: () =>
`<div class="native view-root"><header class="topline"><div class="brand"><span class="orb"><img src="${mark}" alt=""></span><h3 class="brand-name">Transcript</h3></div><div><button class="iconbtn">${icon("settings")}</button><button class="iconbtn">${icon("x")}</button></div></header><main class="layout"><section class="header-card"><div><small>Whisper local</small><b>Pronto para ditar em qualquer app.</b></div><span class="status">Pronto</span></section><section class="transcript-sheet"><p>“Organiza essa nota como um parágrafo curto e cola no documento atual.” <em>O texto fica editável antes de inserir.</em></p></section><section class="dock"><button class="primary">${icon("mic")}<span class="record-label">Gravar</span></button><button class="iconbtn">${icon("copy")}</button><button class="iconbtn">${icon("arrow")}</button><button class="iconbtn">${icon("trash")}</button></section></main>${stateOverlays}</div>`,
island: () =>
`<div class="island view-root"><header class="topline"><div class="brand"><span class="orb"><img src="${mark}" alt=""></span><h3 class="brand-name">Transcript</h3></div><button class="iconbtn">${icon("settings")}</button></header><main class="canvas"><section><span class="status">Pronto</span><div class="focus-orb"><img src="${mark}" alt=""></div><div class="callout"><h3>Fale agora.</h3><p>O app escuta, transcreve localmente e insere no foco anterior.</p></div></section><section class="bottom-island"><div class="wave">${wave(14)}</div><button class="primary"><span class="record-label">Parar</span></button></section></main>${stateOverlays}</div>`,
desk: () =>
`<div class="desk view-root"><section class="paper"><aside class="rail"><span class="orb"><img src="${mark}" alt=""></span><span class="rail-word">TRANSCRIPT</span><button>${icon("settings")}</button></aside><main class="body"><header class="topline"><h3 class="brand-name">Rascunho de voz</h3><button class="iconbtn">${icon("x")}</button></header><span class="status">Texto pronto</span><h3>Uma fala curta, pronta para revisar.</h3><textarea>Esta direção trata a transcrição como escrita. O foco fica em ler, ajustar e inserir com confiança.</textarea><div class="desk-actions"><button class="primary">${icon("mic")}Gravar</button><button>Copiar</button><button>Inserir</button></div></main></section>${stateOverlays}</div>`,
engine: () =>
`<div class="engine view-root"><main class="grid"><header class="topline"><div class="brand"><span class="orb"><img src="${mark}" alt=""></span><h3 class="brand-name">Transcript</h3></div><button class="iconbtn">${icon("settings")}</button></header><section class="engine-card"><span class="status">Pronto</span><br><small>Motor local ativo</small><h3>Whisper Base rodando no computador.</h3></section><section class="timeline"><div class="row"><span>${icon("mic")}</span><div><b>Captura</b><br><small>WAV local finalizado</small></div><span class="badge">ok</span></div><div class="row"><span>${icon("settings")}</span><div><b>Modelo</b><br><small>Base multilingual · PT-BR</small></div><span class="badge">local</span></div><div class="row"><span>${icon("arrow")}</span><div><b>Inserção</b><br><small>Clipboard + Ctrl+V</small></div><span class="badge">armado</span></div></section><button class="primary">${icon("mic")}<span class="record-label">Gravar localmente</span></button></main>${stateOverlays}</div>`,
hud: () =>
`<div class="hud view-root"><header class="topline"><div class="brand"><span class="orb"><img src="${mark}" alt=""></span><h3 class="brand-name">Transcript</h3></div><button class="iconbtn">${icon("settings")}</button></header><main class="radar"><section class="dial"><span class="center"><img src="${mark}" alt=""></span><span class="node">Copiar</span><span class="node">Inserir</span><span class="node">Salvar</span><span class="node">Limpar</span></section></main><footer class="bottom"><span class="status">Ouvindo</span><button class="primary"><span class="record-label">Parar</span></button></footer>${stateOverlays}</div>`,
stack: () =>
`<div class="stack view-root"><header class="topline"><div class="brand"><span class="orb"><img src="${mark}" alt=""></span><h3 class="brand-name">Transcript</h3></div><button class="iconbtn">${icon("settings")}</button></header><main class="deck"><section class="pane one"><span class="status">Pronto</span><h3>Grave, revise, insira.</h3><p>Três estados visíveis como camadas, sem prender tudo em uma grade igual.</p></section><section class="pane two"><textarea>Texto transcrito aparece como uma folha sobre a mesa, pronto para copiar ou continuar.</textarea></section><section class="pane three"><div class="quick"><span>Copiar</span><span>Inserir</span><span>Salvar</span></div><button class="primary">${icon("mic")}<span class="record-label">Gravar</span></button></section></main>${stateOverlays}</div>`,
};
const frame = document.querySelector("#frame");
const brief = document.querySelector("#brief");
const caption = document.querySelector("#caption");
const tabs = [...document.querySelectorAll(".tab")];
const states = [...document.querySelectorAll(".state")];
let current = "clone";
let state = "text";
function renderBrief(id) {
const b = briefs[id];
const title = document.createElement("h2");
title.textContent = b.title;
const intent = document.createElement("p");
intent.textContent = b.intent;
const grid = document.createElement("div");
grid.className = "score-grid";
b.scores.forEach((score, index) => {
const item = document.createElement("div");
item.className = "score";
const label = document.createElement("b");
label.textContent = `Critério ${index + 1}`;
const copy = document.createElement("span");
copy.textContent = score;
item.append(label, copy);
grid.append(item);
});
brief.replaceChildren(title, intent, grid);
caption.textContent = b.caption;
}
function trustedFragment(markup) {
const parsed = new DOMParser().parseFromString(markup, "text/html");
const fragment = document.createDocumentFragment();
fragment.append(...parsed.body.childNodes);
return fragment;
}
function applyState() {
const root = frame.querySelector(".view-root");
if (!root) return;
root.classList.remove(
"idle-state",
"rec-state",
"text-state",
"overlay-state",
"settings-state",
);
root.classList.add(`${state}-state`);
const labels = {
idle: "Gravar",
rec: "Parar",
text: "Gravar",
overlay: "Transcrevendo",
settings: "Gravar",
};
root
.querySelectorAll(".record-label")
.forEach((el) => (el.textContent = labels[state]));
root
.querySelectorAll(".status")
.forEach(
(el) =>
(el.lastChild.textContent =
state === "rec"
? "Gravando"
: state === "overlay"
? "Transcrevendo"
: "Pronto"),
);
}
function render(id) {
current = id;
frame.replaceChildren(trustedFragment(templates[id]()));
renderBrief(id);
tabs.forEach((t) =>
t.setAttribute("aria-selected", String(t.dataset.target === id)),
);
applyState();
}
tabs.forEach((tab) =>
tab.addEventListener("click", () => render(tab.dataset.target)),
);
states.forEach((btn) =>
btn.addEventListener("click", () => {
state = btn.dataset.state;
states.forEach((b) => b.classList.toggle("active", b === btn));
applyState();
}),
);
render("clone");
</script>
</body>
</html>