@font-face{font-family:"Space Grotesk";font-style:normal;font-weight:300 700;font-display:swap;src:url(/assets/fonts/space-grotesk-latin-variable.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:"Onest";font-style:normal;font-weight:100 900;font-display:swap;src:url(/assets/fonts/onest-variable.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:"Geist Mono";font-style:normal;font-weight:400 700;font-display:swap;src:url(/assets/fonts/geist-mono-variable.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}:root{color-scheme:dark;--bg:#1A1816;--card:#242120;--elev:#2E2A28;--line:rgba(237,231,220,.14);--line2:rgba(237,231,220,.22);--ink:#EDE7DA;--mute:#C9C2B4;--faint:#A9A192;--accent:#3FB3A6;--accent2:#6FD0C4;--on-accent:#12100E;--sky:#6FD0C4;--agn-mark:#5FBFB4;--warn:#D9A05B;--on-warn:#1a1206;--ok:#7FB77E;--danger-ink:#EE8272;--danger-line:rgba(224,122,107,.16);--eyebrow:#D9A05B;--ok-soft:rgba(127,183,126,.16);--amber-soft:rgba(217,160,91,.16);--info-soft:rgba(63,179,166,.14);--navpill:#EDE7DA;--navpill-ink:#1A1816;--cta:#EDE7DA;--cta-ink:#12100E;--id-0:#3FB3A6;--id-1:#D9A05B;--id-2:#7FB77E;--id-3:#B9A7D9;--id-4:#7FA7C9;--id-5:#E07A6B;--shadow:none;--shadow-lift:0 8px 24px rgba(0,0,0,.40);--ring:0 0 0 2px var(--bg),0 0 0 4px var(--accent);--ds-surface-1:#12161F;--ds-surface-2:#1A202B;--ds-surface-3:#232B38;--ds-surface-hover:#1F2734;--ds-border:#2B3442;--ds-border-strong:#3D4859;--ds-text-2:#A3AEC0;--ds-text-3:#78829A;--ds-status-pending:#94A3B8;--ds-status-ready:var(--sky);--ds-status-running:#22D3EE;--ds-status-completed:#86EFAC;--ds-status-failed:#F43F5E;--ds-status-revision:#FBBF24;--brand-google-red:#EA4335;--brand-google-blue:#4285F4;--brand-google-yellow:#FBBC05;--brand-google-green:#34A853;--brand-google-text:#1F1F1F;--brand-google-border:#DADCE0;--brand-google-border-hover:#1A73E8;--brand-google-bg-hover:#F8F9FA;--brand-white:#FFFFFF;--brand-apple-bg:#000000;--brand-apple-bg-hover:#1A1A1A;--brand-facebook:#1877F2;--brand-facebook-hover:#166FE5;--brand-github-bg:#151515;--brand-github-border:#2A2A2A;--brand-github-bg-hover:#24292E;--brand-ms-red:#F25022;--brand-ms-green:#7FBA00;--brand-ms-blue:#00A4EF;--brand-ms-yellow:#FFB900;--brand-ms-border:#8C8C8C;--brand-dark-edge:#6A645C;--sans:"Onest","Segoe UI","Segoe UI Variable Text",system-ui,-apple-system,sans-serif;--mono:"Geist Mono",ui-monospace,"Cascadia Code",Consolas,monospace;--font-display:"Space Grotesk",system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;--display:var(--font-display)}@media (prefers-color-scheme:light){:root{color-scheme:light;--bg:#F1ECE3;--card:#FAF7F1;--elev:#F4EFE6;--line:#DDD5C7;--line2:#C9C0B0;--ink:#2B2622;--mute:#5C544B;--faint:#676057;--accent:#0D6E89;--accent2:#0891B2;--on-accent:#FFFFFF;--sky:#0E7490;--agn-mark:#03625A;--warn:#8D5A1C;--on-warn:var(--bg);--ok:#387349;--danger-ink:#A4443A;--danger-line:#F3DFDA;--eyebrow:#9C6420;--ok-soft:#E4EEE3;--amber-soft:#F3E7D3;--info-soft:#DDEBEE;--navpill:#2B2622;--navpill-ink:#F1ECE3;--cta:#2B2622;--cta-ink:#F1ECE3;--id-0:#0E7490;--id-1:#9C6420;--id-2:#3C7A4E;--id-3:#6E5A8A;--id-4:#3F6B8C;--id-5:#A9463C;--shadow:none;--shadow-lift:0 6px 18px rgba(43,38,34,.10);--ring:0 0 0 2px var(--bg),0 0 0 4px var(--accent);--ds-surface-1:var(--card);--ds-surface-2:#FAFAF7;--ds-surface-3:#EDECE6;--ds-surface-hover:#F1F0EA;--ds-border:#DEDCD3;--ds-border-strong:#C2BFB2;--ds-text-2:#4A4F5C;--ds-text-3:#6E7382;--ds-status-pending:#475569;--ds-status-ready:var(--accent);--ds-status-running:#155E75;--ds-status-completed:#15803D;--ds-status-failed:#881337;--ds-status-revision:#B45309;--brand-google-red:#EA4335;--brand-google-blue:#4285F4;--brand-google-yellow:#FBBC05;--brand-google-green:#34A853;--brand-google-text:#1F1F1F;--brand-google-border:#DADCE0;--brand-google-border-hover:#1A73E8;--brand-google-bg-hover:#F8F9FA;--brand-white:#FFFFFF;--brand-apple-bg:#000000;--brand-apple-bg-hover:#1A1A1A;--brand-facebook:#1877F2;--brand-facebook-hover:#166FE5;--brand-github-bg:#151515;--brand-github-border:#2A2A2A;--brand-github-bg-hover:#24292E;--brand-ms-red:#F25022;--brand-ms-green:#7FBA00;--brand-ms-blue:#00A4EF;--brand-ms-yellow:#FFB900;--brand-ms-border:#8C8C8C;--brand-dark-edge:#6A645C}}html[data-theme="dark"]{color-scheme:dark;--bg:#1A1816;--card:#242120;--elev:#2E2A28;--line:rgba(237,231,220,.14);--line2:rgba(237,231,220,.22);--ink:#EDE7DA;--mute:#C9C2B4;--faint:#A9A192;--accent:#3FB3A6;--accent2:#6FD0C4;--on-accent:#12100E;--sky:#6FD0C4;--agn-mark:#5FBFB4;--warn:#D9A05B;--on-warn:#1a1206;--ok:#7FB77E;--danger-ink:#EE8272;--danger-line:rgba(224,122,107,.16);--eyebrow:#D9A05B;--ok-soft:rgba(127,183,126,.16);--amber-soft:rgba(217,160,91,.16);--info-soft:rgba(63,179,166,.14);--navpill:#EDE7DA;--navpill-ink:#1A1816;--cta:#EDE7DA;--cta-ink:#12100E;--id-0:#3FB3A6;--id-1:#D9A05B;--id-2:#7FB77E;--id-3:#B9A7D9;--id-4:#7FA7C9;--id-5:#E07A6B;--shadow:none;--shadow-lift:0 8px 24px rgba(0,0,0,.40);--ring:0 0 0 2px var(--bg),0 0 0 4px var(--accent);--ds-surface-1:#12161F;--ds-surface-2:#1A202B;--ds-surface-3:#232B38;--ds-surface-hover:#1F2734;--ds-border:#2B3442;--ds-border-strong:#3D4859;--ds-text-2:#A3AEC0;--ds-text-3:#78829A;--ds-status-pending:#94A3B8;--ds-status-ready:var(--sky);--ds-status-running:#22D3EE;--ds-status-completed:#86EFAC;--ds-status-failed:#F43F5E;--ds-status-revision:#FBBF24;--brand-google-red:#EA4335;--brand-google-blue:#4285F4;--brand-google-yellow:#FBBC05;--brand-google-green:#34A853;--brand-google-text:#1F1F1F;--brand-google-border:#DADCE0;--brand-google-border-hover:#1A73E8;--brand-google-bg-hover:#F8F9FA;--brand-white:#FFFFFF;--brand-apple-bg:#000000;--brand-apple-bg-hover:#1A1A1A;--brand-facebook:#1877F2;--brand-facebook-hover:#166FE5;--brand-github-bg:#151515;--brand-github-border:#2A2A2A;--brand-github-bg-hover:#24292E;--brand-ms-red:#F25022;--brand-ms-green:#7FBA00;--brand-ms-blue:#00A4EF;--brand-ms-yellow:#FFB900;--brand-ms-border:#8C8C8C;--brand-dark-edge:#6A645C}html[data-theme="light"]{color-scheme:light;--bg:#F1ECE3;--card:#FAF7F1;--elev:#F4EFE6;--line:#DDD5C7;--line2:#C9C0B0;--ink:#2B2622;--mute:#5C544B;--faint:#676057;--accent:#0D6E89;--accent2:#0891B2;--on-accent:#FFFFFF;--sky:#0E7490;--agn-mark:#03625A;--warn:#8D5A1C;--on-warn:var(--bg);--ok:#387349;--danger-ink:#A4443A;--danger-line:#F3DFDA;--eyebrow:#9C6420;--ok-soft:#E4EEE3;--amber-soft:#F3E7D3;--info-soft:#DDEBEE;--navpill:#2B2622;--navpill-ink:#F1ECE3;--cta:#2B2622;--cta-ink:#F1ECE3;--id-0:#0E7490;--id-1:#9C6420;--id-2:#3C7A4E;--id-3:#6E5A8A;--id-4:#3F6B8C;--id-5:#A9463C;--shadow:none;--shadow-lift:0 6px 18px rgba(43,38,34,.10);--ring:0 0 0 2px var(--bg),0 0 0 4px var(--accent);--ds-surface-1:var(--card);--ds-surface-2:#FAFAF7;--ds-surface-3:#EDECE6;--ds-surface-hover:#F1F0EA;--ds-border:#DEDCD3;--ds-border-strong:#C2BFB2;--ds-text-2:#4A4F5C;--ds-text-3:#6E7382;--ds-status-pending:#475569;--ds-status-ready:var(--accent);--ds-status-running:#155E75;--ds-status-completed:#15803D;--ds-status-failed:#881337;--ds-status-revision:#B45309;--brand-google-red:#EA4335;--brand-google-blue:#4285F4;--brand-google-yellow:#FBBC05;--brand-google-green:#34A853;--brand-google-text:#1F1F1F;--brand-google-border:#DADCE0;--brand-google-border-hover:#1A73E8;--brand-google-bg-hover:#F8F9FA;--brand-white:#FFFFFF;--brand-apple-bg:#000000;--brand-apple-bg-hover:#1A1A1A;--brand-facebook:#1877F2;--brand-facebook-hover:#166FE5;--brand-github-bg:#151515;--brand-github-border:#2A2A2A;--brand-github-bg-hover:#24292E;--brand-ms-red:#F25022;--brand-ms-green:#7FBA00;--brand-ms-blue:#00A4EF;--brand-ms-yellow:#FFB900;--brand-ms-border:#8C8C8C;--brand-dark-edge:#6A645C}:root{--hit-min:32px;--gap-min:8px}@media (pointer:coarse){:root{--hit-min:44px}}.act[aria-busy="true"],html[data-ds] .ds-btn[aria-busy="true"],html[data-ds] .ds-btn-primary[aria-busy="true"]{position:relative;cursor:progress;pointer-events:none;opacity:.7}.act[aria-busy="true"]::after,html[data-ds] .ds-btn[aria-busy="true"]::after,html[data-ds] .ds-btn-primary[aria-busy="true"]::after{content:"";display:inline-block;width:12px;height:12px;border-radius:50%;border:2px solid currentColor;border-right-color:transparent;animation:gspin .8s linear infinite;flex:none}@keyframes gspin{to{transform:rotate(360deg)}}.act:active:not([disabled]):not([aria-busy="true"]),html[data-ds] .ds-btn:active:not(:disabled):not([aria-busy="true"]),html[data-ds] .ds-btn-primary:active:not(:disabled):not([aria-busy="true"]){transform:scale(.98)}@media (prefers-reduced-motion:reduce){.act[aria-busy="true"]::after,html[data-ds] .ds-btn[aria-busy="true"]::after,html[data-ds] .ds-btn-primary[aria-busy="true"]::after{animation:none}}*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}html{-webkit-text-size-adjust:100%}:focus-visible{outline:2px solid var(--accent);outline-offset:2px}body{margin:0;font:16px/1.55 var(--sans);background:var(--bg);color:var(--ink);min-height:100vh;padding:0 env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);font-feature-settings:"kern" 1,"liga" 1;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;position:relative}.topbar{display:flex;align-items:center;gap:12px;min-height:50px;padding:env(safe-area-inset-top) calc(16px + env(safe-area-inset-right)) 0 calc(16px + env(safe-area-inset-left));background:var(--card);border-bottom:1px solid var(--line);position:sticky;top:0;z-index:10}.topbar::after{content:'';position:absolute;left:0;right:0;bottom:-1px;height:1px;background:linear-gradient(90deg,transparent,rgba(6,182,212,.5) 40%,rgba(56,189,248,.4) 62%,transparent)}.brand{display:flex;align-items:center;gap:10px;font-weight:700;letter-spacing:-.015em;font-size:15px;flex:0 1 auto;min-width:0;color:var(--ink);text-decoration:none}a.brand:hover{color:var(--ink);text-decoration:none}.brand .slobal-wordmark,.brand img,.brand .bsep{flex:none}.brand .bsep{width:1px;height:19px;background:var(--line2)}.brand .pname{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.who{margin-left:auto;display:flex;align-items:center;gap:9px;font-size:13px;color:var(--mute);min-width:0;flex:0 1 auto}.who>span,.who>a{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.who>a.act,.who .themetoggle{flex:none;overflow:visible}.who>.slgroup{flex:none}.who .avatar{flex:none}.who a.whoami{display:inline-flex;align-items:center;gap:8px;color:var(--mute);font-size:13.5px;font-weight:600;max-width:260px;text-decoration:none}.who a.whoami:hover{color:var(--ink);text-decoration:none}.who a.whoami .em{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}@media(max-width:600px){.topbar{gap:8px}.who{gap:7px}.who .slgroup #slhome{display:none}.who .slgroup #slhome+.slbadge{border-left:0}.who .slgroup #slhome+.soform>.slbadge{border-left:0}.brand{gap:8px}.brand .slobal-wordmark{height:18px}.brand .bsep{height:16px}.brand .pname{font-size:14px}}.themetoggle{position:relative;background:var(--elev);color:var(--ink);border:1px solid var(--line2);border-radius:8px;width:34px;height:34px;padding:0;font:15px/1 var(--sans);cursor:pointer;transition:border-color .16s,color .16s;display:inline-flex;align-items:center;justify-content:center;flex:none}.themetoggle:hover{border-color:var(--accent)}.themetoggle .tgglyph{display:block;line-height:1}.slgroup{display:inline-flex;align-items:center;flex:none;border:1px solid var(--line2);border-radius:999px;overflow:hidden}.slgroup:hover{border-color:var(--accent)}.slbadge{display:inline-flex;align-items:center;height:32px;padding:0 13px;background:var(--elev);font:800 12px/1 var(--sans);letter-spacing:.08em;text-transform:uppercase;color:var(--mute);flex:none;text-decoration:none;transition:background-color .16s,color .16s}.slbadge[hidden]{display:none}a.slbadge:hover{color:var(--ink);text-decoration:none}.slbadge+.slbadge{border-left:1px solid var(--line2)}.slbadge[hidden]+.slbadge{border-left:0}.slgroup .signout{background:transparent;color:var(--ink)}.slgroup a.signout:hover{background:var(--elev);color:var(--ink)}.soform{display:contents}button.slbadge{border:0;margin:0;border-radius:0;-webkit-appearance:none;appearance:none;cursor:pointer}.slbadge+.soform>.slbadge{border-left:1px solid var(--line2)}.slbadge[hidden]+.soform>.slbadge{border-left:0}.slgroup button.signout:hover{background:var(--elev);color:var(--ink)}button.solink{background:none;border:0;margin:0;padding:0;font:inherit;color:var(--sky);cursor:pointer;-webkit-appearance:none;appearance:none}button.solink:hover{text-decoration:underline}.avatar{width:28px;height:28px;border-radius:50%;background:linear-gradient(135deg,var(--accent),var(--accent2));color:var(--on-accent);display:flex;align-items:center;justify-content:center;font-weight:700;font-size:12px}img.avatar{display:block;overflow:hidden;object-fit:cover}.who .avatar{width:18px;height:18px;font-size:8px}.chromefoot{box-sizing:border-box;width:100%;max-width:100%;margin-top:32px;padding:16px calc(16px + env(safe-area-inset-right)) calc(16px + env(safe-area-inset-bottom)) calc(16px + env(safe-area-inset-left));border-top:1px solid var(--line);color:var(--mute);font-size:12.5px;line-height:1.5;text-align:center}.chromefoot p{margin:0;overflow-wrap:anywhere}.chromefoot .footextra{margin-top:6px;overflow-wrap:anywhere}.chromefoot a{color:var(--mute);text-decoration:underline}body::before{content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;background:radial-gradient(1100px 520px at 50% -10%,rgba(6,182,212,.06),transparent 60%)}body::after{content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;opacity:.022;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E")}.wrap{max-width:440px;margin:0 auto;padding:56px 22px}.wide{max-width:960px}.logo{font-size:38px;text-align:center;margin-bottom:8px;filter:drop-shadow(0 2px 10px rgba(6,182,212,.28))}.logo.glyph{filter:none;font-size:0;line-height:1}h1{font-size:23px;margin:0 0 4px;text-align:center;letter-spacing:.02em;font-family:var(--font-display);font-weight:600;text-transform:uppercase}.sub{color:var(--mute);text-align:center;margin:0 0 26px;font-size:14px;line-height:1.5}.card{background:var(--card);border:1px solid var(--line);border-radius:8px;padding:20px}.btn{display:flex;align-items:center;justify-content:center;gap:9px;width:100%;border:0;border-radius:8px;padding:12px;font:600 15px var(--sans);cursor:pointer;text-decoration:none;margin:0 0 10px;transition:border-color .16s,background .16s,filter .16s}.btn.sso{background:var(--elev);color:var(--ink);border:1px solid var(--line2)}.btn.sso:hover{border-color:var(--accent)}.sso-row{display:flex;gap:8px;justify-content:center}.sso-sq{flex:1 1 0;min-width:0;max-width:76px;aspect-ratio:1.3;display:flex;align-items:center;justify-content:center;border-radius:8px;border:1px solid var(--line2);text-decoration:none;transition:border-color .16s,background .16s}.sso-sq:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.sso-sq.sso-apple svg{transform:translateY(-1px)}.sso-sq.sso-google{background:var(--brand-white);border-color:var(--brand-google-border)}.sso-sq.sso-google:hover{border-color:var(--brand-google-border-hover);background:var(--brand-google-bg-hover)}.sso-sq.sso-apple{background:var(--brand-apple-bg);border-color:var(--brand-dark-edge)}.sso-sq.sso-apple:hover{background:var(--brand-apple-bg-hover)}.sso-sq.sso-facebook{background:var(--brand-facebook);border-color:var(--brand-facebook)}.sso-sq.sso-facebook:hover{background:var(--brand-facebook-hover)}.sso-sq.sso-microsoft{background:var(--brand-white);border-color:var(--brand-google-border)}.sso-sq.sso-microsoft:hover{border-color:var(--brand-google-border-hover);background:var(--brand-google-bg-hover)}.sso-sq.sso-github{background:var(--brand-apple-bg);border-color:var(--brand-dark-edge)}.sso-sq.sso-github:hover{background:var(--brand-apple-bg-hover)}.btn.primary{background:var(--accent);color:var(--on-accent)}.btn.primary:hover{filter:brightness(1.08)}.appic{flex:none;display:inline-flex;align-items:center;justify-content:center}.appic>svg{display:block}.muted{color:var(--mute);font-size:12.5px;text-align:center;margin-top:20px;line-height:1.5}.muted a,.muted2 a,.sub a{text-decoration:underline}.muted2{color:var(--mute)}input{width:100%;background:var(--bg);color:var(--ink);border:1px solid var(--line);border-radius:8px;padding:12px 14px;font:inherit;margin:0 0 10px;transition:border-color .16s,box-shadow .16s}input:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px rgba(6,182,212,.14)}table{width:100%;border-collapse:collapse;font-size:14px;font-variant-numeric:tabular-nums lining-nums}th,td{text-align:left;padding:9px 10px;border-bottom:1px solid var(--line);vertical-align:top}th{font-size:10.5px;text-transform:uppercase;letter-spacing:.07em;color:var(--faint);font-weight:650}.chip{display:inline-block;font:600 10.5px/1 var(--mono);letter-spacing:.03em;padding:3px 8px;border-radius:4px;border:1px solid var(--line2);margin:1px 2px;color:var(--mute)}.chip.on{color:var(--accent);border-color:var(--accent)}.chip.off{color:var(--warn);border-color:var(--warn)}.act{display:inline-flex;align-items:center;gap:6px;background:var(--elev);color:var(--ink);border:1px solid var(--line2);border-radius:6px;padding:5px 10px;min-height:var(--hit-min);font:500 12px var(--sans);cursor:pointer;margin:calc(var(--gap-min) / 2);transition:border-color .14s,background .14s}.act:hover{border-color:var(--accent)}.act.danger{color:var(--danger-ink);border-color:var(--danger-line)}.act.go{background:var(--accent);color:var(--on-accent);border:1px solid var(--accent);font-weight:600}.row{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin:8px 0}.pill{font-size:12px;color:var(--mute)}a{color:var(--sky);text-decoration:none}a:hover{text-decoration:underline;text-underline-offset:2px}.tier{border:1px solid var(--line);border-radius:8px;padding:16px;margin:0 0 12px;background:var(--bg)}.tier h3{margin:0 0 2px;font-size:12px;text-transform:uppercase;letter-spacing:.07em;color:var(--accent)}.tier .p{font-size:21px;font-weight:700;margin:4px 0;letter-spacing:-.02em}@media(pointer:coarse){.btn{min-height:48px}.act{min-height:44px;padding:10px 14px}input,select{min-height:46px;font-size:16px}}@media (prefers-reduced-motion:reduce){*{transition:none!important;animation:none!important}}html[data-ds]{--ds-ok-ink:var(--ok);--ds-ok-bg:transparent;--ds-ok-line:var(--ok);--ds-warn-ink:var(--warn);--ds-warn-bg:transparent;--ds-warn-line:var(--warn);--ds-neutral-ink:var(--mute);--ds-neutral-bg:transparent;--ds-neutral-line:var(--line2);--ds-tile-hover:var(--elev);--ds-shadow:none}@media (prefers-color-scheme:light){html[data-ds]:not([data-theme="dark"]){--ds-ok-ink:#067647;--ds-ok-bg:#ECFDF3;--ds-ok-line:#ECFDF3;--ds-warn-ink:#B54708;--ds-warn-bg:#FFFAEB;--ds-warn-line:#FFFAEB;--ds-neutral-ink:var(--mute);--ds-neutral-bg:#EFEEE8;--ds-neutral-line:#EFEEE8;--ds-tile-hover:#E3F1F5;--ds-shadow:0 1px 2px rgba(10,14,26,.05)}}html[data-ds][data-theme="light"]{--ds-ok-ink:#067647;--ds-ok-bg:#ECFDF3;--ds-ok-line:#ECFDF3;--ds-warn-ink:#B54708;--ds-warn-bg:#FFFAEB;--ds-warn-line:#FFFAEB;--ds-neutral-ink:var(--mute);--ds-neutral-bg:#EFEEE8;--ds-neutral-line:#EFEEE8;--ds-tile-hover:#E3F1F5;--ds-shadow:0 1px 2px rgba(10,14,26,.05)}html[data-ds] body{font-size:15px;line-height:1.6}html[data-ds] .pagetitle,html[data-ds] h2.pagetitle{font-family:var(--font-display);font-weight:600;font-size:46px;line-height:1.05;letter-spacing:.02em;text-transform:none;color:var(--ink);margin:0 0 12px}html[data-ds] .ds-h2,html[data-ds] h2:not(.pagetitle):not(.subhead){font-family:var(--font-display);font-weight:600;font-size:26px;line-height:1.25;letter-spacing:-.01em;color:var(--ink);margin:0 0 12px}html[data-ds] .ds-h3,html[data-ds] h3:not(.subhead){font-family:var(--font-display);font-weight:600;font-size:18px;line-height:1.35;letter-spacing:0;color:var(--ink);margin:0 0 8px}html[data-ds] .ds-eyebrow{display:block;font:600 11px/1.4 var(--sans);text-transform:uppercase;letter-spacing:.08em;color:var(--accent);margin:0 0 6px}html[data-ds] .ds-small{font-size:13px;line-height:1.5;color:var(--mute)}html[data-ds] .ds-data{font:400 13px/1.5 var(--mono);font-variant-numeric:tabular-nums lining-nums;color:var(--ink)}html[data-ds] .ds-spec-list{display:block;margin:0;padding:0;border-top:1px solid var(--line)}html[data-ds] .ds-spec-row{display:flex;gap:16px;align-items:baseline;flex-wrap:wrap;padding:10px 0;border-bottom:1px solid var(--line)}html[data-ds] .ds-spec-label{flex:none;width:180px;font:600 11px/1.5 var(--sans);text-transform:uppercase;letter-spacing:.08em;color:var(--faint)}html[data-ds] .ds-spec-value{flex:1;min-width:0;font-size:15px;line-height:1.6;color:var(--ink)}html[data-ds] .ds-spec-value.ds-data{font:400 13px/1.6 var(--mono);font-variant-numeric:tabular-nums lining-nums}@media(max-width:720px){html[data-ds] .ds-spec-row{gap:2px}html[data-ds] .ds-spec-label{width:100%}}html[data-ds] .ds-card{background:var(--card);border:1px solid var(--line);border-radius:8px;padding:24px;box-shadow:var(--ds-shadow)}html[data-ds] .ds-badge{display:inline-flex;align-items:center;gap:7px;height:24px;padding:0 11px;border-radius:999px;font:600 12px/1 var(--sans);white-space:nowrap;background:var(--ds-neutral-bg);border:1px solid var(--ds-neutral-line);color:var(--ds-neutral-ink)}html[data-ds] .ds-badge::before{content:"";flex:none;width:6px;height:6px;border-radius:50%;background:currentColor}html[data-ds] .ds-badge.ok{background:var(--ds-ok-bg);border-color:var(--ds-ok-line);color:var(--ds-ok-ink)}html[data-ds] .ds-badge.warn{background:var(--ds-warn-bg);border-color:var(--ds-warn-line);color:var(--ds-warn-ink)}html[data-ds] .ds-badge.neutral{background:var(--ds-neutral-bg);border-color:var(--ds-neutral-line);color:var(--ds-neutral-ink)}html[data-ds] .tile.app{background:var(--card);border:1px solid var(--line);border-radius:8px}html[data-ds] .tile.app:hover{border-color:var(--accent);background:var(--ds-tile-hover)}html[data-ds] .tile.app:focus-visible{outline:2px solid var(--accent);outline-offset:2px}html[data-ds] .ds-section{margin:0 0 64px}html[data-ds] .ds-section:last-child{margin-bottom:0}html[data-ds] .pagedesc,html[data-ds] .ds-measure{max-width:640px}@media(max-width:720px){html[data-ds] .ds-section{margin-bottom:48px}}@media (prefers-reduced-motion:reduce){html[data-ds] .tile.app{transition:none}}html[data-ds]{--ds-bad-ink:var(--danger-ink);--ds-bad-bg:transparent;--ds-bad-line:var(--danger-line);--ds-bad-edge:var(--danger-line);--ds-row-hover:var(--elev);--ds-input-bg:var(--elev);--ds-accent-hover:var(--accent2)}@media (prefers-color-scheme:light){html[data-ds]:not([data-theme="dark"]){--ds-bad-ink:#B42318;--ds-bad-bg:#FEF3F2;--ds-bad-line:#FEF3F2;--ds-bad-edge:#B42318;--ds-row-hover:var(--bg);--ds-input-bg:var(--card);--ds-accent-hover:#0B5C73}}html[data-ds][data-theme="light"]{--ds-bad-ink:#B42318;--ds-bad-bg:#FEF3F2;--ds-bad-line:#FEF3F2;--ds-bad-edge:#B42318;--ds-row-hover:var(--bg);--ds-input-bg:var(--card);--ds-accent-hover:#0B5C73}html[data-ds] .ds-badge.bad{background:var(--ds-bad-bg);border-color:var(--ds-bad-line);color:var(--ds-bad-ink)}html[data-ds] .ds-btn,html[data-ds] .ds-btn-primary{display:inline-flex;align-items:center;justify-content:center;gap:8px;height:40px;padding:0 16px;border:1px solid var(--accent);border-radius:6px;background:var(--accent);color:var(--on-accent);font:600 14px/1 var(--sans);text-align:center;text-decoration:none;white-space:nowrap;cursor:pointer;transition:background .16s,border-color .16s,color .16s}html[data-ds] .ds-btn:hover,html[data-ds] .ds-btn-primary:hover{background:var(--ds-accent-hover);border-color:var(--ds-accent-hover);text-decoration:none}html[data-ds] .ds-btn-sm{height:32px;padding:0 12px;font-size:13px}html[data-ds] .ds-btn-secondary{background:var(--card);border-color:var(--line);color:var(--accent)}html[data-ds] .ds-btn-secondary:hover{background:var(--ds-tile-hover);border-color:var(--accent);color:var(--accent)}html[data-ds] .ds-btn-ghost{background:transparent;border-color:transparent;color:var(--accent)}html[data-ds] .ds-btn-ghost:hover{background:var(--ds-tile-hover);border-color:transparent;color:var(--accent)}html[data-ds] .ds-btn-danger{background:transparent;border-color:var(--ds-bad-edge);color:var(--ds-bad-ink)}html[data-ds] .ds-btn-danger:hover{background:var(--ds-bad-ink);border-color:var(--ds-bad-ink);color:var(--bg)}html[data-ds] .ds-btn:disabled,html[data-ds] .ds-btn[aria-disabled="true"]{opacity:.55;pointer-events:none}html[data-ds] .ds-field{display:flex;flex-direction:column;gap:6px;margin:0 0 16px}html[data-ds] .ds-label{font:600 13px/1.4 var(--sans);color:var(--ink)}html[data-ds] .ds-input{width:100%;height:40px;padding:0 12px;border:1px solid var(--line);border-radius:6px;background:var(--ds-input-bg);color:var(--ink);font:400 14px/1.4 var(--sans);transition:border-color .16s}html[data-ds] select.ds-input{padding-right:8px}html[data-ds] textarea.ds-input{height:auto;min-height:96px;padding:10px 12px;line-height:1.5;resize:vertical}html[data-ds] .ds-input:focus{outline:2px solid var(--accent);outline-offset:2px;border-color:var(--accent);box-shadow:none}html[data-ds] .ds-input::placeholder{color:var(--faint)}html[data-ds] .ds-help{font:400 13px/1.5 var(--sans);color:var(--mute)}html[data-ds] .ds-field-error>.ds-input{border-color:var(--ds-bad-ink)}html[data-ds] .ds-field-error>.ds-help{color:var(--ds-bad-ink)}html[data-ds] .ds-table,html[data-ds] .ds-tablecard>table{width:100%;border-collapse:collapse;font-variant-numeric:tabular-nums lining-nums}html[data-ds] .ds-table th,html[data-ds] .ds-tablecard>table th{font:600 11px/1.4 var(--sans);text-transform:uppercase;letter-spacing:.08em;color:var(--faint);text-align:left;padding:8px 10px;border-bottom:1px solid var(--line)}html[data-ds] .ds-table td,html[data-ds] .ds-tablecard>table td{font-size:13px;line-height:1.5;color:var(--ink);text-align:left;padding:10px;border-bottom:1px solid var(--line);vertical-align:top}html[data-ds] .ds-table tbody tr:hover,html[data-ds] .ds-tablecard>table tbody tr:hover{background:var(--ds-row-hover)}html[data-ds] .ds-mono{font:400 13px/1.5 var(--mono);font-variant-numeric:tabular-nums lining-nums}html[data-ds] .ds-num{text-align:right;font:400 13px/1.5 var(--mono);font-variant-numeric:tabular-nums lining-nums}html[data-ds] .ds-table td.ds-mono,html[data-ds] .ds-tablecard>table td.ds-mono{font:400 13px/1.5 var(--mono)}html[data-ds] .ds-table td.ds-num,html[data-ds] .ds-tablecard>table td.ds-num{text-align:right;font:400 13px/1.5 var(--mono)}@media(pointer:coarse){html[data-ds] .ds-btn{min-height:44px}html[data-ds] .ds-btn-sm{min-height:40px}html[data-ds] .ds-input{min-height:46px;font-size:16px}html[data-ds] textarea.ds-input{min-height:96px}}@media (prefers-reduced-motion:reduce){html[data-ds] .ds-btn,html[data-ds] .ds-input{transition:none}}@media (max-width:720px){html[data-ds] .pagetitle,html[data-ds] h2.pagetitle{font-size:clamp(26px,7.7vw,34px);overflow-wrap:anywhere}}@media (max-width:480px){html[data-ds] .brand .pname,html[data-ds] .brand .bsep{display:none}html[data-ds] .who .whoami .em{display:none}}html[data-ds] .ds-cardrow{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:16px;margin:0 0 20px;align-items:stretch}html[data-ds] .ds-cardrow .ds-card{display:flex;flex-direction:column;gap:12px}html[data-ds] .ds-cardacts{display:flex;flex-wrap:wrap;gap:8px;align-items:center}html[data-ds] .ds-cardhead{display:flex;flex-wrap:wrap;gap:8px;align-items:center;justify-content:space-between}html[data-ds] .ds-cardhead .ds-h3{margin:0}html[data-ds] .ds-pre{margin:0;padding:12px 14px;background:var(--elev);border:1px solid var(--line);border-radius:6px;overflow-x:auto;-webkit-overflow-scrolling:touch}html[data-ds] .ds-pre code{font:400 13px/1.5 var(--mono);white-space:pre;color:var(--ink)}html[data-ds] .ds-spec-label{color:var(--mute)}html[data-ds] .ds-doc{max-width:840px;margin:0 auto;padding:32px 20px 64px;text-align:left;display:flex;flex-direction:column;gap:24px}html[data-ds] .ds-doc > h1{margin:0;text-align:left}html[data-ds] .ds-doc > .ds-eyebrow{margin:0}html[data-ds] .ds-small a:not(.ds-btn),html[data-ds] .ds-measure a:not(.ds-btn){text-decoration:underline}html[data-ds] .ds-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:4px;font-size:13px;color:var(--mute)}html[data-ds] .ds-list>li{margin:0}html[data-ds] .ds-card[data-product] .ds-kpi{padding:0;gap:2px;border:0;background:transparent;box-shadow:none}html[data-ds] .ds-card[data-product] .ds-kpi-value{font-size:20px;line-height:1.15}/* packages/ui/ui-components.css - ROUND 134 (ADR-103): the shared component
   vocabulary the Q4 platform draws from. CANONICAL FILE. Byte-copies live at
   relay/lib/ui-components.css and app/ui/v3/ui-components.css and are written
   by packages/ui/publish.mjs; never edit a copy.

   Every rule is scoped under the [data-ds] ATTRIBUTE with no html tag in
   front, so both the relay shell (html[data-ds], ADR-102) and a panel
   container stamped data-ds match the same selector. The relay appends this
   file at the END of DS_CSS, which keeps the previous sheets a byte-prefix of
   the new ones; nothing above it is edited.

   Colour comes from the ADR-103 token contract and nothing else: the shell's
   --bg --card --elev --line --line2 --ink --mute --faint --accent --on-accent
   --ok --warn --danger-ink --danger-line --sans --mono --display, plus the
   [data-ds] layer's --ds-ok-* --ds-warn-* --ds-neutral-* --ds-bad-*
   --ds-shadow --ds-row-hover --ds-tile-hover. The four values this file needs
   that no token names directly are declared once, immediately below, in the
   same three-block pattern DS_CSS uses: base carries DARK (the shell's
   default), a prefers-color-scheme:light block that excludes a forced dark
   theme carries LIGHT, and [data-ds][data-theme="light"] carries it again so
   the toggle wins in both directions. UI v4 step 8: they are all token
   references now, and the file carries no raw colour at all.

   Shape comes from docs/HELMSLY-UI-v4.md section 4: the four radius tokens
   are declared here too, with the panel's values, because the relay shell
   does not declare them and a var() with no declaration paints a square
   corner. On the panel, tokens.css declares the same four values at :root. */
[data-ds]{
  --r-ctl:6px;--r-card:10px;--r-area:12px;--r-pill:999px;
  --ds-col-bg:var(--elev);
  --ds-mask-ink:var(--faint);
  --ds-stale-bg:transparent;
  --ds-stale-line:var(--line2)}
@media (prefers-color-scheme:light){[data-ds]:not([data-theme="dark"]){
  --ds-col-bg:var(--elev);
  --ds-mask-ink:var(--faint);
  --ds-stale-bg:var(--elev);
  --ds-stale-line:var(--line)}}
[data-ds][data-theme="light"]{
  --ds-col-bg:var(--elev);
  --ds-mask-ink:var(--faint);
  --ds-stale-bg:var(--elev);
  --ds-stale-line:var(--line)}

/* STATUS PILL (.ds-status, ADR-103 decision 6). Four states and no fifth. The
   dot is 8px and takes currentColor, so a state names its colour once. The
   state word rides data-state, so a gate reads the attribute rather than the
   paint. live takes the ok trio, waking the warn trio (it is progress, not a
   fault), last_seen the neutral trio (the value is remembered, not wrong) and
   unknown the bad trio (nothing is known at all). */
[data-ds] .ds-status{display:inline-flex;align-items:center;gap:7px;height:24px;padding:0 11px;border-radius:var(--r-pill);font:600 12px/1 var(--sans);white-space:nowrap;vertical-align:middle;background:var(--ds-neutral-bg);border:1px solid var(--ds-neutral-line);color:var(--ds-neutral-ink)}
[data-ds] .ds-status-dot{flex:none;width:8px;height:8px;border-radius:50%;background:currentColor}
[data-ds] .ds-status-text{min-width:0}
[data-ds] .ds-status-text time{font:inherit;color:inherit;text-decoration:none}
[data-ds] .ds-status-live{background:var(--ds-ok-bg);border-color:var(--ds-ok-line);color:var(--ds-ok-ink)}
[data-ds] .ds-status-waking{background:var(--ds-warn-bg);border-color:var(--ds-warn-line);color:var(--ds-warn-ink)}
[data-ds] .ds-status-last_seen{background:var(--ds-neutral-bg);border-color:var(--ds-neutral-line);color:var(--ds-neutral-ink)}
/* Pre-launch rule 5: red is reserved for destructive actions and errors.
   "Unknown" is the absence of information, not a failure - nothing has gone
   wrong, nobody has said anything yet - so it takes the neutral trio, the same
   ground as "last seen". A red pill here told a reader something was broken
   every time a heartbeat had simply not arrived. */
[data-ds] .ds-status-unknown{background:var(--ds-neutral-bg);border-color:var(--ds-neutral-line);color:var(--ds-neutral-ink)}
/* The one animation in this file: a waking dot breathes, because starting is
   the only state that is going to change on its own. */
@keyframes ds-waking-pulse{0%,100%{opacity:1}50%{opacity:.35}}
[data-ds] .ds-status-waking .ds-status-dot{animation:ds-waking-pulse 1.6s ease-in-out infinite}
@media (prefers-reduced-motion:reduce){
  [data-ds] .ds-status-waking .ds-status-dot{animation:none}}

/* STAT ROW and KPI (.ds-stat-row, .ds-kpi, round 127A styleguide). The classes
   and the markup are the styleguide's; this file adds the state line. */
[data-ds] .ds-stat-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:16px}
[data-ds] .ds-kpi{display:flex;flex-direction:column;gap:8px;min-width:0}
[data-ds] .ds-kpi-label{font:600 12px/1.4 var(--sans);text-transform:uppercase;letter-spacing:.09em;color:var(--faint)}
[data-ds] .ds-kpi-value{font:500 28px/1.1 var(--mono);font-variant-numeric:tabular-nums lining-nums;color:var(--ink);overflow-wrap:anywhere}
[data-ds] .ds-kpi-value.ds-kpi-words{font:600 22px/1.2 var(--sans);letter-spacing:-.01em}
[data-ds] .ds-kpi-unit{font-size:12.5px;color:var(--mute);margin-left:.35em}
[data-ds] .ds-kpi-note{font:400 13px/1.5 var(--sans);color:var(--mute)}
[data-ds] .ds-kpi-state{display:block}

/* SPLIT SECTION (.ds-split, round 127A styleguide). Words on one side,
   evidence on the other; .ds-split-flip puts the evidence first. */
[data-ds] .ds-split{display:grid;grid-template-columns:1fr 1fr;gap:48px;align-items:center}
[data-ds] .ds-split-copy{min-width:0}
[data-ds] .ds-split-copy>:last-child{margin-bottom:0}
[data-ds] .ds-split-data{min-width:0}
[data-ds] .ds-split-flip .ds-split-data{order:-1}
[data-ds] .ds-split-body{margin:0 0 16px;font-size:14px;line-height:1.6;color:var(--mute);max-width:640px}
[data-ds] .ds-split-link{color:var(--accent);font:600 14px/1.5 var(--sans)}

/* STEP RAIL (.ds-steps, round 127A styleguide). Three to five steps, numbered
   markers joined by a line. data-done and data-current are the hooks a surface
   reads; the marker states its own progress so nothing depends on colour. */
[data-ds] .ds-steps{display:grid;grid-auto-flow:column;grid-auto-columns:1fr;gap:16px;margin:0;padding:0;list-style:none;counter-reset:ds-step}
[data-ds] .ds-step{position:relative;padding-top:40px;font-size:14px;line-height:1.5;color:var(--mute);counter-increment:ds-step;min-width:0;overflow-wrap:anywhere}
[data-ds] .ds-step::before{content:counter(ds-step);position:absolute;top:0;left:0;display:grid;place-items:center;width:28px;height:28px;border:1px solid var(--accent);border-radius:50%;background:var(--card);color:var(--accent);font:400 13px/1 var(--mono);z-index:1}
[data-ds] .ds-step::after{content:"";position:absolute;top:14px;left:28px;right:-16px;height:1px;background:var(--line)}
[data-ds] .ds-step:last-child::after{display:none}
[data-ds] .ds-step[data-done="true"]{color:var(--ink)}
[data-ds] .ds-step[data-done="true"]::before{background:var(--accent);color:var(--on-accent)}
[data-ds] .ds-step[data-current="true"]{color:var(--ink);font-weight:600}
[data-ds] .ds-step[data-current="true"]::before{box-shadow:none}

/* SPEC LIST (.ds-spec-list). Round 129 drew this in DS_CSS, under the selector
   `html[data-ds]`, and round 134 left it there - "the list itself is drawn by
   DS_CSS and is not touched here" - because at that point the only host that
   stamped data-ds was the relay's own <html>.

   Round 135 (WS18) is where that stopped being true. The panel stamps data-ds
   on its STAGE, not on <html>, so `html[data-ds]` matches nothing there and a
   spec list on a panel surface arrived with no layout at all: label and value
   ran together as one string ("Enforced atThe next agent build"). Found by
   looking at the first Rules baseline.

   So the layout is stated here, in the file both estates share, under the
   file's own bare-attribute rule. The declarations are DS_CSS's, value for
   value. On the relay `html[data-ds] .ds-spec-row` is the more specific
   selector and still wins, with the same numbers, so nothing already on a
   relay surface moves by a pixel; on the panel these are the only rules there
   are. DS_CSS keeps its copy: this file is appended to it, and editing what is
   above would break the byte-prefix ADR-102 gates. */
[data-ds] .ds-spec-list{display:block;margin:0;padding:0;border-top:1px solid var(--line)}
[data-ds] .ds-spec-row{display:flex;gap:16px;align-items:baseline;flex-wrap:wrap;padding:10px 0;border-bottom:1px solid var(--line)}
[data-ds] .ds-spec-label{flex:none;width:180px;font:600 12px/1.5 var(--sans);text-transform:uppercase;letter-spacing:.08em;color:var(--faint)}
[data-ds] .ds-spec-value{flex:1;min-width:0;font-size:14px;line-height:1.6;color:var(--ink)}
[data-ds] .ds-spec-value.ds-data{font:400 13px/1.6 var(--mono);font-variant-numeric:tabular-nums lining-nums}
@media(max-width:720px){[data-ds] .ds-spec-row{gap:2px}[data-ds] .ds-spec-label{width:100%}}
/* The state line, which is this file's own from round 134. */
[data-ds] .ds-spec-state{display:inline-flex;margin-left:8px;vertical-align:middle}
/* A 64-character digest in a mono value has no break opportunity in it, and
   at 390 it carries the whole page 137px past the viewport. The rule is
   scoped to a row this LIBRARY drew (dsSpecList is the only thing that stamps
   data-state on a spec row), so every spec list already on a relay surface
   keeps the wrapping it has. */
[data-ds] .ds-spec-row[data-state] .ds-spec-value{min-width:0;overflow-wrap:anywhere}

/* KANBAN BOARD (.ds-kanban). Markup and hooks only: data-column and data-card
   are what phase 4 hangs drag on. No drag behaviour lives here. */
[data-ds] .ds-kanban{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(240px,1fr);gap:16px;align-items:start}
[data-ds] .ds-kanban-col{display:flex;flex-direction:column;gap:10px;min-width:0;padding:12px;border:1px solid var(--line);border-radius:var(--r-card);background:var(--ds-col-bg)}
[data-ds] .ds-kanban-head{display:flex;align-items:baseline;justify-content:space-between;gap:8px}
[data-ds] .ds-kanban-title{font:600 12px/1.4 var(--sans);text-transform:uppercase;letter-spacing:.08em;color:var(--faint);min-width:0;overflow-wrap:anywhere}
[data-ds] .ds-kanban-count{flex:none;font:400 12px/1.4 var(--mono);font-variant-numeric:tabular-nums lining-nums;color:var(--mute)}
[data-ds] .ds-kanban-card{display:flex;flex-direction:column;gap:8px;min-width:0;padding:12px;border:1px solid var(--line);border-radius:var(--r-card);background:var(--card);box-shadow:none}
[data-ds] .ds-kanban-card:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
[data-ds] .ds-kanban-cardtitle{font:600 14px/1.35 var(--sans);color:var(--ink);overflow-wrap:anywhere}
[data-ds] .ds-kanban-meta{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font:400 12px/1.4 var(--sans);color:var(--mute);min-width:0}
[data-ds] .ds-kanban-metatext{min-width:0;overflow-wrap:anywhere}
[data-ds] .ds-avatar{flex:none;display:grid;place-items:center;width:22px;height:22px;border-radius:50%;background:var(--elev);color:var(--ink);font:600 11.5px/1 var(--sans);letter-spacing:.02em}

/* DASHBOARD PANEL (.ds-panel, ADR-103 decision 7). A panel in a state other
   than live never draws its live body: the state sentence replaces it, and a
   remembered body follows the sentence inside .ds-panel-stale so a reader can
   see at a glance that what is under the sentence is memory. */
[data-ds] .ds-panel{display:flex;flex-direction:column;gap:16px;padding:24px;border:1px solid var(--line);border-radius:var(--r-card);background:var(--card);box-shadow:none;min-width:0}
[data-ds] .ds-panel-head{display:flex;align-items:flex-start;gap:12px;flex-wrap:wrap;min-width:0}
[data-ds] .ds-panel-heading{flex:1;min-width:0}
[data-ds] .ds-panel-title{margin:0;font:600 14.5px/1.35 var(--sans);color:var(--ink);overflow-wrap:anywhere}
[data-ds] .ds-panel-actions{flex:none;display:flex;align-items:center;gap:8px;margin-left:auto;flex-wrap:wrap}
[data-ds] .ds-panel-body{min-width:0}
[data-ds] .ds-panel-state{margin:0;font-size:14px;line-height:1.6;color:var(--mute)}
[data-ds] .ds-panel-stale{margin-top:12px;padding-top:12px;border-top:1px solid var(--ds-stale-line);background:var(--ds-stale-bg);opacity:.72;min-width:0}

/* FILE BROWSER (.ds-files). A breadcrumb over a table of entries; the kind
   glyph is one outline path in currentColor with no fill, the family every
   icon in this estate belongs to. */
[data-ds] .ds-files-path{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin:0 0 12px;font:400 13px/1.5 var(--sans);color:var(--mute);min-width:0}
[data-ds] .ds-files-crumb{min-width:0;overflow-wrap:anywhere}
[data-ds] .ds-files-crumb:last-child{color:var(--ink);font-weight:600}
[data-ds] .ds-files-sep{flex:none;color:var(--faint)}
[data-ds] .ds-files{width:100%;table-layout:fixed;border-collapse:collapse;font-variant-numeric:tabular-nums lining-nums}
[data-ds] .ds-files th{font:600 12px/1.4 var(--sans);text-transform:uppercase;letter-spacing:.08em;color:var(--faint);text-align:left;padding:8px 10px;border-bottom:1px solid var(--line)}
[data-ds] .ds-files td{font-size:13px;line-height:1.5;color:var(--ink);padding:10px;border-bottom:1px solid var(--line);vertical-align:top;overflow-wrap:anywhere}
[data-ds] .ds-files tbody tr:hover{background:var(--ds-row-hover)}
[data-ds] .ds-files-name{display:flex;align-items:center;gap:8px;min-width:0}
[data-ds] .ds-files-name a{color:var(--ink)}
[data-ds] .ds-files-glyph{flex:none;color:var(--faint)}
/* A cell rule beats a class rule on specificity, so the two data columns are
   named AS cells; without this the td rule above would keep the body face on a
   size that is meant to be mono. The same correction DS_CSS makes for
   td.ds-mono. The header keeps its own tracked face, so only the width is
   shared between th and td. */
[data-ds] .ds-files th.ds-files-size,[data-ds] .ds-files td.ds-files-size{width:96px;text-align:right}
[data-ds] .ds-files th.ds-files-when,[data-ds] .ds-files td.ds-files-when{width:140px}
[data-ds] .ds-files td.ds-files-size{font:400 13px/1.5 var(--mono);font-variant-numeric:tabular-nums lining-nums}
[data-ds] .ds-files td.ds-files-when{font:400 13px/1.5 var(--sans);color:var(--mute)}

/* FLOW CANVAS NODE (.ds-node). The n8n grammar design.md records: a glyph in a
   framed square with the title BELOW it, and a port marker on each side. Hooks
   only: data-node, data-kind, data-state, data-port. */
/* The box is 132px wide at rest (a 44px glyph over a title that wraps at
   112px), and grows only to hold a state pill: a corner pill that is out of
   flow sizes nothing, so "Last seen 4 Sep 14:02" hung 55px off the left edge
   of the frame and would sit over the next node on a canvas. The pill is a
   flowed item ordered to the top right instead, so the node states its own
   width and the instant stays whole. */
[data-ds] .ds-node{position:relative;display:flex;flex-direction:column;align-items:center;gap:8px;width:max-content;min-width:132px;max-width:100%;padding:14px 10px;border:1px solid var(--line);border-radius:var(--r-card);background:var(--card);box-shadow:none;text-align:center}
[data-ds] .ds-node:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
[data-ds] .ds-node[data-selected="true"]{border-color:var(--accent);box-shadow:none}
[data-ds] .ds-node-glyph{display:grid;place-items:center;width:44px;height:44px;border:1px solid var(--line2);border-radius:var(--r-card);background:var(--ds-col-bg);color:var(--accent)}
[data-ds] .ds-node-title{max-width:112px;font:600 13px/1.35 var(--sans);color:var(--ink);overflow-wrap:anywhere}
[data-ds] .ds-node-state{order:-1;align-self:flex-end;margin:-6px -4px -4px 0;max-width:100%}
[data-ds] .ds-node-state .ds-status{height:18px;padding:0 7px;font-size:11.5px;gap:5px}
[data-ds] .ds-node-state .ds-status-dot{width:6px;height:6px}
[data-ds] .ds-port{position:absolute;top:50%;width:9px;height:9px;margin-top:-4.5px;border:1px solid var(--line2);border-radius:50%;background:var(--card)}
[data-ds] .ds-port-in{left:-5px}
[data-ds] .ds-port-out{right:-5px}

/* VAULT ROW (.ds-vault-row). The masked value is CSS content and is never
   data: the renderer refuses a value or a secret property outright, so there
   is no path by which a secret reaches this markup. */
[data-ds] .ds-vault-row{display:flex;align-items:center;gap:12px;flex-wrap:wrap;min-width:0;padding:12px 0;border-bottom:1px solid var(--line)}
[data-ds] .ds-vault-name{font:400 13px/1.5 var(--mono);color:var(--ink);min-width:0;overflow-wrap:anywhere}
[data-ds] .ds-vault-mask{flex:none;font:400 13px/1.5 var(--mono);letter-spacing:.18em;color:var(--ds-mask-ink)}
[data-ds] .ds-vault-mask::before{content:"\2022\2022\2022\2022\2022\2022\2022\2022"}
[data-ds] .ds-vault-rotated{font:400 13px/1.5 var(--sans);color:var(--mute)}
[data-ds] .ds-vault-consumers{flex-basis:100%;font:400 12px/1.5 var(--sans);color:var(--faint);min-width:0;overflow-wrap:anywhere}

/* QUEUE ROW (.ds-queue-row). L3 of the goal: a queued thing states its
   position AND the reason it is waiting, in full, on the row itself. */
[data-ds] .ds-queue-row{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;min-width:0;padding:12px 0;border-bottom:1px solid var(--line)}
[data-ds] .ds-queue-pos{flex:none;font:400 13px/1.5 var(--mono);font-variant-numeric:tabular-nums lining-nums;color:var(--mute)}
[data-ds] .ds-queue-main{flex:1;min-width:0}
[data-ds] .ds-queue-title{display:block;font:600 14px/1.4 var(--sans);color:var(--ink);overflow-wrap:anywhere}
[data-ds] .ds-queue-reason{display:block;font:400 13px/1.5 var(--sans);color:var(--mute);overflow-wrap:anywhere}
[data-ds] .ds-queue-since{flex:none;font:400 13px/1.5 var(--sans);color:var(--faint)}

/* PHONE (max-width 720px). Everything that is a row of columns on a desktop
   becomes one column: a board that scrolls sideways on a phone hides work, and
   a gate that measures overflow would fail it anyway. */
@media (max-width:720px){
  [data-ds] .ds-stat-row{grid-template-columns:1fr}
  [data-ds] .ds-split{grid-template-columns:1fr;gap:24px}
  [data-ds] .ds-split-flip .ds-split-data{order:0}
  [data-ds] .ds-steps{grid-auto-flow:row;gap:12px}
  [data-ds] .ds-step{padding-top:0;padding-left:40px;min-height:28px}
  [data-ds] .ds-step::after{top:28px;bottom:-12px;left:13px;right:auto;width:1px;height:auto}
  [data-ds] .ds-kanban{grid-auto-flow:row;grid-auto-columns:auto}
  [data-ds] .ds-files-size{width:72px}
  [data-ds] .ds-files-when{width:88px;font-size:12px}
  [data-ds] .ds-panel{padding:16px}
  /* flex:none on a desktop keeps the cluster on one line beside the title; on
     a phone that same rule refuses to shrink, so three nowrap controls push
     the page 137px past a 390 viewport. Below 720 the cluster takes its own
     full-width line and wraps inside itself. */
  [data-ds] .ds-panel-actions{flex:1 1 100%;min-width:0;margin-left:0}
  [data-ds] .ds-node{width:100%}
}

/* ===========================================================================
   THE ADR-103 BASE SHAPES (round 135, phase 5 integration).
   ===========================================================================
   The renderers above lean on a layer of base shapes - the type roles, the
   card, the badge, the button and the ds form field - that round 129 drew in
   the RELAY's DS_CSS (relay/lib/shell.mjs) under html[data-ds]. The panel
   never loads that sheet and never stamps the attribute on <html>, so four of
   the five phase 5 surface groups each arrived carrying their own copy of the
   block: dashboards.css, browsers.css, flows.css and WS19's ds-base.css.
   dashboards.css recorded the debt in the file itself ("fold this block into
   packages/ui/ui-components.css so one file draws them for both estates") and
   left it because five groups were in flight at once. They have landed, so it
   is taken here: the rules live ONCE, in the library both estates publish.

   DS_CSS STAYS THE ORIGIN. Every declaration below is that block value for
   value, with the two transforms ADR-103 decision 4 already requires:
   `html[data-ds] X` becomes `[data-ds] X`, and a compound selector that also
   names a bare element (`h2:not(.pagetitle):not(.subhead)`) keeps only its
   `.ds-*` half, because restyling every h2 in a panel view would repaint
   surfaces phase 5 has not migrated. Nothing is retyped and no colour is a raw
   hex. On the relay this file is appended INSIDE DS_CSS's layer, so DS_CSS's
   own `html[data-ds]` rules are both later and more specific and keep winning:
   no relay surface can move because of this section.

   The spec list is NOT repeated here - the library has drawn it since round
   134 (see the SPEC LIST section above), and the four lane copies of it were
   duplicates of this file, not of DS_CSS. */

/* TYPE ROLES. The class forms only. */
[data-ds] .ds-h2{font-family:var(--font-display,var(--sans));font-weight:600;font-size:28px;line-height:1.25;letter-spacing:-.01em;color:var(--ink);margin:0 0 12px}
[data-ds] .ds-h3{font-family:var(--font-display,var(--sans));font-weight:600;font-size:14.5px;line-height:1.35;letter-spacing:0;color:var(--ink);margin:0 0 8px}
[data-ds] .ds-eyebrow{display:block;font:600 12px/1.4 var(--sans);text-transform:uppercase;letter-spacing:.08em;color:var(--accent);margin:0 0 6px}
[data-ds] .ds-small{font-size:13px;line-height:1.5;color:var(--mute)}
[data-ds] .ds-data{font:400 13px/1.5 var(--mono);font-variant-numeric:tabular-nums lining-nums;color:var(--ink)}
[data-ds] .ds-mono{font:400 13px/1.5 var(--mono);font-variant-numeric:tabular-nums lining-nums}

/* CARD. Surface, 1px line border, radius 8, padding 24. dsStatRow's KPI cells
   are `.ds-card .ds-kpi`, so without this rule a stat row has no ground. */
[data-ds] .ds-card{background:var(--card);border:1px solid var(--line);border-radius:var(--r-card);padding:24px;box-shadow:none}

/* BADGE. Pill, 24px, dot indicator in currentColor. */
[data-ds] .ds-badge{display:inline-flex;align-items:center;gap:7px;height:24px;padding:0 11px;border-radius:var(--r-pill);font:600 12px/1 var(--sans);white-space:nowrap;background:var(--ds-neutral-bg);border:1px solid var(--ds-neutral-line);color:var(--ds-neutral-ink)}
[data-ds] .ds-badge::before{content:"";flex:none;width:6px;height:6px;border-radius:50%;background:currentColor}
[data-ds] .ds-badge.ok{background:var(--ds-ok-bg);border-color:var(--ds-ok-line);color:var(--ds-ok-ink)}
[data-ds] .ds-badge.warn{background:var(--ds-warn-bg);border-color:var(--ds-warn-line);color:var(--ds-warn-ink)}
[data-ds] .ds-badge.neutral{background:var(--ds-neutral-bg);border-color:var(--ds-neutral-line);color:var(--ds-neutral-ink)}
[data-ds] .ds-badge.bad{background:var(--ds-bad-bg);border-color:var(--ds-bad-line);color:var(--ds-bad-ink)}

/* BUTTONS. Heights 40 and 32, radius 6, one 1px box on every variant so a
   mixed row lines up. The law of one primary per view is the page's to keep. */
[data-ds] .ds-btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;height:40px;padding:0 16px;border:1px solid var(--accent);border-radius:var(--r-ctl);background:var(--accent);color:var(--on-accent);font:600 14px/1 var(--sans);text-align:center;text-decoration:none;white-space:nowrap;cursor:pointer;transition:background .16s,border-color .16s,color .16s}
[data-ds] .ds-btn:hover{background:var(--ds-accent-hover);border-color:var(--ds-accent-hover);text-decoration:none}
[data-ds] .ds-btn-sm{height:32px;padding:0 12px;font-size:13px}
[data-ds] .ds-btn-secondary{background:var(--card);border-color:var(--line);color:var(--accent)}
[data-ds] .ds-btn-secondary:hover{background:var(--ds-tile-hover);border-color:var(--accent);color:var(--accent)}
[data-ds] .ds-btn-ghost{background:transparent;border-color:transparent;color:var(--accent)}
[data-ds] .ds-btn-ghost:hover{background:var(--ds-tile-hover);border-color:transparent;color:var(--accent)}
[data-ds] .ds-btn-danger{background:transparent;border-color:var(--ds-bad-edge);color:var(--ds-bad-ink)}
[data-ds] .ds-btn-danger:hover{background:var(--ds-bad-ink);border-color:var(--ds-bad-ink);color:var(--bg)}
[data-ds] .ds-btn:disabled,[data-ds] .ds-btn[aria-disabled="true"]{opacity:.55;pointer-events:none}

/* FORM FIELD. Label above, 40px control, radius 6, help text under. */
[data-ds] .ds-field{display:flex;flex-direction:column;gap:6px;margin:0 0 16px}
[data-ds] .ds-label{font:600 13px/1.4 var(--sans);color:var(--ink)}
[data-ds] .ds-input{width:100%;height:40px;padding:0 12px;border:1px solid var(--line);border-radius:var(--r-ctl);background:var(--ds-input-bg);color:var(--ink);font:400 14px/1.4 var(--sans);transition:border-color .16s}
[data-ds] select.ds-input{padding-right:8px}
[data-ds] textarea.ds-input{height:auto;min-height:96px;padding:10px 12px;line-height:1.5;resize:vertical}
[data-ds] .ds-input:focus{outline:2px solid var(--accent);outline-offset:2px;border-color:var(--accent);box-shadow:none}
[data-ds] .ds-input::placeholder{color:var(--faint)}
[data-ds] .ds-help{font:400 13px/1.5 var(--sans);color:var(--mute)}
[data-ds] .ds-field-error>.ds-input{border-color:var(--ds-bad-ink)}
[data-ds] .ds-field-error>.ds-help{color:var(--ds-bad-ink)}
/* THE SHARED ERROR CARD (pre-launch section 1, item 5). One card, three layers:
   what the reader does next, the service state under it, and the diagnostic
   reference last. Only the card's edge carries the bad ink - the sentence a
   person acts on stays in the body colour, because a paragraph of red reads as
   an alarm rather than as an instruction. */
[data-ds] .ds-error-card{border-color:var(--ds-bad-ink);display:flex;flex-direction:column;gap:8px}
[data-ds] .ds-error-card>.ds-help:last-child{color:var(--faint);font-variant-numeric:tabular-nums}

/* THE PANEL BODY STACK. This one is the library's own, not a DS_CSS lift:
   dashboards.css wrote it because a run of evidence shapes inside one panel
   body (a stat row over a list, a spec list over a control cluster) carries no
   gap of its own, and the shape it spaces is `.ds-panel-body`, which this file
   draws. A surface that wants a different rhythm says so on its own root with
   one more class in the selector, the way market.css does. */
[data-ds] .ds-panel-body>*+*{margin-top:16px}

@media (max-width:720px){
  /* A 16px step between panels reads as a hairline of air on a 390px screen,
     where the panels are already edge to edge. */
  [data-ds] .ds-panel-body>*+*{margin-top:12px}
}
@media(pointer:coarse){
  [data-ds] .ds-btn{min-height:44px}
  [data-ds] .ds-btn-sm{min-height:40px}
  [data-ds] .ds-input{min-height:46px;font-size:16px}
  [data-ds] textarea.ds-input{min-height:96px}}
@media (prefers-reduced-motion:reduce){[data-ds] .ds-btn,[data-ds] .ds-input{transition:none}}

/* ===========================================================================
   ROUND 147. The shapes the four hub surface lanes build on.
   ===========================================================================
   Everything below is APPENDED. Not one byte above this line moves, which is
   what keeps every existing SHELL_CSS and ADMIN_CSS a byte-prefix of the new
   ones (ADR-102's gate) and every existing capture in qa/visual unmoved.

   Six shapes: the data table, the toolbar above it, the tree, the switch, the
   usage meter and the two-pane file split, plus the chips, due date, faces and
   add control the Kanban card gained. No new colour: every value is a token,
   and the four raw values at the head of this file are still the only ones. */

/* Visually hidden, for a name a reader does not need and a screen reader does:
   a table's caption, the label on a search field whose magnifier says what it
   is. clip-path rather than the deprecated clip, and white-space:nowrap so a
   long name cannot be read out with its words run together. */
[data-ds] .ds-vh{position:absolute;width:1px;height:1px;margin:-1px;padding:0;border:0;overflow:hidden;clip-path:inset(50%);white-space:nowrap}

/* THE CELL CONTRACT (.ds-col-*). One description of a column, shared by
   .ds-table and dsFileBrowser's columns override, so the two cannot drift.
   Every rule names the CELL as well as the class: `[data-ds] .ds-table td` is
   a more specific selector than a bare class, so a class rule alone would lose
   the font to it. The same correction the file already makes for
   td.ds-files-size.

   A pinned width arrives as the custom property --ds-col-w rather than as an
   inline width, because the inline-style law (docs/ui-contract.md) fails a px
   width in markup and passes a custom property. */
[data-ds] .ds-table th.ds-col-right,[data-ds] .ds-table td.ds-col-right,[data-ds] .ds-files th.ds-col-right,[data-ds] .ds-files td.ds-col-right{text-align:right}
[data-ds] .ds-table td.ds-col-mono,[data-ds] .ds-files td.ds-col-mono{font:400 13px/1.5 var(--mono);font-variant-numeric:tabular-nums lining-nums}
[data-ds] .ds-table th.ds-col-w,[data-ds] .ds-table td.ds-col-w,[data-ds] .ds-files th.ds-col-w,[data-ds] .ds-files td.ds-col-w{width:var(--ds-col-w)}

/* DATA TABLE (.ds-table). The design system's table, said once: 11px uppercase
   tracked header in --faint, 1px row lines, hover tint, numbers right aligned
   in mono where the column says so. The row height is PINNED at 40 rather than
   derived from the line box, so two tables of different content line up.

   .ds-table-wrap is the reason a wide table never takes the page sideways with
   it: the scroll happens in the wrap, and the page's own overflow is untouched
   (a gate that measures document width would fail the alternative). */
[data-ds] .ds-table-wrap{max-width:100%;overflow-x:auto}
[data-ds] .ds-table{width:100%;border-collapse:collapse;font-variant-numeric:tabular-nums lining-nums}
[data-ds] .ds-table th{height:32px;padding:0 12px;border-bottom:1px solid var(--line);font:600 12px/1.4 var(--sans);text-transform:uppercase;letter-spacing:.08em;color:var(--faint);text-align:left;vertical-align:middle;white-space:nowrap}
[data-ds] .ds-table td{height:40px;padding:0 12px;border-bottom:1px solid var(--line);font-size:13px;line-height:1.5;color:var(--ink);vertical-align:middle;overflow-wrap:anywhere}
[data-ds] .ds-table tbody tr:hover{background:var(--ds-row-hover)}
[data-ds] .ds-table tbody tr.is-selected{background:var(--ds-tile-hover)}
[data-ds] .ds-table-empty td{color:var(--mute)}
[data-ds] .ds-table-empty:hover{background:transparent}
[data-ds] .ds-table th.ds-table-pickcol,[data-ds] .ds-table td.ds-table-pickcol{width:40px;padding:0 0 0 12px}
[data-ds] .ds-table-pick{width:16px;height:16px;margin:0;accent-color:var(--accent);cursor:pointer}
[data-ds] .ds-table-pick:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* TOOLBAR (.ds-toolbar). Actions left, search in the middle, actions right.
   The search control is 32 rather than the field's 40: it sits in a row of
   32px buttons and a 40px box in that row reads as a mistake. */
[data-ds] .ds-toolbar{display:flex;align-items:center;gap:12px;flex-wrap:wrap;min-width:0;margin:0 0 12px}
[data-ds] .ds-toolbar-left,[data-ds] .ds-toolbar-right{display:flex;align-items:center;gap:8px;flex-wrap:wrap;min-width:0}
[data-ds] .ds-toolbar-right{margin-left:auto}
[data-ds] .ds-search{position:relative;display:flex;align-items:center;flex:1 1 220px;min-width:0;max-width:360px}
[data-ds] .ds-search-glyph{position:absolute;left:10px;color:var(--faint);pointer-events:none}
[data-ds] .ds-search .ds-input{height:32px;padding:0 12px 0 32px;font-size:13px}

/* TREE (.ds-tree). Depth rides --ds-tree-depth on the item rather than nested
   padding on the lists, so the hover and selection tints run the full width of
   the column at every depth instead of stepping in with the text. */
[data-ds] .ds-tree,[data-ds] .ds-tree-group{margin:0;padding:0;list-style:none;min-width:0}
[data-ds] .ds-tree-row{display:flex;align-items:center;gap:8px;min-width:0;height:32px;padding-right:8px;padding-left:calc(8px + var(--ds-tree-depth,0) * 16px);border-radius:var(--r-ctl);font:400 13px/1.4 var(--sans);color:var(--ink)}
[data-ds] .ds-tree-row:hover{background:var(--ds-row-hover)}
[data-ds] .ds-tree-item.is-selected>.ds-tree-row{background:var(--ds-tile-hover);font-weight:600}
[data-ds] .ds-tree-toggle{flex:none;display:grid;place-items:center;width:20px;height:20px;padding:0;border:0;border-radius:var(--r-ctl);background:transparent;color:var(--faint);cursor:pointer;transition:transform .16s}
[data-ds] .ds-tree-toggle:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
[data-ds] .ds-tree-leaf{cursor:default}
[data-ds] .ds-tree-item[aria-expanded="true"]>.ds-tree-row>.ds-tree-toggle{transform:rotate(90deg)}
[data-ds] .ds-tree-glyph{flex:none;display:grid;place-items:center;color:var(--faint)}
[data-ds] .ds-tree-item[data-locked="true"]>.ds-tree-row>.ds-tree-glyph{color:var(--ds-warn-ink)}
[data-ds] .ds-tree-label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
[data-ds] .ds-tree-count{flex:none;display:inline-flex;align-items:center;height:18px;padding:0 7px;border-radius:var(--r-pill);background:var(--ds-neutral-bg);color:var(--ds-neutral-ink);font:400 12px/1 var(--mono);font-variant-numeric:tabular-nums lining-nums}
[data-ds] .ds-tree-meta{flex:none;margin-left:auto;padding-left:8px;font:400 12px/1.5 var(--sans);color:var(--mute)}

/* SWITCH (.ds-switch). Track 36 by 20, thumb 16, travel 16. The input is the
   focusable thing and carries the checked state; the track is painted from it
   with a sibling selector, so the ring is driven by :focus-visible on a real
   control rather than by a class a script would have to keep in step. */
[data-ds] .ds-switch{position:relative;display:flex;align-items:center;gap:16px;min-width:0;padding:8px 0;cursor:pointer}
[data-ds] .ds-switch[data-disabled="true"]{opacity:.55;cursor:not-allowed}
[data-ds] .ds-switch-text{flex:1;display:flex;flex-direction:column;gap:2px;min-width:0}
[data-ds] .ds-switch-label{font:600 13px/1.4 var(--sans);color:var(--ink);overflow-wrap:anywhere}
[data-ds] .ds-switch-help{font:400 13px/1.5 var(--sans);color:var(--mute);overflow-wrap:anywhere}
[data-ds] .ds-switch input{position:absolute;width:1px;height:1px;margin:0;opacity:0;pointer-events:none}
[data-ds] .ds-switch-track{flex:none;position:relative;display:block;width:36px;height:20px;border:1px solid var(--line2);border-radius:var(--r-pill);background:var(--ds-neutral-bg);transition:background .16s,border-color .16s}
[data-ds] .ds-switch-thumb{position:absolute;top:1px;left:1px;width:16px;height:16px;border-radius:50%;background:var(--card);box-shadow:none;transition:transform .16s}
[data-ds] .ds-switch input:checked~.ds-switch-track{background:var(--accent);border-color:var(--accent)}
[data-ds] .ds-switch input:checked~.ds-switch-track .ds-switch-thumb{background:var(--on-accent);transform:translateX(16px)}
[data-ds] .ds-switch input:focus-visible~.ds-switch-track{outline:2px solid var(--accent);outline-offset:2px}

/* METER (.ds-meter). The figure is words first, because a bar on its own is a
   picture of a number nobody can read. The track is 8px and is hidden from
   assistive technology: it says the same thing the head and the legend say. */
[data-ds] .ds-meter{display:flex;flex-direction:column;gap:8px;min-width:0}
[data-ds] .ds-meter-head{display:flex;align-items:baseline;justify-content:space-between;gap:12px;min-width:0}
[data-ds] .ds-meter-label{font:600 13px/1.4 var(--sans);color:var(--ink);min-width:0;overflow-wrap:anywhere}
[data-ds] .ds-meter-figure{flex:none;color:var(--mute)}
[data-ds] .ds-meter-track{display:flex;width:100%;height:8px;border-radius:var(--r-pill);background:var(--ds-neutral-bg);overflow:hidden}
[data-ds] .ds-meter-seg{display:block;width:var(--ds-seg,0%);min-width:0}
[data-ds] .ds-meter-legend{display:flex;flex-wrap:wrap;gap:8px 20px;margin:4px 0 0;padding:0;list-style:none;min-width:0}
[data-ds] .ds-meter-item{display:flex;align-items:center;gap:8px;min-width:0;font:400 13px/1.5 var(--sans);color:var(--mute)}
[data-ds] .ds-meter-swatch{flex:none;width:10px;height:10px;border-radius:var(--r-ctl)}
[data-ds] .ds-meter-name{min-width:0;overflow-wrap:anywhere}
[data-ds] .ds-meter-value{flex:none;color:var(--ink)}
[data-ds] .ds-meter-ok{background:var(--ds-ok-ink)}
[data-ds] .ds-meter-warn{background:var(--ds-warn-ink)}
[data-ds] .ds-meter-bad{background:var(--ds-bad-ink)}
[data-ds] .ds-meter-neutral{background:var(--ds-neutral-ink)}
[data-ds] .ds-meter-brand{background:var(--accent)}

/* KANBAN CARD, ENRICHED. Chips under the title, a due date and a face stack in
   the foot, an add control at the column's own foot. Every one of them is
   drawn only when the card or the column asks for it, so a board that passes
   none of the new options paints exactly what it painted before. */
[data-ds] .ds-kanban-chips{display:flex;align-items:center;gap:6px;flex-wrap:wrap;min-width:0}
[data-ds] .ds-chip{display:inline-flex;align-items:center;height:22px;padding:0 9px;border:1px solid var(--ds-neutral-line);border-radius:var(--r-pill);background:var(--ds-neutral-bg);color:var(--ds-neutral-ink);font:600 11.5px/1 var(--sans);white-space:nowrap}
[data-ds] .ds-chip-ok{background:var(--ds-ok-bg);border-color:var(--ds-ok-line);color:var(--ds-ok-ink)}
[data-ds] .ds-chip-warn{background:var(--ds-warn-bg);border-color:var(--ds-warn-line);color:var(--ds-warn-ink)}
[data-ds] .ds-chip-bad{background:var(--ds-bad-bg);border-color:var(--ds-bad-line);color:var(--ds-bad-ink)}
[data-ds] .ds-chip-neutral{background:var(--ds-neutral-bg);border-color:var(--ds-neutral-line);color:var(--ds-neutral-ink)}
[data-ds] .ds-chip-brand{background:var(--ds-tile-hover);border-color:var(--accent);color:var(--accent)}
[data-ds] .ds-kanban-foot{display:flex;align-items:center;gap:8px;flex-wrap:wrap;min-width:0}
[data-ds] .ds-kanban-due{display:inline-flex;align-items:center;gap:6px;min-width:0;font:400 12px/1.4 var(--mono);font-variant-numeric:tabular-nums lining-nums;color:var(--mute);overflow-wrap:anywhere}
[data-ds] .ds-kanban-due time{font:inherit;color:inherit;text-decoration:none}
[data-ds] .ds-kanban-dueglyph{flex:none}
[data-ds] .ds-kanban-faces{display:inline-flex;align-items:center;margin-left:auto;padding-left:8px}
[data-ds] .ds-kanban-face{flex:none;display:grid;place-items:center;width:22px;height:22px;margin-left:-6px;border:1px solid var(--card);border-radius:50%;background:var(--elev);color:var(--ink);font:600 11.5px/1 var(--sans);overflow:hidden}
[data-ds] .ds-kanban-face:first-child{margin-left:0}
[data-ds] .ds-kanban-face img{display:block;width:100%;height:100%;object-fit:cover}
[data-ds] .ds-kanban-add{display:flex;align-items:center;justify-content:center;gap:6px;height:32px;padding:0 12px;border:1px dashed var(--line2);border-radius:var(--r-card);background:transparent;color:var(--mute);font:600 12px/1 var(--sans);cursor:pointer;transition:background .16s,border-color .16s,color .16s}
[data-ds] .ds-kanban-add:hover{border-color:var(--accent);background:var(--ds-tile-hover);color:var(--accent)}
[data-ds] .ds-kanban-add:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* FILE SPLIT (.ds-files-split). A 260px tree column, a 1px divider, and the
   browser in the rest. The state sentence, when the split is not live, spans
   both columns rather than sitting in the tree's 260. */
[data-ds] .ds-files-split{display:grid;grid-template-columns:260px minmax(0,1fr);min-width:0}
[data-ds] .ds-files-tree{min-width:0;padding:0 16px 0 0;border-right:1px solid var(--line)}
[data-ds] .ds-files-main{min-width:0;padding:0 0 0 16px}
[data-ds] .ds-files-split>.ds-panel-state{grid-column:1/-1}

/* The two column drops. 640 and 900 are the only two hideBelow answers, so
   they are the only two the sheet can be asked for. */
@media (max-width:899px){
  [data-ds] .ds-col-hide-900{display:none}
  [data-ds] .ds-files-split{grid-template-columns:minmax(0,1fr)}
  [data-ds] .ds-files-tree{padding:0 0 16px;border-right:0;border-bottom:1px solid var(--line)}
  [data-ds] .ds-files-main{padding:16px 0 0}
}
@media (max-width:639px){
  [data-ds] .ds-col-hide-640{display:none}
  /* The toolbar takes three lines below 640: the left cluster, the search
     field at full width, then the right cluster. The DOM is already in that
     order, so each part asking for a whole line is the whole rule. */
  [data-ds] .ds-toolbar{gap:8px}
  [data-ds] .ds-toolbar-left,[data-ds] .ds-toolbar-right{flex:1 1 100%}
  [data-ds] .ds-toolbar-right{margin-left:0}
  [data-ds] .ds-search{flex:1 1 100%;max-width:none}
}

/* The coarse-pointer floor (docs/ui-contract.md rule 6): the hit area grows,
   the painted face does not. A surface that puts one of these shapes inside
   its own responsive layer extends THESE selectors rather than restating the
   numbers: .ds-switch, .ds-tree-row, .ds-table td and .ds-table-pick. */
@media (pointer:coarse){
  [data-ds] .ds-switch{min-height:44px}
  [data-ds] .ds-tree-row{min-height:44px}
  [data-ds] .ds-table td{height:44px}
  [data-ds] .ds-table-pick{width:20px;height:20px}
  [data-ds] .ds-search .ds-input{min-height:40px;font-size:16px}
}
@media (prefers-reduced-motion:reduce){
  [data-ds] .ds-tree-toggle,[data-ds] .ds-switch-track,[data-ds] .ds-switch-thumb,[data-ds] .ds-kanban-add{transition:none}
}
