/* Palette, radius and faces all come from /shared/molca-theme.css, which is the molca-ui kit's token
   set. Nothing colour-shaped is declared here — a value written down twice is a value that drifts. */
:root{
  --tabbar-height:58px;
  /* How much of the viewport the on-screen keyboard is covering, published by the app from
     visualViewport. Zero everywhere that has no such thing, which is why it is safe to subtract
     unconditionally. */
  --keyboard:0px;
  font:13px/1.5 var(--font-sans);
}
*{box-sizing:border-box}
html{background:var(--background)}
body{margin:0;background:var(--background);color:var(--foreground);min-width:320px}
button,input,select,textarea{font:inherit}
button{cursor:pointer}
button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible{outline:2px solid var(--primary);outline-offset:2px}

.app-shell{min-height:100vh;display:grid;grid-template-columns:220px minmax(0,1fr)}
.sidebar{position:sticky;top:0;height:100vh;padding:22px 14px 16px;border-right:1px solid var(--border-secondary);background:var(--sidebar);display:flex;flex-direction:column}
.brand{display:flex;align-items:center;gap:11px;padding:0 9px 24px;color:var(--foreground);text-decoration:none;font-size:15px;font-weight:700;line-height:1.15}
.brand img{width:34px;height:34px;padding:6px;border:1px solid var(--border-secondary);border-radius:9px;background:var(--surface-raised)}
.brand small{display:block;margin-top:3px;color:var(--text-tertiary);font-size:9px;font-weight:600;letter-spacing:.12em;text-transform:uppercase}
main{min-width:0}

nav{display:grid;gap:3px}
nav button{display:flex;align-items:center;width:100%;min-height:38px;padding:8px 10px;border:1px solid transparent;border-radius:8px;background:transparent;color:var(--text-tertiary);text-align:left;font-weight:600;transition:background .15s,color .15s,border-color .15s}
nav button:hover{background:var(--card);color:var(--foreground)}
nav button.active{border-color:var(--border-secondary);background:var(--surface-raised);color:var(--foreground)}
.nav-icon{width:27px;color:var(--text-quaternary);font-size:9px;font-weight:600;letter-spacing:.08em}
nav button.active .nav-icon{color:var(--primary)}
.sidebar-foot{margin-top:auto;padding:14px 10px 4px;border-top:1px solid var(--border-secondary);color:var(--text-tertiary);font-size:10px}
.status-dot{display:inline-block;width:6px;height:6px;margin-right:8px;border-radius:50%;background:var(--primary);box-shadow:0 0 0 3px var(--accent-soft)}

.topbar{height:88px;padding:20px clamp(18px,2vw,36px);border-bottom:1px solid var(--border-secondary);display:flex;align-items:center;justify-content:space-between}
h1,h2,h3,p{margin-top:0}
h1{margin-bottom:0;font-size:23px;line-height:1.2;font-weight:650;letter-spacing:-.025em}
h2{font-size:18px;line-height:1.3;font-weight:650;letter-spacing:-.015em}
h3{font-size:14px;font-weight:650}
.eyebrow{margin-bottom:5px;color:var(--primary);font-size:9px;font-weight:700;letter-spacing:.15em;text-transform:uppercase}
.account{display:flex;align-items:center;gap:12px;text-align:right}
.account strong,.account small{display:block}
.account strong{font-size:11px}
.account small{color:var(--text-tertiary);font-size:9px;text-transform:capitalize}
.content{width:100%;padding:clamp(18px,2vw,32px) clamp(18px,2vw,36px) 48px}

.page-head{display:flex;justify-content:space-between;align-items:flex-end;gap:18px;margin-bottom:18px}
.page-head h2{margin-bottom:3px}
.page-head p,.subtle{color:var(--text-tertiary);font-size:11px}
.page-head p{margin-bottom:0}
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(100%,260px),1fr));gap:12px;align-items:start}
.card{padding:18px;border:1px solid var(--border-secondary);border-radius:var(--radius);background:var(--card)}
.badge{display:inline-flex;align-items:center;width:max-content;padding:3px 7px;border:1px solid var(--accent-line);border-radius:999px;background:var(--accent-soft);color:var(--primary);font-size:8px;font-weight:700;letter-spacing:.07em;text-transform:uppercase}
.badge.archived{border-color:var(--border-secondary);background:var(--surface-raised);color:var(--text-tertiary)}
/* An Editor on its way back. Not the accent (it is not working yet) and not the grey of an archived
   thing (it is not gone) — a reconnect is a state the reader should be able to wait out. */
