Tasks 5-7: eval harness, FastAPI backend, Paper & Ink UI- src/eval/ β precision/recall/F1 harness with type-aware comparators,micro/macro F1, CSV + markdown reports, --model benchmark flag- src/api/ β FastAPI backend with /extract, /schemas, /health,request-ID middleware, typed error envelope, injectable extractor- ui/ β Vite + React + TS + Tailwind + Motion + React Three FiberPaper & Ink editorial UI with 3D paper hero, dark/light mode,confidence inkwell, wax-stamp metrics, kinetic typography- 95 passing tests (up from 54); UI is a separate npm workspace
557ab38 | @tailwind base; | |
| @tailwind components; | |
| @tailwind utilities; | |
| @import "./theme.css"; | |
| /* ---- Base ---------------------------------------------------------------- */ | |
| *, | |
| *::before, | |
| *::after { | |
| box-sizing: border-box; | |
| } | |
| html, | |
| body, | |
| #root { | |
| height: 100%; | |
| } | |
| html { | |
| -webkit-font-smoothing: antialiased; | |
| -moz-osx-font-smoothing: grayscale; | |
| text-rendering: optimizeLegibility; | |
| } | |
| body { | |
| margin: 0; | |
| background: var(--bg); | |
| color: var(--ink); | |
| font-family: "Geist", system-ui, sans-serif; | |
| font-weight: 400; | |
| font-feature-settings: "ss01", "ss02", "cv11"; | |
| transition: background 500ms cubic-bezier(0.16, 1, 0.3, 1), | |
| color 500ms cubic-bezier(0.16, 1, 0.3, 1); | |
| } | |
| ::selection { | |
| background: var(--accent); | |
| color: var(--surface); | |
| } | |
| /* Editorial paper grain β the whole point of the aesthetic. Overlaid on the | |
| entire document at low opacity. Uses SVG feTurbulence for zero-request grain. */ | |
| body::before { | |
| content: ""; | |
| position: fixed; | |
| inset: 0; | |
| pointer-events: none; | |
| z-index: 100; | |
| opacity: var(--grain); | |
| mix-blend-mode: multiply; | |
| background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='240' height='240'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' seed='7'/><feColorMatrix values='0 0 0 0 0.06 0 0 0 0 0.12 0 0 0 0 0.23 0 0 0 1 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>"); | |
| background-size: 240px 240px; | |
| } | |
| [data-theme="dark"] body::before { | |
| mix-blend-mode: screen; | |
| background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='240' height='240'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' seed='11'/><feColorMatrix values='0 0 0 0 0.93 0 0 0 0 0.88 0 0 0 0 0.78 0 0 0 0.8 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>"); | |
| } | |
| /* ---- Type utilities ----------------------------------------------------- */ | |
| .font-display { | |
| font-family: "Instrument Serif", serif; | |
| font-weight: 400; | |
| letter-spacing: -0.015em; | |
| line-height: 0.92; | |
| } | |
| .font-display-italic { | |
| font-family: "Instrument Serif", serif; | |
| font-style: italic; | |
| font-weight: 400; | |
| letter-spacing: -0.02em; | |
| line-height: 0.92; | |
| } | |
| .font-mono { | |
| font-family: "JetBrains Mono", ui-monospace, monospace; | |
| font-feature-settings: "calt", "liga", "ss01"; | |
| } | |
| /* Small caps + tracking for section labels β the "chapter marker" of the site */ | |
| .eyebrow { | |
| font-family: "Geist", system-ui, sans-serif; | |
| font-size: 11px; | |
| font-weight: 500; | |
| letter-spacing: 0.18em; | |
| text-transform: uppercase; | |
| color: var(--ink-mute); | |
| } | |
| /* ---- Focus rings β replaced with editorial underline ------------------- */ | |
| :focus-visible { | |
| outline: 2px solid var(--focus); | |
| outline-offset: 3px; | |
| border-radius: 2px; | |
| } | |
| /* Hide the default focus on decorative elements */ | |
| button:focus, | |
| a:focus { | |
| outline: none; | |
| } | |
| button:focus-visible, | |
| a:focus-visible { | |
| outline: 2px solid var(--focus); | |
| outline-offset: 3px; | |
| } | |
| /* ---- Custom cursor β soft ink dot on interactive elements -------------- */ | |
| .cursor-ink { | |
| cursor: none; | |
| } | |
| /* ---- Scrollbar --------------------------------------------------------- */ | |
| ::-webkit-scrollbar { | |
| width: 10px; | |
| height: 10px; | |
| } | |
| ::-webkit-scrollbar-track { | |
| background: transparent; | |
| } | |
| ::-webkit-scrollbar-thumb { | |
| background: var(--rule); | |
| border-radius: 6px; | |
| } | |
| ::-webkit-scrollbar-thumb:hover { | |
| background: var(--ink-mute); | |
| } | |
| /* ---- Motion β respect user preference ---------------------------------- */ | |
| @media (prefers-reduced-motion: reduce) { | |
| *, | |
| *::before, | |
| *::after { | |
| animation-duration: 0.001ms ; | |
| animation-iteration-count: 1 ; | |
| transition-duration: 0.001ms ; | |
| } | |
| } | |