texlite 0.6.7 → 0.6.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ :root{font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;color:#202421;background:#f3f4f1;font-synthesis:none}*{box-sizing:border-box}html,body,#root{margin:0;min-height:100%}button,input,select,textarea{font:inherit}button{cursor:pointer}button:disabled{cursor:not-allowed;opacity:.45}.muted{color:#737a75}.error{color:#b3261e;font-size:14px}.dialog-error{margin:0;padding:8px 10px;border:1px solid #e9b6b0;border-radius:6px;background:#fff3f1}.field-hint{color:#778179;font-size:11px;font-weight:400}.primary,.compile{border:0;border-radius:8px;background:#176b44;color:#fff;padding:10px 18px;font-weight:650}.icon-button{display:inline-flex;align-items:center;gap:6px}.ghost{border:0;background:transparent;color:inherit}.page{min-height:100vh;display:flex;flex-direction:column}.login-page{min-height:100vh;display:grid;grid-template-rows:1fr auto;place-items:center;padding-top:44px;background:radial-gradient(circle at 50% 0,#d8e8dd,#f5f5f1 45%)}.login-card{width:min(390px,calc(100vw - 32px));padding:38px;display:flex;flex-direction:column;gap:16px;background:#ffffffeb;border:1px solid #dfe4df;border-radius:16px;box-shadow:0 24px 70px #1d31241f}.login-card h1{text-align:center;margin:0;letter-spacing:-.04em}.login-card>p{text-align:center;margin:-8px 0 8px}.login-card label,.settings label{display:flex;flex-direction:column;gap:7px;font-size:13px;font-weight:650}.login-card input,.settings input,.settings select,.settings textarea{width:100%;border:1px solid #cbd2cc;border-radius:8px;padding:10px 11px;background:#fff;outline:none}.login-card input:focus,.settings input:focus{border-color:#176b44;box-shadow:0 0 0 3px #176b4420}.site-logo{width:40px;height:40px;flex:none;display:inline-flex;align-items:center;justify-content:center}.site-logo img{display:block;width:100%;height:100%}.site-logo.compact{width:34px;height:34px;margin:0 16px 0 10px}.site-logo.auth-logo{width:76px;height:76px;margin:0 auto 2px;filter:drop-shadow(0 10px 18px #1e2a4a25)}.site-title{margin-right:11px;font-size:20px;font-weight:800;letter-spacing:-.04em}.sr-only{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.support{color:#737a75;text-align:center}.topbar,.editor-topbar{height:62px;display:flex;align-items:center;padding:0 26px;background:#123c2a;color:#fff}.top-actions{margin-left:auto;display:flex;align-items:center;gap:18px;font-size:14px}.top-actions .ghost{display:inline-flex;align-items:center;gap:5px}.top-user-identity{min-width:0;display:flex;flex-direction:column;line-height:1.15}.top-user-identity strong{overflow:hidden;max-width:180px;font-size:13px;font-weight:650;text-overflow:ellipsis;white-space:nowrap}.top-user-identity small{overflow:hidden;max-width:180px;margin-top:3px;color:#b9d0c2;font-size:10px;text-overflow:ellipsis;white-space:nowrap}.language-switcher{position:fixed;top:18px;right:20px;z-index:5;display:flex;align-items:center;gap:6px;color:#536059;font-size:12px}.language-switcher select{border:1px solid #c9d0ca;border-radius:6px;padding:5px 7px;background:#fff;color:#26342b}.language-switcher.compact{position:static;color:inherit}.language-switcher.compact select{border-color:#ffffff35;background:#ffffff10;color:inherit}.language-switcher.compact option{color:#202421}.dashboard{width:100%;max-width:1180px;flex:1;margin:0 auto;padding:52px 34px}.site-footer{width:100%;display:flex;align-items:center;justify-content:center;flex-wrap:wrap;gap:7px 16px;padding:18px 24px;border-top:1px solid #dfe3df;background:#eef0ed;color:#737b75;font-size:11px;text-align:center}.site-footer a{color:#176b44;text-decoration:none}.site-footer a:hover{text-decoration:underline}.login-page>.site-footer{align-self:end;background:#ffffff50}.section-title{display:flex;justify-content:space-between;align-items:end;margin-bottom:28px}.section-title h1{display:flex;align-items:center;gap:9px;margin:0;font-size:30px;letter-spacing:-.04em}.section-title h1 svg{flex:none;color:#315b43}.section-title p{margin:7px 0 0}.section-actions{display:flex;gap:9px}.section-actions>button{display:inline-flex;align-items:center;gap:6px;border:1px solid #bfc8c1;border-radius:8px;background:#fff;padding:10px 16px}.section-actions>.primary{border-color:#176b44;background:#176b44;color:#fff}.project-toolbar{display:flex;align-items:center;flex-wrap:wrap;gap:12px;margin-bottom:18px;padding:10px;background:#e9ece8;border-radius:10px}.project-toolbar>input{width:220px;border:1px solid #cbd2cc;border-radius:7px;padding:8px 10px;background:#fff}.project-scope{display:flex;flex:none;gap:2px}.project-scope button{display:flex;align-items:center;gap:5px;flex:none;border:1px solid transparent;border-radius:7px;padding:7px 9px;background:transparent;color:#536059;font-size:12px}.project-scope button.active{border-color:#b8c4ba;background:#fff;color:#174b33}.tag-filters{min-width:0;flex:1;display:flex;gap:6px;overflow-x:auto}.tag-filters button,.view-toggle button{display:flex;align-items:center;gap:5px;flex:none;border:1px solid transparent;border-radius:7px;padding:7px 9px;background:transparent;color:#536059;font-size:12px}.tag-filters button.active,.view-toggle button.active{border-color:#b8c4ba;background:#fff;color:#174b33}.project-sort{flex:none;display:flex;align-items:center;gap:5px;color:#536059;font-size:11px}.project-sort>span{white-space:nowrap}.project-sort select{max-width:150px;border:1px solid #c4ccc6;border-radius:7px;padding:7px 25px 7px 8px;background:#fff;color:#34433a;font-size:12px}.view-toggle{display:flex;gap:2px}.project-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(270px,1fr));gap:16px}.project-card{position:relative;min-height:250px;display:flex;flex-direction:column;text-align:left;background:#fff;border:1px solid #dfe2de;border-radius:12px;overflow:hidden;transition:.15s ease}.project-card:hover{border-color:#8bae9a;transform:translateY(-2px);box-shadow:0 10px 30px #25352a10}.project-card-open{all:unset;box-sizing:border-box;min-width:0;flex:1;display:flex;flex-direction:column;align-items:flex-start;gap:10px;padding:20px 20px 14px;cursor:pointer}.project-card-open:focus-visible{outline:3px solid #176b4455;outline-offset:-3px}.project-card strong{font-size:17px}.project-card-main{min-width:0;display:flex;flex-direction:column;gap:7px}.project-tags,.settings-tags{display:flex;flex-wrap:wrap;gap:5px}.owner-badge{max-width:100%;overflow:hidden;padding:6px 9px;border-radius:7px;background:#e2f0e7;color:#176b44;font-size:11px;font-weight:750;text-overflow:ellipsis;white-space:nowrap}.project-grid:not(.list-view) .owned-project .owner-badge{max-width:calc(100% - 94px)}.project-transfer-action{position:absolute;z-index:2;top:17px;right:16px;display:inline-flex;align-items:center;gap:4px;border:1px solid #cbd7cf;border-radius:6px;padding:5px 7px;background:#f7faf8;color:#315c43;font-size:10px}.project-transfer-action:hover{border-color:#8caf99;background:#e8f1eb;color:#176b44}.project-meta{width:100%;display:grid;grid-template-columns:1fr;gap:8px;margin:auto 0 0}.project-meta div{min-width:0}.project-meta dt{display:flex;align-items:center;gap:4px;color:#8a918c;font-size:10px;text-transform:uppercase}.project-meta dt svg{flex:none;color:#6f8e7a}.project-meta dd{overflow:hidden;margin:2px 0 0;color:#555e58;font-size:11px;text-overflow:ellipsis;white-space:nowrap}.project-grid:not(.list-view) .project-meta dd{overflow:visible;text-overflow:clip;white-space:normal;overflow-wrap:anywhere}.project-modified-by{color:#68716b}.project-card-actions{display:flex;flex-wrap:wrap;gap:5px;padding:9px 12px;border-top:1px solid #eceeeb;background:#fafbf9}.project-card-actions button,.project-card-actions a{display:inline-flex;align-items:center;gap:5px;border:0;border-radius:5px;padding:5px 7px;background:transparent;color:#4f5b53;font-size:11px;text-decoration:none}.project-card-actions button:hover,.project-card-actions a:hover{background:#e8eeea;color:#176b44}.project-card-actions .danger-text{margin-left:auto;color:#b3261e}.project-grid:not(.list-view) .project-card-actions{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:4px}.project-grid:not(.list-view) .project-card-actions button,.project-grid:not(.list-view) .project-card-actions a{width:100%;min-width:0;justify-content:flex-start;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.project-grid:not(.list-view) .project-card-actions .danger-text{margin-left:0}.project-grid.list-view{display:flex;flex-direction:column;gap:7px}.project-grid.list-view .project-card{min-height:88px;flex-direction:row;align-items:stretch}.project-grid.list-view .project-card-open{display:grid;grid-template-columns:minmax(90px,140px) minmax(170px,1fr) minmax(390px,2fr);align-items:center;gap:14px;padding:12px 15px}.project-grid.list-view .project-card-main{min-width:170px}.project-grid.list-view .project-meta{grid-template-columns:minmax(145px,.75fr) minmax(0,1.25fr);gap:8px 12px;margin:0}.project-grid.list-view .project-meta>div:last-child dd{overflow:visible;text-overflow:clip;white-space:normal;overflow-wrap:anywhere}.project-grid.list-view .project-card-actions{width:190px;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));align-content:center;gap:4px;border-top:0;border-left:1px solid #eceeeb}.project-grid.list-view .project-card-actions button,.project-grid.list-view .project-card-actions a{width:100%;justify-content:flex-start}.project-grid.list-view .project-card-actions .danger-text{margin-left:0}.project-comments-badge{display:inline-flex;align-items:center;gap:3px;width:fit-content;border-radius:999px;padding:1px 6px;font-size:10px;font-weight:650;line-height:1.4}.project-comments-badge.unresolved{background:#fde8e7;color:#b3261e;border:1px solid #f8c8c5}.tag{display:inline-flex;align-items:center;gap:4px;width:fit-content;border-radius:999px;padding:2px 7px;background:#eef0ee;color:#4a524c;font-size:10px;font-weight:650}.tag-dot{display:inline-block;width:9px;height:9px;border-radius:50%;background:currentColor}.tag-red{--tag-color: #e04b45}.tag-orange{--tag-color: #ef9135}.tag-yellow{--tag-color: #dbb62f}.tag-green{--tag-color: #49a563}.tag-blue{--tag-color: #4c83db}.tag-purple{--tag-color: #9566ce}.tag-gray{--tag-color: #929994}.tag-dot[class*=tag-]{color:var(--tag-color)}.tag[class*=tag-]{border:1px solid color-mix(in srgb,var(--tag-color) 35%,transparent);background:color-mix(in srgb,var(--tag-color) 12%,white)}.empty,.center-card{padding:50px;color:#737a75;text-align:center}.project-empty{grid-column:1 / -1;width:100%;min-height:320px;display:flex;align-items:center;justify-content:center;flex-direction:column;box-sizing:border-box;padding:64px 24px;border:1px dashed #cbd7ce;border-radius:14px;background:linear-gradient(145deg,#fbfcfa,#f2f7f3);text-align:center}.project-empty-icon{width:58px;height:58px;display:grid;place-items:center;margin-bottom:18px;border-radius:18px;background:#dfeee4;color:#176b44}.project-empty h2{margin:0;color:#203f2e;font-size:clamp(27px,3vw,38px);line-height:1.15;letter-spacing:-.035em}.project-empty p{max-width:520px;margin:13px 0 0;color:#6e7b72;font-size:15px;line-height:1.6}.project-pagination{display:flex;align-items:center;justify-content:center;gap:12px;margin:22px 0 4px;color:#66726a;font-size:12px}.project-pagination button{display:inline-flex;align-items:center;gap:5px;border:1px solid #cbd4ce;border-radius:7px;padding:7px 10px;background:#fff;color:#405248;font-size:12px}.project-pagination button:hover:not(:disabled){border-color:#8bae9a;background:#f2f7f3;color:#176b44}.table-card{overflow:hidden;background:#fff;border:1px solid #dfe2de;border-radius:12px}table{width:100%;border-collapse:collapse}th,td{padding:14px 18px;border-bottom:1px solid #eceeeb;text-align:left;font-size:14px}th{background:#f8f9f7;color:#667069;font-size:12px;text-transform:uppercase}td small{display:block;color:#7d837f;margin-top:3px}td button{margin-right:8px;border:1px solid #cdd2ce;background:#fff;border-radius:5px;padding:5px 9px}.danger-text{color:#b3261e}.workspace{height:100vh;display:flex;flex-direction:column;overflow:hidden}.editor-topbar{height:56px;padding:0 14px;flex:none}.back{color:#fff;border:0;background:#ffffff10;width:32px;height:32px;display:grid;place-items:center;border-radius:6px}.project-heading{display:flex;flex-direction:column;min-width:0;margin-right:auto}.project-heading small{color:#b9d0c2;font-size:11px;margin-top:2px}.vim-status-badge{display:inline-flex;align-items:center;gap:5px;margin-right:8px;border:1px solid #7fd39e80;border-radius:999px;padding:5px 9px;background:#1d6b4638;color:#d7ffe3;font-size:10px;font-weight:750;letter-spacing:.04em;white-space:nowrap}.vim-status-badge svg{color:#9df0b5}.collaboration-presence{min-width:0;display:flex;align-items:center;gap:7px;padding-left:8px}.collaboration-status-dot{width:7px;height:7px;flex:none;border-radius:50%;background:#efb84b;box-shadow:0 0 0 2px #efb84b2e}.collaboration-connected .collaboration-status-dot{background:#69d391;box-shadow:0 0 0 2px #69d3912e}.collaboration-disconnected .collaboration-status-dot{background:#e07167;box-shadow:0 0 0 2px #e071672e}.collaboration-avatars{display:flex;align-items:center;padding-left:8px}.collaboration-avatar{--session-color: #1677c8;position:relative;width:28px;height:28px;display:grid;place-items:center;margin-left:-8px;border:2px solid #214d35;border-radius:50%;background:var(--session-color);color:#fff;font-size:11px;font-weight:750;cursor:default;box-shadow:0 1px 4px #061c1145}.collaboration-avatar.editing:after{content:"";position:absolute;right:-2px;bottom:-2px;width:7px;height:7px;border:2px solid #214d35;border-radius:50%;background:#8ff0af}.collaboration-avatar.local{outline:1px solid #ffffff8a;outline-offset:-4px}.collaboration-avatar-overflow{appearance:none;padding:0;border-color:#72877b;background:#f4f7f5;color:#284536;font-family:inherit;font-size:10px;cursor:pointer}.collaboration-avatar-overflow:hover,.collaboration-avatar-overflow:focus-visible{background:#dfe9e3;outline:2px solid #9bc6aa;outline-offset:1px}.collaboration-avatar-tooltip{position:absolute;z-index:80;top:calc(100% + 9px);right:-8px;width:max-content;max-width:280px;display:none;gap:2px;padding:9px 11px;border:1px solid #d7ded9;border-radius:7px;background:#fff;color:#20352a;font-size:12px;font-weight:400;line-height:1.35;text-align:left;box-shadow:0 8px 24px #061c1130}.collaboration-avatar-tooltip:before{content:"";position:absolute;top:-5px;right:15px;width:8px;height:8px;transform:rotate(45deg);border-left:1px solid #d7ded9;border-top:1px solid #d7ded9;background:#fff}.collaboration-avatar-tooltip strong,.collaboration-avatar-tooltip span,.collaboration-avatar-tooltip small{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.collaboration-avatar-tooltip strong{font-size:13px}.collaboration-avatar-tooltip span{color:#526158}.collaboration-avatar-tooltip small{margin-top:3px;color:#77837b;font-size:11px}.collaboration-avatar:hover .collaboration-avatar-tooltip,.collaboration-avatar:focus-visible .collaboration-avatar-tooltip{display:block}.collaboration-recovery{min-width:0;display:inline-flex;align-items:center;gap:7px;margin:0 8px;border:1px solid #e0716780;border-radius:999px;padding:4px 6px 4px 9px;background:#6f2b2b66;color:#ffe0dd;font-size:10px;white-space:nowrap}.collaboration-recovery button{border:1px solid #ffffff55;border-radius:999px;padding:3px 7px;background:#ffffff18;color:inherit;font-size:10px}.collaboration-recovery button:hover{background:#ffffff2c}.compile-status-strip{min-height:31px;display:flex;align-items:center;justify-content:center;gap:7px;padding:6px 14px;background:#fff6dc;color:#72530d;border-bottom:1px solid #e8cd7d;font-size:11px}.compile-status-strip.failed{background:#fff0ee;color:#9a3028;border-bottom-color:#e8aaa4}.editor-actions{display:flex;gap:8px}.editor-actions button{padding:8px 10px;display:inline-flex;align-items:center;gap:6px;border-radius:6px;border:1px solid #ffffff28;color:#fff;background:#ffffff0d;font-size:12px;white-space:nowrap}.editor-actions .compile{background:#f3b943;border-color:#f3b943;color:#193023;font-weight:700}.editor-actions button.active{background:#d9eadf;color:#164c33}.layout-menu{position:relative}.editor-actions .layout-trigger{min-width:138px;justify-content:flex-start;padding-block:5px}.layout-trigger>span{min-width:0;display:flex;flex:1;flex-direction:column;align-items:flex-start;line-height:1.15}.layout-trigger>span small{color:#b9d0c2;font-size:9px;font-weight:500;letter-spacing:.025em;text-transform:uppercase}.layout-trigger.active>span small{color:#52715f}.layout-popover{position:absolute;z-index:100;top:calc(100% + 8px);right:0;width:290px;padding:7px;border:1px solid #d4dcd6;border-radius:9px;background:#fff;color:#25362c;box-shadow:0 14px 38px #061c1138}.layout-popover-title{padding:6px 8px 8px;color:#768178;font-size:10px;font-weight:700;letter-spacing:.055em;text-transform:uppercase}.editor-actions .layout-option{width:100%;min-height:52px;display:grid;grid-template-columns:25px minmax(0,1fr) 18px;gap:9px;padding:8px 9px;border:0;color:#25362c;background:transparent;text-align:left}.editor-actions .layout-option:hover,.editor-actions .layout-option.selected{background:#edf5ef;color:#185d3d}.layout-option>span{min-width:0;display:flex;flex-direction:column;align-items:flex-start;gap:2px}.layout-option strong{font-size:12px}.layout-option small{color:#748078;font-size:10px;line-height:1.35;white-space:normal}.toast{position:fixed;z-index:10;top:66px;left:50%;transform:translate(-50%);background:#8f271f;color:#fff;padding:9px 16px;border-radius:7px;font-size:13px;box-shadow:0 8px 30px #0003}.toast.success{background:#1d6b46}.work-grid{min-height:0;flex:1;background:#fff}.resize-handle{position:relative;width:6px;flex:0 0 6px;display:grid;place-items:center;background:#e4e7e4;color:#98a09a;outline:none;transition:background .12s ease}.resize-handle:hover,.resize-handle[data-resize-handle-active]{background:#89ad98;color:#fff}.resize-handle svg{pointer-events:none}.sync-resize-handle{z-index:20!important;overflow:visible}.sync-direction-buttons{position:absolute;z-index:21;top:50%;left:50%;display:flex;flex-direction:row;gap:2px;padding:3px;transform:translate(-50%,-50%);border:1px solid #aebdb3;border-radius:7px;background:#fff;box-shadow:0 4px 16px #15251b38}.sync-direction-buttons button{width:27px;height:27px;display:grid;place-items:center;border:0;border-radius:4px;padding:0;background:transparent;color:#214d35;font-size:17px;font-weight:750;line-height:1}.sync-direction-buttons button:hover:not(:disabled){background:#deebe2;color:#176b44}.sync-direction-buttons button:disabled{cursor:not-allowed;opacity:.35}.sync-resize-handle .resize-grip{opacity:0}.cm-ySelectionInfo{opacity:1!important;padding:2px 5px!important;border-radius:4px 4px 4px 0;font-family:Inter,ui-sans-serif,system-ui,sans-serif!important;font-size:10px!important;transform:translateY(-2px);box-shadow:0 2px 5px #0002}.left-panel,.context-panel,.source-panel,.preview-panel{min-width:0;min-height:0;border-right:1px solid #dfe2de}.left-panel,.source-panel,.preview-panel,.context-panel{height:100%}.left-panel{display:flex;flex-direction:column;overflow:hidden}.files-panel{position:relative;min-height:180px;flex:3;overflow:auto;border-bottom:1px solid #dfe2de}.files-panel.drop-active{outline:2px solid #2c9564;outline-offset:-2px}.file-drop-overlay{position:absolute;z-index:8;inset:42px 0 0;min-height:130px;display:flex;align-items:center;justify-content:center;flex-direction:column;gap:6px;padding:16px;background:#e8f4edee;color:#185d3c;text-align:center;pointer-events:none;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.file-drop-overlay strong{font-size:13px}.file-drop-overlay span{max-width:90%;overflow:hidden;color:#5e7668;font-size:10px;text-overflow:ellipsis;white-space:nowrap}.outline-panel{min-height:150px;flex:2;overflow:auto}.panel-title{height:42px;display:flex;align-items:center;justify-content:space-between;padding:0 12px;border-bottom:1px solid #e6e8e5;color:#647069;text-transform:uppercase;font-size:11px;font-weight:700}.panel-title>span{min-width:0;display:flex;align-items:center;gap:6px}.panel-title button{width:28px;height:28px;display:grid;place-items:center;border:0;border-radius:5px;background:transparent;color:#5d6961}.panel-title button:hover{background:#e8eeea;color:#176b44}.file-tools{flex:none;display:flex;align-items:center;gap:4px;margin-left:8px}.file-tools button{box-sizing:border-box}.file-list{padding:6px 7px 10px}.file-entry{min-width:0;height:calc(1em + 18px);min-height:30px;display:flex;align-items:center;border-radius:5px;color:#4f5952}.file-entry:hover{background:#f0f3f0}.file-entry.active,.file-entry.selected{background:#e2efe7;color:#15583a;font-weight:650}.file-entry-main{min-width:0;height:100%;flex:1;overflow:hidden;display:flex;align-items:center;gap:5px;border:0;padding:0 4px;background:transparent;color:inherit;text-align:left;font-size:inherit}.file-entry-main span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.file-entry-main svg{flex:none;color:#28724e}.file-entry.root-document .file-entry-main>svg{color:#2d6f9f}.file-entry.compile-target{background:#e9f2ec;box-shadow:inset 2px 0 #28724e}.file-entry-main small{flex:none;padding:1px 4px;border-radius:999px;background:#d9eadf;color:#1d5b3e;font-size:8px;line-height:1.35}.folder-entry .file-entry-main svg:first-child{color:#78837b}.folder-entry .file-entry-main svg:nth-child(2){color:#d49b2d}.root-entry{padding-left:5px}.root-entry .file-entry-main svg{color:#d49b2d}.file-entry-action{width:26px;height:26px;flex:none;display:none;place-items:center;border:0;border-radius:4px;background:transparent;color:#657069}.file-entry:hover .file-entry-action,.file-entry:focus-within .file-entry-action{display:grid}.file-entry-action:hover{background:#dfe7e1;color:#176b44}.resource-download{display:inline-flex;align-items:center;gap:6px;text-decoration:none}.resource-preview-message{min-height:180px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;color:#536158;text-align:center}.resource-preview-message strong{color:#263d2e;font-size:15px}.resource-preview-message span{max-width:440px;color:#748078;font-size:12px}.resource-image-wrap{display:flex;max-height:min(620px,65vh);align-items:center;justify-content:center;overflow:auto;padding:8px;background:#e9ecea;border-radius:7px}.resource-image{display:block;max-width:100%;max-height:min(590px,62vh);object-fit:contain}.resource-pdf{width:100%;height:min(650px,68vh);border:1px solid #d9dfda;border-radius:6px;background:#69706c}.resource-text{max-height:min(650px,68vh);overflow:auto;margin:0;padding:14px;border:1px solid #d9dfda;border-radius:6px;background:#f7f9f7;color:#26352c;font:12px/1.55 ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;white-space:pre-wrap;overflow-wrap:anywhere}.source-panel{position:relative;overflow:hidden;display:flex;flex-direction:column;height:100%;min-height:0}.editor-tabs-bar{flex:none;min-height:35px;background:#eaefe9;border-bottom:1px solid #d4ded7;display:flex;align-items:stretch;padding:4px 6px 0;overflow:hidden}.editor-tabs-scroll{display:flex;align-items:stretch;gap:3px;overflow-x:auto;overflow-y:hidden;scrollbar-width:none}.editor-tabs-scroll::-webkit-scrollbar{display:none}.editor-tab-item{display:inline-flex;align-items:center;max-width:220px;border:1px solid #ccd6ce;border-bottom:0;border-radius:6px 6px 0 0;background:#dce4de;color:#55665c}.editor-tab-item:hover{background:#e6eee8;color:#1e3628}.editor-tab-item.active{background:#fff;border-color:#cad7ce;box-shadow:0 -1px 3px #0000000a}.editor-tab{display:inline-flex;align-items:center;gap:5px;min-width:0;flex:1 1 auto;padding:4px 7px 4px 10px;border:0;border-radius:6px 0 0;background:transparent;color:inherit;font:inherit;font-size:12px;text-align:left;cursor:pointer;-webkit-user-select:none;user-select:none;white-space:nowrap}.editor-tab:hover{color:#1e3628}.editor-tab.active{color:#184f36;font-weight:600}.editor-tab:focus-visible{position:relative;z-index:1;outline:2px solid #4c9a6d;outline-offset:-2px}.editor-tab-icon{display:inline-flex;align-items:center;color:#697a70}.editor-tab.active .editor-tab-icon{color:#184f36}.editor-tab-title{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.editor-tab-badge{font-size:9px;padding:1px 4px;border-radius:4px;background:#e3eee6;color:#1a6442;font-weight:600;flex-shrink:0}.editor-tab-close{display:inline-flex;align-items:center;justify-content:center;width:22px;height:24px;border:0;border-radius:0 5px 0 0;background:transparent;color:#76887e;padding:0;cursor:pointer;flex-shrink:0}.editor-tab-close:hover{background:#cbd7cf;color:#153123}.editor-tab-item.active .editor-tab-close:hover{background:#e3ece5;color:#184f36}.editor-tab-close:focus-visible{position:relative;z-index:1;outline:2px solid #4c9a6d;outline-offset:-2px}.editor-content-container{position:relative;flex:1 1 auto;min-height:0;height:100%;overflow:hidden}.editor-centered-notice{position:absolute;z-index:8;top:50%;left:50%;max-width:calc(100% - 32px);transform:translate(-50%,-50%);pointer-events:none;border:1px solid #69a780;border-radius:8px;padding:9px 15px;background:#1d6b46ed;color:#fff;font:600 12px/1.4 inherit;text-align:center;box-shadow:0 8px 26px #071d1238}.editor-shell{height:100%;min-height:0;display:flex;flex-direction:column}.editor-shell .editor-host{height:auto;min-height:0;flex:1 1 auto}.editor-host,.cm-editor{height:100%;min-height:0}.editor-host .cm-editor{font-family:inherit;font-size:inherit;line-height:inherit}.editor-host .cm-editor{font-variant-ligatures:contextual;font-feature-settings:"liga" 1,"calt" 1}.editor-host .cm-scroller{min-height:0;height:auto;flex:1 1 auto;overflow:auto;font-family:inherit;line-height:inherit}.editor-host .cm-panels{flex:none}.editor-host .cm-vim-panel{min-height:25px;display:flex;align-items:center;box-sizing:border-box;width:100%;border-top:1px solid #cbd8ce;padding:3px 10px;background:#f1f6f2;color:#31523e;font:11px/1.3 SFMono-Regular,Consolas,monospace}.vim-editor-status{min-height:25px;flex:0 0 25px;display:flex;align-items:center;box-sizing:border-box;border-top:1px solid #cbd8ce;padding:3px 10px;background:#f1f6f2;color:#31523e;font:11px/1.3 SFMono-Regular,Consolas,monospace}.editor-host .cm-content,.editor-host .cm-gutters{font-family:inherit;font-size:inherit}.cm-editor.cm-focused{outline:none}.editor-host .cm-spell-error-active{border-radius:2px;background:#f6d66f;box-shadow:0 0 0 1px #c99324;color:#3f3010;text-decoration:underline wavy #9b6715 1.5px;text-decoration-skip-ink:none}.editor-host .cm-panel.cm-search{padding:8px 38px 8px 10px;border-top:1px solid #ccd5cf;background:#f7f9f7;color:#35443a;box-shadow:0 -3px 10px #1f382710;font-family:Inter,ui-sans-serif,system-ui,sans-serif;font-size:12px;line-height:1.4}.editor-host .cm-panel.cm-search .cm-textfield{min-width:170px;height:29px;margin:2px 6px 2px 0;border:1px solid #bcc8c0;border-radius:5px;padding:4px 8px;background:#fff;color:#202b24;outline:none;font-family:inherit;font-size:12px}.editor-host .cm-panel.cm-search .cm-textfield:focus{border-color:#3d8a60;box-shadow:0 0 0 2px #3d8a6025}.editor-host .cm-panel.cm-search .cm-button{height:29px;margin:2px 5px 2px 0;border:1px solid #bdc8c0;border-radius:5px;padding:3px 9px;background:#fff;background-image:none;color:#31513d;font-family:inherit;font-size:12px;text-transform:none}.editor-host .cm-panel.cm-search .cm-button:hover{border-color:#7c9f89;background:#e9f1ec}.editor-host .cm-panel.cm-search label{display:inline-flex;align-items:center;gap:3px;margin:3px 9px 3px 0;color:#59665d;font-family:inherit;font-size:12px}.editor-host .cm-panel.cm-search input[type=checkbox]{accent-color:#176b44}.editor-host .cm-panel.cm-search [name=close]{top:8px;right:10px;width:25px;height:25px;border-radius:5px;color:#647069;font-size:19px;line-height:1}.editor-host .cm-panel.cm-search [name=close]:hover{background:#e3e9e5;color:#244d36}.editor-host .cm-search-count{display:inline-flex;align-items:center;min-height:29px;margin:2px 5px 2px 4px;color:#506057;font-size:12px;font-variant-numeric:tabular-nums;white-space:nowrap}.editor-host .cm-searchMatch{background:#f5d76e99;outline:1px solid #d9a91c88}.editor-host .cm-searchMatch.cm-searchMatch-selected{background:#f0a94a99;outline-color:#cc7720}.editor-host .cm-spell-error{text-decoration:underline wavy #c53b32 1.5px;text-decoration-skip-ink:none;text-decoration-thickness:1.5px}.editor-host .cm-grammar-warning{text-decoration:underline wavy #d19a26 1.5px;text-decoration-skip-ink:none;text-decoration-thickness:1.5px}.spell-suggestions-menu{position:fixed;z-index:1200;display:flex;min-width:190px;max-width:250px;flex-direction:column;gap:3px;padding:7px;border:1px solid #b9c8bd;border-radius:7px;background:#fff;box-shadow:0 10px 28px #1930222e;color:#26352c;font-size:12px}.spell-suggestions-title{padding:3px 6px 5px;color:#607067;font-size:10px;font-weight:700;letter-spacing:.02em;text-transform:uppercase}.spell-suggestions-message{padding:3px 6px 6px;border-bottom:1px solid #e2e8e3;color:#58685e;font-size:11px;line-height:1.4}.spell-suggestions-menu button{min-height:29px;border:1px solid transparent;border-radius:5px;padding:4px 8px;background:transparent;color:#214f37;font:inherit;text-align:left;cursor:pointer}.spell-suggestions-menu button:hover:not(:disabled),.spell-suggestions-menu button:focus-visible:not(:disabled){border-color:#a9c9b3;background:#edf6ef;outline:none}.spell-suggestions-menu button:disabled{color:#78847d;cursor:not-allowed;opacity:.7}.spell-suggestions-empty,.spell-suggestions-readonly{display:block;padding:4px 6px;color:#78847d;font-size:10px;line-height:1.35}.spell-suggestions-readonly{border-top:1px solid #e2e8e3;margin-top:3px;padding-top:7px}.cm-source-comment{background:#ffe49b99;border-bottom:2px solid #d68b00;cursor:text}.cm-source-comment-resolved{background:#dce5de99;border-bottom-color:#829087}.cm-comment-pin{color:#d68b00;font-size:9px;padding:0 2px;cursor:pointer}.preview-panel{display:flex;flex-direction:column;background:#6f7471}.preview-tabs{min-height:48px;flex:none;display:flex;align-items:stretch;padding:5px 6px 0;background:#4d544f}.preview-tab-list{min-width:0;flex:1;display:grid;grid-template-columns:minmax(0,1.8fr) minmax(120px,1fr);gap:3px}.preview-tabs button{min-width:0;display:flex;align-items:center;justify-content:center;gap:5px;border:0;border-radius:6px 6px 0 0;background:transparent;color:#d7dcd8;font-size:11px}.preview-tabs button.active{background:#f3f4f1;color:#184f36;font-weight:700}.preview-tabs button span{min-width:17px;padding:1px 4px;border-radius:999px;background:#ffffff20;font-size:9px}.preview-tabs button.active span{background:#dfe8e2}.preview-tabs .pdf-tab{justify-content:flex-start;padding:0 12px;font-size:12px}.preview-tabs button .pdf-tab-label{min-width:0;overflow:hidden;padding:0;border-radius:0;background:transparent;display:flex;flex-direction:column;align-items:flex-start;gap:2px;font-size:12px;line-height:1;text-overflow:ellipsis;white-space:nowrap}.preview-tabs button.active .pdf-tab-label{background:transparent}.preview-tabs .pdf-tab small{max-width:100%;overflow:hidden;color:#bcc4bf;font-size:8px;font-weight:400;line-height:1;text-overflow:ellipsis;white-space:nowrap}.preview-tabs .pdf-tab.active small{color:#65756c}.pdf-download-top{flex:none;display:inline-flex;align-items:center;gap:5px;margin-left:4px;padding:0 11px;border:0;border-radius:6px 6px 0 0;color:#d7dcd8;font-size:10px;text-decoration:none;white-space:nowrap}.pdf-download-top:hover{background:#ffffff1b;color:#fff}.preview-subtabs{height:36px;flex:none;display:flex;align-items:center;gap:3px;padding:4px 7px;border-bottom:1px solid #cfd6d1;background:#e4e9e5}.preview-subtabs button{display:inline-flex;align-items:center;gap:5px;height:28px;padding:0 10px;border:0;border-radius:5px;background:transparent;color:#58665d;font-size:10px}.preview-subtabs button:hover{background:#d8e3db;color:#205c40}.preview-subtabs button.active{background:#fff;color:#184f36;font-weight:700;box-shadow:0 1px 3px #26312b22}.preview-subtabs button span{min-width:16px;padding:1px 4px;border-radius:999px;background:#d5ded7;font-size:9px;text-align:center}.preview-subtabs button.active span{background:#dfe8e2}.preview-content{min-height:0;flex:1}.preview-pdf{overflow:hidden}.pdf-viewer{position:relative;width:100%;height:100%;min-height:0;display:flex;flex-direction:column}.pdf-toolbar{height:36px;flex:none;display:flex;align-items:center;justify-content:flex-end;gap:3px;padding:4px 8px;border-bottom:1px solid #343a36;background:#414843;color:#e4e8e5;font:11px/1 Inter,ui-sans-serif,system-ui,sans-serif}.pdf-toolbar button{height:27px;min-width:27px;display:inline-flex;align-items:center;justify-content:center;gap:5px;border:1px solid #ffffff24;border-radius:5px;padding:0 6px;background:#ffffff0b;color:inherit}.pdf-toolbar button:hover:not(:disabled){border-color:#ffffff48;background:#ffffff1b}.pdf-toolbar button:disabled{opacity:.3}.pdf-zoom-value{min-width:42px;text-align:center;font-variant-numeric:tabular-nums}.pdf-toolbar .pdf-fit-width{margin-left:3px;padding:0 8px}.pdf-compiling-overlay{position:absolute;z-index:4;inset:36px 0 0;display:flex;align-items:flex-start;justify-content:center;gap:8px;padding-top:24px;background:#26312bb8;color:#fff;font-size:13px;pointer-events:none}.pdf-compiling-overlay span{padding:3px 8px;border-radius:5px;background:#17231cdd}.pdf-loading-state{width:100%;height:100%;min-height:220px;display:grid;place-items:center;align-content:center;gap:10px;background:#6f7471;color:#eef2ef;font-size:12px}.pdf-document{position:relative;width:100%;min-width:0;min-height:0;flex:1;overflow-x:scroll;overflow-y:auto;overscroll-behavior:contain;scrollbar-color:#aeb8b1 #4f5652;scrollbar-width:auto;scrollbar-gutter:stable;padding:14px 14px 20px;background:#6f7471}.pdf-document::-webkit-scrollbar{width:12px;height:12px}.pdf-document::-webkit-scrollbar-track{background:#4f5652}.pdf-document::-webkit-scrollbar-thumb{min-width:38px;border:2px solid #4f5652;border-radius:999px;background:#aeb8b1}.pdf-document::-webkit-scrollbar-thumb:hover{background:#d5dcd7}.pdf-document::-webkit-scrollbar-corner{background:#4f5652}.pdf-pages{min-width:100%}.pdf-loading{min-height:220px;display:grid;place-items:center;align-content:center;gap:10px;color:#eef2ef;font-size:12px}.pdf-page{position:relative;flex:none;max-width:none;overflow:hidden;margin:0 auto 16px;background:#fff;box-shadow:0 3px 14px #0004}.pdf-page.loading{background:#f7f8f7}.pdf-page canvas{display:block;width:100%!important;max-width:100%;height:auto!important}.pdf-annotation-layer{position:absolute;inset:0;z-index:3;pointer-events:none}.pdf-annotation-link{position:absolute;display:block;pointer-events:auto;border-radius:2px;background:transparent;cursor:pointer}.pdf-annotation-link:hover{background:#3f9b6426;box-shadow:inset 0 0 0 1px #3f9b6440}.pdf-page figcaption{position:absolute;right:7px;bottom:5px;padding:2px 5px;border-radius:4px;background:#26312bb5;color:#fff;font-size:9px;pointer-events:none}.pdf-sync-marker{position:absolute;z-index:2;width:14px;height:14px;border:3px solid #ef9c24;border-radius:50%;transform:translate(-50%,-50%);background:#ffe0a580;box-shadow:0 0 0 4px #ef9c2435;pointer-events:none;animation:sync-pulse 1.2s ease-out}@keyframes sync-pulse{0%{box-shadow:0 0 0 14px #ef9c2460}to{box-shadow:0 0 0 4px #ef9c2435}}.preview-empty{height:100%;display:grid;place-content:center;gap:8px;color:#e7e9e7;text-align:center}.preview-empty span{font-size:12px;color:#c2c7c4}.preview-log,.preview-warnings,.preview-errors{overflow:auto;background:#202522}.preview-clean{overflow:auto;background:#f4f6f4}.preview-artifacts{overflow:hidden;background:#f4f6f4}.artifact-browser{width:100%;height:100%;min-height:0;display:grid;grid-template-columns:minmax(135px,38%) minmax(0,1fr)}.artifact-list{min-width:0;overflow:auto;border-right:1px solid #d9dedb;background:#fff}.artifact-row{min-width:0;display:flex;align-items:stretch;border-bottom:1px solid #edf0ee}.artifact-row.active{background:#e5f0e9}.artifact-row>button{min-width:0;flex:1;display:flex;align-items:center;gap:7px;padding:8px 6px 8px 9px;border:0;background:transparent;color:#33463b;text-align:left}.artifact-row>button:disabled{cursor:default;opacity:.7}.artifact-row>button>span{min-width:0;display:flex;flex-direction:column;gap:2px}.artifact-row strong{overflow:hidden;font-size:11px;font-weight:600;text-overflow:ellipsis;white-space:nowrap}.artifact-row small{color:#89928c;font-size:9px}.artifact-row>a{width:30px;flex:none;display:grid;place-items:center;color:#52705f}.artifact-row>a:hover{background:#dce8e0;color:#176641}.artifact-preview{min-width:0;min-height:0;display:flex;flex-direction:column;background:#202522;color:#dbe2dd}.artifact-preview>header{height:36px;flex:none;display:flex;align-items:center;justify-content:space-between;gap:8px;padding:0 10px;border-bottom:1px solid #39413c;background:#303732;font-size:11px}.artifact-preview>header strong{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.artifact-preview>header a{flex:none;display:inline-flex;align-items:center;gap:4px;color:#c9ddd1}.artifact-preview>pre{min-height:0;flex:1;margin:0;overflow:auto;padding:13px;white-space:pre-wrap;overflow-wrap:anywhere;font:11px/1.55 SFMono-Regular,Consolas,monospace}.compile-output{min-height:100%;margin:0;padding:16px;color:#dbe2dd;white-space:pre-wrap;overflow-wrap:anywhere;font:11px/1.55 SFMono-Regular,Consolas,monospace}.compile-output.compile-warning{color:#ffdfa0;background:#2d281c}.compile-output.compile-error{color:#ffc2bd;background:#301e1d}.compile-empty{height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:9px;color:#bfc7c1;font-size:12px}.compile-empty.compile-warning{color:#e8c46d;background:#2d281c}.compile-empty.compile-error{color:#e99b94;background:#301e1d}.compile-clean-panel{max-width:820px;margin:0 auto;padding:24px;color:#30453a}.compile-clean-intro{display:flex;align-items:flex-start;gap:12px;padding:15px;border:1px solid #e3d1a7;border-radius:9px;background:#fffaf0;color:#80631f;box-shadow:0 3px 12px #5c48100d}.compile-clean-intro>div{min-width:0}.compile-clean-intro strong{display:block;font-size:14px}.compile-clean-intro p,.compile-clean-actions p{margin:5px 0 0;color:#718078;font-size:11px;line-height:1.5}.compile-clean-actions{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin-top:14px}.compile-clean-actions article{display:grid;grid-template-columns:34px minmax(0,1fr);gap:10px;min-width:0;padding:14px;border:1px solid #d4dfd7;border-radius:8px;background:#fff}.compile-clean-actions article.danger{border-color:#e3c9c5}.compile-clean-action-icon{display:grid;place-items:center;width:32px;height:32px;border-radius:7px;background:#e7f2ea;color:#28714a}.compile-clean-actions article.danger .compile-clean-action-icon{background:#f8e8e6;color:#a6433a}.compile-clean-actions strong{color:#2d4638;font-size:12px}.compile-clean-actions article.danger strong{color:#874039}.compile-clean-actions button{display:inline-flex;align-items:center;gap:5px;margin-top:12px;padding:6px 10px;border:1px solid #b8d1bd;border-radius:5px;background:#f0f8f1;color:#21633d;font-size:11px}.compile-clean-actions button:hover:not(:disabled){border-color:#79aa86;background:#e3f2e6}.compile-clean-actions button.danger{border-color:#e2b9b4;background:#fff4f2;color:#a23d35}.compile-clean-actions button.danger:hover:not(:disabled){border-color:#c8837a;background:#fce7e4}.compile-clean-actions button:disabled{cursor:not-allowed;opacity:.45}.compile-diagnostic-list{min-height:100%;padding:8px;background:#202522;overflow:auto}.compile-diagnostic-list.compile-warning{background:#2d281c}.compile-diagnostic-list.compile-error{background:#301e1d}.compile-diagnostic-row{display:grid;grid-template-columns:20px minmax(0,1fr);gap:7px;width:100%;padding:9px 10px;border:0;border-bottom:1px solid #ffffff12;border-radius:4px;background:transparent;color:#eef2ef;text-align:left}.compile-diagnostic-row:not(:disabled):hover{background:#ffffff10;box-shadow:inset 2px 0 #63b889}.compile-diagnostic-row:disabled{opacity:.78;cursor:default}.compile-diagnostic-row>span{min-width:0;display:grid;gap:4px}.compile-diagnostic-row strong{font-size:11px;font-weight:500;white-space:normal}.compile-diagnostic-row small{color:#aeb8b1;font:10px/1.4 SFMono-Regular,Consolas,monospace;overflow-wrap:anywhere}.compile-warning .compile-diagnostic-row>svg{color:#e8c46d}.compile-error .compile-diagnostic-row>svg{color:#e99b94}.context-panel{border-right:0;overflow:auto}.drawer-title{position:sticky;top:0;z-index:2;height:42px;display:flex;align-items:center;justify-content:space-between;padding:0 12px;border-bottom:1px solid #e3e6e3;background:#fff;font-size:13px}.drawer-title button{width:28px;height:28px;display:grid;place-items:center;border:0;border-radius:5px;background:transparent;color:#737a75}.drawer-title button:hover{background:#edf1ee}.tabs{height:42px;display:flex;border-bottom:1px solid #e3e6e3}.tabs button{flex:1;border:0;background:#fff;color:#707872;font-size:12px}.tabs button.active{color:#176b44;border-bottom:2px solid #176b44;font-weight:700}.outline{padding:10px 8px}.outline-item{width:100%;min-width:0;display:flex;align-items:stretch;border:0;padding:6px 0;background:transparent;font-size:12px;text-align:left}.outline-item:hover,.outline-item:focus-visible{background:#edf3ef;color:#176b44;outline:none}.outline-item.current{background:#e2efe7;color:#176b44;font-weight:700}.outline-guides{flex:none;background:repeating-linear-gradient(to right,#dfe5e0 0,#dfe5e0 1px,transparent 1px,transparent 12px)}.outline small{flex:none;min-width:22px;margin-left:8px;color:#a1a7a2}.outline-title{min-width:0;overflow:hidden;color:#3f4942;text-overflow:ellipsis;white-space:nowrap}.padded{padding:14px}.comments{padding:9px}.comments article{margin-bottom:9px;padding:10px;border:1px solid #dde2de;border-radius:7px;font-size:12px;cursor:pointer;user-select:text;-webkit-user-select:text}.comments article.resolved{opacity:.55;background:#f3f5f3}.comments article.orphaned{border-color:#d8847d;background:#fff4f2}.comments header{display:flex;align-items:flex-start;justify-content:space-between;gap:8px}.comments header small{color:#858b87}.comments time{flex:none;color:#8b928d;font-size:9px;white-space:nowrap}.comment-times{flex:none;display:flex;align-items:flex-end;flex-direction:column;gap:2px}.comment-times small{font-size:8px;white-space:nowrap}.comment-author{min-width:0;display:flex;flex-direction:column;gap:1px}.comment-author strong,.comment-author small{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.comment-location{margin-top:5px;color:#768079;font-size:10px}.comments blockquote{margin:8px 0;padding:6px 8px;border-left:2px solid #85ad96;background:#f2f6f3;color:#657069;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.comments p{white-space:pre-wrap;user-select:text;-webkit-user-select:text;cursor:text}.comments blockquote,.comments .comment-content{user-select:text;-webkit-user-select:text;cursor:text}.comments .resolve{display:inline-flex;align-items:center;gap:4px;border:0;background:transparent;color:#176b44;padding:0;font-size:11px}.comment-replies{display:flex;flex-direction:column;gap:7px;margin:10px 0 8px;padding-left:9px;border-left:2px solid #d6dfd9}.comment-reply{position:relative;padding:7px 8px;border-radius:6px;background:#f5f7f5}.comment-reply p{margin:7px 0 1px}.comment-actions{display:flex;align-items:center;gap:12px}.comments .reply-action{display:inline-flex;align-items:center;gap:4px;border:0;padding:0;background:transparent;color:#526c5d;font-size:11px}.comment-owner-actions{display:inline-flex;align-items:center;gap:2px;margin-left:auto}.comment-reply>.comment-owner-actions{position:absolute;right:5px;bottom:4px}.comments .comment-owner-actions button{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0;border:0;border-radius:5px;background:transparent;color:#66716a}.comments .comment-owner-actions button:hover{background:#e2e8e3;color:#244c35}.comments .comment-owner-actions button.danger-text:hover{background:#f8e4e2;color:#a7312a}.comment-reply-form{display:flex;flex-direction:column;gap:7px;margin-top:9px}.comment-edit-form{margin:7px 0}.comment-reply-form textarea{width:100%;resize:vertical;border:1px solid #cbd2cc;border-radius:6px;padding:7px 8px;outline:none;font-size:11px}.comment-reply-form textarea:focus{border-color:#176b44;box-shadow:0 0 0 2px #176b4420}.comment-reply-form>div{display:flex;justify-content:flex-end;gap:5px}.comment-reply-form button{display:inline-flex;align-items:center;gap:4px;border:1px solid #cbd2cc;border-radius:5px;padding:5px 7px;background:#fff;font-size:10px}.comment-reply-form button.primary{border-color:#176b44;background:#176b44;color:#fff}.settings{display:flex;flex-direction:column;gap:14px}.settings>section{display:flex;flex-direction:column;gap:14px}.settings button{border:1px solid #c9d0ca;background:#fff;border-radius:6px;padding:7px 9px;font-size:12px}.settings-tabs{display:flex;gap:4px;padding:3px;border:1px solid #d7ded8;border-radius:9px;background:#f4f7f4}.settings-tab{display:inline-flex;flex:1;align-items:center;justify-content:center;gap:6px;min-height:34px;border:1px solid transparent!important;border-radius:7px!important;background:transparent!important;color:#66716a;font-weight:650}.settings-tab:hover{background:#eaf1eb!important;color:#31523e}.settings-tab.active{border-color:#c8d9cb!important;background:#fff!important;color:#176b44;box-shadow:0 1px 2px #233c2a12}.settings-tab:focus-visible{outline:2px solid #176b44;outline-offset:1px}.settings-actions{display:flex;width:100%;justify-content:flex-end;padding-top:2px}.settings-section-title{display:flex;align-items:center;gap:7px;color:#31523e;font-size:13px}.settings-description{margin:0;color:#7b837e;font-size:11px;line-height:1.45}.settings .editor-preference{display:flex;flex-direction:column;gap:4px}.settings .editor-preference .field-hint{margin:0 9px;line-height:1.4}.settings .editor-checkbox{flex-direction:row;align-items:center;gap:7px;padding:8px 9px;border:1px solid #d9ded9;border-radius:7px;font-weight:500}.settings .editor-checkbox input{width:auto;margin:0;accent-color:#176b44}.spell-check-result{display:inline-flex;align-items:center;gap:6px;color:#66716a;font-size:11px}.spell-check-result.has-issues{color:#a3342c;font-weight:650}.spell-check-controls{display:inline-flex;align-items:center;gap:2px;margin-left:3px;color:#6f4a45;font-weight:500}.spell-check-controls button{width:24px;height:24px;display:inline-grid;place-items:center;border:1px solid #d7b8b4;border-radius:4px;padding:0;background:#fff8f7;color:#8e4a42}.spell-check-controls button:hover:not(:disabled){border-color:#b98279;background:#fce9e6}.spell-check-controls button:disabled{cursor:not-allowed;opacity:.35}.spell-check-position{min-width:34px;text-align:center;color:#825850;font-variant-numeric:tabular-nums;white-space:nowrap}.password-generator{display:flex;align-items:stretch;gap:7px}.password-generator input{min-width:0;flex:1;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace}.password-generator button{flex:none;display:inline-flex;align-items:center;justify-content:center;gap:5px;padding:0 10px;border:1px solid #c9d0ca;border-radius:6px;background:#f6f8f6;color:#31523e;font-size:11px;white-space:nowrap}.password-generator button:hover{border-color:#8eaa98;background:#edf3ef}.settings-save{width:100%;display:inline-flex;align-items:center;justify-content:center;gap:6px}.latexmkrc-editor{resize:vertical;min-height:160px;font:12px/1.5 SFMono-Regular,Consolas,monospace!important}.dictionary-add{display:flex;align-items:stretch;gap:7px}.dictionary-add input{min-width:0;flex:1}.dictionary-add button{flex:none;color:#176b44}.dictionary-words{display:flex;flex-wrap:wrap;gap:6px}.dictionary-word{display:inline-flex;align-items:center;gap:3px;min-height:27px;padding:3px 5px 3px 8px;border:1px solid #d5ded7;border-radius:999px;background:#f1f6f2;color:#31523e;font-size:11px}.dictionary-word code{font:11px/1.2 SFMono-Regular,Consolas,monospace}.dictionary-word button{width:20px;height:20px;display:grid;place-items:center;padding:0;border:0;background:transparent;color:#748078}.dictionary-word button:hover{color:#a7312a}.dictionary-empty{color:#7b837e;font-size:11px}.dictionary-error{margin:-6px 0 0;font-size:11px}.share-dialog{display:flex;flex-direction:column;gap:16px}.share-owner{display:flex;align-items:center;gap:10px;padding:11px 13px;border-radius:8px;background:#edf4ef;color:#18583a}.share-owner>span{display:flex;flex-direction:column;gap:2px}.share-owner small{color:#6f7d74;font-size:10px;text-transform:uppercase}.share-add{display:grid;grid-template-columns:minmax(0,1fr) 150px auto;align-items:end;gap:9px;padding-bottom:16px;border-bottom:1px solid #e4e7e4}.share-add .icon-button{height:39px;display:inline-flex;align-items:center;gap:6px;padding:0 13px;font-size:12px}.shared-members-heading{display:flex;align-items:center;justify-content:space-between;color:#48524b;font-size:13px}.shared-members-heading span{min-width:22px;padding:2px 6px;border-radius:999px;background:#e8ece9;color:#6a746d;font-size:10px;text-align:center}.shared-members{display:flex;flex-direction:column;gap:7px}.shared-member{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:10px;border:1px solid #dfe3df;border-radius:8px}.member-identity{min-width:0;display:flex;align-items:center;gap:9px}.member-identity>span:last-child{min-width:0;display:flex;flex-direction:column}.member-identity strong,.member-identity small{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.member-identity small{color:#7c857e;font-size:10px}.member-avatar{width:30px;height:30px;flex:none;display:grid;place-items:center;border-radius:50%;background:#dfece4;color:#176b44;font-size:12px;font-weight:750}.member-controls{display:flex;align-items:center;gap:5px}.member-controls select{border:1px solid #cbd2cc;border-radius:6px;padding:6px 8px;background:#fff;font-size:11px}.icon-only{width:31px;height:31px;display:grid;place-items:center;border:0;border-radius:6px;background:transparent}.icon-only:hover{background:#f8e9e7}.share-empty{min-height:90px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:7px;color:#89928c;font-size:12px}.spin{animation:spin .8s linear infinite}.dialog-overlay{position:fixed;z-index:100;inset:0;background:#101b15aa;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);animation:fade-in .12s ease-out}.dialog-content{position:fixed;z-index:101;top:50%;left:50%;width:min(460px,calc(100vw - 32px));max-height:min(760px,calc(100vh - 40px));overflow:auto;transform:translate(-50%,-50%);background:#fff;border-radius:12px;box-shadow:0 25px 80px #0004;animation:dialog-in .15s ease-out}.dialog-wide{width:min(660px,calc(100vw - 32px))}.dialog-extra-wide{width:min(900px,calc(100vw - 32px))}.dialog-header{display:flex;align-items:flex-start;justify-content:space-between;padding:20px 22px 14px;border-bottom:1px solid #e5e8e5}.dialog-header h2{margin:0;font-size:19px}.dialog-header p{margin:6px 0 0;color:#737a75;font-size:12px;line-height:1.5}.dialog-close{border:0;background:transparent;color:#6d746f;font-size:22px}.dialog-body{padding:20px 22px}.dialog-body .warning{display:flex;align-items:flex-start;gap:8px;margin:0;padding:10px 11px;border:1px solid #e4cf91;border-radius:7px;background:#fff8df;color:#735a18;font-size:11px;line-height:1.5}.dialog-body .warning svg{flex:none;margin-top:1px}.system-metrics{display:grid;gap:20px}.metric-summary-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}.metric-card{min-width:0;padding:14px 16px;border:1px solid #dfe4df;border-radius:10px;background:#f7f8f6;display:grid;gap:4px}.metric-card>span,.metric-card small{color:var(--muted);font-size:12px}.metric-card strong{font-size:20px;font-weight:650}.metric-section{display:grid;gap:10px}.metric-section h3{margin:0;display:flex;align-items:center;gap:7px;font-size:14px}.metric-section p{margin:0;font-size:13px}.metric-table-wrap{overflow-x:auto;border:1px solid #dfe4df;border-radius:9px}.metric-table{width:100%;border-collapse:collapse;font-size:12px;white-space:nowrap}.metric-table th,.metric-table td{padding:8px 10px;border-bottom:1px solid #e4e8e4;text-align:right}.metric-table th:first-child,.metric-table td:first-child{text-align:left}.metric-table tbody tr:last-child td{border-bottom:0}@media(max-width:640px){.metric-summary-grid{grid-template-columns:1fr}}.dialog-footer{display:flex;justify-content:flex-end;gap:8px;padding:14px 22px;border-top:1px solid #e5e8e5;background:#f8f9f7}.dialog-footer button{border:1px solid #cbd2cc;border-radius:7px;padding:8px 14px;background:#fff}.dialog-footer .primary{display:inline-flex;align-items:center;justify-content:center;gap:6px;border-color:#176b44;background:#176b44;color:#fff}.dialog-footer .danger,button.danger{border-color:#b3261e;background:#b3261e;color:#fff}.form-stack{display:flex;flex-direction:column;gap:14px}.import-error{margin:0;padding:10px 12px;border:1px solid #e3b5b1;border-radius:8px;background:#fff3f2;line-height:1.45}.form-field{display:flex;flex-direction:column;gap:7px;font-size:13px;font-weight:650}.form-field input,.form-field select,.form-field textarea{width:100%;border:1px solid #cbd2cc;border-radius:8px;padding:10px 11px;background:#fff;outline:none}.form-field input:focus,.form-field select:focus,.form-field textarea:focus{border-color:#176b44;box-shadow:0 0 0 3px #176b4420}.upload-picker{position:relative;min-height:116px;display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:14px;padding:20px;border:1.5px dashed #aebbb2;border-radius:10px;background:#f6f8f6;color:#5f6b63;transition:border-color .15s ease,background .15s ease}.upload-picker:hover,.upload-picker:focus-within{border-color:#4f8a68;background:#f0f6f2}.upload-picker.has-file{border-style:solid;border-color:#83aa91;background:#edf5ef;color:#276044}.upload-picker>svg{flex:none;color:#176b44}.upload-picker-copy{min-width:0;display:flex;flex-direction:column;gap:4px}.upload-picker-copy strong,.upload-picker-copy span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.upload-picker-copy strong{color:#29382f;font-size:13px}.upload-picker-copy span{color:#758078;font-size:11px}.upload-picker>button{display:inline-flex;align-items:center;gap:6px;border:1px solid #9fb0a4;border-radius:7px;padding:8px 11px;background:#fff;color:#235c3d;font-size:12px;font-weight:650}.upload-picker>button:hover{border-color:#176b44;background:#e4efe8}.upload-picker>.upload-clear{position:absolute;top:7px;right:7px;width:26px;height:26px;display:grid;place-items:center;border:0;padding:0;background:transparent;color:#6c776f}.upload-picker>.upload-clear:hover{background:#dce9e0;color:#9d2f27}.choice-group{display:flex;flex-direction:column;gap:10px;border:1px solid #dfe3df;border-radius:8px;padding:14px}.choice-group legend{padding:0 5px;font-size:12px;color:#69716b}.choice-group label{font-size:13px}.color-picker{display:grid;grid-template-columns:repeat(2,1fr);gap:7px;border:0;padding:0}.color-picker legend{margin-bottom:8px;font-size:13px;font-weight:650}.color-picker label{display:flex;align-items:center;gap:7px;border:1px solid #dce1dd;border-radius:7px;padding:8px;font-size:12px}.color-picker label.active{border-color:#176b44;background:#edf5f0}.color-picker input{position:absolute;opacity:0;pointer-events:none}.tag-assignment-list{display:flex;flex-direction:column;gap:7px}.tag-assignment-list label,.tag-assignment-list button{display:flex;align-items:center;gap:9px;min-height:38px;border:1px solid #dce1dd;border-radius:7px;padding:8px 10px;background:#fff;color:#38423b;font-size:13px;text-align:left}.tag-assignment-list label:hover,.tag-assignment-list button:hover{border-color:#8bae9a;background:#f4f8f5}.tag-assignment-list input{width:auto;accent-color:#176b44}.checkbox-field{display:flex;align-items:center;gap:8px;font-size:13px}.checkbox-field input{width:auto}.selection-preview{max-height:130px;overflow:auto;margin:14px 0 0;padding:10px 12px;border-left:3px solid #d6a128;background:#fff8e5;white-space:pre-wrap;font:12px/1.5 SFMono-Regular,Consolas,monospace}.git-dialog{display:flex;flex-direction:column;gap:14px}.git-dialog-modal-fullscreen{top:0;left:0;width:100vw;height:100vh;max-height:100vh;transform:none;overflow:hidden;border-radius:0}.git-loading{min-height:120px;display:flex;align-items:center;justify-content:center;gap:8px;color:#6e7871;font-size:13px}.git-message{margin:0;display:flex;align-items:center;gap:7px;padding:9px 11px;border:1px solid;border-radius:7px;font-size:12px}.git-message.error{border-color:#e2b4b0;background:#fff2f1}.git-message.success{border-color:#acd0b8;background:#edf7f0;color:#17623d}.git-section{display:flex;flex-direction:column;gap:11px;padding:14px;border:1px solid #dfe4e0;border-radius:9px;background:#fbfcfb}.git-section-toggle{width:100%;display:flex;align-items:center;justify-content:space-between;gap:10px;border:0;padding:0;background:transparent;color:#607068;text-align:left}.git-section-toggle:hover{color:#176b44}.git-section-heading{min-width:0;display:flex;align-items:flex-start;gap:8px;color:#27533a}.git-section-heading>svg{flex:none;margin-top:1px}.git-section-heading>div,.git-section-heading>span{min-width:0;display:flex;flex-direction:column;gap:3px}.git-section-heading strong{font-size:13px}.git-section-heading small{max-width:650px;overflow:hidden;color:#78817b;font-size:10px;line-height:1.4;text-overflow:ellipsis;white-space:nowrap}.git-section-content{display:flex;flex-direction:column;gap:11px;padding-top:2px}.git-token-guidance{display:flex;flex-direction:column;gap:4px;padding:10px 11px;border:1px solid #c6d9cb;border-left:3px solid #28714b;border-radius:7px;background:#f0f7f2}.git-token-guidance strong{color:#225d3c;font-size:11px}.git-token-guidance span{color:#66756b;font-size:10px;line-height:1.5}.git-account,.git-repository-card{display:flex;align-items:center;gap:8px;padding:9px 10px;border-radius:7px;background:#eaf3ed;color:#23563a;font-size:12px}.git-account>span{min-width:0;flex:1}.git-account button{display:inline-flex;align-items:center;gap:4px;border:0;background:transparent;color:#a3342c;font-size:10px}.git-inline-actions,.git-action-row{display:flex;align-items:center;flex-wrap:wrap;gap:7px}.git-inline-actions{justify-content:space-between}.git-inline-actions a,.git-repository-card a{display:inline-flex;align-items:center;gap:4px;color:#176b44;font-size:11px;text-decoration:none}.git-inline-actions button,.git-action-row button,.git-primary-action{display:inline-flex;align-items:center;justify-content:center;gap:5px;border:1px solid #bdc9c0;border-radius:6px;padding:7px 9px;background:#fff;color:#31523e;font-size:11px}.git-action-row .git-discard-button:not(:disabled){border-color:#d9aaa5;color:#9b332b}.git-action-row .git-discard-button:not(:disabled):hover{background:#fff0ee}.git-primary-action{align-self:flex-start;border-color:#176b44;background:#176b44;color:#fff}.git-repository-card{justify-content:space-between}.git-repository-card>div{min-width:0;display:flex;flex-direction:column;gap:3px}.git-repository-card strong,.git-repository-card small{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.git-repository-card small{color:#6e7c73;font-size:10px}.git-count{min-width:17px;padding:1px 5px;border-radius:999px;background:#d9e9df;font-size:9px}.git-diff-section{padding-bottom:0;overflow:hidden}.git-diff-heading{display:flex;align-items:flex-start;justify-content:space-between;gap:10px}.git-diff-controls{display:flex;align-items:center;gap:7px;flex:none}.git-diff-font-controls{display:inline-flex;align-items:center;gap:2px;border:1px solid #cbd5ce;border-radius:6px;padding:2px;background:#fff;color:#52685a}.git-diff-font-button{width:25px;height:25px;display:grid;place-items:center;border:0;border-radius:4px;padding:0;background:transparent;color:inherit}.git-diff-font-button:hover:not(:disabled){background:#edf4ef;color:#176b44}.git-diff-font-value{min-width:34px;color:#52685a;font-size:10px;font-variant-numeric:tabular-nums;text-align:center}.git-diff-fullscreen{width:29px;height:29px;flex:none;display:grid;place-items:center;padding:0!important;border:1px solid #cbd5ce!important;border-radius:6px!important;background:#fff!important;color:#52685a}.git-diff-fullscreen:hover{border-color:#8eaa98!important;background:#edf4ef!important;color:#176b44}.git-diff-section.is-fullscreen,.git-diff-section:fullscreen{position:fixed;z-index:1000;inset:0;width:100vw;height:100vh;max-height:none;box-sizing:border-box;margin:0;padding:20px!important;border:0;border-radius:0;overflow:hidden;background:#fbfcfb}.git-diff-section.is-fullscreen .git-diff,.git-diff-section:fullscreen .git-diff{flex:1;min-height:0;max-height:none;margin:0}.git-diff-section.is-fullscreen .git-diff-empty,.git-diff-section:fullscreen .git-diff-empty{flex:1;min-height:0;margin:0}.git-diff{max-height:360px;margin:0 -14px;overflow:auto;padding:11px 0;background:#202522;color:#d9e1dc;font:10px/1.5 SFMono-Regular,Consolas,monospace;tab-size:4}.git-diff span{display:block;min-width:max-content;padding:0 12px;white-space:pre}.git-diff span.addition{background:#173b28;color:#bfe8cb}.git-diff span.deletion{background:#442421;color:#f1c1bc}.git-diff span.hunk{background:#283a48;color:#b8daf4}.git-diff span.header{color:#e8cf8b;font-weight:650}.git-diff-empty{margin:0 -14px;padding:28px;background:#252a27;color:#b9c0bc;font-size:12px;text-align:center}.git-history{max-height:300px;display:flex;flex-direction:column;gap:5px;overflow:auto}.git-history article{min-width:0;display:grid;grid-template-columns:66px minmax(0,1fr) auto;align-items:center;gap:8px;padding:8px;border:1px solid #e2e6e3;border-radius:6px;background:#fff}.git-history code{color:#176b44;font-size:10px}.git-history article>div{min-width:0;display:flex;flex-direction:column;gap:2px}.git-history article strong,.git-history article small{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.git-history article strong{font-size:11px}.git-history article small{color:#7b847e;font-size:9px}.git-history article>span{display:flex;gap:3px}.git-history button{width:27px;height:27px;display:grid;place-items:center;border:0;border-radius:5px;background:transparent;color:#52685a}.git-history button:hover{background:#e8f0eb;color:#176b44}.git-force-checkout{display:flex;align-items:flex-start;gap:9px;padding:11px;border:1px solid #e4b9b5;border-radius:8px;background:#fff6f5}.git-force-checkout input{margin-top:2px;accent-color:#b3261e}.git-force-checkout span{display:flex;flex-direction:column;gap:3px}.git-force-checkout strong{color:#932c25;font-size:12px}.git-force-checkout small{color:#7d6562;font-size:10px;line-height:1.45}.quick-open-dialog>label,.project-search-query{display:flex;align-items:center;gap:8px;border:1px solid #bfcac2;border-radius:7px;padding:0 10px;background:#fff}.quick-open-dialog>label:focus-within,.project-search-query:focus-within{border-color:#418060;box-shadow:0 0 0 2px #41806020}.quick-open-dialog input,.project-search-query input{width:100%;border:0;outline:0;padding:10px 0;background:transparent}.quick-open-results{max-height:420px;overflow:auto;margin-top:8px;border:1px solid #d9e0db;border-radius:7px}.quick-open-results button{display:grid;grid-template-columns:20px minmax(0,1fr) 18px;align-items:center;gap:6px;width:100%;padding:8px 10px;border:0;border-radius:0;background:#fff;text-align:left}.quick-open-results button+button{border-top:1px solid #eef1ef}.quick-open-results button.active{background:#e4efe8;color:#195f3d}.quick-open-results span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font:11px/1.4 JetBrains Mono,monospace}.project-search-dialog{display:grid;gap:9px}.project-search-form{display:grid;grid-template-columns:1fr 1fr;gap:8px}.project-search-options{grid-column:1 / -1;display:flex;align-items:center;gap:14px}.project-search-options label{display:inline-flex;align-items:center;gap:5px;color:#55645a;font-size:11px}.project-search-options label input{accent-color:#28734b}.project-search-options button{margin-left:auto;display:inline-flex;align-items:center;gap:5px}.project-search-summary{display:flex;align-items:center;justify-content:space-between;min-height:22px;color:#5e6c63;font-size:11px}.project-search-summary span{display:inline-flex;align-items:center;gap:5px}.project-search-results{max-height:480px;overflow:auto;border:1px solid #d9e0db;border-radius:7px;background:#fff}.project-search-results>button{display:grid;grid-template-columns:20px minmax(0,1fr);gap:7px;width:100%;padding:9px 10px;border:0;border-radius:0;background:#fff;text-align:left}.project-search-results>button+button{border-top:1px solid #e8ece9}.project-search-results>button:hover{background:#edf4ef}.project-search-results>button>span{min-width:0;display:grid;gap:4px}.project-search-results strong{color:#31503d;font-size:11px}.project-search-results strong small{color:#7c877f;font-weight:400}.project-search-results code{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:#4e5952;font:10px/1.45 JetBrains Mono,monospace}.project-search-results mark{border-radius:2px;padding:1px;background:#f2d36e;color:#4b3b0b}.history-dialog-modal{width:min(1120px,calc(100vw - 32px))}.history-dialog{display:grid;grid-template-columns:270px minmax(0,1fr);min-height:560px;max-height:min(72vh,760px);border:1px solid #d9e0db;border-radius:8px;overflow:hidden;background:#fff}.history-loading{grid-column:1 / -1;display:flex;align-items:center;justify-content:center;gap:8px;min-height:420px;color:#68736b}.history-message{grid-column:1 / -1;margin:10px}.history-timeline{overflow:auto;border-right:1px solid #d9e0db;background:#f5f7f5}.history-stats{position:sticky;top:0;z-index:2;display:grid;gap:5px;padding:10px 12px;border-bottom:1px solid #d8dfda;background:#edf3ef;color:#33483b}.history-stats header{display:flex;align-items:center;justify-content:space-between;gap:8px}.history-stats header span{display:inline-flex;align-items:center;gap:6px;font-size:11px;font-weight:700}.history-stats header button{width:26px;height:26px;display:grid;place-items:center;border:0;padding:0;background:transparent;color:#9d332b}.history-stats header button:hover:not(:disabled){background:#f5deda}.history-stats strong{font-size:11px}.history-stats small{color:#68766d;font-size:9px;line-height:1.4}.history-stats progress{width:100%;height:6px;border:0;border-radius:999px;overflow:hidden;accent-color:#34845a}.history-stats.exceeded progress{accent-color:#bd483e}.history-stats .history-storage-warning{color:#9d332b}.history-timeline>button{display:grid;grid-template-columns:20px minmax(0,1fr);gap:7px;width:100%;padding:11px 12px;border:0;border-bottom:1px solid #e1e6e2;border-radius:0;background:transparent;text-align:left;color:#34443a}.history-timeline>button:hover{background:#eaf0ec}.history-timeline>button.active{background:#dfece4;box-shadow:inset 3px 0 #28734b}.history-timeline>button span{min-width:0;display:grid;gap:2px}.history-timeline>button strong,.history-timeline>button small{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.history-timeline>button small{color:#68736b;font-size:10px}.history-detail{min-width:0;overflow:auto;padding:14px}.history-detail-header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;margin-bottom:12px}.history-detail-header>div{display:grid;gap:4px}.history-detail-header small{display:flex;align-items:center;gap:4px;color:#68736b}.history-detail-actions{display:flex;align-items:center;gap:6px}.history-detail-actions button{display:inline-flex;align-items:center;gap:5px;white-space:nowrap}.history-label{display:flex;gap:8px;margin-bottom:12px}.history-label label{flex:1;display:flex;align-items:center;gap:7px;padding:0 9px;border:1px solid #cdd6cf;border-radius:6px;background:#fff}.history-label input{width:100%;border:0;padding:8px 0;outline:0}.history-files{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:8px;align-items:start}.history-file-list{display:flex;gap:5px;overflow-x:auto;padding-bottom:5px}.history-file-list button{display:inline-flex;align-items:center;gap:5px;flex:0 0 auto;max-width:230px}.history-file-list button span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.history-file-list button small{padding:1px 4px;border-radius:8px;background:#f2d675;color:#695414;font-size:9px}.history-file-list button.active{border-color:#418060;background:#e7f0ea}.history-file-actions{display:flex;gap:5px}.history-file-actions button{display:inline-flex;align-items:center;gap:5px;white-space:nowrap}.history-comparison{min-height:360px;margin-top:10px;border:1px solid #d8dfda;border-radius:7px;overflow:hidden;background:#fbfcfb}.history-comparison>header{display:flex;align-items:baseline;justify-content:space-between;gap:10px;padding:8px 10px;border-bottom:1px solid #d8dfda;background:#f1f4f2}.history-comparison>header small{color:#68736b}.history-comparison pre{min-height:330px;max-height:430px;margin:0;overflow:auto;padding:11px;white-space:pre-wrap;overflow-wrap:anywhere;font:11px/1.5 JetBrains Mono,Source Code Pro,monospace;color:#26342b}.history-comparison pre .history-removed{background:#f8c9c9;color:#7b2525;text-decoration:line-through}.history-comparison pre .history-added{background:#ccebd5;color:#15552c}.history-comparison-empty{min-height:360px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;color:#78827b}@keyframes fade-in{0%{opacity:0}}@keyframes dialog-in{0%{opacity:0;transform:translate(-50%,-48%) scale(.98)}}@keyframes spin{to{transform:rotate(360deg)}}@media(max-width:1100px){.project-grid.list-view .project-card-open{grid-template-columns:110px minmax(160px,1fr)}.project-grid.list-view .project-meta{grid-column:1 / -1}.editor-actions button{padding:8px}.editor-actions button svg+*{display:none}}@media(max-width:720px){.upload-picker{grid-template-columns:auto 1fr}.upload-picker>button{grid-column:1 / -1;justify-content:center}.share-add{grid-template-columns:1fr}.shared-member{align-items:flex-start}.member-controls{flex:none}.history-dialog{grid-template-columns:1fr;max-height:none}.history-timeline{max-height:180px;border-right:0;border-bottom:1px solid #d9e0db}.history-files,.project-search-form{grid-template-columns:1fr}}
@@ -1,4 +1,4 @@
1
- import{P as Kn,r as Qn,L as un}from"./BinaryModule-Aj1vLnwf-Cdan601z.js";import{D as ke,S as Ne,c as ze}from"./BinaryModule-Aj1vLnwf-Cdan601z.js";import"./index-1WTcEinQ.js";import"./react-CsO_xvbl.js";var Yn=Object.defineProperty,Xn=(e,n,r)=>n in e?Yn(e,n,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[n]=r,I=(e,n,r)=>Xn(e,typeof n!="symbol"?n+"":n,r);function Zn(e){switch(e){case"plaintext":return un.Plain;case"typst":return un.Typst;case"markdown":case void 0:return un.Markdown;default:return console.warn(`Unknown Harper language '${String(e)}'; using markdown.`),un.Markdown}}function On(e,n){return[e,Zn(n?.language),n?.forceAllHeadings??!1,n?.regex_mask,n?.dedup??!0,n?.isolateEnglish??!1]}class We{constructor(n){I(this,"binary"),I(this,"inner"),I(this,"disposed",!1),this.binary=n.binary,this.binary.setup(),this.inner=this.createInner(n.dialect)}createInner(n){return Kn.from(async()=>(await this.binary.setup(),this.binary.createLinter(n)))}async setup(){await this.lint("",{language:"plaintext"});const n=await this.exportIgnoredLints();await this.importIgnoredLints(n)}async lint(n,r){return(await this.inner).lint(...On(n,r))}async organizedLints(n,r){const a=(await this.inner).organized_lints(...On(n,r)),i={};for(const o of a)i[o.group]=o.lints,o.free();return i}async applySuggestion(n,r,t){return(await this.inner).apply_suggestion(n,r,t)}async isLikelyEnglish(n){return(await this.inner).is_likely_english(n)}async isolateEnglish(n){return(await this.inner).isolate_english(n)}async getLintConfig(){return(await this.inner).get_lint_config_as_object()}async getDefaultLintConfigAsJSON(){return await this.binary.getDefaultLintConfigAsJSON()}async getDefaultLintConfig(){return await this.binary.getDefaultLintConfig()}async getStructuredLintConfig(){return(await this.inner).get_structured_lint_config_as_object()}async getStructuredLintConfigJSON(){return(await this.inner).get_structured_lint_config_as_json()}async setLintConfig(n){(await this.inner).set_lint_config_from_object(n)}async getLintConfigAsJSON(){return(await this.inner).get_lint_config_as_json()}async setLintConfigWithJSON(n){(await this.inner).set_lint_config_from_json(n)}async toTitleCase(n){return await this.binary.toTitleCase(n)}async getLintDescriptions(){return(await this.inner).get_lint_descriptions_as_object()}async getLintDescriptionsAsJSON(){return(await this.inner).get_lint_descriptions_as_json()}async getLintDescriptionsHTML(){return(await this.inner).get_lint_descriptions_html_as_object()}async getLintDescriptionsHTMLAsJSON(){return(await this.inner).get_lint_descriptions_html_as_json()}async ignoreLint(n,r){return await this.ignoreLints(n,[r])}async ignoreLints(n,r){(await this.inner).ignore_lints(n,r)}async ignoreLintHash(n){(await this.inner).ignore_hashes(new BigUint64Array([n]))}async exportIgnoredLints(){return(await this.inner).export_ignored_lints()}async importIgnoredLints(n){(await this.inner).import_ignored_lints(n)}async contextHash(n,r){return(await this.inner).context_hash(n,r)}async clearIgnoredLints(){(await this.inner).clear_ignored_lints()}async clearWords(){return(await this.inner).clear_words()}async importWords(n){return(await this.inner).import_words(n)}async exportWords(){return(await this.inner).export_words()}async getDialect(){return(await this.inner).get_dialect()}async setDialect(n){const r=await this.inner;return r.get_dialect()!==n&&(r.free(),this.inner=this.createInner(n)),Promise.resolve()}async summarizeStats(n,r){return(await this.inner).summarize_stats(n,r)}async generateStatsFile(){return(await this.inner).generate_stats_file()}async importStatsFile(n){return(await this.inner).import_stats_file(n)}async loadWeirpackFromBlob(n){const r=new Uint8Array(await n.arrayBuffer());return this.loadWeirpackFromBytes(r)}async loadWeirpackFromBytes(n){const r=await this.inner,t=n instanceof Uint8Array?n:Uint8Array.from(n);return r.import_weirpack(t)}async dispose(){if(this.disposed)return;this.disposed=!0,(await this.inner).free()}}function ne(e,n){if(!e)throw new Error("Assertion failed")}class ee{constructor(n){I(this,"binary"),this.binary=n,this.binary.setup()}async serializeArg(n){var r;const{Lint:t,Span:a,Suggestion:i}=await this.binary.getBinaryModule();if(Array.isArray(n))return{json:JSON.stringify(await Promise.all(n.map(g=>this.serializeArg(g)))),type:"Array"};const o=typeof n;switch(o){case"string":case"number":case"boolean":case"undefined":return{json:JSON.stringify(n),type:o};case"bigint":return{json:n.toString(),type:o}}if(n.to_json!==void 0){const g=n.to_json();let _;const c=(r=n.constructor)==null?void 0:r.name;if(n instanceof t||c==="Lint"?_="Lint":n instanceof i||c==="Suggestion"?_="Suggestion":(n instanceof a||c==="Span")&&(_="Span"),_===void 0)throw new Error("Unhandled case: type undefined");return{json:g,type:_}}if(o=="object")return{json:JSON.stringify(await Promise.all(Object.entries(n).map(([g,_])=>this.serializeArg([g,_])))),type:"object"};throw new Error(`Unhandled case: ${n}`)}async serialize(n){return{procName:n.procName,args:await Promise.all(n.args.map(r=>this.serializeArg(r)))}}async deserializeArg(n){const{Lint:r,Span:t,Suggestion:a}=await this.binary.getBinaryModule();switch(n.type){case"bigint":return BigInt(n.json);case"undefined":return;case"boolean":case"number":case"string":return JSON.parse(n.json);case"Suggestion":return a.from_json(n.json);case"Lint":return r.from_json(n.json);case"Span":return t.from_json(n.json);case"Array":{const i=JSON.parse(n.json);return ne(Array.isArray(i)),await Promise.all(i.map(o=>this.deserializeArg(o)))}case"object":{const i=JSON.parse(n.json);return Object.fromEntries(await Promise.all(i.map(o=>this.deserializeArg(o))))}default:throw new Error(`Unhandled case: ${n.type}`)}}async deserialize(n){return{procName:n.procName,args:await Promise.all(n.args.map(r=>this.deserializeArg(r)))}}}const Vn=`var __defProp = Object.defineProperty;
1
+ import{P as Kn,r as Qn,L as un}from"./BinaryModule-Aj1vLnwf-DtjQ0MTe.js";import{D as ke,S as Ne,c as ze}from"./BinaryModule-Aj1vLnwf-DtjQ0MTe.js";import"./index-CFIrNdl3.js";import"./react-CsO_xvbl.js";var Yn=Object.defineProperty,Xn=(e,n,r)=>n in e?Yn(e,n,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[n]=r,I=(e,n,r)=>Xn(e,typeof n!="symbol"?n+"":n,r);function Zn(e){switch(e){case"plaintext":return un.Plain;case"typst":return un.Typst;case"markdown":case void 0:return un.Markdown;default:return console.warn(`Unknown Harper language '${String(e)}'; using markdown.`),un.Markdown}}function On(e,n){return[e,Zn(n?.language),n?.forceAllHeadings??!1,n?.regex_mask,n?.dedup??!0,n?.isolateEnglish??!1]}class We{constructor(n){I(this,"binary"),I(this,"inner"),I(this,"disposed",!1),this.binary=n.binary,this.binary.setup(),this.inner=this.createInner(n.dialect)}createInner(n){return Kn.from(async()=>(await this.binary.setup(),this.binary.createLinter(n)))}async setup(){await this.lint("",{language:"plaintext"});const n=await this.exportIgnoredLints();await this.importIgnoredLints(n)}async lint(n,r){return(await this.inner).lint(...On(n,r))}async organizedLints(n,r){const a=(await this.inner).organized_lints(...On(n,r)),i={};for(const o of a)i[o.group]=o.lints,o.free();return i}async applySuggestion(n,r,t){return(await this.inner).apply_suggestion(n,r,t)}async isLikelyEnglish(n){return(await this.inner).is_likely_english(n)}async isolateEnglish(n){return(await this.inner).isolate_english(n)}async getLintConfig(){return(await this.inner).get_lint_config_as_object()}async getDefaultLintConfigAsJSON(){return await this.binary.getDefaultLintConfigAsJSON()}async getDefaultLintConfig(){return await this.binary.getDefaultLintConfig()}async getStructuredLintConfig(){return(await this.inner).get_structured_lint_config_as_object()}async getStructuredLintConfigJSON(){return(await this.inner).get_structured_lint_config_as_json()}async setLintConfig(n){(await this.inner).set_lint_config_from_object(n)}async getLintConfigAsJSON(){return(await this.inner).get_lint_config_as_json()}async setLintConfigWithJSON(n){(await this.inner).set_lint_config_from_json(n)}async toTitleCase(n){return await this.binary.toTitleCase(n)}async getLintDescriptions(){return(await this.inner).get_lint_descriptions_as_object()}async getLintDescriptionsAsJSON(){return(await this.inner).get_lint_descriptions_as_json()}async getLintDescriptionsHTML(){return(await this.inner).get_lint_descriptions_html_as_object()}async getLintDescriptionsHTMLAsJSON(){return(await this.inner).get_lint_descriptions_html_as_json()}async ignoreLint(n,r){return await this.ignoreLints(n,[r])}async ignoreLints(n,r){(await this.inner).ignore_lints(n,r)}async ignoreLintHash(n){(await this.inner).ignore_hashes(new BigUint64Array([n]))}async exportIgnoredLints(){return(await this.inner).export_ignored_lints()}async importIgnoredLints(n){(await this.inner).import_ignored_lints(n)}async contextHash(n,r){return(await this.inner).context_hash(n,r)}async clearIgnoredLints(){(await this.inner).clear_ignored_lints()}async clearWords(){return(await this.inner).clear_words()}async importWords(n){return(await this.inner).import_words(n)}async exportWords(){return(await this.inner).export_words()}async getDialect(){return(await this.inner).get_dialect()}async setDialect(n){const r=await this.inner;return r.get_dialect()!==n&&(r.free(),this.inner=this.createInner(n)),Promise.resolve()}async summarizeStats(n,r){return(await this.inner).summarize_stats(n,r)}async generateStatsFile(){return(await this.inner).generate_stats_file()}async importStatsFile(n){return(await this.inner).import_stats_file(n)}async loadWeirpackFromBlob(n){const r=new Uint8Array(await n.arrayBuffer());return this.loadWeirpackFromBytes(r)}async loadWeirpackFromBytes(n){const r=await this.inner,t=n instanceof Uint8Array?n:Uint8Array.from(n);return r.import_weirpack(t)}async dispose(){if(this.disposed)return;this.disposed=!0,(await this.inner).free()}}function ne(e,n){if(!e)throw new Error("Assertion failed")}class ee{constructor(n){I(this,"binary"),this.binary=n,this.binary.setup()}async serializeArg(n){var r;const{Lint:t,Span:a,Suggestion:i}=await this.binary.getBinaryModule();if(Array.isArray(n))return{json:JSON.stringify(await Promise.all(n.map(g=>this.serializeArg(g)))),type:"Array"};const o=typeof n;switch(o){case"string":case"number":case"boolean":case"undefined":return{json:JSON.stringify(n),type:o};case"bigint":return{json:n.toString(),type:o}}if(n.to_json!==void 0){const g=n.to_json();let _;const c=(r=n.constructor)==null?void 0:r.name;if(n instanceof t||c==="Lint"?_="Lint":n instanceof i||c==="Suggestion"?_="Suggestion":(n instanceof a||c==="Span")&&(_="Span"),_===void 0)throw new Error("Unhandled case: type undefined");return{json:g,type:_}}if(o=="object")return{json:JSON.stringify(await Promise.all(Object.entries(n).map(([g,_])=>this.serializeArg([g,_])))),type:"object"};throw new Error(`Unhandled case: ${n}`)}async serialize(n){return{procName:n.procName,args:await Promise.all(n.args.map(r=>this.serializeArg(r)))}}async deserializeArg(n){const{Lint:r,Span:t,Suggestion:a}=await this.binary.getBinaryModule();switch(n.type){case"bigint":return BigInt(n.json);case"undefined":return;case"boolean":case"number":case"string":return JSON.parse(n.json);case"Suggestion":return a.from_json(n.json);case"Lint":return r.from_json(n.json);case"Span":return t.from_json(n.json);case"Array":{const i=JSON.parse(n.json);return ne(Array.isArray(i)),await Promise.all(i.map(o=>this.deserializeArg(o)))}case"object":{const i=JSON.parse(n.json);return Object.fromEntries(await Promise.all(i.map(o=>this.deserializeArg(o))))}default:throw new Error(`Unhandled case: ${n.type}`)}}async deserialize(n){return{procName:n.procName,args:await Promise.all(n.args.map(r=>this.deserializeArg(r)))}}}const Vn=`var __defProp = Object.defineProperty;
2
2
  var __typeError = (msg) => {
3
3
  throw TypeError(msg);
4
4
  };
@@ -1 +1 @@
1
- import{i as e}from"./index-1WTcEinQ.js";const i=e("Maximize2",[["polyline",{points:"15 3 21 3 21 9",key:"mznyad"}],["polyline",{points:"9 21 3 21 3 15",key:"1avn1i"}],["line",{x1:"21",x2:"14",y1:"3",y2:"10",key:"ota7mn"}],["line",{x1:"3",x2:"10",y1:"21",y2:"14",key:"1atl0r"}]]);const s=e("Minus",[["path",{d:"M5 12h14",key:"1ays0h"}]]);const y=e("Plus",[["path",{d:"M5 12h14",key:"1ays0h"}],["path",{d:"M12 5v14",key:"s699le"}]]);export{s as M,y as P,i as a};
1
+ import{i as e}from"./index-CFIrNdl3.js";const i=e("Maximize2",[["polyline",{points:"15 3 21 3 21 9",key:"mznyad"}],["polyline",{points:"9 21 3 21 3 15",key:"1avn1i"}],["line",{x1:"21",x2:"14",y1:"3",y2:"10",key:"ota7mn"}],["line",{x1:"3",x2:"10",y1:"21",y2:"14",key:"1atl0r"}]]);const s=e("Minus",[["path",{d:"M5 12h14",key:"1ays0h"}]]);const y=e("Plus",[["path",{d:"M5 12h14",key:"1ays0h"}],["path",{d:"M12 5v14",key:"s699le"}]]);export{s as M,y as P,i as a};
@@ -1,5 +1,5 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/index-2b7AbIWx.js","assets/BinaryModule-Aj1vLnwf-Cdan601z.js","assets/index-1WTcEinQ.js","assets/react-CsO_xvbl.js","assets/index-D64q_1vP.css","assets/binary-oOwCHZsk.js"])))=>i.map(i=>d[i]);
2
- import{_ as w}from"./index-1WTcEinQ.js";import"./react-CsO_xvbl.js";const k=/([A-Za-z][A-Za-z0-9_.:/-]*(?:\s+[A-Za-z][A-Za-z0-9_.:/-]*){0,7})\s*$/,S=new Set(["tabular","tabularx","tabulary","longtable","array","matrix","pmatrix","bmatrix","Bmatrix","vmatrix","Vmatrix"]),A=new Set(["math","displaymath","equation","equation*","align","align*","alignat","alignat*","gather","gather*","multline","multline*","flalign","flalign*","tikzpicture","axis","scope","pgfonlayer","pgfpicture","tabular","tabularx","tabulary","longtable","array","matrix","pmatrix","bmatrix","Bmatrix","vmatrix","Vmatrix","verbatim","Verbatim","lstlisting","minted","comment","algorithmic","alignat"]),b=new Set(["documentclass","usepackage","RequirePackage","includegraphics","tikzset","pgfplotsset","hypersetup","lstset","definecolor","colorlet","setlength","setcounter","draw","path","fill","filldraw","shade","node","addplot","color","textcolor","colorbox","pagecolor"]),L=new Set(["label","hypertarget","ref","pageref","autoref","nameref","hyperref","index","gls","Gls","glspl","Glspl","cite","citep","citet","citeauthor","citeyear","citenum","parencite","textcite","autocite","footcite"]),z=5;let d=null,_=Promise.resolve(),x="";function c(t,i,n){n>i&&t.push({from:i,to:n})}function p(t,i,n,a){if(t[i]!==n)return null;let e=0;for(let r=i;r<t.length;r+=1){const l=t[r-1]==="\\"&&t[r-2]!=="\\";if(!l&&t[r]===n&&(e+=1),!l&&t[r]===a&&(e-=1,e===0))return{from:i,to:r+1,end:r+1}}return null}function u(t,i){let n=i;for(;n<t.length&&/[ \t\r\n]/.test(t[n]);)n+=1;return n}function E(t,i){if(t[i]!=="%")return!1;let n=0;for(let a=i-1;a>=0&&t[a]==="\\";a-=1)n+=1;return n%2===0}function P(t){return/[=,!/]/.test(t)||/\b(?:colorbar|legend|width|height|draw|fill|style|domain|samples|anchor|at|axis)\b/.test(t)}function O(t){return L.has(t)||/^cite[A-Za-z]*/.test(t)}function Z(t,i){for(let n=t.indexOf("=");n>=0;n=t.indexOf("=",n+1)){const e=Math.max(...[`
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/index-sO8WQtsV.js","assets/BinaryModule-Aj1vLnwf-DtjQ0MTe.js","assets/index-CFIrNdl3.js","assets/react-CsO_xvbl.js","assets/index-DdrajKQB.css","assets/binary-Pf35qK34.js"])))=>i.map(i=>d[i]);
2
+ import{_ as w}from"./index-CFIrNdl3.js";import"./react-CsO_xvbl.js";const k=/([A-Za-z][A-Za-z0-9_.:/-]*(?:\s+[A-Za-z][A-Za-z0-9_.:/-]*){0,7})\s*$/,S=new Set(["tabular","tabularx","tabulary","longtable","array","matrix","pmatrix","bmatrix","Bmatrix","vmatrix","Vmatrix"]),A=new Set(["math","displaymath","equation","equation*","align","align*","alignat","alignat*","gather","gather*","multline","multline*","flalign","flalign*","tikzpicture","axis","scope","pgfonlayer","pgfpicture","tabular","tabularx","tabulary","longtable","array","matrix","pmatrix","bmatrix","Bmatrix","vmatrix","Vmatrix","verbatim","Verbatim","lstlisting","minted","comment","algorithmic","alignat"]),b=new Set(["documentclass","usepackage","RequirePackage","includegraphics","tikzset","pgfplotsset","hypersetup","lstset","definecolor","colorlet","setlength","setcounter","draw","path","fill","filldraw","shade","node","addplot","color","textcolor","colorbox","pagecolor"]),L=new Set(["label","hypertarget","ref","pageref","autoref","nameref","hyperref","index","gls","Gls","glspl","Glspl","cite","citep","citet","citeauthor","citeyear","citenum","parencite","textcite","autocite","footcite"]),z=5;let d=null,_=Promise.resolve(),x="";function c(t,i,n){n>i&&t.push({from:i,to:n})}function p(t,i,n,a){if(t[i]!==n)return null;let e=0;for(let r=i;r<t.length;r+=1){const l=t[r-1]==="\\"&&t[r-2]!=="\\";if(!l&&t[r]===n&&(e+=1),!l&&t[r]===a&&(e-=1,e===0))return{from:i,to:r+1,end:r+1}}return null}function u(t,i){let n=i;for(;n<t.length&&/[ \t\r\n]/.test(t[n]);)n+=1;return n}function E(t,i){if(t[i]!=="%")return!1;let n=0;for(let a=i-1;a>=0&&t[a]==="\\";a-=1)n+=1;return n%2===0}function P(t){return/[=,!/]/.test(t)||/\b(?:colorbar|legend|width|height|draw|fill|style|domain|samples|anchor|at|axis)\b/.test(t)}function O(t){return L.has(t)||/^cite[A-Za-z]*/.test(t)}function Z(t,i){for(let n=t.indexOf("=");n>=0;n=t.indexOf("=",n+1)){const e=Math.max(...[`
3
3
  `,"[","{","]","}",",",";"].map(o=>t.lastIndexOf(o,n-1)+1)),l=t.slice(e,n).match(k);l?.index!==void 0&&c(i,e+l.index,n);let f=n+1;for(;f<t.length&&/\s/.test(t[f]);)f+=1;let s=f;if(t[f]==="{")s=p(t,f,"{","}")?.end??f;else for(;s<t.length&&!/[,\]\}\n]/.test(t[s]);)s+=1;c(i,f,s)}}function I(t,i,n){const a=/\\(begin|end)\s*\{\s*([^{}]+?)\s*\}/g;a.lastIndex=i;let e=1;for(let r=a.exec(t);r;r=a.exec(t))if(r[2].trim()===n){if(r[1]==="begin")e+=1;else if(--e===0)return a.lastIndex}return null}function R(t,i){for(const n of t.matchAll(/\\\((?:\\.|[^])*?\\\)|\\\[(?:\\.|[^])*?\\\]/g))n.index!==void 0&&c(i,n.index,n.index+n[0].length);for(let n=0;n<t.length;n+=1){if(t[n]!=="$"||t[n-1]==="\\")continue;const a=t[n+1]==="$"?"$$":"$",e=t.indexOf(a,n+a.length);e>=0&&(c(i,n,e+a.length),n=e+a.length-1)}}function $(t){const i=[],n=/[A-Za-z@]/;for(let e=0;e<t.length;e+=1){if(E(t,e)){const o=t.indexOf(`
4
4
  `,e);c(i,e,o<0?t.length:o),e=o<0?t.length:o;continue}if(t[e]!=="\\")continue;const r=e;let l=e+1;if(n.test(t[l]??""))for(;l<t.length&&/[A-Za-z@0-9:_]/.test(t[l]);)l+=1;else l<t.length&&(l+=1);const f=t.slice(e+1,l);c(i,r,l);let s=u(t,l);if(f==="begin"||f==="end"){const o=p(t,s,"{","}");if(o){c(i,o.from,o.to);const h=t.slice(o.from+1,o.to-1).trim();if(s=u(t,o.end),f==="begin"){const g=p(t,s,"[","]");if(g&&(c(i,g.from,g.to),s=u(t,g.end)),S.has(h)){const m=p(t,s,"{","}");m&&c(i,m.from,m.to)}if(A.has(h)){const m=I(t,o.end,h);if(m!==null){c(i,r,m),e=m-1;continue}}}}e=l-1;continue}if(O(f))for(t[s]==="*"&&(s=u(t,s+1));;){const o=p(t,s,"[","]")??p(t,s,"{","}");if(!o)break;c(i,o.from,o.to),s=u(t,o.end)}else{const o=p(t,s,"[","]");if(o&&(b.has(f)||P(t.slice(o.from+1,o.to-1)))&&(c(i,o.from,o.to),s=u(t,o.end)),b.has(f)){const h=f==="definecolor"||f==="colorlet"?3:1;for(let g=0;g<h;g+=1){const m=p(t,s,"{","}");if(!m)break;c(i,m.from,m.to),s=u(t,m.end)}}}e=l-1}R(t,i),Z(t,i);for(const e of t.matchAll(/(?:https?|ftp):\/\/[^\s]+/gi))e.index!==void 0&&c(i,e.index,e.index+e[0].length);i.sort((e,r)=>e.from-r.from||e.to-r.to);const a=[];for(const e of i){const r=a.at(-1);r&&e.from<=r.to?r.to=Math.max(r.to,e.to):a.push({...e})}return a}function T(t){const i=$(t),n=[];let a=0,e=0;for(const r of t){for(;e<i.length&&i[e].to<=a;)e+=1;const l=i[e];n.push(l&&l.from<=a&&a<l.to&&r!==`
5
- `&&r!=="\r"?" ":r),a+=r.length}return n.join("")}function V(t){const i=[0];let n=0;for(const a of t)n+=a.length,i.push(n);return i}function B(t){return[...new Set(t.map(i=>i.trim()).filter(Boolean))].sort((i,n)=>i.localeCompare(n)).join("\0")}async function C(t,i){const n=_.then(async()=>{if(!d)try{const[{WorkerLinter:e,LocalLinter:r},{binary:l}]=await Promise.all([w(()=>import("./index-2b7AbIWx.js"),__vite__mapDeps([0,1,2,3,4])),w(()=>import("./binary-oOwCHZsk.js"),__vite__mapDeps([5,1,2,3,4]))]),f=typeof Worker<"u";try{d=new(f?e:r)({binary:l}),await d.setup()}catch(s){const o=d;if(d=null,await o?.dispose().catch(()=>{}),!f)throw s;d=new r({binary:l}),await d.setup()}}catch(e){throw d=null,x="",e}const a=B(t);return a!==x&&(await d.clearWords(),t.length&&await d.importWords([...new Set(t.map(e=>e.trim()).filter(Boolean))]),x=a),i(d)});return _=n.then(()=>{},()=>{}),n}function q(t){return t.get_replacement_text()}function W(t,i,n,a,e){const r={from:a.start,to:a.end},l={from:e[a.start]??-1,to:e[a.end]??-1},f=[r,l].filter((o,h,g)=>o.from>=0&&o.to>o.from&&o.to<=t.length&&g.findIndex(m=>m.from===o.from&&m.to===o.to)===h);if(f.length===0)return null;const s=n.get_problem_text();return f.find(o=>i.slice(o.from,o.to)===s)??f.find(o=>/[A-Za-z]/.test(i.slice(o.from,o.to)))??f[0]??null}function D(t,i,n,a){const e=n.span();try{const r=W(t,i,n,e,a);if(!r)return null;const{from:l,to:f}=r;if(!/[A-Za-z]/.test(i.slice(l,f)))return null;const s=t.slice(l,f);if(!s.trim()||/[\\%$]/.test(s))return null;const o=n.lint_kind()==="Spelling"||n.lint_kind()==="Typo"?"spelling":"grammar",h=n.suggestions(),g=h.map(q).filter((m,y,v)=>y<z&&v.indexOf(m)===y);for(const m of h)m.free();return{from:l,to:f,word:s,kind:o,message:n.message(),suggestions:g}}finally{e.free()}}function G(t,i=[]){const n=T(t),a=V(t);return C(i,async e=>{const r=await e.lint(n,{language:"plaintext",dedup:!0,isolateEnglish:!1});try{return r.map(l=>D(t,n,l,a)).filter(l=>!!l).sort((l,f)=>l.from-f.from||l.to-f.to)}finally{for(const l of r)l.free()}})}export{$ as ignoredRanges,G as lintLatex,T as maskLatexSource};
5
+ `&&r!=="\r"?" ":r),a+=r.length}return n.join("")}function V(t){const i=[0];let n=0;for(const a of t)n+=a.length,i.push(n);return i}function B(t){return[...new Set(t.map(i=>i.trim()).filter(Boolean))].sort((i,n)=>i.localeCompare(n)).join("\0")}async function C(t,i){const n=_.then(async()=>{if(!d)try{const[{WorkerLinter:e,LocalLinter:r},{binary:l}]=await Promise.all([w(()=>import("./index-sO8WQtsV.js"),__vite__mapDeps([0,1,2,3,4])),w(()=>import("./binary-Pf35qK34.js"),__vite__mapDeps([5,1,2,3,4]))]),f=typeof Worker<"u";try{d=new(f?e:r)({binary:l}),await d.setup()}catch(s){const o=d;if(d=null,await o?.dispose().catch(()=>{}),!f)throw s;d=new r({binary:l}),await d.setup()}}catch(e){throw d=null,x="",e}const a=B(t);return a!==x&&(await d.clearWords(),t.length&&await d.importWords([...new Set(t.map(e=>e.trim()).filter(Boolean))]),x=a),i(d)});return _=n.then(()=>{},()=>{}),n}function q(t){return t.get_replacement_text()}function W(t,i,n,a,e){const r={from:a.start,to:a.end},l={from:e[a.start]??-1,to:e[a.end]??-1},f=[r,l].filter((o,h,g)=>o.from>=0&&o.to>o.from&&o.to<=t.length&&g.findIndex(m=>m.from===o.from&&m.to===o.to)===h);if(f.length===0)return null;const s=n.get_problem_text();return f.find(o=>i.slice(o.from,o.to)===s)??f.find(o=>/[A-Za-z]/.test(i.slice(o.from,o.to)))??f[0]??null}function D(t,i,n,a){const e=n.span();try{const r=W(t,i,n,e,a);if(!r)return null;const{from:l,to:f}=r;if(!/[A-Za-z]/.test(i.slice(l,f)))return null;const s=t.slice(l,f);if(!s.trim()||/[\\%$]/.test(s))return null;const o=n.lint_kind()==="Spelling"||n.lint_kind()==="Typo"?"spelling":"grammar",h=n.suggestions(),g=h.map(q).filter((m,y,v)=>y<z&&v.indexOf(m)===y);for(const m of h)m.free();return{from:l,to:f,word:s,kind:o,message:n.message(),suggestions:g}}finally{e.free()}}function G(t,i=[]){const n=T(t),a=V(t);return C(i,async e=>{const r=await e.lint(n,{language:"plaintext",dedup:!0,isolateEnglish:!1});try{return r.map(l=>D(t,n,l,a)).filter(l=>!!l).sort((l,f)=>l.from-f.from||l.to-f.to)}finally{for(const l of r)l.free()}})}export{$ as ignoredRanges,G as lintLatex,T as maskLatexSource};
@@ -10,9 +10,9 @@
10
10
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource/iosevka@5.2.5/400.css" />
11
11
  <link rel="icon" type="image/svg+xml" href="/logo.svg" />
12
12
  <title>TexLite</title>
13
- <script type="module" crossorigin src="/assets/index-1WTcEinQ.js"></script>
13
+ <script type="module" crossorigin src="/assets/index-CFIrNdl3.js"></script>
14
14
  <link rel="modulepreload" crossorigin href="/assets/react-CsO_xvbl.js">
15
- <link rel="stylesheet" crossorigin href="/assets/index-D64q_1vP.css">
15
+ <link rel="stylesheet" crossorigin href="/assets/index-DdrajKQB.css">
16
16
  </head>
17
17
  <body>
18
18
  <div id="root"></div>
@@ -13,7 +13,7 @@ import { activeAdminCount, pruneExpiredSessions } from "./db.js";
13
13
  import { createSessionToken, hashPassword, verifyPassword, digestToken, LoginRateLimiter } from "./security.js";
14
14
  import { currentUser, publicUser, requireAdmin, requireUser } from "./auth.js";
15
15
  import { accessibleProject, canEdit } from "./projects.js";
16
- import { createProjectFiles, duplicateProjectFiles, assertNoSourceSymlinks, listProjectFiles, listProjectFilesAsync, outputRoot, pruneTrashDirectory, removeProjectDirectory, resolveSourcePath, safeRelativePath, sourceRoot } from "./files.js";
16
+ import { createProjectFiles, duplicateProjectFiles, assertNoSourceSymlinks, listProjectFiles, listProjectFilesAsync, outputRoot, pruneTrashDirectory, removeProjectDirectory, resolveSourcePath, safePathSegment, safeRelativePath, sourceRoot } from "./files.js";
17
17
  import { CompileQueue, ProjectCompileCoordinator, listPublishedCompileArtifacts, pruneOrphanedCompileRuns, reconcilePublishedCompileRuns } from "./compiler.js";
18
18
  import { createSourceAnchor, offsetToLine, reanchorFileComments } from "./anchors.js";
19
19
  import { extractProjectZip } from "./zip.js";
@@ -967,6 +967,7 @@ export async function buildApp(config, db, options = {}) {
967
967
  if (!history.version(versionId, id)) {
968
968
  throw Object.assign(new Error("历史版本不存在"), { statusCode: 404, code: "HISTORY_VERSION_NOT_FOUND" });
969
969
  }
970
+ history.validateRestoreTarget(id, versionId, filePath);
970
971
  } });
971
972
  });
