1371 lines · 117.1 KB · CSS
RawDownload
* { box-sizing: border-box; }html, body, #root { width: 100%; height: 100%; margin: 0; overflow: hidden; background: var(--surface-window); }button, input, textarea, select { font: inherit; color: inherit; }button { border: 0; cursor: pointer; transition: background-color var(--motion-fast), border-color var(--motion-fast), color var(--motion-fast); }button:disabled { cursor: default; opacity: 0.45; }input[type="search"] { -webkit-appearance: none; appearance: none; }input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-results-button,input[type="search"]::-webkit-search-results-decoration {  -webkit-appearance: none;  appearance: none;}input[type="search"]:focus { outline: none; }input[type="search"]:focus-visible {  border-color: var(--border-strong);  box-shadow: 0 0 0 1px color-mix(in srgb, var(--text-primary) 12%, transparent);}.copy-button-icon { position: relative; width: 14px; height: 14px; display: inline-grid; place-items: center; flex: none; }.copy-button-icon > svg { position: absolute; transition: opacity var(--motion-moderate), transform var(--motion-moderate); }.copy-icon-idle { opacity: 1; transform: scale(1) rotate(0); }.copy-icon-success { opacity: 0; transform: scale(.85); color: var(--status-success); }.copy-button.copied .copy-icon-idle { opacity: 0; transform: scale(.85); }.copy-button.copied .copy-icon-success { opacity: 1; transform: scale(1) rotate(0); } .root-error-page { min-height: 100vh; padding: var(--space-16); display: grid; place-items: center; background: var(--surface-app); color: var(--text-primary); }.root-error-card { width: min(100%, 520px); padding: var(--space-16); border-radius: var(--radius-dialog); }.root-error-card h1 { margin: 0; font-family: var(--type-display-font); font-size: var(--type-display-size); line-height: var(--type-display-line-height); font-weight: var(--type-display-weight); }.root-error-card > p { margin: var(--space-6) 0 0; color: var(--text-secondary); font-size: var(--type-body-size); line-height: 1.6; }.root-error-actions { margin-top: 22px; display: flex; flex-wrap: wrap; gap: var(--space-4); }.root-error-card > .root-error-action-error { color: var(--status-danger); font-size: var(--type-caption-size); }.root-error-details { margin-top: 22px; border-top: 1px solid var(--border-subtle); padding-top: 14px; color: var(--text-secondary); font-size: var(--type-caption-size); }.root-error-details summary { width: max-content; cursor: pointer; font-weight: 600; }.root-error-details pre { max-height: 180px; margin: var(--space-6) 0 0; padding: var(--space-6); overflow: auto; border-radius: var(--radius-control); background: var(--surface-panel); color: var(--text-primary); font-family: var(--editor-font); font-size: var(--type-micro-size); line-height: 1.5; white-space: pre-wrap; overflow-wrap: anywhere; }/* A panel that crashed (telemetry/panel-error-boundary.tsx): its card fills the panel, centered, as an empty state does. */.panel-error { box-sizing: border-box; height: 100%; padding: var(--space-8); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--space-4); overflow: auto; text-align: center; color: var(--text-secondary); font-size: var(--type-body-compact-size); }.panel-error > strong { color: var(--text-primary); }.panel-error > p { margin: 0; }.panel-error > .root-error-details { width: min(100%, 420px); margin-top: var(--space-4); text-align: start; } /* Focus, in two parts. * * WebKit paints a native blue halo on plain `:focus`, including pointer clicks, * even where the product already shows the state with its own border and fill. * That halo is suppressed. * * Keyboard focus is different: it must always be visible, so `:focus-visible` * draws one product ring for controls in the Tab order. Not for focus a * pointer caused, though: script focus after a click or a hover matches * `:focus-visible` too, so components/ui/pointer-focus.ts marks such an element * `data-pointer-focus` and the rule below hides every ring on it, this one * and those components draw themselves (a checkbox, an outline row). * Menu items (every `menuitem*` role), Radix's and the project tree's own row * menu, expose focus through their active-row fill, while the project switcher * and the Overleaf split-menu trigger use a chrome fill. Outlining those * composite controls can leave a stray black frame when WebKit restores focus * after app activation. Radix also temporarily focuses dialog surfaces with * `tabindex="-1"`; those composites already expose focus through their active * row or modal context. Text entry is excluded because a field already answers * with its own border treatment (see the `--field-control-*` contract), and * doubling the two reads as an error state. */:where(button, a, input, textarea, select, summary, [role="button"], [tabindex]):focus {  outline: none;}:where(button:not(.project-title):not(.overleaf-toolbar-menu-button):not([role^="menuitem"]), a, select, summary, [role="button"], [tabindex]:not(.ProseMirror):not([tabindex="-1"]):not([role^="menuitem"])):focus-visible {  outline: var(--focus-ring-width) solid var(--focus-ring);  outline-offset: var(--focus-ring-offset);}/* Specific enough to beat a component's own ring (`.ui-checkbox:focus-visible`,   `.latex-selection-tool button:focus-visible`), so one rule covers them all.   A ring more specific than this, or drawn some other way (a fill, a shadow,   a parent's outline), checks the mark itself. */:root [data-pointer-focus]:focus-visible { outline-color: transparent; } .app-shell { height: 100%; background: var(--surface-window); display: flex; flex-direction: column; }.titlebar { container: titlebar / inline-size; position: relative; z-index: var(--z-chrome); height: var(--titlebar-height); flex: none; display: flex; align-items: center; background: var(--surface-titlebar); box-shadow: inset 0 -1px 0 var(--titlebar-rule); user-select: none; }.titlebar-sidebar { width: var(--titlebar-sidebar-width); min-width: 0; height: 100%; flex: none; display: flex; align-items: center; }.titlebar-navigator { width: var(--titlebar-navigator-width); height: 100%; flex: none; display: flex; align-items: center; padding-right: var(--titlebar-leading-gap); }.traffic-space { width: var(--titlebar-traffic-space-width); height: 100%; flex: none; }/* No traffic lights beside the bar: a browser tab and the website's demo have   none, and full screen hides them. There the switcher starts at the bar's   own padding. In full screen AppKit shows them again only while the pointer   holds the menu bar down, in its own bar that slides in over this one. */:is(.app-shell.browser-hosted, .app-shell.fullscreen, .titlebar-without-lights) .titlebar-navigator { width: var(--titlebar-navigator-width-browser); padding: 0 var(--space-4); }:is(.app-shell.browser-hosted, .app-shell.fullscreen, .titlebar-without-lights) .traffic-space { width: 0; }.icon-button { width: var(--titlebar-action-size); height: var(--titlebar-action-size); border-radius: var(--radius-chrome); background: transparent; display: grid; place-items: center; color: var(--text-secondary); }.icon-button:hover { background: var(--chrome-hover-surface); color: var(--text-primary); }/* Soften the light/dark switch on the big themed surfaces (a rare action, so a   short color transition here is cheap even on weak WebKit). */.app-shell, .titlebar { transition: background-color var(--motion-slow), color var(--motion-slow); }.project-switcher { min-width: 0; height: 100%; flex: none; position: relative; display: flex; align-items: center; overflow: hidden; }.project-title { max-width: var(--titlebar-project-title-max-width); height: var(--titlebar-action-size); min-width: 0; flex: none; border-radius: var(--radius-chrome); padding: 0 var(--space-4); background: transparent; color: var(--text-chrome); display: flex; align-items: center; gap: var(--gap-inline); font-size: var(--type-subtitle-size); font-weight: var(--weight-semibold); text-align: left; }.project-title:hover, .project-title:focus-visible, .project-title[aria-expanded="true"] { background: var(--chrome-hover-surface); }.project-title:disabled { opacity: 1; cursor: default; }.project-title > span:first-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }.project-title > svg { flex: none; color: var(--text-tertiary); }/* A long name clamps at the title's max width; the percentage cap this used to   carry is cyclic inside the content-sized switcher, so the unclamped name set   the switcher's width and pushed Panels away. The gap after it is fixed, so   the switcher stays centered between the lights and Panels. *//* Near the window's minimum width a full-length name would starve the panel   controls beside it; measured on the bar itself so interface zoom and the   browser tab's missing traffic lights are already accounted for. */@container titlebar (max-width: 800px) { .project-title { max-width: var(--titlebar-project-title-max-width-compact); } }.titlebar-drag-area { width: var(--titlebar-trailing-gap); height: 100%; flex: none; }/* Focus mode (focus-mode-bar.tsx): the bar keeps the window's controls, the   document's name centered on the window and the way out, on the ground the   panels sit on and without its rule, so the page is all that stands out. */.titlebar.titlebar-focus { background: var(--surface-shell); box-shadow: none; }.focus-bar { min-width: 0; height: 100%; flex: 1; padding-inline: var(--space-4); display: flex; align-items: center; justify-content: flex-end; animation: focus-bar-in var(--motion-fast) both; }.focus-bar-title { position: absolute; left: 50%; max-width: min(40%, 420px); translate: -50% 0; overflow: hidden; color: var(--text-tertiary); font-size: var(--type-body-compact-size); line-height: var(--type-body-compact-line-height); font-weight: var(--weight-regular); text-overflow: ellipsis; white-space: nowrap; pointer-events: none; }.focus-bar-actions { position: relative; display: flex; align-items: center; gap: var(--space-2); }.focus-bar-exit .focus-bar-keys { margin-inline-start: var(--space-1); }@keyframes focus-bar-in { from { opacity: 0; } }.titlebar-main { min-width: 0; height: 100%; flex: 1; background: transparent; display: flex; align-items: center; overflow: hidden; }.titlebar-main > .canvas-toolbar { min-width: max-content; width: auto; height: 100%; flex: none; padding: 0 var(--space-3); border: 0; background: transparent; display: flex; align-items: center; gap: var(--space-4); overflow: visible; container-type: normal; container-name: none; }.titlebar-main > .canvas-toolbar .active-document { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }.titlebar-main > .canvas-toolbar .canvas-actions { min-width: max-content; width: max-content; flex: none; overflow: visible; }.spin { animation: spin 0.8s linear infinite; }@keyframes spin { to { transform: rotate(360deg); } } .compile-diagnostics { box-shadow: 0 0 0 1px var(--border-subtle), var(--elevation-floating-shadow); position: absolute; z-index: var(--z-diagnostics); top: 46px; right: var(--space-4); width: min(440px, calc(100% - 16px)); border-radius: var(--radius-panel); color: var(--text-secondary); overflow: hidden; }.compile-diagnostics.error .compile-diagnostics-toggle > svg:first-child { color: var(--status-danger); }.compile-diagnostics.warning .compile-diagnostics-toggle > svg:first-child { color: var(--status-warning); }.compile-diagnostics-bar { min-height: 34px; display: flex; align-items: center; gap: var(--space-3); padding: var(--space-2) var(--space-5) var(--space-2) var(--space-4); }.compile-diagnostics-toggle { flex: 1; min-width: 0; height: var(--control-height-compact); border: 0; border-radius: var(--radius-icon); padding: 0 var(--space-3); background: transparent; color: inherit; display: flex; align-items: center; gap: var(--gap-inline); font-size: var(--type-caption-size); font-weight: var(--weight-regular); }.compile-diagnostics-toggle:hover { background: var(--tone-hover-surface); }.compile-diagnostics-toggle > svg:first-child { width: 15px; height: 15px; flex: none; }.compile-diagnostics-toggle span { flex: 1; min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; text-align: left; font-weight: 400; }.compile-diagnostics-bar > button:last-child { width: var(--control-size-icon-compact); height: var(--control-size-icon-compact); border: 0; border-radius: calc(var(--radius-icon) * var(--corner-smoothing)); corner-shape: squircle; padding: 0; background: transparent; color: inherit; display: grid; place-items: center; }.compile-diagnostics-bar > button:last-child:hover { background: var(--tone-hover-surface); }.compile-repair-progress { display: flex; align-items: center; gap: var(--space-3); white-space: nowrap; font-size: var(--type-caption-size); }.compile-repair-action { flex: none; gap: var(--space-3); }.compile-repair-detail { margin: 0; padding: var(--space-2) var(--space-5) var(--space-4); font-size: var(--type-caption-size); overflow-wrap: anywhere; max-height: 120px; overflow-y: auto; }.compile-repair-footer { display: flex; align-items: center; justify-content: flex-end; gap: var(--space-4); padding: var(--space-2) var(--space-4); border-top: 1px solid var(--border-subtle); font-size: var(--type-caption-size); }.compile-repair-footer > span { margin-right: auto; }.compile-diagnostics-body { padding: 0 var(--space-4) var(--space-4); display: grid; gap: var(--space-3); }.compile-diagnostics-switch { min-height: var(--control-height-compact); display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); }.compile-log-copy { margin-inline-start: auto; }.compile-diagnostics-tabs .ui-segmented-tab { gap: var(--space-2); }/* The list scrolls, so it clips: it reaches into the body's padding by as much   as it pads back in, which keeps the focus rings of its rows whole. */.compile-diagnostics-list { list-style: none; margin: calc(-1 * var(--focus-ring-reach)); padding: var(--focus-ring-reach); max-height: calc(168px + 2 * var(--focus-ring-reach)); overflow: auto; display: grid; align-content: start; gap: var(--space-4); }.compile-diagnostics-group { min-width: 0; display: grid; gap: var(--space-1); }.compile-diagnostics-group > ul { list-style: none; margin: 0; padding: 0; display: grid; }.compile-diagnostics-group > ul > li { min-width: 0; display: flex; align-items: center; gap: var(--gap-tight); }/* A path wraps rather than truncates: its last segment is the part that matters. */.compile-diagnostics-file { min-width: 0; padding: 0 var(--space-4); display: flex; align-items: baseline; gap: var(--space-3); color: var(--text-tertiary); font-size: var(--type-micro-size); font-weight: var(--weight-medium); overflow-wrap: anywhere; }.compile-diagnostics-count { flex: none; font-weight: var(--weight-regular); font-variant-numeric: tabular-nums; opacity: .8; }.compile-diagnostic-item { min-width: 0; flex: 1; min-height: 30px; border: 0; border-radius: var(--radius-chrome); padding: var(--space-3) var(--space-4); background: transparent; color: inherit; display: grid; grid-template-columns: auto minmax(0, 1fr) auto; column-gap: var(--gap-inline); align-items: start; text-align: left; font-size: var(--type-caption-size); }.compile-diagnostic-item:hover:not(:disabled) { background: var(--tone-hover-surface); }.compile-diagnostic-item:disabled { opacity: 0.88; cursor: default; }.compile-diagnostic-item.error > svg { color: var(--status-danger); }.compile-diagnostic-item.warning > svg { color: var(--status-warning); }.compile-diagnostic-message { min-width: 0; color: var(--text-primary); overflow-wrap: anywhere; line-height: 1.45; }.compile-diagnostic-line { color: var(--text-tertiary); font-size: var(--type-micro-size); line-height: 1.6; white-space: nowrap; font-variant-numeric: tabular-nums; }.compile-diagnostic-copy { width: var(--control-size-icon-compact); height: var(--control-size-icon-compact); flex: none; border: 0; border-radius: var(--radius-icon); padding: 0; background: transparent; color: inherit; display: grid; place-items: center; opacity: .72; transition: background-color var(--motion-fast), opacity var(--motion-fast); }.compile-diagnostic-copy:hover { background: var(--tone-hover-surface); opacity: 1; }/* An error the build explains (compile-explain.ts) opens into a card: the   headline row, an excerpt of the failing line, one sentence, then the fix   first and TeX's own words last, small at the end. */.compile-diagnostics-group > ul > li.compile-explained { flex-direction: column; align-items: stretch; gap: var(--space-3); padding-bottom: var(--space-3); }.compile-explained .compile-diagnostic-message { font-weight: var(--weight-medium); }.compile-excerpt { margin: 0 var(--space-4); padding: var(--space-3) 0; border-radius: calc(var(--radius-control) * var(--corner-smoothing)); corner-shape: squircle; background: var(--editor-bg); box-shadow: inset 0 0 0 1px var(--border-subtle); color: var(--text-secondary); font-family: var(--editor-font); font-size: var(--type-micro-size); line-height: 20px; overflow: hidden; display: grid; }.compile-excerpt-line { display: grid; grid-template-columns: 30px minmax(0, 1fr); padding-inline-end: var(--space-4); white-space: pre; }.compile-excerpt-line[data-failing] { background: color-mix(in srgb, var(--status-danger) 7%, transparent); box-shadow: inset 2px 0 0 var(--status-danger); color: var(--text-primary); }.compile-excerpt-number { padding-inline-end: var(--space-4); text-align: right; color: var(--text-tertiary); font-variant-numeric: tabular-nums; }.compile-excerpt-text { overflow: hidden; text-overflow: ellipsis; }/* The marked line shrinks its end first and then its lead, which is clipped   from the start (its text is packed to the end), so the token never leaves. */.compile-excerpt-marked { display: flex; }.compile-excerpt-lead { flex: 0 1 auto; min-width: 0; display: flex; justify-content: flex-end; overflow: hidden; }.compile-excerpt-lead > span { flex: none; }.compile-excerpt-marked > mark { flex: none; }.compile-excerpt-rest { flex: 0 100 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }.compile-excerpt mark { background: none; color: var(--status-danger); text-decoration: underline wavy var(--status-danger); text-decoration-thickness: 1px; text-underline-offset: 2px; text-decoration-skip-ink: none; font-weight: var(--weight-semibold); }.compile-explained-text { margin: 0; padding: 0 var(--space-4); color: var(--text-primary); font-size: var(--type-caption-size); line-height: 1.5; text-wrap: pretty; }.compile-explained-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); padding-inline-start: var(--space-4); }.compile-explained-actions code { font-family: var(--editor-font); }/* An error just fixed from its card waits, checked off, for the build that confirms it. */.compile-fixed .compile-diagnostic-item > svg { color: var(--status-success); }.compile-fixed .compile-diagnostic-message { color: var(--text-secondary); text-decoration: line-through; text-decoration-color: var(--text-tertiary); }.compile-fixed .compile-explained-text { color: var(--text-secondary); }.compile-fixed code { font-family: var(--editor-font); }.compile-explained-enter { opacity: .55; }/* The row's Copy stands at its end, as on every other message row. */.compile-explained-actions > .compile-diagnostic-copy { margin-inline-start: auto; }/* An explained card is taller than a row: the list gets room for it and the rows after it. */.compile-diagnostics-list:has(.compile-explained) { max-height: calc(320px + 2 * var(--focus-ring-reach)); }.compile-log { display: block; box-sizing: border-box; width: 100%; field-sizing: content; min-height: 0; max-height: 220px; margin: 0; overflow: auto; resize: none; border: 1px solid var(--tone-border); border-radius: var(--radius-chrome); padding: var(--space-4) var(--space-5); background: color-mix(in srgb, var(--surface-panel-raised) 90%, transparent); color: var(--text-primary); font-family: var(--editor-font); font-size: var(--type-micro-size); line-height: 1.45; white-space: pre-wrap; overflow-wrap: anywhere; }/* Without field-sizing a textarea is two rows tall; give it the old cap. */@supports not (field-sizing: content) { .compile-log { height: 220px; } }/* Docked, the output takes a strip under the page instead of covering its   top. The strip's height is fixed while it is open, so switching tabs or a   new build's messages never resize the PDF; only opening and closing do,   and the viewer settles its refit after those. */.compile-diagnostics.docked { order: 1; position: relative; z-index: auto; top: auto; right: auto; width: auto; border-top: 1px solid var(--border-subtle); border-radius: 0; background: var(--editor-bg); box-shadow: none; }.compile-diagnostics.docked.expanded { height: min(240px, 40%); display: flex; flex-direction: column; }.compile-diagnostics.docked.expanded > * { flex: none; }.compile-diagnostics.docked.expanded > .compile-repair-detail { flex: 0 1 auto; min-height: 0; overflow-y: auto; }.compile-diagnostics.docked.expanded > .compile-diagnostics-body { flex: 1 1 0; min-height: 80px; display: flex; flex-direction: column; }.compile-diagnostics.docked .compile-diagnostics-switch { flex: none; }.compile-diagnostics.docked .compile-diagnostics-list,.compile-diagnostics.docked .compile-log { flex: 1 1 0; min-height: 0; max-height: none; }.compile-diagnostics.docked .compile-log { field-sizing: fixed; }.editor-status-bar {  container-type: inline-size;  flex: none;  height: var(--control-height-compact);  min-height: var(--control-height-compact);  /* Each item pads its own 6px, so the text still starts 12px in. */  padding: 0 var(--space-3);  border-top: 1px solid var(--border-subtle);  background: var(--editor-bg);  color: var(--text-secondary);  display: flex;  align-items: center;  gap: var(--space-1);  font-size: var(--type-caption-size);  line-height: var(--type-caption-line-height);  font-variant-numeric: tabular-nums;  flex-wrap: nowrap;  overflow: hidden;}.editor-status-bar > * { flex: none; white-space: nowrap; }/* The bar clips its overflow and leaves 2-3px above and below a 22px item:   the ring hugs the item so it fits. */.editor-status-bar .status-item:focus-visible { outline-offset: 0; }/* Every item a pointer lands on is one slab: 22px on the 28px bar, the   control radius, the control hover and press fills, and the secondary ink   stepping up to the primary, as the titlebar's and toolbar's controls do. */.editor-status-bar .status-item { height: 22px; min-width: 0; border: 0; border-radius: var(--radius-control); padding: 0 var(--space-3); background: transparent; color: var(--text-secondary); font: inherit; display: inline-flex; align-items: center; gap: var(--gap-inline-tight); cursor: pointer; transition: background-color var(--motion-fast), color var(--motion-fast); }.editor-status-bar .status-item:hover { background: var(--control-hover-surface); color: var(--text-primary); }.editor-status-bar .status-item:is(:active, [data-state="open"]) { background: var(--control-pressed-surface); color: var(--text-primary); }.editor-status-bar .status-item > svg { flex: none; }.editor-status-bar .status-item > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; }.editor-status-bar .status-caret-word { white-space: pre; }/* Comments and TODOs travel together toward the counts at the end rather than   floating mid-bar whenever the hint and the breadcrumb are absent. */.editor-status-bar .status-comments { margin-left: auto; }/* An open count is the one coloured thing on the bar: the icon and the   number take the accent, the noun keeps the bar's ink. */.editor-status-bar .status-count { font-weight: var(--weight-medium); }.editor-status-bar .status-counter[data-active] :is(svg, .status-count) { color: var(--control-active); }/* The count reads first and names its scope in the quieter ink after a gap;   the scope is the first thing to go. */.editor-status-bar .status-body-words { margin-left: var(--space-2); gap: var(--space-2); }.editor-status-bar .status-body-words .status-word-scope::after { content: "\00a0"; margin-left: var(--space-2); }.editor-status-bar .status-body-words .status-word-count { color: var(--text-primary); }.editor-status-bar .status-more { display: none; width: 22px; padding: 0; justify-content: center; }.editor-status-bar .editor-breadcrumb { min-width: 0; flex: 1 1 auto; overflow: hidden; color: var(--text-secondary); text-align: center; display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2); flex-wrap: nowrap; }.editor-status-bar .editor-breadcrumb button { border: 0; background: transparent; color: inherit; padding: 0; font: inherit; max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; transition: color var(--motion-fast); }.editor-status-bar .editor-breadcrumb button:hover { color: var(--text-primary); }.editor-status-bar .editor-breadcrumb i { flex: none; color: var(--text-tertiary); font-style: normal; }/* Each crumb (separator and button) is the flex item, so it is the one that   must be allowed under its text's width: then the button ellipsizes, where a   crumb wider than the bar was cut at both ends of the centred row. */.editor-status-bar .editor-breadcrumb > span { min-width: 0; display: flex; align-items: center; gap: var(--space-2); }.editor-status-bar .status-vim-mode { min-width: max-content; flex: none; padding: 0 var(--space-3); color: var(--text-primary); font-size: var(--type-micro-size); font-weight: var(--weight-semibold); letter-spacing: .02em; font-variant-numeric: tabular-nums; }.editor-status-bar .status-vim-compact { display: none; }/* The save slot after the caret: tertiary ink while all is well, the   secondary ink and a warning-tinted icon offline, danger only for a write   that failed. The age trails the label after a space. */.editor-status-bar .status-save { color: var(--text-tertiary); }.editor-status-bar .status-save .status-save-age::before { content: "\00a0"; margin-inline-end: var(--space-2); }.editor-status-bar .status-save .status-save-age { margin-inline-start: var(--space-2); }.editor-status-bar .status-save[data-mode="offline"] { color: var(--text-secondary); }.editor-status-bar .status-save[data-mode="offline"] > svg { color: var(--status-warning); }.editor-status-bar .status-save[data-mode="error"] { color: var(--status-danger); }/* The bar gives way in one order as it narrows, so what stays is what a   writer glances at most, and nothing ever wraps, overlaps or is cut:     1. the breadcrumb keeps only the current section, then goes;     2. the counters drop their nouns and keep icon and count;     3. the word count drops its scope, then folds with everything below it        into More (…), which lists the counters and every word count;     4. the caret shortens to line:column and Vim's mode to its initial;     5. the counters fold into More.   The save slot drops its age with the breadcrumb's parents (1), its label   with the breadcrumb (3), and keeps its icon, which still opens its details.   The caret, Vim's mode and More never leave. Each step is the measured   width of the English bar that stays (the longer language) with a 5-digit   line, a 3-digit column, two-digit counts and a 7-digit manuscript, plus the   gaps; the breadcrumb, the one item that shrinks rather than goes, absorbs   the slack between steps. Vim's mode is about 80px, so a bar showing it   takes each step that much sooner (the `:has` twins). Keep them here as one   ladder: a second copy elsewhere in the cascade silently wins and strands the   step you are reading. A Split source at its minimum (SPLIT_SOURCE_MIN_WIDTH)   leaves the bar 216px; a panel narrower than both Split minimums shrinks the   source below that, and the caret ellipsizes before anything spills. */@container (max-width: 600px) { .editor-status-bar .status-save .status-save-age { display: none; } }@container (max-width: 680px) { .editor-status-bar:has(.status-vim-mode) .status-save .status-save-age { display: none; } }@container (max-width: 420px) { .editor-status-bar .status-save .status-save-label { display: none; } }@container (max-width: 500px) { .editor-status-bar:has(.status-vim-mode) .status-save .status-save-label { display: none; } }@container (max-width: 600px) {  .editor-status-bar .editor-breadcrumb > span:not(:last-child),  .editor-status-bar .editor-breadcrumb > span > i { display: none; }}@container (max-width: 680px) {  .editor-status-bar:has(.status-vim-mode) .editor-breadcrumb > span:not(:last-child),  .editor-status-bar:has(.status-vim-mode) .editor-breadcrumb > span > i { display: none; }}@container (max-width: 520px) { .editor-status-bar .status-counter .status-label { display: none; } }@container (max-width: 600px) { .editor-status-bar:has(.status-vim-mode) .status-counter .status-label { display: none; } }@container (max-width: 420px) {  .editor-status-bar .editor-breadcrumb { display: none; }  .editor-status-bar .status-body-words .status-word-scope { display: none; }}@container (max-width: 500px) {  .editor-status-bar:has(.status-vim-mode) :is(.editor-breadcrumb, .status-body-words .status-word-scope) { display: none; }}@container (max-width: 340px) {  .editor-status-bar .status-body-words { display: none; }  .editor-status-bar .status-more { display: inline-flex; margin-left: var(--space-2); }}@container (max-width: 420px) {  .editor-status-bar:has(.status-vim-mode) .status-body-words { display: none; }  .editor-status-bar:has(.status-vim-mode) .status-more { display: inline-flex; margin-left: var(--space-2); }}/* From here the caret may also shrink, with an ellipsis, so a bar narrower   than the last step never spills past its end. */@container (max-width: 240px) {  .editor-status-bar .status-goto { flex: 0 1 auto; }  .editor-status-bar :is(.status-caret-word, .status-vim-full) { display: none; }  .editor-status-bar .status-caret-column::before { content: ":"; }  .editor-status-bar .status-vim-compact { display: inline; }}@container (max-width: 350px) {  .editor-status-bar:has(.status-vim-mode) .status-goto { flex: 0 1 auto; }  .editor-status-bar:has(.status-vim-mode) :is(.status-caret-word, .status-vim-full) { display: none; }  .editor-status-bar:has(.status-vim-mode) .status-caret-column::before { content: ":"; }  .editor-status-bar:has(.status-vim-mode) .status-vim-compact { display: inline; }}/* With the counters folded, More takes the end of the bar on its own. */@container (max-width: 180px) {  .editor-status-bar .status-counter { display: none; }  .editor-status-bar .status-more { margin-left: auto; }}@container (max-width: 210px) {  .editor-status-bar:has(.status-vim-mode) .status-counter { display: none; }  .editor-status-bar:has(.status-vim-mode) .status-more { margin-left: auto; }}.word-count-popover { width: 284px; padding: var(--space-2); }/* A filename is one unbroken token; the notes break it anywhere rather than   run out of the popover, and the label column may shrink below its text. */.word-count-popover dl { margin: 0; display: grid; }.word-count-popover dl > div { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: baseline; gap: var(--space-1) var(--space-6); padding: var(--space-5) var(--space-6); }.word-count-popover dl > div + div { border-top: 1px solid var(--border-subtle); }.word-count-popover dt { color: var(--text-primary); font-size: var(--type-body-compact-size); font-weight: var(--weight-semibold); }.word-count-popover dd { margin: 0; color: var(--text-primary); font-size: var(--type-body-compact-size); font-weight: var(--weight-semibold); font-variant-numeric: tabular-nums; white-space: nowrap; }.word-count-popover dd.word-count-note { grid-column: 1 / -1; color: var(--text-tertiary); font-size: var(--type-micro-size); font-weight: var(--weight-regular); line-height: var(--type-micro-line-height); white-space: normal; text-wrap: pretty; min-width: 0; overflow-wrap: anywhere; }/* The save slot's details: a sentence or two above the rows when there is   something to say (offline, a failed write), and the actions under them. */.save-state-popover { display: grid; gap: var(--space-2); }.save-state-popover > strong { padding: var(--space-4) var(--space-6) 0; color: var(--text-primary); font-size: var(--type-body-compact-size); font-weight: var(--weight-semibold); overflow-wrap: anywhere; }.save-state-popover > p { margin: 0; padding: 0 var(--space-6); color: var(--text-secondary); font-size: var(--type-caption-size); line-height: var(--type-caption-line-height); text-wrap: pretty; }.save-state-popover > p.save-state-reason { color: var(--text-primary); font-family: var(--editor-font); font-size: var(--type-micro-size); overflow-wrap: anywhere; }.save-state-popover .save-state-actions { display: flex; flex-wrap: wrap; gap: var(--space-3); padding: var(--space-2) var(--space-6) var(--space-4); }.save-state-popover > dl + .save-state-actions { padding-top: 0; }/* At the narrowest steps More lists what the bar folded: the counters as   rows that open their drawers, the open count at the end in the accent,   then the word counts by scope. */.status-more-rows { --fluid-hover-fill: var(--control-hover-surface); position: relative; display: grid; padding-bottom: var(--space-2); border-bottom: 1px solid var(--border-subtle); }.status-more-row { min-height: var(--row-height-compact); border: 0; border-radius: calc(var(--nested-radius) * var(--nested-corner-smoothing, 1)); corner-shape: var(--nested-corner-shape, round); padding: 0 var(--space-4); background: transparent; color: var(--text-primary); font: inherit; font-size: var(--type-body-compact-size); line-height: var(--type-body-compact-line-height); display: flex; align-items: center; gap: var(--space-4); text-align: left; cursor: pointer; }.status-more-row > svg { flex: none; width: 14px; height: 14px; stroke-width: 1.5; color: var(--text-secondary); }.status-more-row > span:first-of-type { flex: 1 1 auto; min-width: 0; }.status-more-row .status-count { font-weight: var(--weight-medium); font-variant-numeric: tabular-nums; color: var(--text-secondary); }.status-more-row[data-active] :is(svg, .status-count) { color: var(--control-active); }/* `.modal` (dialogs.css) loads later with its own width and padding, so these   carry the base class too or they silently lose to it. */.modal.quick-open-modal { width: min(560px, calc(100vw - 40px)); padding: 0; overflow: hidden; }.quick-open-header { position: relative; padding: var(--space-3) var(--space-4); display: flex; align-items: center; }.quick-open-header::after { content: ""; position: absolute; inset-inline: 0; bottom: 0; height: 1px; background: var(--border-subtle); }/* The divider already frames the query, so the field drops its own box; it   stands a row taller than the results, so the query reads as the way in. */.quick-open-header .ui-search-field { height: var(--row-height-default); border-color: transparent; background: transparent; }.quick-open-header .ui-search-field-input { font-size: var(--type-body-size); line-height: var(--type-body-line-height); }/* Pickers whose details are short (the command palette's shortcuts) keep each   row to one line, with the detail trailing at the end. */.quick-open-modal[data-detail="end"] .quick-open-list button { flex-direction: row; align-items: center; justify-content: space-between; gap: var(--space-8); }.quick-open-modal[data-detail="end"] .picker-label { flex: 1 1 auto; }.quick-open-modal[data-detail="end"] .picker-detail { flex: 0 1 auto; max-width: 45%; }.quick-open-list { --surface-radius: var(--radius-dialog); --surface-inset: var(--space-3); padding: var(--surface-inset); display: grid; }/* Arrowing to a row past the fold stops it clear of the edge fades. */.quick-open-scroll [data-slot="scroll-area-viewport"] { max-height: min(360px, 50vh); scroll-padding-block: var(--scroll-fade-size); }.quick-open-list button { min-height: var(--row-height-compact); border: 0; border-radius: calc(var(--nested-radius) * var(--nested-corner-smoothing, 1)); corner-shape: var(--nested-corner-shape, round); padding: var(--space-3) var(--space-5); background: transparent; color: var(--text-primary); text-align: left; font-size: var(--type-body-size); line-height: var(--type-body-line-height); display: flex; flex-direction: column; align-items: stretch; justify-content: center; gap: var(--gap-tight); min-width: 0; overflow: hidden; }/* The pointer moves the current row too (on a real move), so `.active` is the   only highlight; a :hover fill would light a second row under a resting   pointer while the arrows move on. */.quick-open-list { --fluid-hover-fill: var(--control-active-soft); }.quick-open-list button.active { background: var(--control-active-soft); color: var(--text-primary); }/* A block: labels are plain text, and an ellipsis draws only in a block   container, so a long file name ends in "…" rather than mid-letter. */.quick-open-list .picker-label { min-width: 0; display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }/* One heading per section at the caption role, quiet enough that the rows   stay the thing to read. */.quick-open-list .picker-section { padding: var(--space-6) var(--space-5) var(--space-2); color: var(--text-secondary); font-size: var(--type-caption-size); line-height: var(--type-caption-line-height); font-weight: var(--weight-medium); }/* The first heading by class, not :first-of-type: the hover fill is a div that   mounts first in the list, and counting it moved every row 8px down under a   fill measured before it came. */.quick-open-list .picker-section:not(.picker-section ~ .picker-section) { padding-top: var(--space-2); }.quick-open-list .picker-file { min-width: 0; display: flex; align-items: center; gap: var(--space-4); }.quick-open-list .picker-file-icon { flex: none; display: inline-flex; color: var(--text-secondary); }.quick-open-list button.active .picker-file-icon { color: var(--text-primary); }.quick-open-list .picker-file-name { flex: none; max-width: 70%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-primary); }.quick-open-list button.active .picker-file-name { color: inherit; }.quick-open-list .picker-file-folder { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-secondary); font-size: var(--type-caption-size); }.quick-open-list .picker-detail { color: var(--text-secondary); font-size: var(--type-caption-size); font-style: normal; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }/* A row with an icon or a shortcut: icon, then its text, then the keycaps at   the end, all on one line whatever the detail placement. */.quick-open-list button:has(> .picker-text) { flex-direction: row; align-items: center; gap: var(--space-4); }.quick-open-list .picker-icon { flex: none; display: inline-flex; color: var(--text-secondary); }/* The palette's icon symbols: in the document for <use>, never on screen. */.picker-icon-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }.quick-open-list button.active .picker-icon { color: var(--text-primary); }.quick-open-list .picker-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: var(--gap-tight); }.quick-open-modal[data-detail="end"] .picker-text { flex-direction: row; align-items: baseline; justify-content: space-between; gap: var(--space-8); }.quick-open-list .picker-shortcut { flex: none; margin-inline-start: var(--space-2); }/* The command palette reaches files, papers and settings as well as   commands, so it gives its rows more room than the single-purpose pickers. *//* A query that found nothing names what was not found, set as an empty   state's title and description, at the rows' text edge; the one row that   may still answer it (the palette's Find in project) follows. */.picker-no-match { padding: var(--space-8) var(--space-8) var(--space-2); display: grid; gap: var(--space-1); color: var(--text-tertiary); font-size: var(--type-caption-size); line-height: var(--type-caption-line-height); overflow-wrap: anywhere; }.picker-no-match > strong { color: var(--text-primary); font-size: var(--type-subtitle-size); line-height: var(--type-subtitle-line-height); font-weight: var(--type-subtitle-weight); }.picker-no-match:has(+ .quick-open-scroll[hidden]) { padding-bottom: var(--space-8); }.quick-open-scroll[hidden] { display: none; }.modal.quick-open-modal.command-palette-modal { width: min(640px, calc(100vw - 40px)); }.command-palette-modal .quick-open-scroll [data-slot="scroll-area-viewport"] { max-height: min(460px, 60vh); }.command-palette-footer { position: relative; padding: var(--space-4) var(--space-6); display: flex; align-items: center; justify-content: flex-end; gap: var(--space-8); color: var(--text-secondary); font-size: var(--type-caption-size); line-height: var(--type-caption-line-height); }.command-palette-footer::before { content: ""; position: absolute; inset-inline: 0; top: 0; height: 1px; background: var(--border-subtle); }.command-palette-footer > span { display: inline-flex; align-items: center; gap: var(--space-3); white-space: nowrap; }/* Quick open marks the typed characters in each name: semibold on an accent   underline, the rest of the name a step quieter, so the match is what reads. */.quick-open-list .picker-match { background: none; color: var(--text-primary); font-weight: var(--weight-semibold); text-decoration: underline; text-decoration-color: color-mix(in srgb, var(--accent) 55%, transparent); text-decoration-thickness: 1.5px; text-underline-offset: 3px; }.quick-open-list .picker-file-name:has(.picker-match) { color: var(--text-secondary); }/* "Current" or the `:42` a query asked for, at the row's end. */.quick-open-list .picker-file-tag { margin-inline-start: auto; flex: none; padding-inline-start: var(--space-4); color: var(--text-tertiary); font-size: var(--type-caption-size); font-variant-numeric: tabular-nums; white-space: nowrap; }/* The prefixes, the one thing the footer shows (↑↓ and ↵ need no telling), lead at the start. */.quick-open-footer .quick-open-scopes { display: inline-flex; gap: var(--space-8); margin-inline-end: auto; min-width: 0; overflow: hidden; }.quick-open-footer .quick-open-scopes > span { display: inline-flex; align-items: center; gap: var(--space-3); white-space: nowrap; }/* A narrow window drops the line prefix first: it is the one the writer can reach with ⌘G. */@media (max-width: 480px) { .quick-open-footer .quick-open-scopes > span:last-child { display: none; } }/* Each crumb (separator and button) is the flex item, so it is the one that   must be allowed under its text's width: then the button ellipsizes, where a   crumb wider than the bar was cut at both ends of the centred row. */.modal:is(.goto-line-modal, .figure-insert-modal) { width: min(420px, calc(100vw - 40px)); }.goto-line-field { display: flex; align-items: center; gap: var(--space-4); }.goto-line-field > input { flex: 1 1 auto; min-width: 0; }.goto-line-range { flex: none; color: var(--text-secondary); font-weight: var(--weight-regular); font-variant-numeric: tabular-nums; }.canvas-body { position: relative; flex: 1 1 0; min-width: 0; min-height: 0; width: 100%; max-width: 100%; display: flex; flex-direction: column; overflow: hidden; }.primary-opening-overlay { position: absolute; inset: 0; z-index: var(--z-editor-popover); display: flex; align-items: center; justify-content: center; background: color-mix(in srgb, var(--surface-app) 82%, transparent); color: var(--text-secondary); cursor: progress; }/* The titlebar overrides this height to fill its single chrome row. Keeping the   strip's own default compact also makes the component usable in isolation. *//* While a tab is being dragged, the whole strip shows the grab cursor and stops   selecting text under the pointer. *//* Embedded documents own their pointer stream. Let the parent canvas receive   the rest of a tab/tree drag so HTML previews remain valid split drop targets. *//* The bibliography entry editor shares the Add papers sheet's frame (see   --dialog-sheet-width) so "Enter manually" swaps contents, not sizes. The   form is a column: the lookup, the entry as it reads, the work (title,   authors, year beside venue), then the record (DOI, URL, type, key) past a   hairline. Each field's label sits at its start, the way a reference   manager's info pane reads, so the whole entry fits the sheet unscrolled. */.modal.sheet-dialog.bib-entry-dialog { width: var(--dialog-sheet-width); container: bib-entry / inline-size; }.bib-entry-form { display: grid; gap: var(--space-8); }.bib-entry-form label { min-width: 0; display: flex; flex-direction: column; gap: var(--space-3); color: var(--text-secondary); font-size: var(--type-caption-size); line-height: var(--type-caption-line-height); font-weight: var(--weight-medium); font-family: var(--ui-font); }/* Four columns: a label, its field, and on a shared row a second label and   field; a label on a row of its own spans them and its field takes the rest. */.bib-entry-group { display: grid; text-align: start; grid-template-columns: 64px minmax(0, 1fr) auto minmax(0, 1fr); gap: var(--space-5) var(--space-5); align-items: center; }.bib-entry-form .bib-entry-group > label { grid-column: span 2; display: grid; grid-template-columns: subgrid; align-items: center; gap: inherit; }.bib-entry-label { min-width: 0; overflow-wrap: anywhere; }/* A year is four digits: its column holds them and the stepper, and the venue takes the rest. */.bib-entry-work { grid-template-columns: 64px 112px auto minmax(0, 1fr); }.bib-entry-form .bib-entry-work > label:nth-child(-n + 2) { grid-column: 1 / -1; }.bib-entry-work > label:nth-child(-n + 2) > :last-child { grid-column: 2 / -1; }.bib-entry-record { padding-top: var(--space-8); border-top: 1px solid var(--border-subtle); }.bib-citation-records { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-4); font: var(--type-caption-size)/1.5 var(--ui-font); }.bib-citation-records[data-edited] .bib-citation-evidence { color: var(--text-tertiary); }/* How a record was matched: one quiet line, its parts set apart by spacing;   the source links to the record without leaving the type's own ink. */.bib-citation-evidence { display: inline-flex; flex-wrap: wrap; align-items: center; color: var(--text-secondary); }.bib-citation-evidence > span + span::before { content: "\00a0"; padding-inline: var(--space-3); }.bib-evidence-source { color: inherit; text-decoration: underline; text-decoration-color: var(--border-strong); text-underline-offset: 2px; transition: color var(--motion-fast), text-decoration-color var(--motion-fast); }.bib-evidence-source:hover { color: var(--text-primary); text-decoration-color: currentColor; }/* Records a lookup could not tell apart: one radio list in a raised card, each   record read as it would be cited, the chosen one washed and edged in the accent. */.bib-candidates { display: grid; gap: var(--space-5); }.bib-candidate-list { border: 1px solid var(--border-subtle); border-radius: var(--radius-panel); overflow: hidden; background: var(--surface-panel-raised); }.bib-candidate-list .bib-candidate { padding: var(--space-6) var(--space-8) var(--space-6) var(--space-6); display: grid; grid-template-columns: 16px minmax(0, 1fr); align-items: start; gap: var(--space-5); cursor: pointer; color: var(--text-primary); font-weight: var(--weight-regular); transition: background-color var(--motion-fast); }.bib-candidate + .bib-candidate { border-top: 1px solid var(--border-subtle); }.bib-candidate:hover { background: var(--control-hover-surface); }.bib-candidate[data-chosen] { background: color-mix(in srgb, var(--control-active) 6%, transparent); box-shadow: inset 2px 0 0 var(--control-active); }.bib-candidate > input { margin: var(--space-2) 0 0; accent-color: var(--control-active); }.bib-candidate-body { min-width: 0; display: grid; gap: var(--space-1); }.bib-candidate-body > strong { overflow-wrap: anywhere; font-family: var(--reading-font); font-size: var(--type-typeset-size); line-height: var(--type-body-line-height); font-weight: var(--weight-regular); text-wrap: pretty; }.bib-candidate-byline { color: var(--text-secondary); font-size: var(--type-caption-size); line-height: var(--type-caption-line-height); overflow-wrap: anywhere; }.bib-candidate-body > em { color: var(--text-secondary); font-family: var(--reading-font); font-size: var(--type-caption-size); line-height: var(--type-caption-line-height); overflow-wrap: anywhere; }.bib-candidate-evidence { margin-top: var(--space-2); display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-4); color: var(--text-secondary); font-size: var(--type-micro-size); line-height: var(--type-micro-line-height); }.bib-candidate-kind { height: 18px; padding: 0 var(--space-3); border-radius: var(--radius-compact); display: inline-flex; align-items: center; flex: none; font-weight: var(--weight-medium); white-space: nowrap; color: var(--text-secondary); box-shadow: inset 0 0 0 1px var(--border-subtle); }.bib-candidate-kind[data-kind="published"] { color: color-mix(in srgb, var(--status-success) 80%, var(--text-primary)); background: var(--status-success-soft); box-shadow: none; }

Lines 1–500 of 1371.