/* ============ tokens ============
   Palette, type scale, spacing and radius follow the Jira-inspired design
   principles: neutral surfaces, one blue accent, restrained everything else. */
:root{
  --surface:#FFFFFF; --surface-muted:#F8F8F8; --surface-sunken:#F1F1F3;
  --ink:#292A2E; --ink-2:#505258; --ink-3:#6B6E76;
  --line:#DDDEE1; --line-soft:#EBECEE; --page:#F1F2F4;
  --accent:#1868DB; --accent-ink:#1558BC; --accent-soft:#E9F2FE;
  --lip:#F0F6FE; --lip-on:#DCEAFC;
  --danger:#C9372C;

  /* issue types: task green, bug red, story blue — each with a very light
     tint used as the background of its row and card */
  --task:#1F845A; --task-tint:#F1F8F4; --task-tint-2:#E5F2EB;
  --bug:#C9372C;  --bug-tint:#FDF4F3;  --bug-tint-2:#F9E8E6;
  --story:#1868DB;--story-tint:#F2F7FE;--story-tint-2:#E6EFFC;

  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:24px; --s6:32px; --s7:48px;
  --r:6px; --r-sm:4px;
  --font:system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;
  --shadow:0 1px 2px rgba(41,42,46,.08);
  --shadow-lift:0 8px 24px rgba(41,42,46,.16);
}
*{box-sizing:border-box}
html,body{height:100%}
body{margin:0;background:var(--page);color:var(--ink);
  font:14px/1.5 var(--font);-webkit-font-smoothing:antialiased}
a{color:var(--accent);text-decoration:none}
a:hover{text-decoration:underline}
button{font:inherit;color:inherit}
h1,h2{margin:0;font-weight:600;letter-spacing:-.01em}
h1{font-size:22px}
h2{font-size:16px}
:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
#app{height:100%;overflow:auto}

/* ============ app bar ============ */
.appbar{display:flex;align-items:center;gap:var(--s2);height:52px;padding:0 var(--s5);
  background:var(--surface);border-bottom:1px solid var(--line);
  position:sticky;top:0;z-index:20}
.appbar .mark{display:flex;align-items:center;gap:var(--s2);
  color:var(--ink);font-size:15px;font-weight:600;letter-spacing:-.01em}
.appbar .mark:hover{text-decoration:none;color:var(--accent-ink)}
/* the switch for the issue-type tint: lit while the colour is on */
.appbar .glyph{width:20px;height:20px;border-radius:var(--r-sm);background:var(--accent);
  position:relative;flex:none;border:0;padding:0;cursor:pointer}