972
973
  app.put("/api/projects/:id/archive", async (request, reply) => {
@@ -1539,9 +1540,10 @@ export async function buildApp(config, db, options = {}) {
1539
1540
  const source = safeRelativePath(typeof body.source === "string" ? body.source : "");
1540
1541
  const destinationDirectory = body.destinationDirectory === "" ? ""
1541
1542
  : safeRelativePath(typeof body.destinationDirectory === "string" ? body.destinationDirectory : "");
1542
- const destination = destinationDirectory
1543
- ? `${destinationDirectory}/${path.posix.basename(source)}`
1544
- : path.posix.basename(source);
1543
+ const destinationName = body.destinationName === undefined
1544
+ ? path.posix.basename(source)
1545
+ : safePathSegment(typeof body.destinationName === "string" ? body.destinationName : "");
1546
+ const destination = destinationDirectory ? `${destinationDirectory}/${destinationName}` : destinationName;
1545
1547
  const sourceAbsolute = resolveSourcePath(config, id, source);
1546
1548
  if (!fs.existsSync(sourceAbsolute))
1547
1549
  return apiError(reply, 404, "PATH_NOT_FOUND", "要移动的文件或目录不存在", { path: source });
@@ -60,6 +60,14 @@ export function safeRelativePath(input) {
60
60
  }
61
61
  return normalized;
62
62
  }
63
+ /** Validate a user-provided file or directory name used within one folder. */
64
+ export function safePathSegment(input) {
65
+ const name = input.trim();
66
+ if (!name || name.includes("\0") || name.includes("/") || name.includes("\\")) {
67
+ throw Object.assign(new Error("无效的文件名"), { statusCode: 400, code: "INVALID_PATH" });
68
+ }
69
+ return safeRelativePath(name);
70
+ }
63
71
  export function symbolicLinkError(relativePath) {
64
72
  return Object.assign(new Error(`项目源文件包含不受支持的符号链接,已拒绝访问:${relativePath || "source"}`), { statusCode: 409, code: "SYMLINK_FORBIDDEN" });
65
73
  }
@@ -131,6 +131,24 @@ export class ProjectHistoryService {
131
131
  .get(versionId, projectId);
132
132
  return row ? parseManifest(row.manifest_json) : null;
133
133
  }
134
+ /**
135
+ * Validate a single-file restore before the project enters maintenance.
136
+ * restore() repeats the target check while the exclusive operation is held
137
+ * so a directory created between these two checks cannot be replaced.
138
+ */
139
+ validateRestoreTarget(projectId, versionId, filePathInput) {
140
+ if (!filePathInput)
141
+ return;
142
+ const manifest = this.manifest(projectId, versionId);
143
+ if (!manifest) {
144
+ throw Object.assign(new Error("历史版本不存在"), { code: "HISTORY_VERSION_NOT_FOUND", statusCode: 404 });
145
+ }
146
+ const filePath = safeRelativePath(filePathInput);
147
+ if (!manifest.files[filePath]) {
148
+ throw Object.assign(new Error("该历史版本中不存在此文件"), { code: "HISTORY_FILE_NOT_FOUND", statusCode: 404 });
149
+ }
150
+ this.assertRestoreTargetIsFile(projectId, filePath);
151
+ }
134
152
  setLabel(projectId, versionId, label) {
135
153
  const result = this.db.prepare("UPDATE project_history_versions SET label = ? WHERE id = ? AND project_id = ?")
136
154
  .run(label, versionId, projectId);
@@ -152,12 +170,18 @@ export class ProjectHistoryService {
152
170
  const entry = manifest.files[filePath];
153
171
  if (!entry)
154
172
  throw Object.assign(new Error("该历史版本中不存在此文件"), { code: "HISTORY_FILE_NOT_FOUND", statusCode: 404 });
173
+ this.assertRestoreTargetIsFile(projectId, filePath);
155
174
  const target = resolveSourcePath(this.config, projectId, filePath);
156
175
  fs.mkdirSync(path.dirname(target), { recursive: true, mode: 0o700 });
157
176
  const temporary = `${target}.history-${randomUUID()}.tmp`;
158
- fs.copyFileSync(this.objectPath(projectId, entry.digest), temporary);
159
- fs.chmodSync(temporary, 0o600);
160
- fs.renameSync(temporary, target);
177
+ try {
178
+ fs.copyFileSync(this.objectPath(projectId, entry.digest), temporary);
179
+ fs.chmodSync(temporary, 0o600);
180
+ fs.renameSync(temporary, target);
181
+ }
182
+ finally {
183
+ fs.rmSync(temporary, { force: true });
184
+ }
161
185
  return { restoredPaths: [filePath], manifest };
162
186
  }
163
187
  this.restoreProjectTree(projectId, manifest);
@@ -165,6 +189,13 @@ export class ProjectHistoryService {
165
189
  .run(manifest.settings.mainFile, manifest.settings.engine, manifest.settings.latexmkrc, projectId);
166
190
  return { restoredPaths: Object.keys(manifest.files).sort(), manifest };
167
191
  }
192
+ assertRestoreTargetIsFile(projectId, filePath) {
193
+ const target = resolveSourcePath(this.config, projectId, filePath);
194
+ const targetStat = fs.existsSync(target) ? fs.lstatSync(target) : null;
195
+ if (targetStat && !targetStat.isFile()) {
196
+ throw Object.assign(new Error("历史文件恢复目标不是普通文件"), { code: "HISTORY_TARGET_CONFLICT", statusCode: 409 });
197
+ }
198
+ }
168
199
  latestRow(projectId) {
169
200
  return this.db.prepare(`SELECT * FROM project_history_versions WHERE project_id = ?
170
201
  ORDER BY created_at DESC, rowid DESC LIMIT 1`).get(projectId) ?? null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "texlite",
3
- "version": "0.6.7",
3
+ "version": "0.6.8",
4
4
  "description": "A lightweight local-first collaborative LaTeX workspace",
5
5
  "license": "AGPL-3.0-only",
6
6
  "repository": {
@@ -1 +0,0 @@
1
- import{B as r}from"./BinaryModule-Aj1vLnwf-Cdan601z.js";import"./index-1WTcEinQ.js";import"./react-CsO_xvbl.js";const a=""+new URL("/assets/harper_wasm_bg-LWXDb7Ll.wasm",import.meta.url).href,o=r.create(a,"full");export{o as binary};