.badge.pending{border-color:var(--warning-line);background:var(--warning-fill);color:var(--warning-text)}
code{color:var(--primary);font:11px ui-monospace,SFMono-Regular,Consolas,monospace}
.empty{padding:40px 18px;border:1px dashed var(--border);border-radius:var(--radius);color:var(--text-tertiary);text-align:center}
.empty h3{margin-bottom:5px;color:var(--foreground)}
.empty p{margin-bottom:0}
.detail-head{display:flex;align-items:flex-start;justify-content:space-between;gap:20px;margin:10px 0 18px}
.detail-head h2{margin-bottom:7px;font-size:22px}
.detail-actions{display:flex;gap:6px;flex-wrap:wrap}
.facts{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px;margin-bottom:12px}
.fact{padding:14px;border:1px solid var(--border-secondary);border-radius:9px;background:var(--surface-raised)}
.fact small{display:block;margin-bottom:4px;color:var(--text-tertiary);font-size:10px}
.fact strong{overflow-wrap:anywhere}
.split{display:grid;grid-template-columns:minmax(0,1.45fr) minmax(250px,.7fr);gap:12px}
.section-head{display:flex;justify-content:space-between;align-items:center;gap:12px;margin-bottom:10px}
.section-head h3{margin:0}
.member{display:grid;grid-template-columns:minmax(0,1fr) auto auto;gap:10px;align-items:center;padding:10px 0;border-top:1px solid var(--border-secondary)}
.member:first-of-type{border-top:0}
.member small{display:block;color:var(--text-tertiary);font-size:10px}

button{min-height:34px;padding:7px 11px;border:1px solid var(--border);border-radius:8px;background:var(--surface-soft);color:var(--foreground);font-weight:600;transition:background .15s,border-color .15s,color .15s}
button:hover{border-color:var(--border);background:var(--accent)}
.primary{border-color:var(--primary);background:var(--primary);color:var(--primary-foreground);font-weight:700}
.primary:hover{border-color:var(--accent-hover);background:var(--accent-hover)}
.quiet{min-height:30px;padding:5px 8px;border-color:transparent;background:transparent;color:var(--text-tertiary)}
.quiet:hover{border-color:transparent;background:var(--surface-soft);color:var(--foreground)}
.danger{color:var(--danger-text)}
.wide{width:100%}
label{display:grid;gap:6px;margin-bottom:13px;color:var(--text-tertiary);font-size:11px;font-weight:600}
input,select,textarea{width:100%;padding:9px 11px;border:1px solid var(--border);border-radius:8px;background:var(--background);color:var(--foreground);outline:none;transition:border-color .15s,box-shadow .15s}
input:hover,select:hover,textarea:hover{border-color:var(--text-quaternary)}
input:focus,select:focus,textarea:focus{border-color:var(--primary);box-shadow:0 0 0 3px var(--accent-soft)}
textarea{min-height:136px;resize:vertical}
.notice{padding:10px 12px;border:1px solid var(--accent-line);border-radius:8px;background:var(--accent-soft);color:var(--primary);font-size:11px}

/* Checkbox rows. The generic `label` above is a grid so a text field sits *under* its caption, and
   `input` is full-width for the same reason — both are wrong for a checkbox, which lands on top of
   its own text and stretches across the dialog without these. Scoped to `.check` rather than fixing
   the base rule, because every other field in the app wants the stacked shape. */
fieldset{margin:0 0 13px;padding:8px 12px 10px;border:1px solid var(--border-secondary);border-radius:8px}
legend{padding:0 5px;color:var(--text-tertiary);font-size:11px;font-weight:600}
.check{display:flex;align-items:center;gap:9px;margin:0;padding:5px 0;font-weight:400;cursor:pointer}
.check:hover code{color:var(--accent-hover)}
.check input[type=checkbox]{flex:none;width:14px;height:14px;padding:0;accent-color:var(--primary);cursor:pointer}
/* Twelve scopes in one column made the dialog taller than most laptops. Two columns where there is
   room, one where there is not — the checkbox is its own hit target either way. */
.check-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,196px),1fr));gap:0 14px}

/* Project health. Severity is a border and a badge, never colour alone: the three states have to be
   distinguishable without relying on hue, and a red-green pair is the one thing that fails first. */
