@import "tailwindcss"; @import "tw-animate-css"; @import "shadcn/tailwind.css"; @import "@fontsource-variable/noto-sans"; @import "@fontsource-variable/playfair-display"; @custom-variant dark (&:is(.dark *)); :root { --background: oklch(1 0 0); --foreground: oklch(0.147 0.004 49.3); --card: oklch(1 0 0); --card-foreground: oklch(0.147 0.004 49.3); --popover: oklch(1 0 0); --popover-foreground: oklch(0.147 0.004 49.3); --primary: oklch(0.214 0.009 43.1); --primary-foreground: oklch(0.986 0.002 67.8); --secondary: oklch(0.96 0.002 17.2); --secondary-foreground: oklch(0.214 0.009 43.1); --muted: oklch(0.96 0.002 17.2); --muted-foreground: oklch(0.547 0.021 43.1); --accent: oklch(0.96 0.002 17.2); --accent-foreground: oklch(0.214 0.009 43.1); --destructive: oklch(0.577 0.245 27.325); --border: oklch(0.922 0.005 34.3); --input: oklch(0.922 0.005 34.3); --ring: oklch(0.714 0.014 41.2); --chart-1: oklch(0.868 0.007 39.5); --chart-2: oklch(0.547 0.021 43.1); --chart-3: oklch(0.438 0.017 39.3); --chart-4: oklch(0.367 0.016 35.7); --chart-5: oklch(0.268 0.011 36.5); --radius: 0.625rem; --sidebar: oklch(0.986 0.002 67.8); --sidebar-foreground: oklch(0.147 0.004 49.3); --sidebar-primary: oklch(0.214 0.009 43.1); --sidebar-primary-foreground: oklch(0.986 0.002 67.8); --sidebar-accent: oklch(0.96 0.002 17.2); --sidebar-accent-foreground: oklch(0.214 0.009 43.1); --sidebar-border: oklch(0.922 0.005 34.3); --sidebar-ring: oklch(0.714 0.014 41.2); } .dark { --background: oklch(0.147 0.004 49.3); --foreground: oklch(0.986 0.002 67.8); --card: oklch(0.214 0.009 43.1); --card-foreground: oklch(0.986 0.002 67.8); --popover: oklch(0.214 0.009 43.1); --popover-foreground: oklch(0.986 0.002 67.8); --primary: oklch(0.922 0.005 34.3); --primary-foreground: oklch(0.214 0.009 43.1); --secondary: oklch(0.268 0.011 36.5); --secondary-foreground: oklch(0.986 0.002 67.8); --muted: oklch(0.268 0.011 36.5); --muted-foreground: oklch(0.714 0.014 41.2); --accent: oklch(0.268 0.011 36.5); --accent-foreground: oklch(0.986 0.002 67.8); --destructive: oklch(0.704 0.191 22.216); --border: oklch(1 0 0 / 10%); --input: oklch(1 0 0 / 15%); --ring: oklch(0.547 0.021 43.1); --chart-1: oklch(0.868 0.007 39.5); --chart-2: oklch(0.547 0.021 43.1); --chart-3: oklch(0.438 0.017 39.3); --chart-4: oklch(0.367 0.016 35.7); --chart-5: oklch(0.268 0.011 36.5); --sidebar: oklch(0.214 0.009 43.1); --sidebar-foreground: oklch(0.986 0.002 67.8); --sidebar-primary: oklch(0.488 0.243 264.376); --sidebar-primary-foreground: oklch(0.986 0.002 67.8); --sidebar-accent: oklch(0.268 0.011 36.5); --sidebar-accent-foreground: oklch(0.986 0.002 67.8); --sidebar-border: oklch(1 0 0 / 10%); --sidebar-ring: oklch(0.547 0.021 43.1); } @theme inline { --font-sans: "Noto Sans Variable", sans-serif; --font-heading: "Playfair Display Variable", serif; --color-sidebar-ring: var(--sidebar-ring); --color-sidebar-border: var(--sidebar-border); --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); --color-sidebar-accent: var(--sidebar-accent); --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); --color-sidebar-primary: var(--sidebar-primary); --color-sidebar-foreground: var(--sidebar-foreground); --color-sidebar: var(--sidebar); --color-chart-5: var(--chart-5); --color-chart-4: var(--chart-4); --color-chart-3: var(--chart-3); --color-chart-2: var(--chart-2); --color-chart-1: var(--chart-1); --color-ring: var(--ring); --color-input: var(--input); --color-border: var(--border); --color-destructive: var(--destructive); --color-accent-foreground: var(--accent-foreground); --color-accent: var(--accent); --color-muted-foreground: var(--muted-foreground); --color-muted: var(--muted); --color-secondary-foreground: var(--secondary-foreground); --color-secondary: var(--secondary); --color-primary-foreground: var(--primary-foreground); --color-primary: var(--primary); --color-popover-foreground: var(--popover-foreground); --color-popover: var(--popover); --color-card-foreground: var(--card-foreground); --color-card: var(--card); --color-foreground: var(--foreground); --color-background: var(--background); --radius-sm: calc(var(--radius) * 0.6); --radius-md: calc(var(--radius) * 0.8); --radius-lg: var(--radius); --radius-xl: calc(var(--radius) * 1.4); --radius-2xl: calc(var(--radius) * 1.8); --radius-3xl: calc(var(--radius) * 2.2); --radius-4xl: calc(var(--radius) * 2.6); } @layer base { * { @apply border-border outline-ring/50; } body { @apply bg-background text-foreground; } html { @apply font-sans; } } /* * lekterion — editorial / critical-edition typography. * Warm paper ground + warm ink, a narrow justified measure, Playfair Display * for the apparatus and marginalia over the polytonic-capable Noto Sans body. */ :root { --paper: oklch(0.986 0.007 83); --paper-raised: oklch(0.998 0.004 83); --ink: oklch(0.247 0.012 55); --ink-soft: oklch(0.46 0.018 50); --ink-faint: oklch(0.62 0.02 50); --rule: oklch(0.86 0.012 60); --accent-ink: oklch(0.49 0.1 38); --selection: oklch(0.9 0.066 75); /* Where a jump target comes to rest, clear of the sticky running head. Footnote returns land deeper (20% down) so the referring line is in view; locus + heading/TOC jumps land higher (10% down) to maximize reading space. */ --jump-offset: 20vh; --jump-offset-nav: 10vh; } .dark { --paper: oklch(0.168 0.006 58); --paper-raised: oklch(0.205 0.008 55); --ink: oklch(0.9 0.01 80); --ink-soft: oklch(0.74 0.014 70); --ink-faint: oklch(0.58 0.014 65); --rule: oklch(0.34 0.01 55); --accent-ink: oklch(0.78 0.09 55); --selection: oklch(0.42 0.06 60); } @layer components { /* ---- shared shells ------------------------------------------------ */ .lib-shell, .reader-shell { min-height: 100svh; background: var(--paper); color: var(--ink); } /* ---- library index ------------------------------------------------ */ .lib-shell { display: flex; flex-direction: column; } .lib-column { flex: 1; width: 100%; max-width: 46rem; margin-inline: auto; padding: clamp(2.5rem, 6vw, 5.5rem) 1.5rem 4rem; } .lib-masthead { margin-bottom: 3.5rem; } .lib-kicker { font-size: 0.72rem; letter-spacing: 0.22em; text-transform: uppercase; color: var(--ink-faint); margin-bottom: 0.9rem; } .lib-wordmark { font-family: var(--font-heading); font-style: italic; font-weight: 600; font-size: clamp(3rem, 9vw, 4.75rem); line-height: 0.95; letter-spacing: -0.01em; color: var(--ink); } .lib-tagline { margin-top: 1.1rem; max-width: 34rem; color: var(--ink-soft); font-size: 1.02rem; line-height: 1.6; } .lib-grid { display: flex; flex-direction: column; gap: 2.75rem; } .lib-author { border-top: 1px solid var(--rule); padding-top: 1.5rem; } .lib-author-head { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; margin-bottom: 1.1rem; } .lib-author-name { font-family: var(--font-heading); font-weight: 600; font-size: 1.65rem; color: var(--ink); } .lib-author-meta { font-size: 0.72rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-faint); white-space: nowrap; } .lib-work { margin-top: 1.25rem; } .lib-work-title { font-family: var(--font-heading); font-style: italic; font-size: 1.05rem; color: var(--ink-soft); margin-bottom: 0.35rem; } .lib-text-list { list-style: none; margin: 0; padding: 0; } .lib-text-row { display: flex; align-items: baseline; gap: 0.6rem; padding: 0.32rem 0.4rem; margin-inline: -0.4rem; border-radius: var(--radius-sm); color: var(--ink); text-decoration: none; transition: background-color 120ms ease, color 120ms ease; } .lib-text-row:hover { background: var(--paper-raised); color: var(--accent-ink); } .lib-text-title { font-variant-numeric: oldstyle-nums; } .lib-leader { flex: 1 1 auto; align-self: stretch; margin-bottom: 0.35em; border-bottom: 1px dotted var(--rule); } .lib-text-scheme { font-size: 0.72rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-faint); white-space: nowrap; } .lib-footer { border-top: 1px solid var(--rule); padding: 1.1rem 1.5rem; text-align: center; font-size: 0.72rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-faint); } /* ---- reader: running head ----------------------------------------- */ .reader-head { position: sticky; top: 0; z-index: 20; backdrop-filter: blur(8px); background: color-mix(in oklab, var(--paper) 82%, transparent); border-bottom: 1px solid var(--rule); } .reader-head-inner { max-width: 76rem; margin-inline: auto; height: 3.25rem; padding-inline: 1.25rem; display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 1rem; } .reader-head-left { display: flex; align-items: center; gap: 0.85rem; justify-self: start; min-width: 0; } .reader-head-right { display: flex; align-items: center; gap: 0.85rem; justify-self: end; } .reader-citation { font-family: var(--font-heading); font-size: 1rem; color: var(--ink); white-space: nowrap; font-variant-numeric: tabular-nums oldstyle-nums; } .reader-head-action { display: inline-flex; align-items: center; gap: 0.4rem; font-size: 0.82rem; color: var(--ink-soft); padding: 0.3rem 0.55rem; border-radius: var(--radius-sm); cursor: pointer; transition: background-color 120ms ease, color 120ms ease; } .reader-head-action:hover { background: var(--paper-raised); color: var(--accent-ink); } .reader-head-back { display: inline-flex; align-items: center; gap: 0.4rem; font-size: 0.82rem; color: var(--ink-soft); text-decoration: none; transition: color 120ms ease; } .reader-head-back:hover { color: var(--accent-ink); } .reader-head-meta { display: inline-flex; align-items: center; gap: 0.6rem; font-size: 0.72rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-faint); } .reader-head-dot { width: 3px; height: 3px; border-radius: 9999px; background: var(--ink-faint); } /* ---- reader: column + prose --------------------------------------- */ .reader-main { padding: clamp(2.25rem, 5vw, 4.5rem) 1.5rem 6rem; } .reader-column { max-width: 38rem; margin-inline: auto; } .reading { color: var(--ink); font-size: 1.155rem; line-height: 1.82; text-rendering: optimizeLegibility; font-feature-settings: "liga" 1, "calt" 1; hanging-punctuation: first allow-end; /* Tap-to-word drives our own menu (§9): suppress iOS's duplicate callout and the grey tap flash, but keep text selectable so drag-to-quote still works. */ -webkit-touch-callout: none; -webkit-tap-highlight-color: transparent; } .reading ::selection { background: var(--selection); } .reader-para { margin: 0; text-align: justify; text-justify: inter-word; hyphens: auto; } .reader-para + .reader-para { text-indent: 1.5em; } .reader-para + .reader-heading, .reader-heading + .reader-para { text-indent: 0; } /* A drop-cap paragraph is never first-line indented — even when it follows another paragraph (e.g. the lead lands after a non-letter epigraph). */ .reader-para.reader-lead { text-indent: 0; display: flow-root; /* contain the floated cap so it can't bleed into the next block */ } .reader-lead::first-letter { float: left; font-family: var(--font-heading), var(--font-sans), serif; font-weight: 600; font-size: 3.1em; line-height: 0.82; padding-right: 0.08em; margin-top: 0.06em; color: var(--accent-ink); } .reading em { font-style: italic; } /* ---- reader: headings --------------------------------------------- */ .reader-heading { font-family: var(--font-heading); color: var(--ink); text-wrap: balance; scroll-margin-top: var(--jump-offset-nav); line-height: 1.2; } .reader-heading[data-heading-level="2"] { font-size: 1.7rem; font-weight: 600; margin: 2.75rem 0 1.1rem; } .reader-heading[data-heading-level="3"] { font-size: 1.24rem; font-weight: 600; margin: 2.1rem 0 0.85rem; } .reader-heading[data-heading-level="4"] { font-size: 1.02rem; font-weight: 600; font-style: italic; color: var(--ink-soft); margin: 1.6rem 0 0.7rem; } .reader-column > .reading > .reader-heading:first-child { margin-top: 0; } /* ---- reader: locus anchors (invisible) ---------------------------- */ .reader-anchor { display: inline; width: 0; scroll-margin-top: var(--jump-offset-nav); } /* ---- reader: footnotes -------------------------------------------- */ .reader-fnref { font-size: 0.66em; line-height: 0; vertical-align: super; } .reader-fnref a { color: var(--accent-ink); text-decoration: none; padding-inline: 0.12em; scroll-margin-top: var(--jump-offset); } .reader-fnref a:hover { text-decoration: underline; } .reader-apparatus { margin-top: 3.5rem; } .reader-apparatus-rule { width: 8rem; margin: 0 0 1.4rem; border: 0; border-top: 1px solid var(--rule); } .reader-footnotes { list-style: none; margin: 0; padding: 0; font-size: 0.92rem; line-height: 1.6; color: var(--ink-soft); } .reader-footnote { display: flex; gap: 0.7rem; margin-bottom: 0.7rem; scroll-margin-top: var(--jump-offset); } .reader-footnote-back { flex: none; min-width: 1.4rem; text-align: right; font-variant-numeric: tabular-nums; color: var(--accent-ink); text-decoration: none; } .reader-footnote-back:hover { text-decoration: underline; } .reader-footnote-body em { font-style: italic; } /* ---- reader: work navigation (§2 prev/next + contents) ------------ */ .worknav { margin-top: 4rem; padding-top: 1.75rem; border-top: 1px solid var(--rule); } .worknav-pager { display: flex; justify-content: space-between; gap: 1rem; } .worknav-step { display: inline-flex; align-items: center; gap: 0.55rem; max-width: 46%; padding: 0.5rem 0.7rem; border-radius: var(--radius-sm); color: var(--ink-soft); text-decoration: none; transition: background-color 120ms ease, color 120ms ease; } .worknav-step.is-empty { visibility: hidden; } .worknav-next { text-align: end; } .worknav-step:hover { background: var(--paper-raised); color: var(--accent-ink); } .worknav-step svg { flex: none; color: var(--ink-faint); } .worknav-step:hover svg { color: var(--accent-ink); } .worknav-step-text { display: flex; flex-direction: column; min-width: 0; } .worknav-dir { font-size: 0.66rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink-faint); } .worknav-step-title { font-family: var(--font-heading); font-size: 0.96rem; color: inherit; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .worknav-contents { margin-top: 2rem; } .worknav-contents-head { font-size: 0.68rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink-faint); margin-bottom: 0.85rem; } .worknav-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr)); gap: 0.1rem 1.5rem; list-style: none; counter-reset: none; } .worknav-item { display: flex; align-items: baseline; gap: 0.65rem; padding: 0.32rem 0.5rem; border-radius: var(--radius-sm); color: var(--ink-soft); text-decoration: none; transition: background-color 120ms ease, color 120ms ease; } a.worknav-item:hover { background: var(--paper-raised); color: var(--accent-ink); } .worknav-item.is-current { color: var(--accent-ink); font-weight: 600; } .worknav-num { flex: none; width: 1.4rem; font-size: 0.74rem; text-align: end; color: var(--ink-faint); font-variant-numeric: tabular-nums; } .worknav-item.is-current .worknav-num { color: var(--accent-ink); } .worknav-item-title { min-width: 0; } /* ---- reader: notices (loading / error) ---------------------------- */ .reader-notice-kicker { font-size: 0.72rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--ink-faint); margin-bottom: 0.6rem; } .reader-notice-title { font-family: var(--font-heading); font-size: 1.6rem; color: var(--ink); margin-bottom: 0.6rem; } .reader-notice-body { color: var(--ink-soft); line-height: 1.6; } .reader-notice-link { display: inline-flex; align-items: center; gap: 0.4rem; margin-top: 1.4rem; color: var(--accent-ink); text-decoration: none; } .reader-notice-link:hover { text-decoration: underline; } /* ---- reader: §2 layout (TOC | column | rail) ---------------------- */ .reader-layout { max-width: 76rem; margin-inline: auto; } .reader-aside { display: none; position: sticky; top: 3.25rem; align-self: start; max-height: calc(100svh - 3.25rem); overflow-y: auto; overscroll-behavior: contain; padding-block: 2.5rem 1.5rem; } .reader-toc-trigger { display: inline-flex; } /* collapsible desktop contents sidebar */ .reader-aside-head { display: none; /* only meaningful in the ≥1280 sidebar */ align-items: center; justify-content: space-between; gap: 0.5rem; margin-bottom: 0.85rem; } .reader-aside-title { font-size: 0.68rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--ink-faint); } .reader-aside-collapse { display: inline-flex; padding: 0.25rem; border-radius: var(--radius-sm); color: var(--ink-faint); cursor: pointer; transition: color 120ms ease, background-color 120ms ease; } .reader-aside-collapse:hover { color: var(--accent-ink); background: var(--paper-raised); } .reader-toc-expand { display: none; /* shown only when ≥1280 + collapsed */ position: fixed; left: 0; top: 4rem; z-index: 18; align-items: center; gap: 0.4rem; padding: 0.5rem 0.7rem; font-size: 0.66rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink-soft); background: var(--paper-raised); border: 1px solid var(--rule); border-left: none; border-radius: 0 var(--radius-md) var(--radius-md) 0; box-shadow: 2px 2px 14px -10px rgb(0 0 0 / 0.5); cursor: pointer; transition: color 120ms ease, background-color 120ms ease; } .reader-toc-expand:hover { color: var(--accent-ink); background: var(--paper); } @media (min-width: 1280px) { .reader-layout { display: grid; grid-template-columns: 15rem minmax(0, 1fr); column-gap: 1.5rem; } .reader-aside { display: block; } .reader-toc-trigger { display: none; } .reader-aside-head { display: flex; } /* contents collapsed → drop the TOC column, surface the edge tab. Give the reading column real side gutters so it never hugs the left edge (esp. with the side panel open, where the freed width is otherwise all on the left). */ .reader-shell.toc-collapsed .reader-layout { grid-template-columns: minmax(0, 1fr); } .reader-shell.toc-collapsed .reader-main { padding-inline: clamp(2rem, 7vw, 5rem); } .reader-shell.toc-collapsed .reader-aside-toc { display: none; } .reader-shell.toc-collapsed .reader-toc-expand { display: inline-flex; } } /* Running head: the secondary action row (Facsimile · Artifact · Markdown · account) collapses into the ⋯ overflow menu below this breakpoint so the bar stays legible on a phone (§2). Back · Contents · citation · Go to stay. */ .reader-head-inline { display: contents; } .reader-head-overflow { display: none; } @media (max-width: 768px) { .reader-head-inner { padding-inline: 0.85rem; gap: 0.5rem; } .reader-head-left { gap: 0.5rem; } .reader-head-right { gap: 0.2rem; } .reader-head-meta, .reader-head-inline { display: none; } .reader-head-overflow { display: inline-flex; } /* icon-only for the controls that stay in the bar */ .reader-head-back span, .reader-head-action span { display: none; } .reader-head-action { padding: 0.35rem; } .reader-citation { font-size: 0.92rem; min-width: 0; overflow: hidden; text-overflow: ellipsis; } } /* ---- reader: §4/§12 side panel (facsimile | artifact) ------------- */ .side-panel { position: fixed; top: 3.25rem; right: 0; bottom: 0; width: 100vw; max-width: 32rem; z-index: 15; display: flex; flex-direction: column; background: var(--paper-raised); border-left: 1px solid var(--rule); box-shadow: -8px 0 24px -16px rgb(0 0 0 / 0.4); } .side-panel-resize { display: none; } @media (min-width: 1280px) { /* Offset only the reading body for the side panel — the header stays full-width across the top of the panel (not resized when it opens). */ .reader-shell.has-panel .reader-body { padding-right: var(--panel-w, clamp(20rem, 30vw, 32rem)); } .side-panel { width: var(--panel-w, clamp(20rem, 30vw, 32rem)); max-width: 80vw; } .side-panel-resize { display: block; position: absolute; left: 0; top: 0; bottom: 0; width: 8px; cursor: ew-resize; touch-action: none; } .side-panel-resize::after { content: ""; position: absolute; left: 3px; top: 0; bottom: 0; width: 2px; background: transparent; transition: background-color 120ms ease; } .side-panel-resize:hover::after { background: var(--accent-ink); } } body.is-resizing { cursor: ew-resize; user-select: none; } .side-panel-head { flex: none; display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; padding: 0.5rem 0.75rem; border-bottom: 1px solid var(--rule); } .side-panel-head-right { display: inline-flex; align-items: center; gap: 0.5rem; } .facsimile-zoom { display: inline-flex; align-items: center; gap: 0.1rem; border: 1px solid var(--rule); border-radius: var(--radius-sm); padding: 0.1rem; } .facsimile-zoom-btn { display: inline-flex; padding: 0.2rem; border-radius: calc(var(--radius-sm) - 1px); color: var(--ink-soft); cursor: pointer; } .facsimile-zoom-btn:hover:not(:disabled) { background: var(--paper); color: var(--accent-ink); } .facsimile-zoom-btn:disabled { opacity: 0.4; cursor: default; } .facsimile-zoom-level { min-width: 3rem; font-size: 0.72rem; font-variant-numeric: tabular-nums; color: var(--ink-soft); cursor: pointer; } .facsimile-zoom-level:hover { color: var(--accent-ink); } .side-panel-title { display: inline-flex; align-items: center; gap: 0.4rem; font-size: 0.72rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-faint); } .side-panel-tabs { display: inline-flex; gap: 0.25rem; } .side-panel-tab { display: inline-flex; align-items: center; gap: 0.35rem; font-size: 0.78rem; padding: 0.25rem 0.55rem; border-radius: var(--radius-sm); color: var(--ink-soft); cursor: pointer; } .side-panel-tab.is-active { background: var(--paper); color: var(--accent-ink); } .side-panel-close { display: inline-flex; padding: 0.25rem; border-radius: var(--radius-sm); color: var(--ink-soft); cursor: pointer; } .side-panel-close:hover { background: var(--paper); color: var(--accent-ink); } .side-panel-body { flex: 1; min-height: 0; display: flex; flex-direction: column; overflow: hidden; } .side-pane-scroll { flex: 1; min-height: 0; overflow: auto; overscroll-behavior: contain; padding: 1rem; } /* back-to-list link above a single artifact in the pane (§12) */ .artifact-back { display: inline-flex; align-items: center; gap: 0.2rem; margin-bottom: 0.6rem; padding: 0.2rem 0.4rem 0.2rem 0.2rem; border-radius: var(--radius-sm); font-size: 0.78rem; color: var(--ink-faint); cursor: pointer; transition: color 120ms ease, background-color 120ms ease; } .artifact-back:hover { color: var(--accent-ink); background: var(--paper); } .facsimile-viewport { flex: 1; min-height: 0; overflow: auto; overscroll-behavior: contain; padding: 0.75rem; cursor: grab; } .facsimile-viewport.is-panning { cursor: grabbing; } .facsimile-figure { margin: 0; } .facsimile-img, .facsimile-canvas { display: block; width: 100%; /* Override Tailwind preflight's `img { max-width: 100% }`, which otherwise caps the image at the pane width and makes zoom a no-op. */ max-width: none; height: auto; border-radius: var(--radius-sm); border: 1px solid var(--rule); background: #fff; } .facsimile-canvas[data-ready="false"] { display: none; } .facsimile-caption { margin-top: 0.5rem; text-align: center; font-size: 0.75rem; color: var(--ink-faint); font-variant-numeric: tabular-nums; } .facsimile-pdf { min-height: 6rem; } .facsimile-status { display: flex; align-items: center; gap: 0.4rem; padding: 1rem 0; font-size: 0.85rem; color: var(--ink-soft); } /* artifact pane (§12) */ .artifact { display: flex; flex-direction: column; gap: 0.85rem; } .artifact-citation { font-family: var(--font-heading); font-size: 0.85rem; color: var(--ink-soft); font-variant-numeric: tabular-nums oldstyle-nums; } .artifact-section { display: flex; flex-direction: column; gap: 0.35rem; padding-bottom: 0.85rem; border-bottom: 1px solid var(--rule); } /* artifacts-by-locus right-click list (§12) */ .locus-menu { display: flex; flex-direction: column; min-width: 14rem; max-width: 22rem; } .locus-empty { font-size: 0.85rem; color: var(--ink-soft); padding: 0.4rem 0.2rem; } .locus-item { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; padding: 0.4rem 0.5rem; border-radius: var(--radius-sm); cursor: pointer; text-align: start; } .locus-item:hover { background: var(--paper); } .locus-quote { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 0.9rem; color: var(--ink); } .locus-badges { flex: none; display: inline-flex; gap: 0.3rem; color: var(--ink-faint); } /* ---- reader: table of contents ------------------------------------ */ .toc-heading { font-size: 0.68rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink-faint); margin-bottom: 0.75rem; padding-inline-start: 0.5rem; } .toc-list { list-style: none; margin: 0; padding: 0; } .toc-row { display: flex; align-items: flex-start; gap: 0.1rem; } .toc-caret { flex: none; margin-top: 0.34rem; color: var(--ink-faint); cursor: pointer; } .toc-caret svg { transition: transform 150ms ease; } .toc-caret[data-state="open"] svg { transform: rotate(90deg); } .toc-link { width: 100%; text-align: start; font-size: 0.84rem; line-height: 1.35; color: var(--ink-soft); padding: 0.28rem 0.4rem; border-radius: var(--radius-sm); cursor: pointer; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; transition: background-color 120ms ease, color 120ms ease; } .toc-link:hover { color: var(--accent-ink); background: var(--paper-raised); } .toc-active { color: var(--ink); font-weight: 600; } /* ---- reader: browse bar (§2, perseus-style minimap) --------------- */ /* Nav jumps (loci / headings) and the scroll tracker must clear the sticky header (3.25rem) + this bar, whose height is published as --browse-bar-h. */ .reader-shell { --jump-offset-nav: calc(3.25rem + var(--browse-bar-h, 0px) + 0.85rem); } .browse-bar { position: sticky; top: 3.25rem; z-index: 12; max-width: 76rem; margin-inline: auto; padding: 0.5rem 1.25rem 0.6rem; display: flex; flex-direction: column; gap: 0.3rem; background: color-mix(in oklab, var(--paper) 85%, transparent); backdrop-filter: blur(8px); border-bottom: 1px solid var(--rule); } .browse-readout { margin: 0 0 0.1rem; min-height: 1rem; font-size: 0.68rem; letter-spacing: 0.02em; color: var(--ink-faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .browse-readout-strong { color: var(--accent-ink); font-weight: 600; } .browse-tier { display: grid; grid-template-columns: 4.8rem minmax(0, 1fr); align-items: center; gap: 0.6rem; } .browse-tier-label { font-size: 0.6rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-faint); text-align: right; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .browse-track { display: flex; height: 0.85rem; border-radius: var(--radius-sm); overflow: hidden; } .browse-seg { flex: 0 1 0; min-width: 2px; height: 100%; border: 0; padding: 0; cursor: pointer; background: color-mix(in oklab, var(--ink) 13%, var(--paper)); transition: background-color 100ms ease; } .browse-seg.is-odd { background: color-mix(in oklab, var(--ink) 22%, var(--paper)); } .browse-seg:hover { background: color-mix(in oklab, var(--accent-ink) 45%, var(--paper)); } .browse-seg.is-active { background: var(--accent-ink); } /* ---- reader: Go To ------------------------------------------------- */ .reader-goto-label { font-size: 0.68rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-faint); } .reader-goto-error { margin-top: 0.45rem; font-size: 0.78rem; color: var(--destructive); } /* ---- reader: selection menu (§9) ---------------------------------- */ .sel-pop { width: auto; padding: 0; gap: 0; } .sel-pop-actions { min-width: 18rem; max-width: 27rem; } .sel-pop-gloss { width: 24rem; max-width: 92vw; max-height: var(--radix-popover-content-available-height); overflow-y: auto; overscroll-behavior: contain; } .sel-menu { display: flex; flex-direction: column; padding: 0.3rem; } .sel-item { display: flex; align-items: center; gap: 0.6rem; width: 100%; padding: 0.5rem 0.6rem; border-radius: var(--radius-sm); font-size: 0.86rem; color: var(--ink); cursor: pointer; text-align: start; transition: background-color 110ms ease, color 110ms ease; } .sel-item:hover:not(:disabled), .sel-item:focus-visible:not(:disabled) { background: var(--paper-raised); color: var(--accent-ink); outline: none; } .sel-item:disabled { color: var(--ink-faint); cursor: not-allowed; opacity: 0.65; } .sel-item svg { flex: none; color: var(--ink-faint); } .sel-item:hover:not(:disabled) svg { color: var(--accent-ink); } .sel-item-label { flex: 1 1 auto; } .sel-item-key { flex: none; font-size: 0.7rem; letter-spacing: 0.04em; color: var(--ink-faint); font-variant-numeric: tabular-nums; } .sel-sep { height: 1px; margin: 0.3rem 0.4rem; background: var(--rule); } /* arg-max translation hint, below Read aloud (§5+). A single word sits inline (Welt → world); a long phrase wraps so the translation drops to its own full-width line instead of collapsing into a one-word-per-line column. */ .sel-xlate { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.25rem 0.45rem; margin: 0.35rem 0.3rem 0.1rem; padding: 0.6rem 0.6rem 0.35rem; border-top: 1px solid var(--rule); font-size: 0.92rem; line-height: 1.4; } .sel-xlate-lang { flex: none; font-size: 0.78rem; font-style: italic; color: var(--accent-ink); } .sel-xlate-word { flex: 0 1 auto; min-width: 0; color: var(--ink-soft); } .sel-xlate-arrow { flex: none; color: var(--ink-faint); } .sel-xlate-value { flex: 1 1 auto; min-width: 0; color: var(--ink); } .sel-xlate-count { flex: none; font-size: 0.68rem; color: var(--ink-faint); font-variant-numeric: tabular-nums; } /* engagement gate — match the word to reveal the consensus gloss (§13) */ .sel-gate { margin: 0.35rem 0.3rem 0.1rem; padding: 0.6rem 0.6rem 0.5rem; border-top: 1px solid var(--rule); } .sel-gate-prompt { font-size: 0.76rem; color: var(--ink-faint); margin-bottom: 0.45rem; } .sel-gate-options { display: flex; flex-wrap: wrap; gap: 0.4rem; } .sel-gate-chip { padding: 0.3rem 0.55rem; border: 1px solid var(--rule); border-radius: var(--radius-sm); font-size: 0.9rem; color: var(--ink); cursor: pointer; /* Each chip fades up on mount — and again on every reshuffle, since the new round re-keys them into fresh elements (§13). */ animation: wd-fade-up 0.34s cubic-bezier(0.34, 1.56, 0.64, 1) both; transition: background-color 110ms ease, color 110ms ease, border-color 110ms ease; } .sel-gate-chip:hover:not(:disabled), .sel-gate-chip:focus-visible:not(:disabled) { background: var(--paper-raised); color: var(--accent-ink); border-color: var(--accent-ink); outline: none; } /* Wrong pick: shake the row (light first, harder on repeats), then fade it out before the fresh set fades back in — sara-drawer style (§13). */ .sel-gate-options.shake-light { animation: wd-shake-light 0.5s ease; } .sel-gate-options.shake-hard { animation: wd-shake-hard 0.5s ease; } .sel-gate-options.is-fading { opacity: 0; transition: opacity 0.26s ease; } @keyframes wd-shake-light { 0%, 100% { transform: translateX(0); } 15% { transform: translateX(-6px); } 30% { transform: translateX(6px); } 45% { transform: translateX(-4px); } 60% { transform: translateX(4px); } 75% { transform: translateX(-2px); } 90% { transform: translateX(2px); } } @keyframes wd-shake-hard { 0%, 100% { transform: translateX(0) rotate(0deg); } 12% { transform: translateX(-10px) rotate(-1deg); } 25% { transform: translateX(10px) rotate(1deg); } 37% { transform: translateX(-8px) rotate(-1deg); } 50% { transform: translateX(8px) rotate(1deg); } 62% { transform: translateX(-5px) rotate(0deg); } 75% { transform: translateX(5px) rotate(0deg); } 87% { transform: translateX(-2px) rotate(0deg); } } @keyframes wd-fade-up { 0% { opacity: 0; transform: translateY(10px); } 100% { opacity: 1; transform: translateY(0); } } @media (prefers-reduced-motion: reduce) { .sel-gate-chip, .sel-gate-options.shake-light, .sel-gate-options.shake-hard { animation: none; } } /* ---- reader: gloss / translate / read-aloud popover (§5/§10) ------ */ .gloss { display: flex; flex-direction: column; gap: 0.6rem; padding: 0.85rem 1rem 0.95rem; } .gloss-head { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; } .gloss-tabs { display: flex; gap: 0.1rem; margin-inline-start: -0.25rem; } .gloss-tab { display: inline-flex; align-items: center; gap: 0.3rem; padding: 0.25rem 0.45rem; border-radius: var(--radius-sm); font-size: 0.74rem; color: var(--ink-faint); cursor: pointer; transition: background-color 110ms ease, color 110ms ease; } .gloss-tab svg { color: currentColor; } .gloss-tab > span { display: none; } .gloss-tab.is-active > span { display: inline; } .gloss-tab:hover:not(.is-active) { color: var(--ink-soft); } .gloss-tab.is-active { background: var(--paper-raised); color: var(--accent-ink); } .gloss-citation { font-family: var(--font-heading); font-size: 0.82rem; color: var(--ink-soft); font-variant-numeric: tabular-nums oldstyle-nums; white-space: nowrap; } .gloss-quote { font-size: 1.05rem; line-height: 1.5; color: var(--ink); } .gloss-body { display: flex; flex-direction: column; gap: 0.4rem; min-height: 1.6rem; } .gloss-result-row { display: flex; align-items: start; justify-content: space-between; gap: 0.5rem; } .gloss-result { font-size: 0.92rem; line-height: 1.55; color: var(--ink); } .gloss-copy { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 1.6rem; height: 1.6rem; margin-top: -0.1rem; border-radius: var(--radius-sm); color: var(--ink-faint); cursor: pointer; transition: background-color 110ms ease, color 110ms ease; } .gloss-copy:hover { background: var(--paper-raised); color: var(--accent-ink); } .gloss-literal { font-size: 0.84rem; line-height: 1.7; font-style: italic; color: var(--ink-soft); } .gloss-tok { border-bottom: 1px dotted var(--ink-faint); cursor: help; outline: none; transition: color 110ms ease, border-color 110ms ease; } .gloss-tok:hover, .gloss-tok:focus-visible { color: var(--accent-ink); border-bottom-color: var(--accent-ink); } .gloss-tip { font-size: 0.9rem; font-style: normal; } .gloss-pos { font-size: 0.72rem; letter-spacing: 0.04em; text-transform: uppercase; color: var(--ink-faint); } .gloss-status { display: inline-flex; align-items: center; gap: 0.45rem; font-size: 0.84rem; color: var(--ink-soft); } .gloss-error { display: flex; flex-direction: column; align-items: start; gap: 0.4rem; font-size: 0.82rem; color: var(--destructive); } .gloss-error-line { font-size: 0.78rem; color: var(--destructive); } .gloss-retry { padding: 0.25rem 0.6rem; border: 1px solid var(--rule); border-radius: var(--radius-sm); font-size: 0.8rem; color: var(--ink); cursor: pointer; } .gloss-retry:hover { background: var(--paper-raised); color: var(--accent-ink); } .gloss-tts { display: inline-flex; align-items: center; gap: 0.45rem; align-self: start; padding: 0.4rem 0.7rem; border: 1px solid var(--rule); border-radius: var(--radius-sm); font-size: 0.84rem; color: var(--ink-soft); cursor: pointer; transition: background-color 110ms ease, color 110ms ease; } .gloss-tts:hover:not(:disabled) { background: var(--paper-raised); color: var(--accent-ink); } .gloss-tts[data-state="playing"] { border-color: var(--accent-ink); color: var(--accent-ink); } .gloss-tts:disabled { cursor: default; } .gloss-pending { font-size: 0.78rem; line-height: 1.5; color: var(--ink-faint); } .gloss-key-row { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; } .gloss-key { font-size: 0.68rem; letter-spacing: 0.06em; color: var(--ink-faint); font-variant-numeric: tabular-nums; } .gloss-sharelink { display: inline-flex; align-items: center; gap: 0.3rem; font-size: 0.7rem; color: var(--ink-soft); padding: 0.15rem 0.35rem; border-radius: var(--radius-sm); cursor: pointer; } .gloss-sharelink:hover { color: var(--accent-ink); background: var(--paper-raised); } .gloss-xlate { margin-top: 0.5rem; font-size: 0.92rem; color: var(--ink); } .gloss-xlate-label { font-size: 0.62rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-faint); margin-inline-end: 0.4rem; } .gloss-xlate-consensus { color: var(--ink-soft); } .gloss-xlate-note { display: block; margin-top: 0.15rem; font-size: 0.68rem; color: var(--ink-faint); } /* ---- reader: §7 correction editor --------------------------------- */ .correction { display: flex; flex-direction: column; gap: 0.6rem; min-width: 16rem; } .correction-head { font-size: 0.7rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-faint); } .correction-before { font-size: 0.95rem; color: var(--ink-soft); text-decoration: line-through; text-decoration-color: var(--ink-faint); } .correction-input { width: 100%; resize: vertical; font: inherit; font-size: 0.95rem; color: var(--ink); background: var(--paper); border: 1px solid var(--rule); border-radius: var(--radius-sm); padding: 0.45rem 0.55rem; } .correction-input:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: 1px; } .correction-actions { display: flex; justify-content: flex-end; gap: 0.5rem; } .correction-cancel, .correction-save { display: inline-flex; align-items: center; gap: 0.35rem; font-size: 0.82rem; padding: 0.3rem 0.7rem; border-radius: var(--radius-sm); cursor: pointer; } .correction-cancel { color: var(--ink-soft); } .correction-cancel:hover { color: var(--accent-ink); } .correction-save { background: var(--accent-ink); color: var(--paper); } .correction-save:disabled { opacity: 0.5; cursor: default; } }