.appbar .glyph.off{background:var(--line)}
.appbar .glyph:after{content:"";position:absolute;left:5px;top:5px;width:4px;height:10px;
  background:#fff;border-radius:1px;box-shadow:6px 0 0 rgba(255,255,255,.6)}

.screen{padding:var(--s5) var(--s5) var(--s7)}

/* the assignee picker with its Ping button beside it */
.with-ping{display:flex;gap:var(--s2);align-items:center}
.with-ping select{flex:1;min-width:0}
.btn:disabled{opacity:.5;cursor:default}
.btn:disabled:hover{background:var(--surface)}

/* ============ sign-in ============ */
.signin{display:grid;place-items:center;min-height:calc(100% - 52px)}
.signin-box{display:flex;flex-direction:column;align-items:center;gap:var(--s4);
  padding:var(--s6);max-width:360px;text-align:center}
.signin-box .err{margin:0}

/* ============ controls ============ */
.btn{display:inline-flex;align-items:center;gap:var(--s2);height:32px;padding:0 var(--s3);
  border:1px solid var(--line);background:var(--surface);border-radius:var(--r-sm);
  cursor:pointer;white-space:nowrap;font-size:14px;color:var(--ink-2)}
.btn:hover{background:var(--surface-sunken);text-decoration:none}
.btn.primary{background:var(--accent);border-color:var(--accent);color:#fff;font-weight:500}
.btn.primary:hover{background:var(--accent-ink)}
.btn.sm{height:26px;padding:0 var(--s2);font-size:13px}
.btn.danger:hover{border-color:var(--danger);color:var(--danger);background:var(--bug-tint)}
.btn.danger-solid{background:var(--danger);border-color:var(--danger);color:#fff;font-weight:500}
.btn.danger-solid:hover{background:#A82D24}
select,input[type=text],input[type=date],textarea{font:14px var(--font);color:var(--ink);
  border:1px solid var(--line);border-radius:var(--r-sm);background:var(--surface);
  padding:6px var(--s2)}
select:focus,input:focus,textarea:focus{outline:2px solid var(--accent);outline-offset:-1px;border-color:var(--accent)}

/* ============ boxes ============
   Every screen is a stack of these. Nothing is written straight onto the
   page background, and a box is never nested inside another box. */
.box{background:var(--surface);border-radius:var(--r);box-shadow:0 1px 2px rgba(41,42,46,.14)}
.screen>.box{margin-bottom:var(--s4)}
.screen-head{padding:var(--s4) var(--s4) 0}
.head-row{display:flex;align-items:center;gap:var(--s3);margin-bottom:var(--s3)}
.head-row.end{justify-content:flex-end}

/* ============ generic ============ */
.spacer{flex:1}
.muted{color:var(--ink-3)}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:var(--s3)}
.grid3{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s3)}
/* left column takes only what it needs, right column takes the rest */
.grid-fit{display:grid;grid-template-columns:auto minmax(0,1fr);gap:var(--s4);align-items:start}
@media (max-width:560px){.grid-fit{grid-template-columns:minmax(0,1fr)}}
.page-head{display:flex;align-items:center;gap:var(--s3);margin-bottom:var(--s4)}
.bar-head{display:flex;align-items:center;gap:var(--s3);margin:var(--s4) 0 var(--s2)}
.empty{padding:var(--s6);text-align:center;color:var(--ink-3)}

.avatar{width:24px;height:24px;border-radius:50%;display:inline-grid;place-items:center;
  color:#fff;font-size:10px;font-weight:600;flex:none}
.ic-type{width:16px;height:16px;border-radius:var(--r-sm);display:inline-grid;place-items:center;
  font-size:10px;font-weight:700;color:#fff;flex:none}
.t-task{background:var(--task)}.t-bug{background:var(--bug)}.t-story{background:var(--story)}
.epic{display:inline-block;max-width:160px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  padding:2px var(--s2);border-radius:var(--r-sm);font-size:12px;font-weight:500;color:#fff;flex:none}
.eff{display:inline-grid;place-items:center;min-width:24px;height:20px;padding:0 6px;
  border-radius:var(--r-sm);background:var(--surface-sunken);color:var(--ink-2);
  font-size:12px;font-weight:600;flex:none}
.flag{border:0;background:none;cursor:pointer;padding:0 2px;font-size:14px;line-height:1;
  color:#C7C9CD;flex:none;border-radius:var(--r-sm)}
.flag:hover{color:var(--ink-3)}
.flag.on{color:var(--danger)}

/* ============ projects ============
   The card is a folder: a tab with a slanted right edge sits on top of the
   card and shares its colour with the head, so the two read as one shape.
   No border anywhere — a single drop-shadow traces the whole silhouette,
   tab included. Collapsed it shows the name and the team's initials; on
   hover it grows to reveal the description and the members' names. */
.proj-grid{display:grid;grid-template-columns:repeat(3,1fr);align-items:start;
  column-gap:var(--s4);row-gap:var(--s5)}

/* the tab: rounded on top, right edge slanted like the folder icon */

/* 0fr -> 1fr animates the height without knowing it in advance */

/* collapsed: a row of initials. hovered: two columns with names. */

/* ============ project header + tabs ============ */

/* ============ rows ============
   Rows are grids so the label strip above them lines up column for column. */

/* the row being confirmed drops the grid and gives the message the middle */

/* the filter strip, built into the table's own head. One control per column,
   sized to the column it sits in — flag and type cycle instead of dropping down. */

/* ============ sprints ============
   The four statuses are four sibling boxes. Cards and rows inside them are
   flat fills, never framed panels of their own. */

/* the switcher reads as one control: arrows hugging a centred label */

/* a card is a fill, not a framed box inside the column */

/* the summary carries the card, and always has room for a second line */

/* ============ modals + issue panel ============ */

/* ---- the issue sheet: two thirds of the screen, anchored right ----
   Laid out the Jira way on the Details screen: the writing down the middle,
   the fields in a column beside it. One switch in the head picks the screen. */

/* the two columns. The fields sit in a fixed lane so the writing keeps the rest */

/* The writing column is two panes sharing one fixed height, divided by the
   three-way picker. Neither pane is ever taken off screen — only its share
   changes. Both scroll inside themselves, so the sheet never grows a
   scrollbar of its own. */

.pane>.sec-h{flex:none;margin:0 0 var(--s2)}

/* description: plain text until it is clicked, so nothing boxes it in */

/* the box to write in is pinned to the foot of the pane and never scrolls away */
.pane-chat .chat-new{flex:none;margin-top:var(--s2);padding-top:var(--s2);
  border-top:1px solid var(--line-soft)}
.composer{position:relative}
.pane-chat .composer textarea{width:100%;min-height:46px;resize:none;display:block;
  padding-right:38px;line-height:1.5}
.composer .send{position:absolute;right:6px;bottom:6px;width:28px;height:28px;
  display:grid;place-items:center;padding:0;border:0;border-radius:var(--r-sm);
  background:var(--accent);color:#fff;cursor:pointer}
.composer .send:hover{background:var(--accent-ink)}

/* Description holds most of the height. Pointing at the comments levels them
   out, and so does writing one — :focus-within while the box has the cursor,
   :not(:placeholder-shown) while a draft is sitting in it. Doing this in CSS
   means typing never triggers a render that would take the cursor away. */
.pane-desc{flex:2}
.pane-chat{flex:1}
.pane-desc,.pane-chat{transition:flex-grow .14s ease}
.pane-chat:hover,
.pane-chat:focus-within,
.pane-chat:has(#cm-body:not(:placeholder-shown)){flex:2}

@media (max-width:1000px){.proj-grid{grid-template-columns:repeat(2,1fr)}}
@media (max-width:660px){.proj-grid{grid-template-columns:1fr}}

.proj-card{position:relative;margin-top:14px;color:inherit;cursor:pointer;
  background:var(--surface);border-radius:var(--r);
  filter:drop-shadow(0 1px 2px rgba(41,42,46,.14));
  transition:filter .16s ease}
.proj-card:hover,.proj-card:focus-within{filter:drop-shadow(0 4px 10px rgba(41,42,46,.18))}
/* the tab: rounded on top, right edge slanted like the folder icon */
.proj-card:before{content:"";position:absolute;left:0;top:-13px;width:46%;min-width:118px;height:20px;
  background:var(--accent-soft);border-radius:var(--r) var(--r) 0 0;
  clip-path:polygon(0 0,calc(100% - 13px) 0,100% 100%,0 100%)}

.proj-card .card-h{display:flex;align-items:center;gap:var(--s2);
  padding:var(--s3) var(--s4);background:var(--accent-soft);
  border-radius:var(--r) var(--r) 0 0}
.proj-card h2{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.proj-card .card-body{background:var(--surface);border-radius:0 0 var(--r) var(--r)}

/* 0fr -> 1fr animates the height without knowing it in advance */
.proj-card .desc{display:grid;grid-template-rows:0fr;transition:grid-template-rows .18s ease}
.proj-card:hover .desc,.proj-card:focus-within .desc{grid-template-rows:1fr}
.proj-card .desc>p{overflow:hidden;margin:0;font-size:14px;color:var(--ink-2)}
.proj-card:hover .desc>p,.proj-card:focus-within .desc>p{padding:var(--s4) var(--s4) var(--s3)}

/* collapsed: a row of initials. hovered: two columns with names. */
.proj-card .team{display:flex;flex-wrap:wrap;gap:var(--s2);padding:var(--s3) var(--s4)}
.proj-card .member{display:flex;align-items:center;gap:var(--s2);min-width:0;
  font-size:13px;color:var(--ink-2)}
.proj-card .name{display:none;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.proj-card:hover .team,.proj-card:focus-within .team{display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s2) var(--s3)}
.proj-card:hover .name,.proj-card:focus-within .name{display:inline}

/* ============ project header + tabs ============ */
.head-row .back{font-size:13px;color:var(--ink-3);white-space:nowrap}
.head-row .back:hover{color:var(--accent-ink)}
.head-row h1{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tabs{display:flex;gap:var(--s1);border-top:1px solid var(--line-soft)}
.tabs a{padding:var(--s3);color:var(--ink-2);font-size:14px;border-bottom:2px solid transparent}
.tabs a:hover{text-decoration:none;color:var(--ink)}
.tabs a.active{color:var(--accent-ink);border-bottom-color:var(--accent);font-weight:500}

/* ============ rows ============
   Rows are grids so the label strip above them lines up column for column. */
.list{overflow:hidden}
.list .rowhead,.list .irow,.list .rowfilters{display:grid;align-items:center;gap:var(--s3);padding:var(--s2) var(--s3)}
.list .rowhead>span,.list .irow>span{min-width:0;overflow:hidden}
.rowhead{border-bottom:1px solid var(--line);font-size:12px;font-weight:600;
  color:var(--ink-3);padding-top:var(--s2);padding-bottom:var(--s2)}
.rows-backlog .rowhead,.rows-backlog .irow,.rows-backlog .rowfilters{grid-template-columns:40px 44px minmax(0,1fr) 180px 56px 76px}
.rows-sprint .rowhead,.rows-sprint .irow{grid-template-columns:44px minmax(0,1fr) 180px 56px 76px}
.rows-epics .rowhead,.rows-epics .irow{grid-template-columns:200px minmax(0,1fr) 140px 52px}
/* the row being confirmed drops the grid and gives the message the middle */
.rows-epics .irow.confirming{display:flex;align-items:center;gap:var(--s3);cursor:default}
.rows-epics .irow.confirming:hover{background:none}
/* the filter strip, built into the table's own head. One control per column,
   sized to the column it sits in — flag and type cycle instead of dropping down. */
.rowfilters{padding-top:0;padding-bottom:var(--s2);border-bottom:1px solid var(--line)}
.rowfilters>*{min-width:0;width:100%}
.colf{height:26px;padding:0 var(--s1);font-size:12px;color:var(--ink-2)}
select.colf{width:100%}
input.colf{width:100%}
.colf::placeholder{color:var(--ink-3)}
button.colf{display:grid;place-items:center;border:1px solid var(--line);
  background:var(--surface);border-radius:var(--r-sm);cursor:pointer;padding:0}
button.colf:hover{border-color:var(--accent)}
button.colf.set{border-color:var(--accent);background:var(--accent-soft)}
.f-flag{color:#C7C9CD;font-size:13px;line-height:1}
.f-flag.set{color:var(--danger)}
.rowfilters .ic-type.t-any{background:var(--line);color:var(--ink-3)}

.irow{border-bottom:1px solid var(--line-soft);cursor:pointer;font-size:14px}
.irow:last-child{border-bottom:0}
.irow:hover{background:var(--surface-muted)}
/* Colour by issue type, switched from the appbar glyph. Every one of these
   carries the same #app prefix so they keep their order among themselves, and
   with it beat the plain hover underneath. Off, a row or card falls back to the
   surface it was drawn on. */
#app:not(.no-tint) .irow.type-task{background:var(--task-tint)}
#app:not(.no-tint) .irow.type-bug{background:var(--bug-tint)}
#app:not(.no-tint) .irow.type-story{background:var(--story-tint)}
#app:not(.no-tint) .irow.type-task:hover{background:var(--task-tint-2)}
#app:not(.no-tint) .irow.type-bug:hover{background:var(--bug-tint-2)}
#app:not(.no-tint) .irow.type-story:hover{background:var(--story-tint-2)}
.irow.dragging{opacity:.4}
.irow .sum{text-overflow:ellipsis;white-space:nowrap}
.irow .pct{font-size:13px;color:var(--ink-3)}
.bar{height:6px;width:100%;border-radius:3px;background:var(--surface-sunken);overflow:hidden;display:flex}
.bar i{display:block;height:100%}

/* ============ sprints ============
   The four statuses are four sibling boxes. Cards and rows inside them are
   flat fills, never framed panels of their own. */
.sprint-head{padding:var(--s3) var(--s4)}
.sprint-head .head-row{margin-bottom:0}
/* the switcher reads as one control: arrows hugging a centred label */
.switch{display:flex;align-items:center;gap:var(--s2)}
.which{min-width:132px;text-align:center}
.which b{display:block;font-size:18px;font-weight:600;letter-spacing:-.01em;line-height:1.25}
.which span{display:block;font-size:12px;color:var(--ink-3)}
.which.empty-sprint{min-width:0;text-align:left}
.arrow{display:grid;place-items:center;width:32px;height:32px;padding:0;
  border:1px solid var(--line);background:var(--surface);border-radius:var(--r-sm);
  cursor:pointer;font-size:18px;line-height:1;color:var(--ink-2)}
.arrow:hover:not(:disabled){background:var(--accent-soft);border-color:var(--accent);color:var(--accent-ink)}
.arrow:disabled{opacity:.35;cursor:default}
.seg{display:inline-flex;border:1px solid var(--line);border-radius:var(--r-sm);overflow:hidden}
.seg button{border:0;background:var(--surface);padding:0 var(--s3);height:32px;cursor:pointer;
  font-size:13px;color:var(--ink-2)}
.seg button+button{border-left:1px solid var(--line)}
.seg button:hover:not(.on){background:var(--surface-sunken)}
.seg button.on{background:var(--accent-soft);color:var(--accent-ink);font-weight:500}

.board{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--s4);align-items:start}
.col{padding:var(--s3) var(--s3) var(--s3);min-height:180px}
.col.drop-hint{box-shadow:0 0 0 2px var(--accent)}
.col-h{padding:var(--s1) var(--s2) var(--s3);font-size:13px;font-weight:600;color:var(--ink-2)}
.cards{display:flex;flex-direction:column;gap:var(--s2);min-height:32px}
/* a card is a fill, not a framed box inside the column */
.icard{background:var(--surface-sunken);border-radius:var(--r-sm);padding:var(--s3);cursor:pointer}
.icard:hover{filter:brightness(.97)}
.icard.dragging{opacity:.4}
#app:not(.no-tint) .icard.type-task{background:var(--task-tint)}
#app:not(.no-tint) .icard.type-bug{background:var(--bug-tint)}
#app:not(.no-tint) .icard.type-story{background:var(--story-tint)}
/* the summary carries the card, and always has room for a second line */
.icard .sum{min-height:2.7em;font-size:15px;font-weight:400;
  line-height:1.35;color:var(--ink);overflow-wrap:anywhere}
.icard .card-foot{display:flex;align-items:center;gap:var(--s2);margin-top:var(--s3)}
.icard .card-foot .epic{max-width:52%}
.add-issue{display:block;width:100%;margin-top:var(--s2);padding:var(--s2);
  border:1px dashed var(--line);background:none;border-radius:var(--r-sm);
  color:var(--ink-3);cursor:pointer;font-size:13px}
.add-issue:hover{border-color:var(--accent);color:var(--accent-ink)}

.group{padding-bottom:var(--s3)}
.group.drop-hint{box-shadow:0 0 0 2px var(--accent)}
.group-h{padding:var(--s3) var(--s4) var(--s2);font-size:13px;font-weight:600;color:var(--ink-2)}
.group .add-issue{margin:var(--s2) var(--s4) 0;width:auto}

/* ============ modals + issue panel ============ */
.scrim{position:fixed;inset:0;background:rgba(41,42,46,.4);z-index:60;
  display:grid;place-items:start center;padding:7vh var(--s3) var(--s6);overflow:auto}
.scrim.side{place-items:stretch end;padding:0}
.modal{background:var(--surface);border-radius:var(--r);box-shadow:var(--shadow-lift);width:min(640px,92vw)}
.modal.sm{width:min(440px,92vw)}
/* ---- the issue sheet: two thirds of the screen, anchored right ----
   Laid out the Jira way on the Details screen: the writing down the middle,
   the fields in a column beside it. One switch in the head picks the screen. */
.sheet{display:flex;flex-direction:column;height:100%;background:var(--surface);
  width:67vw;min-width:min(94vw,600px);max-width:1120px;
  box-shadow:var(--shadow-lift)}
.sheet-head{display:flex;align-items:center;gap:var(--s3);flex:none;
  padding:var(--s3) var(--s5);border-bottom:1px solid var(--line)}
.sheet-head .issue-title{flex:1;min-width:0;margin:0;font-size:16px;font-weight:600;
  border-color:transparent;background:none;padding:6px var(--s2)}
.sheet-head .issue-title:hover{border-color:var(--line);background:var(--surface)}
.sheet-body{flex:1;min-height:0;overflow:auto;padding:var(--s5)}
.sheet-foot{display:flex;align-items:center;gap:var(--s2);flex:none;
  padding:var(--s3) var(--s5);border-top:1px solid var(--line)}

/* the two columns. The fields sit in a fixed lane so the writing keeps the rest */
.issue-cols{display:grid;grid-template-columns:minmax(0,1fr) 300px;gap:var(--s5);
  align-items:start}
.col-fields{min-width:0}

/* The writing column is two panes sharing one fixed height, divided by the
   three-way picker. Neither pane is ever taken off screen — only its share
   changes. Both scroll inside themselves, so the sheet never grows a
   scrollbar of its own. */
.sheet-body.panes{overflow:hidden}
.sheet-body.panes .issue-cols{height:100%;align-items:stretch}
.col-main{min-width:0;display:flex;flex-direction:column;min-height:0;gap:var(--s4)}
.col-fields{overflow:auto}
.pane{display:flex;flex-direction:column;min-height:0}

/* description: plain text until it is clicked, so nothing boxes it in */
.desc-view{flex:1;min-height:0;overflow:auto;cursor:text;font-size:14px;
  line-height:1.65;color:var(--ink);padding:2px 0}
.desc-view:hover{background:var(--surface-muted)}
.col-main .desc-box{flex:1;min-height:0;width:100%;resize:none;
  font-size:14px;line-height:1.65}

.pane-chat .chat{flex:1;min-height:70px;overflow:auto;padding-right:var(--s2)}

/* the three shares. Comments keep a real presence in every one of them. */
  
  
  

/* the links screen: the linked issues on the left, Relation Details on the
   right, the two halves given the same room */
.links-cols{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:var(--s5);align-items:start}
.links-wrap{min-width:0}

/* Relation Details. A relation reads as three lines - the card it belongs to,
   the relationship, the issue at the far end - and stays read-only until it is
   clicked open. */
.col-rel{min-width:0}
.rel-of{display:flex;align-items:center;gap:var(--s2);margin-bottom:var(--s2);
  padding-bottom:var(--s2);border-bottom:1px solid var(--line-soft)}
.rel-of .sum{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  font-size:13px;font-weight:600;color:var(--ink)}
.rel-of.pinned .sum{color:var(--accent-ink)}
.rel-none{padding:var(--s2) 0;font-size:13px;color:var(--ink-3)}
.rel-list{display:flex;flex-direction:column;gap:var(--s2)}

/* the hover narrows the column to one row, and a row is a flex box, so it
   needs telling that hidden means hidden */
.rel-row[hidden]{display:none}
.rel-row{display:flex;flex-direction:column;gap:2px;cursor:pointer;
  padding:var(--s2) var(--s3);border:1px solid var(--line);
  border-radius:var(--r-sm);background:var(--surface)}
.rel-row:hover{border-color:var(--accent)}
.rel-row.open{border-color:var(--accent);background:var(--accent-soft)}
.rel-row>span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rel-a,.rel-b{font-size:13px;color:var(--ink)}
.rel-kind{font-size:12px;font-weight:600;color:var(--accent-ink);padding-left:var(--s2)}
/* said in its own words: while the row is pointed at, what was written stands
   in for the three lines and fills the block. Clicking opens it for writing. */
.rel-said{font-size:12px;color:var(--ink-2);padding-left:var(--s2);font-style:italic}
.rel-row.said .rel-said{display:none}
.rel-row.said:not(.open):hover>.rel-a,
.rel-row.said:not(.open):hover>.rel-kind,
.rel-row.said:not(.open):hover>.rel-b{display:none}
.rel-row.said:not(.open):hover .rel-said{display:block;padding-left:0;
  white-space:normal;overflow:visible;color:var(--ink)}

.rel-more{display:flex;flex-direction:column;gap:var(--s2);margin-top:var(--s2);
  padding-top:var(--s2);border-top:1px solid var(--line)}
.rel-more select,.rel-note{width:100%;height:28px;padding:0 var(--s2);font-size:13px}
.rel-more .btn{align-self:flex-end}

@media (max-width:900px){.links-cols{grid-template-columns:minmax(0,1fr)}}
@media (max-width:1000px){
  .sheet{width:94vw}
  .issue-cols{grid-template-columns:minmax(0,1fr)}
}

/* the archived tabbed panel (mobile/issue-tabs.js) still uses these:
   the issue folder — lips flush along the top, sheet below. The sheet's blue
   top edge is what the open lip attaches to. */

/* the open lip is a shade deeper and sits straight on the sheet's blue edge */

/* that edge is what ties the open lip to the sheet below it */

/* the name and the close button share the sheet's first line */

/* chat */

/* The sprint's budget, inline with its name. Plain text until clicked, and
   hovering it drops the per-stage tally underneath. */

/* The sprint page's filters, sitting with the view switch. They stay on one
   line as a unit — if the toolbar runs out of room the whole row wraps around
   them rather than breaking the group in half. */
.filters{display:flex;align-items:center;gap:var(--s2);flex:none;flex-wrap:nowrap}
.filters .colf{flex:none;width:132px;height:32px;font-size:13px;padding:0 var(--s2)}
.sprint-head .head-row{flex-wrap:wrap;row-gap:var(--s2)}

/* backlog folds: shut until clicked, one flat list inside */

/* the backlog with the current sprint parked beside it */

/* no assignee column in here — the panes are narrow enough as it is */

/* the sprint pane's own head: arrows, name and dates, then its budget */

/* Links cards: three zones side by side, each with one job, so a click can
   only ever mean one thing:
     [ effort, summary, assignee ] [ relations ] [ remove ]
   Remove stays quiet until the row is pointed at; its lane is held open either
   way so nothing shifts. */
.links{display:flex;flex-direction:column;gap:var(--s1)}
.lcard{display:flex;align-items:stretch;gap:var(--s1);
  background:var(--surface-sunken);border-radius:var(--r-sm)}
#app:not(.no-tint) .lcard.type-task{background:var(--task-tint)}
#app:not(.no-tint) .lcard.type-bug{background:var(--bug-tint)}
#app:not(.no-tint) .lcard.type-story{background:var(--story-tint)}

.z-open{flex:1;min-width:0;display:flex;align-items:center;gap:var(--s2);
  padding:var(--s2) var(--s2);cursor:pointer;border-radius:var(--r-sm)}
.z-open:hover{background:rgba(41,42,46,.05)}
.z-open.is-self{cursor:default}
.z-open.is-self:hover{background:none}
.z-open .sum{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.z-open .who{display:flex;flex:none}

/* the lane a linked card keeps where the anchor carries its relations zone */
.z-lane{width:28px;flex:none}

/* the relations zone stays visible — it is the only sign a card has any */
.z-rel{width:28px;flex:none;display:grid;place-items:center;padding:0;
  border:0;border-left:1px solid transparent;background:none;cursor:pointer;
  color:var(--line)}
.z-rel:hover{color:var(--accent);background:var(--accent-soft)}
.z-rel.has{color:var(--accent)}
.z-rel.pinned{background:var(--accent-soft);color:var(--accent-ink)}

.z-del{width:26px;flex:none;display:grid;place-items:center;padding:0;
  border:0;background:none;cursor:pointer;color:var(--ink-3);font-size:12px;
  opacity:0;transition:opacity .1s ease}
.lcard:hover .z-del{opacity:1}
.z-del:hover{color:var(--danger)}
.lcard.self{box-shadow:inset 3px 0 0 var(--accent)}

/* the archived tabbed panel (mobile/issue-tabs.js) still uses these:
   the issue folder — lips flush along the top, sheet below. The sheet's blue
   top edge is what the open lip attaches to. */
.folder{display:flex;flex-direction:column;height:100%;width:min(440px,88vw);
  filter:drop-shadow(-4px 0 14px rgba(41,42,46,.20))}
.lips{display:flex;align-items:flex-end;justify-content:flex-end;padding:0;flex:none}
.lip{position:relative;border:0;cursor:pointer;padding:var(--s2) var(--s5) 9px;
  background:var(--lip);color:var(--ink-2);font-size:13px;font-weight:500;
  border-radius:var(--r) var(--r) 0 0}
.lip:hover:not(.on){background:var(--lip-on)}
/* the open lip is a shade deeper and sits straight on the sheet's blue edge */
.lip.on{background:var(--lip-on);color:var(--accent-ink);font-weight:600}
/* that edge is what ties the open lip to the sheet below it */
.panel{flex:1;min-height:0;background:var(--surface);display:flex;flex-direction:column;
  border-top:4px solid var(--lip-on)}
.panel .modal-b{overflow:auto;flex:1}
/* the name and the close button share the sheet's first line */
.sheet-top{display:flex;align-items:flex-start;gap:var(--s3);margin-bottom:var(--s4)}
.sheet-top .issue-title{flex:1;width:auto;margin:0 0 0 calc(var(--s2) * -1)}

/* chat */
.chat{display:flex;flex-direction:column;gap:var(--s4)}
.msg{display:flex;gap:var(--s2)}
.msg .body{min-width:0;flex:1}
.msg .who{display:flex;align-items:baseline;gap:var(--s2);font-size:13px;font-weight:600}
.msg p{margin:2px 0 0;font-size:14px;color:var(--ink-2);overflow-wrap:anywhere}
.chat-new{margin-top:var(--s5);padding-top:var(--s4);border-top:1px solid var(--line-soft)}
.chat-new textarea{width:100%;min-height:70px;resize:vertical}

/* The sprint's budget, inline with its name. Plain text until clicked, and
   hovering it drops the per-stage tally underneath. */
.meter{position:relative;display:flex;align-items:center;gap:var(--s2);font-size:13px}
.budget{display:inline-flex;align-items:center;gap:var(--s1);height:28px;
  padding:0 var(--s2);border:1px solid transparent;border-radius:var(--r-sm);
  background:none;cursor:pointer;color:var(--ink-2);font-size:13px;white-space:nowrap}
.budget:hover{border-color:var(--line);background:var(--surface-muted)}
.budget b{font-size:15px;color:var(--ink)}
.meter.over .budget b{color:var(--danger)}
.meter .pts{width:72px;padding:2px var(--s1);font-size:13px}
.meter .warn{color:var(--danger);font-weight:500;white-space:nowrap}
.meter .pop{position:absolute;top:calc(100% + var(--s1));left:0;z-index:30;display:none;
  min-width:180px;padding:var(--s2) 0;background:var(--surface);
  border:1px solid var(--line);border-radius:var(--r);box-shadow:var(--shadow-lift)}
.meter:hover .pop{display:grid}
.meter .pop .stage{display:flex;align-items:center;gap:var(--s2);
  padding:var(--s1) var(--s3);color:var(--ink-3)}
.meter .pop .stage b{margin-left:auto;color:var(--ink);font-size:13px}

/* backlog folds: shut until clicked, one flat list inside */
.fold-h{display:flex;align-items:center;gap:var(--s2);width:100%;
  padding:var(--s3) var(--s4);border:0;background:none;cursor:pointer;
  font-size:14px;font-weight:600;color:var(--ink-2);text-align:left}
.fold-h:hover{color:var(--accent-ink)}
.fold-h.as-head{cursor:default}
.fold-h.as-head:hover{color:var(--ink-2)}
.fold .caret{color:var(--ink-3);font-size:11px;width:10px}
.fold .list{padding-bottom:var(--s2)}

/* the backlog with the current sprint parked beside it */
.split{display:grid;grid-template-columns:1fr 1fr;gap:var(--s4);align-items:start;
  margin-bottom:var(--s4)}
.split>.box{margin-bottom:0}
/* no assignee column in here — the panes are narrow enough as it is */
.split .rows-backlog .rowhead,.split .rows-backlog .irow,.split .rows-backlog .rowfilters{
  grid-template-columns:28px 30px minmax(0,1fr) 72px 40px}
.split .rows-sprint .rowhead,.split .rows-sprint .irow{
  grid-template-columns:30px minmax(0,1fr) 72px 40px}
.split .epic{max-width:72px}
/* the sprint pane's own head: arrows, name and dates, then its budget */
.pane-h{display:flex;align-items:center;gap:var(--s2);padding:var(--s3) var(--s4) var(--s2)}
.pane-h .which b{font-size:14px}
.pane-h .arrow{width:26px;height:26px}
.pane-h .meter .budget{height:26px}
.pane-h .meter .pop{left:auto;right:0}
.btn.icon{padding:0 var(--s2);color:var(--ink-3)}
.btn.icon:hover{color:var(--accent-ink);border-color:var(--accent)}
[data-drop-sprint].drop-hint{box-shadow:0 0 0 2px var(--accent)}
.drop-err{padding:var(--s3) var(--s4)}
.drop-err .err{margin:0}
.btn.on{background:var(--accent-soft);border-color:var(--accent);color:var(--accent-ink)}

/* the add row: which issue, and what it has to do with this one */
.link-add{margin-top:var(--s2);display:flex;flex-direction:column;gap:var(--s2)}
.link-add select{flex:1;min-width:0;height:28px;font-size:13px}
/* data */
.sec-h{font-size:13px;font-weight:600;color:var(--ink-2);margin:var(--s5) 0 var(--s2)}
.sec-h:first-child{margin-top:0}
.statlist{display:flex;flex-direction:column;gap:var(--s2)}
.stat-row{display:grid;grid-template-columns:24px minmax(0,1fr) 90px 28px;
  align-items:center;gap:var(--s2);font-size:13px}
.stat-row .nm{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ink-2)}
.stat-row .nm.wide{grid-column:1 / 3}
.stat-row b{text-align:right}
.stat-row .avatar.none{border:1px dashed var(--line);background:transparent}
.modal-h{display:flex;align-items:center;gap:var(--s2);padding:var(--s4) var(--s5) var(--s3);
  font-size:16px;font-weight:600;border-bottom:1px solid var(--line-soft)}
.modal-b{padding:var(--s4) var(--s5)}
.modal-f{display:flex;align-items:center;gap:var(--s2);padding:var(--s3) var(--s5);
  border-top:1px solid var(--line-soft)}
.err{color:var(--danger);font-size:13px;margin-bottom:var(--s2)}
.err:empty{display:none}

/* A write that reached the database and failed. It sits under the app bar
   rather than in a dialog, because the dialog has already closed by then. */
.netfail{display:flex;align-items:center;gap:var(--s2);
  padding:var(--s2) var(--s5);background:var(--bug-tint);
  border-bottom:1px solid var(--line);color:var(--danger);font-size:13px;
  position:sticky;top:52px;z-index:19}
.confirm{flex:1;font-size:13px;color:var(--danger)}
.field{margin-bottom:var(--s4)}
.field>label{display:block;font-size:13px;color:var(--ink-2);margin-bottom:var(--s1);font-weight:500}
.field input,.field select,.field textarea{width:100%}
.field textarea{min-height:80px;resize:vertical}

.picks{display:flex;flex-wrap:wrap;gap:var(--s2)}
.pick{display:flex;align-items:center;gap:var(--s2);padding:6px var(--s3);border:1px solid var(--line);
  border-radius:var(--r-sm);cursor:pointer;font-size:14px;color:var(--ink-2)}
.pick:hover{border-color:var(--accent)}
.pick input{position:absolute;opacity:0;pointer-events:none}
.pick:has(input:checked){border-color:var(--accent);background:var(--accent-soft);color:var(--accent-ink)}

.swatches{display:flex;gap:var(--s2);flex-wrap:wrap}
.swatches .sw input{position:absolute;opacity:0;pointer-events:none}
.swatches .sw i{display:block;width:26px;height:26px;border-radius:var(--r-sm);cursor:pointer;
  box-shadow:inset 0 0 0 1px rgba(41,42,46,.12)}
.swatches .sw input:checked+i{box-shadow:0 0 0 2px var(--surface),0 0 0 4px var(--accent)}
.eff-pick i{display:grid;place-items:center;min-width:34px;height:30px;padding:0 var(--s2);
  border:1px solid var(--line);border-radius:var(--r-sm);background:var(--surface);
  font-size:14px;font-weight:500;color:var(--ink-2);cursor:pointer;font-style:normal;box-shadow:none}
.eff-pick i:hover{border-color:var(--accent)}
.eff-pick input:checked+i{background:var(--accent);border-color:var(--accent);color:#fff;box-shadow:none}

input.issue-title{display:block;width:100%;margin:0;
  padding:6px var(--s2);font-size:18px;font-weight:600;line-height:1.4;color:var(--ink);
  background:transparent;border:1px solid transparent;border-radius:var(--r-sm)}
input.issue-title:hover{border-color:var(--line);background:var(--surface-muted)}
input.issue-title:focus{border-color:var(--accent);background:var(--surface);outline:none}
.fieldbox{border:1px solid var(--line);border-radius:var(--r)}
.fieldbox .f{display:grid;grid-template-columns:80px 1fr;gap:var(--s2);align-items:center;
  padding:var(--s2) var(--s3);border-bottom:1px solid var(--line-soft);font-size:13px}
.fieldbox .f:last-child{border-bottom:0}
.fieldbox .f>label{color:var(--ink-3);font-size:13px}
.fieldbox .f select{width:100%}