.health-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,258px),1fr));gap:10px;align-items:start}
.health-panel{padding:12px 13px;border:1px solid var(--border-secondary);border-left:3px solid var(--border);border-radius:9px;background:var(--surface-raised)}
.health-panel.attention{border-left-color:var(--warning-text)}
.health-panel.problem{border-left-color:var(--danger-text)}
.health-panel .section-head{margin-bottom:0;align-items:flex-start}
.health-panel h4{margin:0 0 3px;font-size:12px;font-weight:650}
.health-panel .subtle{margin:0}
.health-panel .facts-list{margin:9px 0 0;grid-template-columns:repeat(auto-fit,minmax(96px,1fr))}
.finding{display:grid;gap:2px;margin-top:9px;padding:8px 10px;border:1px solid var(--border-secondary);border-radius:7px;background:var(--card)}
.finding strong{font-size:11px;font-weight:650}
.finding small{color:var(--text-tertiary);font-size:10px}
.finding.attention{border-color:var(--warning-line)}
.finding.problem{border-color:var(--danger-line)}
.health>.section-head .badge{margin-left:auto}

/* Activity. Phone default is a single stacked column; the grid only appears once there is room for two
   readable columns, which is what the min-width breakpoint is for. Charts are inline SVG and CSS bars —
   no library, so nothing here can pull a second external origin into a page with a tested CSP. */
.activity-grid{display:grid;gap:10px}
.panel-block{padding:12px 13px;border:1px solid var(--border-secondary);border-radius:9px;background:var(--surface-raised)}
.panel-block h4{margin:0 0 8px;color:var(--text-tertiary);font-size:9px;font-weight:700;letter-spacing:.12em;text-transform:uppercase}
.panel-block>.subtle:last-child{margin:8px 0 0}
.window{display:flex;gap:2px;padding:2px;border:1px solid var(--border-secondary);border-radius:8px;background:var(--surface-raised)}
.window button{min-height:26px;padding:3px 9px;font-size:10px}
.window button.active{border-color:var(--accent-line);background:var(--accent-soft);color:var(--primary)}

.spark{display:block;width:100%;height:34px;overflow:visible}
.spark polyline{fill:none;stroke:var(--primary);stroke-width:1.5;vector-effect:non-scaling-stroke}
.spark polygon{fill:var(--accent-soft);stroke:none}
/* One column per day, so the shape reads as a calendar rather than as a smooth curve that never happened. */
.daybars{display:flex;align-items:flex-end;gap:1px;height:44px;margin-top:8px}
.daybars i{flex:1 1 0;min-width:0;border-radius:1px 1px 0 0;background:var(--border)}
.daybars i:hover{background:var(--primary)}

/* Share of peak, not share of total: one dominant row would otherwise flatten every other bar to nothing. */
.bars{margin:0;padding:0;list-style:none;display:grid;gap:5px}
.bars li{display:grid;grid-template-columns:minmax(0,1fr) auto;grid-template-areas:"label value" "bar bar";gap:2px 8px;align-items:center}
.bars span{grid-area:label;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:11px}
.bars em{grid-area:value;color:var(--text-tertiary);font-size:10px;font-style:normal}
.bars b{grid-area:bar;height:3px;min-width:2px;border-radius:2px;background:var(--primary);opacity:.75}

