Spaces:
Paused
Paused
| /* Codebook tray. | |
| Right-edge toggle below Notes (Notes 42%, Codebook 62%); panel | |
| slides from the right. Consumes the memos design-system tokens | |
| directly (loaded first) so the three sidebars never drift; literal | |
| fallbacks keep this file self-contained. Vanilla CSS, no build. */ | |
| :root { | |
| --cb-space-1: var(--memo-space-1, 4px); | |
| --cb-space-2: var(--memo-space-2, 8px); | |
| --cb-space-3: var(--memo-space-3, 12px); | |
| --cb-space-4: var(--memo-space-4, 16px); | |
| --cb-space-5: var(--memo-space-5, 24px); | |
| --cb-radius: var(--memo-radius, 8px); | |
| --cb-ink: var(--memo-ink, #1f2330); | |
| --cb-ink-soft: var(--memo-ink-soft, #5b6072); | |
| --cb-line: var(--memo-line, #e4e5ec); | |
| --cb-surface: var(--memo-surface, #ffffff); | |
| --cb-surface-2: var(--memo-surface-2, #f7f8fb); | |
| --cb-accent: var(--memo-accent, #4063b8); | |
| --cb-accent-ink: var(--memo-accent-ink, #ffffff); | |
| --cb-focus: var(--memo-focus, #6c8cff); | |
| /* Tertiary surface + pressed tint + stronger hairline, so hover/ | |
| active states stop hard-coding the same literals across the file. | |
| Shadow ink is tokenised (geometry stays per-element). */ | |
| --cb-surface-3: var(--memo-surface-3, #eef0f6); | |
| --cb-press: var(--memo-press, #e4e7f1); | |
| --cb-line-strong: var(--memo-line-strong, #cdd2e4); | |
| --cb-shadow-ink: var(--memo-shadow-ink, 31, 35, 48); | |
| --cb-accent-press: var(--memo-accent-press, #36559e); | |
| /* The single intentional non-neutral: a calm tinted-amber "your | |
| labels may be stale" notice. Defined once here, not spread. */ | |
| --cb-warn-ink: var(--memo-warn-ink, #7a5200); | |
| --cb-warn-surface: var(--memo-warn-surface, #fdf5e6); | |
| --cb-warn-line: var(--memo-warn-line, #ecd9b4); | |
| } | |
| .cb-panel-toggle { | |
| position: fixed; | |
| right: 0; | |
| top: 62%; | |
| transform: translateY(-50%); | |
| z-index: 1040; | |
| display: flex; | |
| align-items: center; | |
| gap: var(--cb-space-2); | |
| min-height: 44px; | |
| border: 1px solid var(--cb-line); | |
| border-right: none; | |
| background: var(--cb-surface); | |
| color: var(--cb-ink); | |
| padding: 10px 14px; | |
| border-radius: var(--cb-radius) 0 0 var(--cb-radius); | |
| box-shadow: -1px 1px 6px rgba(var(--cb-shadow-ink), 0.08); | |
| cursor: pointer; | |
| font-size: 0.85rem; | |
| font-weight: 600; | |
| transition: background-color 160ms ease-out, transform 160ms ease-out; | |
| } | |
| .cb-panel-toggle:hover { | |
| background: var(--cb-surface-2); | |
| transform: translateY(-50%) translateX(-2px); | |
| } | |
| .cb-panel-toggle:active { background: var(--cb-surface-3); } | |
| .cb-panel { | |
| position: fixed; | |
| right: 0; | |
| top: 0; | |
| height: 100vh; | |
| width: 360px; | |
| max-width: 92vw; | |
| background: var(--cb-surface); | |
| border-left: 1px solid var(--cb-line); | |
| box-shadow: -4px 0 24px rgba(var(--cb-shadow-ink), 0.10); | |
| z-index: 1050; | |
| display: flex; | |
| flex-direction: column; | |
| color: var(--cb-ink); | |
| } | |
| .cb-panel:not([hidden]) { animation: cb-panel-in 200ms ease-out; } | |
| @keyframes cb-panel-in { | |
| from { opacity: 0; transform: translateX(12px); } | |
| to { opacity: 1; transform: translateX(0); } | |
| } | |
| .cb-panel-header { | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| padding: var(--cb-space-4); | |
| border-bottom: 1px solid var(--cb-line); | |
| font-size: 0.95rem; | |
| font-weight: 700; | |
| letter-spacing: 0.01em; | |
| } | |
| .cb-panel-header button { | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| width: 32px; | |
| height: 32px; | |
| border: none; | |
| border-radius: 6px; | |
| background: none; | |
| font-size: 1.25rem; | |
| line-height: 1; | |
| cursor: pointer; | |
| color: var(--cb-ink-soft); | |
| transition: background-color 140ms ease-out, color 140ms ease-out; | |
| } | |
| .cb-panel-header button:hover { | |
| background: var(--cb-surface-2); | |
| color: var(--cb-ink); | |
| } | |
| .cb-tree { | |
| flex: 1; | |
| overflow-y: auto; | |
| padding: var(--cb-space-4); | |
| } | |
| .cb-empty { | |
| color: var(--cb-ink-soft); | |
| font-size: 0.85rem; | |
| text-align: center; | |
| margin-top: var(--cb-space-5); | |
| } | |
| .cb-root, .cb-children { | |
| list-style: none; | |
| margin: 0; | |
| padding: 0; | |
| } | |
| /* Semantic nesting only — visual indentation is depth-driven padding | |
| on the row (see --cb-depth) so deep trees don't compound-march off | |
| the panel. */ | |
| .cb-children { margin-left: 0; } | |
| .cb-node-row { | |
| display: flex; | |
| align-items: center; | |
| gap: var(--cb-space-2); | |
| /* Depth indent, capped at 6 levels so it never runs off a 360px | |
| panel; falls back to 0 for flat codebooks. */ | |
| padding: 5px var(--cb-space-2) 5px | |
| calc(var(--cb-space-2) | |
| + min(var(--cb-depth, 0), 6) * var(--cb-space-4)); | |
| font-size: 0.88rem; | |
| line-height: 1.4; | |
| } | |
| .cb-dot { | |
| flex: 0 0 auto; | |
| width: 9px; | |
| height: 9px; | |
| border-radius: 999px; | |
| box-shadow: inset 0 0 0 1px rgba(31, 35, 48, 0.12); | |
| } | |
| .cb-name { word-break: break-word; } | |
| .cb-composer { | |
| border-top: 1px solid var(--cb-line); | |
| padding: var(--cb-space-4); | |
| display: flex; | |
| flex-direction: column; | |
| gap: var(--cb-space-2); | |
| background: var(--cb-surface); | |
| } | |
| .cb-composer-row { | |
| display: flex; | |
| gap: var(--cb-space-2); | |
| } | |
| .cb-composer input { | |
| flex: 1; | |
| min-width: 0; | |
| border: 1px solid var(--cb-line); | |
| border-radius: 6px; | |
| padding: var(--cb-space-2) var(--cb-space-3); | |
| font: inherit; | |
| font-size: 0.9rem; | |
| color: var(--cb-ink); | |
| transition: border-color 140ms ease-out, box-shadow 140ms ease-out; | |
| } | |
| .cb-composer input::placeholder { color: #9aa0b4; } | |
| .cb-composer input:focus { | |
| outline: none; | |
| border-color: var(--cb-focus); | |
| box-shadow: 0 0 0 3px rgba(108, 140, 255, 0.18); | |
| } | |
| .cb-primary { | |
| border: 1px solid var(--cb-accent); | |
| background: var(--cb-accent); | |
| color: var(--cb-accent-ink); | |
| min-height: 36px; | |
| padding: 7px 16px; | |
| border-radius: 6px; | |
| cursor: pointer; | |
| font-size: 0.85rem; | |
| font-weight: 600; | |
| transition: background-color 150ms ease-out, transform 120ms ease-out; | |
| } | |
| .cb-primary:hover { background: var(--cb-accent-press); } | |
| .cb-primary:active { transform: translateY(1px); } | |
| .cb-primary:disabled { | |
| background: #aab2cc; | |
| border-color: #aab2cc; | |
| cursor: progress; | |
| transform: none; | |
| } | |
| .cb-mode-hint { | |
| font-size: 0.72rem; | |
| color: var(--cb-ink-soft); | |
| letter-spacing: 0.02em; | |
| } | |
| .cb-error { | |
| font-size: 0.78rem; | |
| font-weight: 600; | |
| color: #b23b3b; | |
| background: #fbeeee; | |
| border: 1px solid #f0d2d2; | |
| border-radius: 6px; | |
| padding: var(--cb-space-2) var(--cb-space-3); | |
| } | |
| /* Calm "attention" notice — the one intentional non-neutral in the | |
| sidebar system; tinted amber, WCAG-AA (#7a5200 on #fdf5e6 ~ 6.4:1). */ | |
| .cb-stale-banner { | |
| display: flex; | |
| align-items: flex-start; | |
| gap: var(--cb-space-2); | |
| margin: var(--cb-space-3) var(--cb-space-4) 0; | |
| padding: var(--cb-space-2) var(--cb-space-2) | |
| var(--cb-space-2) var(--cb-space-3); | |
| font-size: 0.8rem; | |
| line-height: 1.45; | |
| color: var(--cb-warn-ink); | |
| background: var(--cb-warn-surface); | |
| border: 1px solid var(--cb-warn-line); | |
| border-radius: var(--cb-radius); | |
| } | |
| .cb-stale-msg { flex: 1; padding-top: 3px; } | |
| .cb-stale-x { | |
| flex: 0 0 auto; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| width: 28px; | |
| height: 28px; | |
| border: none; | |
| background: none; | |
| color: var(--cb-warn-ink); | |
| font-size: 1.05rem; | |
| line-height: 1; | |
| cursor: pointer; | |
| border-radius: 6px; | |
| transition: background-color 140ms ease-out; | |
| } | |
| .cb-stale-x:hover { | |
| background: color-mix(in srgb, var(--cb-warn-ink) 14%, transparent); | |
| } | |
| .cb-stale-x:active { | |
| background: color-mix(in srgb, var(--cb-warn-ink) 22%, transparent); | |
| } | |
| @media (prefers-reduced-motion: reduce) { | |
| .cb-stale-x { transition: none; } | |
| } | |
| .cb-worklist-section { | |
| border-top: 1px solid var(--cb-line); | |
| display: flex; | |
| flex-direction: column; | |
| max-height: 34vh; | |
| } | |
| .cb-worklist-head { | |
| margin: 0; /* neutralise <h2> UA margins */ | |
| padding: var(--cb-space-2) var(--cb-space-4); | |
| font-size: 0.72rem; | |
| font-weight: 700; | |
| letter-spacing: 0.04em; | |
| text-transform: uppercase; | |
| color: var(--cb-ink-soft); | |
| } | |
| .cb-worklist { | |
| overflow-y: auto; | |
| padding: 0 var(--cb-space-4) var(--cb-space-3); | |
| } | |
| .cb-worklist-list { | |
| list-style: none; | |
| margin: 0; | |
| padding: 0; | |
| } | |
| .cb-wl-item { | |
| display: grid; | |
| grid-template-columns: 1fr auto; | |
| grid-template-areas: "id go" "sub go"; | |
| align-items: center; | |
| gap: 0 var(--cb-space-2); | |
| padding: var(--cb-space-2) 0; | |
| border-bottom: 1px solid var(--cb-line); | |
| } | |
| .cb-wl-item:last-child { border-bottom: none; } | |
| .cb-wl-id { | |
| grid-area: id; | |
| font-size: 0.82rem; | |
| font-weight: 600; | |
| color: var(--cb-ink); | |
| word-break: break-word; | |
| } | |
| .cb-wl-sub { | |
| grid-area: sub; | |
| font-size: 0.72rem; | |
| color: var(--cb-ink-soft); | |
| word-break: break-word; | |
| } | |
| .cb-go { | |
| grid-area: go; | |
| border: 1px solid var(--cb-accent); | |
| background: none; | |
| color: var(--cb-accent); | |
| font-size: 0.74rem; | |
| font-weight: 600; | |
| min-height: 30px; | |
| padding: 5px 12px; | |
| border-radius: 6px; | |
| cursor: pointer; | |
| transition: background-color 140ms ease-out, color 140ms ease-out; | |
| } | |
| .cb-go:hover { background: var(--cb-accent); color: var(--cb-accent-ink); } | |
| .cb-go:active { | |
| background: var(--cb-accent-press); | |
| border-color: var(--cb-accent-press); | |
| } | |
| /* In-vivo composer — a small popover anchored to the text selection. | |
| Same token system as the tray so the two never drift. */ | |
| .cb-invivo { | |
| position: absolute; | |
| z-index: 1060; | |
| width: 320px; | |
| max-width: calc(100vw - 16px); | |
| display: flex; | |
| flex-direction: column; | |
| gap: var(--cb-space-2); | |
| padding: var(--cb-space-3); | |
| background: var(--cb-surface); | |
| border: 1px solid var(--cb-line); | |
| border-radius: var(--cb-radius); | |
| box-shadow: 0 8px 28px rgba(var(--cb-shadow-ink), 0.16); | |
| color: var(--cb-ink); | |
| } | |
| .cb-invivo:not([hidden]) { animation: cb-iv-in 140ms ease-out; } | |
| @keyframes cb-iv-in { | |
| from { opacity: 0; transform: translateY(-4px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| .cb-iv-quote { | |
| font-size: 0.8rem; | |
| line-height: 1.4; | |
| color: var(--cb-ink-soft); | |
| font-style: italic; | |
| display: -webkit-box; | |
| -webkit-box-orient: vertical; | |
| -webkit-line-clamp: 2; | |
| overflow: hidden; | |
| } | |
| .cb-iv-input { | |
| border: 1px solid var(--cb-line); | |
| border-radius: 6px; | |
| padding: var(--cb-space-2) var(--cb-space-3); | |
| font: inherit; | |
| font-size: 0.92rem; | |
| color: var(--cb-ink); | |
| transition: border-color 140ms ease-out, box-shadow 140ms ease-out; | |
| } | |
| /* Solid ring (not a faint shadow) so the focused state clears WCAG | |
| 1.4.11 non-text contrast for pointer focus too, not only :focus-visible. */ | |
| .cb-iv-input:focus { | |
| outline: 2px solid var(--cb-focus); | |
| outline-offset: 1px; | |
| border-color: var(--cb-focus); | |
| } | |
| .cb-iv-sim { | |
| display: flex; | |
| flex-wrap: wrap; | |
| align-items: center; | |
| gap: var(--cb-space-1) var(--cb-space-2); | |
| } | |
| .cb-iv-sim-label { | |
| width: 100%; | |
| font-size: 0.72rem; | |
| font-weight: 600; | |
| color: var(--cb-ink-soft); | |
| } | |
| .cb-iv-chip { | |
| display: inline-flex; | |
| align-items: center; | |
| border: 1px solid var(--cb-line); | |
| background: var(--cb-surface-2); | |
| color: var(--cb-ink); | |
| font-size: 0.76rem; | |
| font-weight: 500; | |
| min-height: 34px; | |
| padding: 6px 12px; | |
| border-radius: 999px; | |
| cursor: pointer; | |
| transition: background-color 140ms ease-out, | |
| border-color 140ms ease-out, color 140ms ease-out; | |
| } | |
| .cb-iv-chip:hover { | |
| background: var(--cb-surface-3); | |
| border-color: var(--cb-line-strong); | |
| } | |
| .cb-iv-chip:active { background: var(--cb-press); } | |
| .cb-iv-chip-on, | |
| .cb-iv-chip-on:hover { | |
| background: var(--cb-accent); | |
| border-color: var(--cb-accent); | |
| color: var(--cb-accent-ink); | |
| } | |
| .cb-iv-actions { | |
| display: flex; | |
| justify-content: flex-end; | |
| gap: var(--cb-space-2); | |
| margin-top: var(--cb-space-1); | |
| } | |
| .cb-iv-cancel { | |
| border: 1px solid var(--cb-line); | |
| background: var(--cb-surface); | |
| color: var(--cb-ink-soft); | |
| min-height: 36px; | |
| padding: 7px 14px; | |
| border-radius: 6px; | |
| cursor: pointer; | |
| font-size: 0.85rem; | |
| font-weight: 600; | |
| transition: background-color 140ms ease-out, color 140ms ease-out; | |
| } | |
| .cb-iv-cancel:hover { | |
| background: var(--cb-surface-2); | |
| color: var(--cb-ink); | |
| } | |
| .cb-iv-cancel:active { background: var(--cb-surface-3); } | |
| /* Admin curation section — same token system as the rest of the tray. */ | |
| .cb-admin-section { | |
| border-top: 1px solid var(--cb-line); | |
| padding: var(--cb-space-3) var(--cb-space-4) var(--cb-space-4); | |
| display: flex; | |
| flex-direction: column; | |
| gap: var(--cb-space-4); | |
| } | |
| .cb-admin-head { | |
| margin: 0; | |
| font-size: 0.72rem; | |
| font-weight: 700; | |
| letter-spacing: 0.04em; | |
| text-transform: uppercase; | |
| color: var(--cb-ink-soft); | |
| } | |
| .cb-admin-group { | |
| display: flex; | |
| flex-direction: column; | |
| gap: var(--cb-space-2); | |
| } | |
| .cb-admin-label { | |
| font-size: 0.8rem; | |
| font-weight: 600; | |
| color: var(--cb-ink); | |
| } | |
| .cb-admin-sub { | |
| margin: 0; | |
| font-size: 0.78rem; | |
| font-weight: 600; | |
| color: var(--cb-ink-soft); | |
| } | |
| .cb-admin-row { | |
| display: flex; | |
| align-items: center; | |
| gap: var(--cb-space-2); | |
| } | |
| .cb-admin-select, | |
| .cb-admin-input { | |
| flex: 1; | |
| min-width: 0; | |
| min-height: 34px; | |
| border: 1px solid var(--cb-line); | |
| border-radius: 6px; | |
| padding: var(--cb-space-1) var(--cb-space-2); | |
| font: inherit; | |
| font-size: 0.85rem; | |
| color: var(--cb-ink); | |
| background: var(--cb-surface); | |
| transition: border-color 140ms ease-out, box-shadow 140ms ease-out; | |
| } | |
| .cb-admin-select:focus, | |
| .cb-admin-input:focus { | |
| outline: 2px solid var(--cb-focus); | |
| outline-offset: 1px; | |
| border-color: var(--cb-focus); | |
| } | |
| .cb-admin-arrow { | |
| flex: 0 0 auto; | |
| color: var(--cb-ink-soft); | |
| font-size: 0.9rem; | |
| } | |
| .cb-proposals, | |
| .cb-changes-wrap { font-size: 0.82rem; } | |
| .cb-prop-list, | |
| .cb-changes-list { | |
| list-style: none; | |
| margin: 0; | |
| padding: 0; | |
| } | |
| .cb-prop-item { | |
| display: flex; | |
| flex-direction: column; | |
| gap: var(--cb-space-2); | |
| padding: var(--cb-space-2) 0; | |
| border-bottom: 1px solid var(--cb-line); | |
| } | |
| .cb-prop-item:last-child { border-bottom: none; } | |
| .cb-prop-desc { | |
| font-size: 0.78rem; | |
| color: var(--cb-ink); | |
| word-break: break-word; | |
| } | |
| .cb-prop-actions { | |
| display: flex; | |
| gap: var(--cb-space-2); | |
| } | |
| .cb-changes-wrap > summary { | |
| cursor: pointer; | |
| list-style: revert; | |
| } | |
| .cb-chg-item { | |
| padding: var(--cb-space-1) 0; | |
| font-size: 0.76rem; | |
| color: var(--cb-ink-soft); | |
| word-break: break-word; | |
| } | |
| .cb-chg-op { | |
| font-weight: 700; | |
| color: var(--cb-ink); | |
| } | |
| .cb-chg-by { color: var(--cb-ink-soft); font-style: italic; } | |
| /* Calm success/status line — no new success-green; the one-accent | |
| discipline holds, a quiet italic soft-ink note is enough. */ | |
| .cb-admin-status { | |
| font-size: 0.78rem; | |
| font-style: italic; | |
| color: var(--cb-ink-soft); | |
| min-height: 1.1em; /* reserve space — no layout shift */ | |
| } | |
| .cb-admin-status:empty { min-height: 0; } | |
| /* Programmatic focus target (error is announced via role=alert; no | |
| stray ring needed when it is focused for sighted recovery). */ | |
| #cb-admin-error:focus { outline: none; } | |
| .cb-panel-toggle:focus-visible, | |
| .cb-panel button:focus-visible, | |
| .cb-panel input:focus-visible, | |
| .cb-panel select:focus-visible, | |
| .cb-invivo button:focus-visible, | |
| .cb-invivo input:focus-visible { | |
| outline: 2px solid var(--cb-focus); | |
| outline-offset: 2px; | |
| } | |
| @media (prefers-reduced-motion: reduce) { | |
| .cb-panel:not([hidden]) { animation: none; } | |
| .cb-invivo:not([hidden]) { animation: none; } | |
| .cb-panel-toggle, | |
| .cb-primary, | |
| .cb-go, | |
| .cb-iv-chip, | |
| .cb-iv-cancel, | |
| .cb-iv-input, | |
| .cb-admin-select, | |
| .cb-admin-input, | |
| .cb-panel-header button { transition: none; } | |
| } | |