/* TitleVerifi — Mark explorations v2
Three marks, one shape language: rectilinear + one curved accent.
Each hides a T in the geometry. Each animates through the same six
product states as the canonical "Nodes" mark.
Exports (to window):
MarkFolio — Folio seal: corner peeled to reveal T inside
MarkVolume — Volume & page: two offset rects, T in the gap
MarkSection — Section corner: a true T with one boundary-arc
Common API (all three):
size?: number px
color?: string primary stroke / fill
accent?: string one-curve accent color (vermilion by default)
animate?: boolean
state?: 'idle' | 'processing' | 'connecting' | 'resolving' | 'complete' | 'error'
*/
if (typeof document !== 'undefined' && !document.getElementById('tv-mark-v2-anim')) {
const s = document.createElement('style');
s.id = 'tv-mark-v2-anim';
s.textContent = `
/* ---- shared keyframes for all three v2 marks ---- */
@keyframes m2-arc-pulse {
0%, 100% { stroke-opacity: 0.55; }
50% { stroke-opacity: 1; }
}
@keyframes m2-arc-trace {
0% { stroke-dashoffset: var(--m2-arc-len, 40); }
60% { stroke-dashoffset: 0; }
100% { stroke-dashoffset: 0; }
}
@keyframes m2-stem-grow {
0% { transform: scaleY(0); }
100% { transform: scaleY(1); }
}
@keyframes m2-spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
@keyframes m2-bloom {
0% { transform: scale(0.4); opacity: 0.9; }
100% { transform: scale(2.6); opacity: 0; }
}
@keyframes m2-error-shake {
0%, 100% { transform: translateX(0); }
20%, 60% { transform: translateX(-0.6px); }
40%, 80% { transform: translateX(0.6px); }
}
@keyframes m2-scan-row {
0%, 100% { transform: translateY(0); opacity: 0; }
20%, 80% { opacity: 0.8; }
50% { transform: translateY(14px); }
}
@keyframes m2-page-lift {
0%, 100% { transform: translate(0, 0); }
50% { transform: translate(0.6px, -0.6px); }
}
@keyframes m2-arc-rotate-segment {
0% { stroke-dasharray: 0 80; }
50% { stroke-dasharray: 24 80; }
100% { stroke-dasharray: 0 80; stroke-dashoffset: -80; }
}
`;
document.head.appendChild(s);
}
/* ============================================================
MARK A — FOLIO SEAL
A square plate. Top-right corner peeled back along a curved
accent, revealing a thin T inside. Reads as "officially recorded,
opened for inspection."
============================================================ */
const MarkFolio = ({
size = 32, color = 'currentColor', accent = 'var(--accent)',
animate = true, state = 'idle',
}) => {
const eff = animate ? state : 'static';
const c = eff === 'idle' ? 4.5 : 2.4;
return (
);
};
/* ============================================================
MARK B — VOLUME & PAGE
Two rectangles offset like a bound volume with a page lifted
forward. The vertical gutter of the front page is the T-stem;
its top edge is the T-bar. A small curved tab (bookmark) hangs
from the top — the single curved accent.
============================================================ */
const MarkVolume = ({
size = 32, color = 'currentColor', accent = 'var(--accent)',
animate = true, state = 'idle',
}) => {
const eff = animate ? state : 'static';
const c = eff === 'idle' ? 4.5 : 2.4;
return (
);
};
/* ============================================================
MARK C — SECTION CORNER
A true T with one boundary-arc closing the lower-right quadrant —
the way a surveyor caps a section corner. The vertical is the
T-stem; the horizontal is the T-bar; the arc is the single curved
accent. Most legible at small sizes.
============================================================ */
const MarkSection = ({
size = 32, color = 'currentColor', accent = 'var(--accent)',
animate = true, state = 'idle',
}) => {
const eff = animate ? state : 'static';
const c = eff === 'idle' ? 4.5 : 2.4;
// Arc from (24, 8) sweeping down to (16, 24) — a quarter ellipse.
const arcPath = "M 24 8 A 16 16 0 0 1 16 24";
const ARC_LEN = 25;
return (
);
};
Object.assign(window, { MarkFolio, MarkVolume, MarkSection });