@media(min-width:900px){
  /* Two columns only once each is wide enough for a legible event name; below that the stack wins. */
  .activity-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media(min-width:1320px){
  .activity-grid{grid-template-columns:repeat(4,minmax(0,1fr))}
}

/* Remote companion: the Hub activity rail and the automation kernel, projected read-only. */
.chip-rail{display:flex;gap:6px;margin:10px 0 0;overflow-x:auto;overscroll-behavior-inline:contain;scrollbar-width:none}
.chip-rail::-webkit-scrollbar{display:none}
.chip{position:relative;display:inline-flex;align-items:center;gap:6px;flex:0 0 auto;max-width:260px;padding:5px 10px 6px;border:1px solid var(--border-secondary);border-radius:999px;background:var(--surface-raised);font-size:10px;overflow:hidden}
.chip i{flex:0 0 auto;width:6px;height:6px;border-radius:50%;background:var(--text-quaternary)}
.chip.running i{background:var(--primary);box-shadow:0 0 0 3px var(--accent-soft)}
.chip.ok i{background:var(--success-text)}
.chip.warning i{background:var(--warning-text)}
.chip.error i{background:var(--danger-text)}
.chip strong{flex:0 0 auto;font-weight:650}
.chip small{color:var(--text-tertiary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.chip b{position:absolute;left:0;bottom:0;height:2px;background:var(--primary)}

.notice.automation{margin-top:10px;border-color:var(--border-secondary);background:var(--surface-raised);color:var(--foreground)}
.notice.automation>strong{margin-right:7px}
.runs{margin:8px 0 0;padding:0;list-style:none;display:grid;gap:7px}
.runs li{display:grid;gap:3px;padding:7px 9px;border:1px solid var(--border-secondary);border-radius:7px;background:var(--card)}
.run-head{display:flex;align-items:center;justify-content:space-between;gap:8px}
.run-head strong{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:11px}
.run-bar{display:block;height:3px;border-radius:2px;background:var(--surface-soft)}
.run-bar b{display:block;height:100%;border-radius:2px;background:var(--primary)}
.runs small{color:var(--text-tertiary);font-size:10px}
.runs small.warn{color:var(--warning-text)}
.runs h4,.notice.automation h4{margin:12px 0 5px;color:var(--text-tertiary);font-size:9px;font-weight:700;letter-spacing:.12em;text-transform:uppercase}
.workflow{gap:5px}
.workflow.refused{opacity:.72}
.workflow .run-head{flex-wrap:wrap}
.workflow details{margin-top:4px}
.workflow summary{color:var(--text-tertiary);font-size:10px;cursor:pointer}
.workflow button{margin-top:6px;margin-right:6px}
.run-form{display:grid;gap:6px;margin:7px 0}
.run-form label{display:grid;gap:3px;color:var(--text-tertiary);font-size:10px}
.run-form label.inline{display:flex;align-items:center;gap:6px}
.run-form input[type=text],.run-form input:not([type]){padding:6px 8px;border:1px solid var(--border-secondary);border-radius:6px;background:var(--surface-raised);color:var(--foreground)}
.plan{margin:7px 0;padding:8px 10px;border:1px solid var(--border-secondary);border-radius:7px;background:var(--surface-raised)}
.plan p{margin:0 0 4px;font-size:10px}
.plan p:last-child{margin-bottom:0}
.plan .warn{color:var(--warning-text)}

/* Session IA: a sidebar inside the session card on desktop, a bottom tab bar on a phone. Identical
   capability in both — only the layout changes. */
.remote-editor{display:grid;gap:10px}
.session-tabs{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(0,1fr);gap:3px;margin-top:2px;padding:3px;border:1px solid var(--border-secondary);border-radius:9px;background:var(--card)}
.session-tabs button{display:flex;align-items:center;justify-content:center;gap:6px;min-width:0;min-height:34px;padding:6px 10px;border:1px solid transparent;border-radius:7px;background:transparent;color:var(--text-tertiary);font-size:11px;font-weight:600;transition:background .15s,color .15s,border-color .15s}
.session-tabs .tab-label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.session-tabs button:hover{background:var(--surface-raised);color:var(--foreground)}
.session-tabs button.active{border-color:var(--border-secondary);background:var(--surface-raised);color:var(--foreground)}
.session-tabs button.active .tab-icon{color:var(--primary)}
.tab-count{min-width:15px;padding:1px 4px;border-radius:999px;background:var(--primary);color:var(--primary-foreground);font-size:9px;font-weight:700}
.session-body{min-width:0}
.session-body>.notice{margin:0}

.facts-list{margin:8px 0 10px;padding:0;list-style:none;display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:6px}
.facts-list li{display:grid;gap:1px;padding:6px 9px;border:1px solid var(--border-secondary);border-radius:7px;background:var(--card)}
.facts-list span{color:var(--text-quaternary);font-size:9px;font-weight:600;letter-spacing:.09em;text-transform:uppercase}
.facts-list strong{font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

.transcript{max-height:44vh;overflow-y:auto;overscroll-behavior:contain}
.composer{display:grid;gap:6px;margin-top:8px}
.advanced summary{color:var(--text-tertiary);font-size:10px;cursor:pointer}
.sheet{margin:8px 0;padding:9px 11px;border:1px solid var(--accent-line);border-radius:8px;background:var(--accent-soft)}

@media(min-width:861px){
  /* Desktop: the tab strip becomes a rail beside the body, so nothing is more than one click away. */
  .session-tabs{grid-auto-flow:row;align-content:start;grid-template-columns:1fr}
  .session-tabs button{justify-content:flex-start}
  .remote-editor{grid-template-columns:150px minmax(0,1fr);grid-template-areas:"head head" "rail rail" "tabs body";align-items:start}
  .remote-editor>.member{grid-area:head}
  .remote-editor>.chip-rail{grid-area:rail}
  .remote-editor>.session-tabs{grid-area:tabs}
  .remote-editor>.session-body{grid-area:body}
}

@media(max-width:860px){
  /* Phone: the session is its own screen and the app's bottom bar is hidden while it is open, so this
     strip is the only bottom bar on the viewport. Two of them stacked is how a user aiming for "Runs"
     lands on "Projects". */
  .session-tabs{position:sticky;bottom:0;z-index:12;margin:0 -3px;padding:5px 3px calc(5px + env(safe-area-inset-bottom));border-radius:11px 11px 0 0;background:var(--surface-raised);box-shadow:0 -8px 24px color-mix(in srgb,var(--foreground) 18%,transparent)}
  .session-tabs button{flex-direction:column;gap:3px;min-height:48px;padding:6px 2px;font-size:10px}
  .session-tabs .tab-icon{width:20px;height:20px}
  .tab-label{letter-spacing:.02em}
  .facts-list{grid-template-columns:1fr 1fr}
  dialog{width:100%;max-width:none;margin:auto 0 0;border-radius:16px 16px 0 0}
  dialog form>footer{padding-bottom:calc(16px + env(safe-area-inset-bottom))}
}

.auth-backdrop{position:fixed;inset:0;z-index:20;padding:20px;background:var(--scrim);backdrop-filter:blur(10px);display:grid;place-items:center}
.auth-backdrop.hidden{display:none}
.auth-card{width:min(400px,100%);padding:28px;border:1px solid var(--border);border-radius:16px;background:var(--card);box-shadow:var(--shadow)}
.auth-card img{width:38px;height:38px;margin-bottom:20px;padding:7px;border:1px solid var(--border-secondary);border-radius:9px;background:var(--surface-raised)}
.auth-card h2{margin-bottom:8px;font-size:23px}
.auth-card>p:not(.eyebrow):not(.error){margin-bottom:20px;color:var(--text-tertiary)}
.error{min-height:18px;margin:10px 0 0;color:var(--danger-text);font-size:11px}
dialog{width:min(520px,calc(100% - 28px));padding:0;border:1px solid var(--border);border-radius:14px;background:var(--card);color:var(--foreground);box-shadow:var(--shadow-strong)}
dialog::backdrop{background:var(--scrim);backdrop-filter:blur(5px)}
dialog form>header,dialog form>footer{display:flex;align-items:center;justify-content:space-between;padding:16px 18px;border-bottom:1px solid var(--border-secondary)}
dialog form>header h2{margin:0}
dialog form>footer{justify-content:flex-end;gap:6px;border:0;border-top:1px solid var(--border-secondary)}
#dialogBody{padding:18px}
.icon{width:32px;padding:0;border-color:transparent;background:transparent;font-size:20px}
.icon:hover{border-color:transparent;background:var(--surface-soft);color:var(--primary)}
.toast{position:fixed;right:20px;bottom:20px;z-index:30;max-width:380px;padding:11px 14px;border:1px solid var(--accent-line);border-radius:9px;background:var(--surface-raised);color:var(--primary);box-shadow:var(--shadow);opacity:0;transform:translateY(70px);pointer-events:none;transition:.2s}
.toast.show{opacity:1;transform:none}
.toast.danger{border-color:var(--danger-line);background:var(--surface-raised);color:var(--danger-text)}

/* ==== App chrome ================================================================================
   The pieces that exist because this is an installed app rather than a page: a back affordance (a
   standalone window has no browser chrome to provide one), a bottom tab bar, list rows big enough to
   hit with a thumb, and a banner that says out loud when nothing on screen is live. */

.icon-svg{width:18px;height:18px;flex:0 0 auto;fill:none;stroke:currentColor;stroke-width:1.7;
  stroke-linecap:round;stroke-linejoin:round}

.topbar-title{min-width:0}
#back,#switcher{width:36px;min-height:36px;padding:0;border-color:transparent;background:transparent;color:var(--text-tertiary)}
#back:hover,#switcher:hover{background:var(--surface-soft);color:var(--foreground)}
#back[hidden],#switcher[hidden]{display:none}
.back-inline{display:inline-flex;align-items:center;gap:6px;margin-bottom:10px}

.offline-banner{display:flex;align-items:center;gap:9px;margin:0;padding:9px clamp(16px,2vw,36px);
  border-bottom:1px solid var(--warning-line);background:var(--warning-fill);color:var(--warning-text);font-size:11px}
.offline-banner[hidden]{display:none}

/* The bottom tab bar has no desktop form: above 861px the sidebar is the navigation, and a bar pinned
   to the bottom of a 1400px window is nowhere near anything. */
.tabbar{display:none}

.rows{display:grid;gap:1px;border:1px solid var(--border-secondary);border-radius:var(--radius);background:var(--border-secondary);overflow:hidden}
.rows+.rows{margin-top:12px}
.row{display:flex;align-items:center;gap:11px;width:100%;min-height:52px;padding:10px 13px;
  border:0;border-radius:0;background:var(--card);color:var(--foreground);text-align:left;font-weight:500}
.row:hover{border:0;background:var(--surface-raised)}
.row-main{display:grid;gap:2px;min-width:0;flex:1}
.row-main strong{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:650}
.row-main small{color:var(--text-tertiary);font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.row-icon{color:var(--text-quaternary)}
.row-chevron{width:16px;height:16px;color:var(--text-quaternary)}
.row.danger .row-main strong{color:var(--danger-text)}

/* An archived project is still openable, so it is dimmed rather than removed or greyed to unreadable. */
.dimmed{opacity:.62}
.dimmed:hover{opacity:1}

/* The project card is a button, so these rules have to sit after the base `button` block or its border,
   padding and surface win over `.card`. Sized by its content: four short strings and no fixed height,
   where the previous 166px minimum meant three projects filled a phone screen with mostly nothing. */
.project-card{display:flex;flex-direction:column;align-items:flex-start;gap:3px;min-height:0;
  padding:15px 16px 16px;border:1px solid var(--border-secondary);border-radius:var(--radius);background:var(--card);
  text-align:left;font-weight:400;transition:border-color .15s,background .15s,transform .15s}
.project-card:hover{border-color:var(--border);background:var(--surface-raised);transform:translateY(-1px)}
.project-card-head{display:flex;align-items:center;gap:7px;width:100%;margin-bottom:6px}
.project-card-head .row-icon{margin-right:auto}
.project-name{font-size:16px;font-weight:650;letter-spacing:-.01em;overflow-wrap:anywhere}
.project-card small{color:var(--text-tertiary)}

/* A count worth glancing at. `alert` borrows the amber of the reconnecting badge rather than the
   accent: the accent means "working", and something waiting on a person is not working. */
.pip{display:inline-flex;align-items:center;justify-content:center;min-width:19px;height:19px;padding:0 6px;
  border-radius:999px;background:var(--surface-soft);color:var(--text-tertiary);font-size:10px;font-weight:700}
.pip.alert{background:var(--warning-fill);color:var(--warning-text)}

/* ==== Project shell =============================================================================
   Seven sections. On a desktop they are a rail beside the body; on a phone they are a list you drill
   into, because seven items in a horizontal strip on a 360px screen means three are reachable and the
   rest are behind a scroll gesture nobody knows is there. */

.project-shell{display:grid;grid-template-columns:186px minmax(0,1fr);gap:18px;align-items:start}
.section-rail{display:grid;gap:2px;position:sticky;top:18px}
.section-rail button{display:flex;align-items:center;gap:9px;width:100%;min-height:36px;padding:7px 10px;
  border:1px solid transparent;border-radius:8px;background:transparent;color:var(--text-tertiary);text-align:left;font-weight:600}
.section-rail button:hover{background:var(--card);color:var(--foreground)}
.section-rail button.active{border-color:var(--border-secondary);background:var(--surface-raised);color:var(--foreground)}
.section-rail button.active .row-icon{color:var(--primary)}
.section-rail span:not(.pip){flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.section-body{min-width:0}
.section-rows{margin-top:14px}

/* ==== Attention =================================================================================
   What is blocked on a person, at the top of the project and counted on the Editors tab. An Editor
   waiting on an approval is the only genuinely urgent thing in this app, and it used to be the
   hardest thing in it to reach. */

.attention{display:grid;gap:1px;margin-bottom:14px;border:1px solid var(--warning-line);
  border-radius:var(--radius);background:var(--warning-fill);overflow:hidden}
.attention-row{display:flex;align-items:center;gap:11px;width:100%;min-height:54px;padding:11px 13px;
  border:0;border-radius:0;background:var(--card);color:var(--foreground);text-align:left}
.attention-row:hover{border:0;background:var(--surface-raised)}
.attention-row>span{display:grid;gap:2px;min-width:0;flex:1}
.attention-row small{color:var(--text-tertiary);font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.attention-row .icon-svg{color:var(--text-quaternary)}
.attention-row.waiting .icon-svg{color:var(--warning-text)}
.session-row .row-main small{font-size:10px}

/* ==== Chat ======================================================================================
   The Assistant tab is a conversation, so it is laid out as one: the transcript owns the space
   between the header and the composer and scrolls inside it, and the composer is docked. It used to
   be a 52vh box with the composer below it in page flow, which meant typing a message began by
   scrolling down to find the box you were about to type into. */

.chat{display:flex;flex-direction:column;gap:8px;min-height:0}
.chat-status{display:flex;align-items:center;gap:7px;flex-wrap:wrap;margin:0}
.chat-status small{color:var(--text-tertiary);font-size:10px}
.chat .transcript{flex:1;min-height:120px;padding:2px;border:1px solid var(--border-secondary);border-radius:10px;
  background:var(--card);display:flex;flex-direction:column;gap:1px}
.chat .transcript:focus-visible{outline:2px solid var(--primary);outline-offset:2px}
.empty-chat{margin:auto;padding:20px;text-align:center}

.turn{padding:8px 11px;border-radius:8px}
.turn p{margin:0;overflow-wrap:anywhere}
.turn-role{display:block;margin-bottom:2px;color:var(--text-quaternary);font-size:9px;font-weight:700;
  letter-spacing:.1em;text-transform:uppercase}
.turn.user{background:var(--surface-raised)}
.turn.assistant .turn-role{color:var(--primary)}
.turn.tool,.turn.system{color:var(--text-tertiary)}
.turn.tool p,.turn.system p{font-size:11px}

.composer{display:flex;align-items:flex-end;gap:7px;margin:0}
.composer textarea{flex:1;min-height:44px;max-height:132px;padding:11px 13px;border-radius:12px;resize:none}
.composer .send{display:flex;align-items:center;justify-content:center;width:44px;min-height:44px;padding:0;
  border-color:var(--primary);background:var(--primary);color:var(--primary-foreground)}
.composer .send:disabled{border-color:var(--border-secondary);background:var(--surface-soft);color:var(--text-quaternary);cursor:not-allowed}
.composer .send .icon-svg{width:20px;height:20px;stroke-width:1.6}
.composer .stop{min-height:44px}
.command-echo{margin:0}

.sheet-head{display:flex;align-items:flex-start;gap:9px;margin:0 0 9px}
.sheet-head .icon-svg{color:var(--warning-text);margin-top:1px}
.sheet-actions{display:flex;gap:7px;flex-wrap:wrap}
.sheet-actions button{flex:1 0 auto;min-width:96px}

.account-card{display:flex;align-items:center;gap:13px;margin-bottom:14px}
.account-card strong{display:block}
.account-card small{color:var(--text-tertiary);text-transform:capitalize}
.avatar{display:flex;align-items:center;justify-content:center;width:42px;height:42px;flex:0 0 auto;
  border:1px solid var(--border-secondary);border-radius:50%;background:var(--surface-raised);color:var(--text-tertiary)}
.avatar .icon-svg{width:22px;height:22px}
.build-line{margin:16px 0 0;text-align:center}

/* ==== The phone app =============================================================================
   Below 861px this stops being a narrow dashboard and becomes an app: the sidebar is replaced by a
   bottom tab bar, the document stops scrolling and the content pane scrolls instead, and the whole
   thing is pinned to the visual viewport so the bar sits on the bottom edge rather than wherever the
   page happens to have been scrolled to.

   The type scale moves too. 13px base with 9px labels is a desktop density; on a phone held at arm's
   length it is a squint. Form controls go to 16px specifically: below that, iOS Safari zooms the page
   on focus and never zooms back out, which on the chat composer is unusable. */

@media(max-width:860px){
  :root{font-size:15px}
  body{overscroll-behavior-y:none}

  /* The shell is exactly the viewport: one scrolling content row, one bar row. `dvh` handles the
     collapsing URL bar; the `vh` line before it is the fallback for browsers without it. */
  .app-shell{grid-template-columns:1fr;grid-template-rows:minmax(0,1fr) auto;height:100vh;height:100dvh}
  .sidebar{display:none}
  main{display:flex;flex-direction:column;min-height:0}

  /* The content pane is the scroller, not the document. A fixed bottom bar over a document scroll is
     the layout that famously drifts on iOS; this way the bar is simply outside the scrolling box. */
  .content{flex:1;min-width:0;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch;
    padding:16px 16px calc(20px + var(--tabbar-height) + env(safe-area-inset-bottom))}
  body.session-open .content{padding-bottom:12px}

  .topbar{height:auto;min-height:0;padding:10px 14px;gap:8px;align-items:center;
    padding-top:calc(10px + env(safe-area-inset-top))}
  .topbar .eyebrow{margin-bottom:1px;font-size:9px}
  .topbar-title{min-width:0;flex:1}
  h1{font-size:19px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  /* The account block moves to the More screen: four items of chrome across a 360px header leaves no
     room for the one thing the header is for, which is saying what screen you are on. */
  .topbar .account{display:none}

  /* 16px on text-entry fields only. That is what the iOS rule is about — Safari zooms when a *focused
     field* has a font under 16px, and never zooms back out — and it does not apply to buttons. Including
     buttons in it is what made every inline control on the page read as a primary action. */
  input,select,textarea{font-size:16px}
  button{font-size:15px}

  /* 44px belongs to the things a thumb aims at: navigation, list rows, primary actions. The page is also
     full of inline secondary controls — Refresh, Remove, Clear, the 7d/30d/90d window switch — and giving
     those the same height turns a dense panel into a column of slabs. They get 36px, comfortably past the
     24px WCAG 2.2 AA minimum, and take their reachability from spacing rather than from bulk. */
  .row,.attention-row,.primary,.tabbar button,.session-tabs button,.composer .send,
  .sheet-actions button{min-height:44px}
  .quiet{min-height:36px;padding:7px 10px;font-size:13px}
  .badge{font-size:10px}
  .subtle,.member small{font-size:12px}

  .page-head,.detail-head{align-items:flex-start;flex-direction:column;gap:10px}
  .grid{grid-template-columns:1fr;gap:10px}
  .facts,.split{grid-template-columns:1fr}
  .member{grid-template-columns:minmax(0,1fr) auto}
  .member>button,.member>span:last-child{grid-column:1/-1;justify-self:start}
  .card{padding:14px}
  dialog form>header,dialog form>footer,#dialogBody{padding:15px}

  .project-shell{display:block}
  .section-rail{display:none}

  /* The bar. Not fixed: the shell is already the height of the visual viewport and the content pane is
     the thing that scrolls, so the bar is simply the last row of the shell and stays put without any
     of the positioning that makes fixed bars drift on iOS. */
  .tabbar{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(0,1fr);
    padding:5px 4px calc(5px + env(safe-area-inset-bottom));border-top:1px solid var(--border-secondary);
    background:var(--sidebar)}
  /* `--muted`, not `--dim`: the label is 10px, and dim on the bar's own background is about 3.8:1 — enough
     for the icon beside it and under AA for the text. It also matches what the desktop sidebar uses for the
     same "not the current one" state. */
  .tabbar button{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;
    gap:3px;min-height:48px;padding:5px 2px;border:0;border-radius:9px;background:transparent;
    color:var(--text-tertiary);font-size:10px;font-weight:600}
  .tabbar button:hover{border:0;background:transparent;color:var(--foreground)}
  .tabbar button.active{color:var(--foreground)}
  .tabbar button.active .tab-icon{color:var(--primary)}
  .tabbar .tab-icon{width:21px;height:21px}
  .tabbar .pip{position:absolute;top:2px;left:50%;margin-left:4px;min-width:16px;height:16px;font-size:9px}
  body.session-open .tabbar{display:none}

  /* A session takes the viewport. The session tab strip is ordered last so it sits on the bottom edge
     as a flex item rather than as a sticky element that needs a scrollport to stick to — and with the
     app bar hidden above, it is the only bottom bar on screen. */
  body.session-open .content{display:flex;flex-direction:column;overflow:hidden}
  body.session-open .remote-editor{display:flex;flex-direction:column;gap:8px;flex:1;min-height:0}
  body.session-open .session-head,body.session-open .chip-rail{flex:0 0 auto}
  body.session-open .session-body{order:3;flex:1;min-height:0;overflow-y:auto;overscroll-behavior:contain}
  body.session-open .session-tabs{order:4;flex:0 0 auto;position:static;margin:0 -16px;border-radius:0}
  body.session-open .chat{height:100%}
  body.session-open .chat .transcript{max-height:none}

  /* The keyboard covers the layout viewport on iOS rather than resizing it, so the app takes itself out
     of the covered area. Everything inside is already a flex chain, so the transcript is what shrinks
     and the composer stays on screen with it. */
  .app-shell{height:calc(100dvh - var(--keyboard))}
  .sheet{margin:0;flex:0 0 auto}
}
