/* Cabana design system: oceanic color with human warmth. Deep ink on warm sailcloth surfaces over a
   slate ground, one sea-glass accent used sparingly, and movement that settles rather than announces.
   Tokens first, then primitives (type, buttons, inputs, badges), then components. */

:root{
  --font:"Inter",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  --mono:"JetBrains Mono",ui-monospace,SFMono-Regular,Menlo,monospace;
  --bg:#cfd8e5;--bg-top:#e1e7f0;--surface:#faf8f4;--surface-2:#eff2f0;--surface-3:#e3e9e8;--track:#c3cdcd;
  --ink:#132330;--ink-2:#2b3d49;--muted:#526270;--faint:#7a8a95;
  --line:#b2bfc0;--line-2:#d1d9d9;--zebra:#f3f5f3;--hover:#e5eeeb;
  --line-strong:#a3b2b4;
  --accent:#237a71;--accent-hover:#1c655e;--accent-soft:#e1f1ed;--accent-soft-hover:#cfe8e1;--accent-ink:#174f49;--accent-line:#a4d6ca;--accent-line-strong:#78c1b2;
  --ok:#1f8a62;--ok-hover:#187452;--ok-soft:#dcf1e5;--ok-ink:#155b40;
  --warn:#d69a2e;--warn-soft:#fbf3e1;--warn-ink:#875913;--warn-line:#efd48c;
  --bad-soft:#fbe8e6;--bad-ink:#94322f;--bad-line:#f2b7b2;
  --violet:#7357c4;--violet-soft:#ece6f9;--violet-ink:#4a3592;--violet-line:#c7b8ee;
  --orange-ink:#8f4712;--orange-soft:#fbe8d6;
  --teal-ink:#186670;
  --blue-ink:#22489a;--blue-soft:#e2e9f7;
  --code-bg:#132330;--code-ink:#dfe7ea;
  /* a ticket row wears its status as a wash; the badge is a stamp in the status ink */
  --tint-backlog:#e8ecec;--tint-todo:var(--surface);--tint-progress:#fbf1dc;--tint-review:#e6def7;--tint-done:#d5ecdf;--tint-canceled:#f4d5d1;
  --ring:color-mix(in srgb,var(--accent) 20%,transparent);--focus:var(--accent);
  --fs-xs:11.5px;--fs-sm:12.5px;--fs-md:13px;--fs:14px;--fs-lg:17px;--fs-xl:22px;
  --r:10px;--r-sm:7px;--r-xs:5px;--r-pill:999px;
  --pencil:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M3 21v-6L15 3l6 6L9 21z'/%3E%3C/svg%3E");
  color-scheme:light;
  --sh-sm:0 1px 2px rgba(19,35,48,.08);--sh:0 1px 3px rgba(19,35,48,.10),0 1px 2px rgba(19,35,48,.06);--sh-lg:0 12px 32px rgba(19,35,48,.16);
}
/* Higher contrast for displays that flatten hairlines (toggle in the header, remembered per browser).
   The row tints deepen for their boundaries, so the stamp inks that sit on them deepen too (measured:
   each clears 4.5 on its tint at rest and on hover, and on --bg, --bg-top and --surface). */
html.hc{--bg:#bcc8da;--bg-top:#d2dbe7;--surface-2:#e8ecea;--surface-3:#d8e0df;--track:#a6b4b5;--line:#8da0a2;--line-2:#afbdbe;--line-strong:#788e91;--zebra:#eef1ef;--hover:#d5e4df;--muted:#3d4f5c;--faint:#5a6c78;--ink-2:#172731;
  --accent-line:#78c1b2;--accent-line-strong:#4fa896;--warn-line:#e2bd58;--bad-line:#e78f8a;--violet-line:#b09ae6;
  --warn-ink:#714a10;--bad-ink:#852d2a;--orange-ink:#814010;--teal-ink:#155b63;
  --tint-backlog:#dae0e1;--tint-progress:#f6e5bf;--tint-review:#d5c8f0;--tint-done:#bfe2cf;--tint-canceled:#eabdb7}
html.hc table.grid th{border-bottom:2px solid var(--line)}
*{box-sizing:border-box}
[hidden]{display:none!important}
html{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}
body{margin:0;font:var(--fs)/1.5 var(--font);color:var(--ink);background:var(--bg) linear-gradient(180deg,var(--bg-top),var(--bg) 480px) no-repeat;font-feature-settings:"cv11","ss01","tnum"}
a{color:var(--accent);text-decoration:none}a:hover{text-decoration:underline}
h1,h2,h3{margin:0;font-weight:600;letter-spacing:-.01em}
h1{font-size:var(--fs-xl);line-height:1.3}
code{font-family:var(--mono);font-size:var(--fs-sm);background:var(--surface-3);padding:1px 5px;border-radius:4px}
.mono{font-family:var(--mono);font-size:var(--fs-sm);word-break:break-all}
.muted{color:var(--muted)}.small{font-size:var(--fs-sm)}.nowrap{white-space:nowrap}
.key{font-family:var(--mono);font-weight:600;font-size:var(--fs-sm);letter-spacing:.01em}

/* ---------------------------------------------------------------- top bar */
header.top{position:sticky;top:0;z-index:20;display:flex;align-items:center;gap:20px;height:56px;padding:0 28px;background:color-mix(in srgb,var(--bg-top) 86%,transparent);backdrop-filter:saturate(180%) blur(12px);border-bottom:1px solid var(--line)}
.brand{display:flex;align-items:center;gap:9px;font-weight:700;color:var(--ink);letter-spacing:-.01em}
.brand:hover{text-decoration:none}
.brand .mark{width:26px;height:26px;border-radius:var(--r-sm);background:var(--accent);color:#fff;display:grid;place-items:center;font-size:var(--fs-md);font-weight:700}
nav{display:flex;align-items:center;gap:2px;flex:1}
nav a{padding:6px 11px;border-radius:var(--r);color:var(--ink-2);font-weight:500}
nav a:hover{text-decoration:none;background:var(--surface-3);color:var(--ink)}
nav a.active{background:var(--accent-soft);color:var(--accent-ink)}
nav a.inbox{display:inline-flex;align-items:center;gap:7px;border:1px solid var(--line);background:var(--surface);padding:6px 12px 6px 10px;border-radius:var(--r-pill);box-shadow:var(--sh-sm)}
nav a.inbox svg{width:15px;height:15px;stroke:currentColor;fill:none;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
nav a.inbox.active{border-color:var(--accent-line);background:var(--accent-soft)}
nav a.gear{width:34px;padding:0;justify-content:center;border-radius:var(--r-pill);color:var(--ink-2)}
nav a.gear svg{width:17px;height:17px;stroke:currentColor;fill:none;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round}
nav a.gear.active{background:var(--accent-soft);border-color:var(--accent-line);color:var(--accent-ink)}
.pill{display:inline-grid;place-items:center;min-width:18px;height:18px;padding:0 6px;border-radius:var(--r);background:var(--accent);color:#fff;font-size:var(--fs-xs);font-weight:600;line-height:1}
.icon-btn{display:inline-flex;align-items:center;gap:6px;height:32px;padding:0 10px;border:1px solid var(--line);border-radius:var(--r-pill);background:var(--surface);color:var(--ink-2);font:inherit;font-size:var(--fs-sm);font-weight:500;cursor:pointer;box-shadow:var(--sh-sm)}
.icon-btn:hover{background:var(--surface-3)}
.icon-btn svg{width:14px;height:14px}
.icon-btn[aria-pressed=true]{background:var(--ink);border-color:var(--ink);color:#fff}
nav .toggle{margin-left:auto}
a.pill:hover{text-decoration:none;background:var(--accent-hover)}

/* ---------------------------------------------------------------- page scaffold */
main{max-width:1280px;margin:0 auto;padding:28px 28px 72px}
footer.bottom{max-width:1280px;margin:0 auto;padding:0 28px 28px;color:var(--muted);font-size:var(--fs-sm);display:flex;gap:14px;flex-wrap:wrap;align-items:center}
footer.bottom a{color:var(--muted);text-decoration:underline;text-decoration-color:var(--line)}
footer.bottom b{color:var(--muted);font-weight:500}
.page-head{display:flex;justify-content:space-between;align-items:flex-start;gap:16px;margin-bottom:18px}
.page-head>div:last-child:not(:first-child){flex:none;display:flex;gap:8px;align-items:center;padding-top:2px}
.page-head h1{margin-bottom:2px}
.intro{color:var(--muted);margin:0;max-width:820px}
.crumb{color:var(--muted);font-size:var(--fs-md)}.crumb:hover{color:var(--ink)}
.crumbs{display:flex;gap:6px;align-items:center;color:var(--faint);font-size:var(--fs-md);margin-bottom:10px}
.card{background:var(--surface);border:1px solid var(--line);border-radius:var(--r);padding:18px 20px;margin-bottom:16px;box-shadow:var(--sh-sm)}
.card h2{font-size:var(--fs-md);font-weight:600;color:var(--ink-2);margin:0 0 12px;display:flex;align-items:center;gap:8px}
.card h2 .muted{font-weight:400}
.card-head{display:flex;justify-content:space-between;align-items:center;gap:12px;margin-bottom:12px}
.card-head h2{margin:0}
.two-col{display:grid;grid-template-columns:minmax(0,1fr) 340px;gap:16px;align-items:start}
.two-col>*{min-width:0}
/* A table wider than the page scrolls inside its holder rather than pushing the document sideways:
   the two-column pages have .main-col, a live list its #results, a settings page its body, and a card
   whose own child is the table. The menus app.js opens hang off <body>, so no holder clips them. */
.main-col,#results,.settings-body,.card:has(>table.grid){overflow-x:auto}
.subnav{display:flex;gap:2px;margin:0 0 16px;border-bottom:1px solid var(--line)}
.subnav a{padding:8px 12px;color:var(--muted);border-bottom:2px solid transparent;margin-bottom:-1px;font-weight:500}
.subnav a.on{color:var(--ink);border-bottom-color:var(--accent)}
.subnav a:hover{text-decoration:none;color:var(--ink)}
.help{background:var(--surface);border:1px solid var(--line);border-left:3px solid var(--accent);border-radius:var(--r-sm);padding:12px 16px;margin-bottom:16px;color:var(--ink-2)}
.help b{color:var(--ink)}
details.help summary{cursor:pointer;font-weight:600;color:var(--ink)}
.flash{background:var(--accent-soft);border:1px solid var(--accent-line);color:var(--accent-ink);padding:10px 14px;border-radius:var(--r-sm);margin-bottom:16px;font-weight:500}
.flash.error{background:var(--bad-soft);border-color:var(--bad-line);color:var(--bad-ink)}
.flash.js{position:fixed;top:68px;right:28px;z-index:30;box-shadow:var(--sh-lg);max-width:420px}
.empty{text-align:center;color:var(--muted);padding:32px 16px}
.stat-row{display:flex;gap:12px;flex-wrap:wrap;margin:0 0 16px}
.stat{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-sm);padding:10px 14px;min-width:120px;box-shadow:var(--sh-sm)}
.stat .v{font-size:20px;font-weight:600;letter-spacing:-.02em}.stat .l{font-size:var(--fs-xs);color:var(--muted);margin-top:2px}
.steps{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:12px;margin:0 0 20px}
.step{background:var(--surface);border:1px solid var(--line);border-radius:var(--r);padding:14px 16px;box-shadow:var(--sh-sm)}
.step .n{display:inline-grid;place-items:center;width:22px;height:22px;border-radius:11px;background:var(--accent-soft);color:var(--accent-ink);font-size:var(--fs-sm);font-weight:700;margin-right:8px}
.step h3{font-size:var(--fs);margin-bottom:6px;display:flex;align-items:center}.step p{margin:0;color:var(--muted);font-size:var(--fs-md)}
.legend{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:8px 20px;margin-top:10px;font-size:var(--fs-md);color:var(--muted)}
.legend b{display:block;color:var(--ink);font-weight:600}

/* ---------------------------------------------------------------- tables */
table.grid{width:100%;border-collapse:separate;border-spacing:0;background:var(--surface);border:1px solid var(--line);border-radius:var(--r);overflow:hidden;box-shadow:var(--sh-sm)}
table.grid th{font-size:var(--fs-xs);font-weight:600;color:var(--muted);text-align:left;padding:10px 14px;border-bottom:1px solid var(--line);background:var(--surface-2);white-space:nowrap}
table.grid td{padding:11px 14px;border-bottom:1px solid var(--line-2);vertical-align:top;font-size:var(--fs-md)}
table.grid th[data-col="key"],table.grid td:has(> .key:only-child){width:1%;white-space:nowrap}
table.grid td .key{white-space:nowrap}
table.grid th[data-col="assignee"],table.grid th[data-col="owner"],table.grid td.col-av{width:1%;text-align:center;white-space:nowrap}
table.grid th[data-col="assignee"]>span,table.grid th[data-col="owner"]>span{justify-content:center}
table.grid th[data-col="target"],table.grid th[data-col="updated"],table.grid td.col-date{width:1%;white-space:nowrap}
table.grid tbody tr:last-child td{border-bottom:0}
table.grid tbody tr:nth-child(even) td{background:var(--zebra)}
table.grid tbody tr:hover td{background:var(--hover)}
table.grid tr.clickable,table.grid tr[data-quick-row],table.grid tr[data-href]{cursor:pointer}
table.grid tr[data-quick-row]:focus-visible,table.grid tr[data-href]:focus-visible{outline:2px solid var(--focus);outline-offset:-2px}
table.grid tr[data-quick-row]:hover td,table.grid tr[data-href]:hover td{background:var(--hover)}
/* a ticket row wears its status (ticket_rows sets tr.st-*): backlog grey, todo plain, and a wash for the rest, a shade deeper on hover; no zebra on these */
table.grid tbody tr.st-backlog{--tint:var(--tint-backlog)}table.grid tbody tr.st-todo{--tint:var(--tint-todo)}table.grid tbody tr.st-in_progress{--tint:var(--tint-progress)}table.grid tbody tr.st-in_review{--tint:var(--tint-review)}table.grid tbody tr.st-done{--tint:var(--tint-done)}table.grid tbody tr.st-canceled{--tint:var(--tint-canceled)}
table.grid tbody tr.st-backlog td,table.grid tbody tr.st-todo td,table.grid tbody tr.st-in_progress td,table.grid tbody tr.st-in_review td,table.grid tbody tr.st-done td,table.grid tbody tr.st-canceled td{background:var(--tint)}
table.grid tbody tr.st-backlog:hover td,table.grid tbody tr.st-todo:hover td,table.grid tbody tr.st-in_progress:hover td,table.grid tbody tr.st-in_review:hover td,table.grid tbody tr.st-done:hover td,table.grid tbody tr.st-canceled:hover td{background:color-mix(in srgb,var(--tint),var(--ink) 7%)}
/* the list's order on the tickets page: every row drags anywhere; a status change slides the row to its place */
tbody[data-sortable] tr[data-quick-row]{cursor:grab}
tr.drag-ghost td{opacity:.35}tr.drag-chosen td{background:var(--hover)}
tbody.moving tr{transition:transform .55s cubic-bezier(.2,.7,.2,1)}
.status-cell{display:flex;flex-direction:column;align-items:flex-start;gap:3px}  /* a div inside the cell: a td that is a flex box stops filling its row */
.btn.xs{height:20px;padding:0 6px;font-size:var(--fs-xs);border-radius:var(--r-xs)}
.btn.archive{color:var(--muted)}.btn.archive:hover{color:var(--ink)}
.btn.armed{border-color:var(--warn);background:var(--warn-soft);color:var(--warn-ink)}
@keyframes pulse{from{background-color:color-mix(in srgb,var(--tint),var(--ink) 18%)}to{background-color:var(--tint)}}
table.grid tbody tr.pulse td{animation:pulse .9s ease-out}
table.grid tbody tr.inactive td{background:var(--surface-3);color:var(--muted)}  /* a person who is no longer active; tbody so it outranks the zebra rule on even rows */
table.grid tbody tr.inactive:hover td{background:color-mix(in srgb,var(--surface-3),var(--ink) 7%)}
table.grid th[draggable=true]{cursor:grab;user-select:none}
table.grid th[draggable=true]::before{content:"";display:inline-block;width:6px;height:10px;margin-right:7px;vertical-align:-1px;opacity:.35;background:radial-gradient(circle,var(--faint) 1px,transparent 1.2px) 0 0/3px 3px}
table.grid th.dragging{opacity:.4}
table.grid th.drop-target{box-shadow:inset 3px 0 0 var(--accent)}
.col-reset{color:var(--muted)}
.results-head .col-reset{margin-left:auto}
.table-tools{display:flex;justify-content:flex-end;margin:0 2px 6px}
/* a button that looks like a link: an in-page action that is not a navigation */
button.link{border:0;background:none;padding:0;font:inherit;color:var(--accent);text-decoration:underline;cursor:pointer}
.kv-table{width:100%;border-collapse:collapse;font-size:var(--fs-sm)}
.kv-table td{padding:5px 8px;border-bottom:1px solid var(--line-2);vertical-align:top}
.kv-table td:first-child{color:var(--muted);white-space:nowrap;width:190px;font-family:var(--mono);font-size:var(--fs-sm)}
.kv-table td.redacted{color:var(--warn-ink);font-style:italic}
.kv{display:grid;grid-template-columns:150px 1fr;gap:6px 14px;font-size:var(--fs-md)}.kv dt{color:var(--muted)}.kv dd{margin:0}

/* ---------------------------------------------------------------- badges */
/* Badges are stamps: the word set as a small uppercase label inside a hairline of its own colour. No
   dot and no pastel ground; the colour is the ink (a status, a priority, a source) and the border follows
   it through currentColor. A ticket row already wears its status as a wash, so on the list the stamp
   is the word in that ink; on a detail page it carries the colour alone. (Steven, 2026-09-21.) */
.badge{display:inline-block;padding:1px 6px;border:1px solid currentColor;border-radius:3px;font-size:var(--fs-xs);font-weight:600;letter-spacing:.07em;text-transform:uppercase;line-height:1.5;color:var(--muted);background:transparent;white-space:nowrap;vertical-align:middle}
.badge.st-todo{color:var(--ink)}.badge.st-in_progress{color:var(--warn-ink)}.badge.st-in_review{color:var(--violet-ink)}.badge.st-done{color:var(--ok-ink)}.badge.st-canceled{color:var(--bad-ink)}
.pr-none{color:var(--muted)}.pr-low{color:var(--muted)}.pr-medium{color:var(--blue-ink)}.pr-high{color:var(--orange-ink)}.pr-urgent{color:var(--bad-ink)}
/* A priority is a filled chip and a source a bare word, so the status stamp (the word in its ink inside a hairline) is the one
   thing on a row wearing a border (Steven, 2026-09-22). The inks above are what the contrast test reads. */
.pr-none,.pr-low,.pr-medium,.pr-high,.pr-urgent,.src-internal,.src-client,.src-pipeline,.src-human{border-color:transparent}
.pr-none,.pr-low{background:var(--surface-3)}.pr-medium{background:var(--blue-soft)}.pr-high{background:var(--orange-soft)}.pr-urgent{background:var(--bad-soft)}
.src-internal{color:var(--ok-ink)}.src-client{color:var(--bad-ink)}.src-pipeline{color:var(--violet-ink)}.src-human{color:var(--muted)}
.act-update{color:var(--blue-ink)}.act-create{color:var(--ok-ink)}.act-status_change{color:var(--warn-ink)}.act-reassign{color:var(--violet-ink)}
.ps-queued{color:var(--warn-ink)}.ps-approved{color:var(--blue-ink)}.ps-rejected{color:var(--muted)}.ps-applied{color:var(--ok-ink)}.ps-failed{color:var(--bad-ink)}.ps-reverted{color:var(--muted)}
.kind-decision{color:var(--blue-ink)}.kind-action_item{color:var(--ok-ink)}.kind-blocker{color:var(--bad-ink)}.kind-status_signal{color:var(--warn-ink)}.kind-owner_mention{color:var(--violet-ink)}
.cat-source,.cat-auth{color:var(--blue-ink)}.cat-model{color:var(--violet-ink)}.cat-embedding{color:var(--teal-ink)}.cat-ticket_system{color:var(--ok-ink)}.cat-escalation{color:var(--orange-ink)}.cat-other{color:var(--muted)}
.out-ok{color:var(--ok-ink)}.out-error{color:var(--bad-ink)}.out-pending{color:var(--warn-ink)}
.cs-done{background:var(--ok-soft);color:var(--ok-ink)}.cs-failed{background:var(--bad-soft);color:var(--bad-ink)}
/* The -ink members carry the text: the base --ok/--warn/--bad are ground and border colours and read at 4.07, 2.32 and 3.83 on a card, all under AA. */
.conf-word{font-weight:600;font-size:var(--fs-sm)}.conf-word.high{color:var(--ok-ink)}.conf-word.medium{color:var(--warn-ink)}.conf-word.low{color:var(--bad-ink)}

/* ---------------------------------------------------------------- buttons, inputs, filters */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;height:32px;padding:0 12px;border:1px solid var(--line);border-radius:var(--r);background:var(--surface);color:var(--ink);cursor:pointer;font:inherit;font-weight:500;line-height:1;white-space:nowrap;flex:none;box-shadow:var(--sh-sm);transition:background .12s,border-color .12s,box-shadow .12s}
.btn:hover{background:var(--surface-3);text-decoration:none;border-color:var(--line)}
.btn:active{transform:translateY(.5px)}
.btn.primary{background:var(--accent);border-color:var(--accent);color:#fff}.btn.primary:hover{background:var(--accent-hover);border-color:var(--accent-hover)}
.btn.ok{background:var(--ok);border-color:var(--ok);color:#fff}.btn.ok:hover{background:var(--ok-hover);border-color:var(--ok-hover)}
.btn.danger{color:var(--bad-ink);border-color:var(--bad-line);background:var(--surface)}.btn.danger:hover{background:var(--bad-soft)}
.btn.ghost{border-color:transparent;box-shadow:none;background:transparent}.btn.ghost:hover{background:var(--surface-3)}
.btn.sm{height:27px;padding:0 9px;font-size:var(--fs-sm);border-radius:var(--r-sm)}
.btn svg{width:14px;height:14px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.btn[disabled]{opacity:.5;cursor:default}
input,select,textarea{font:inherit;color:var(--ink);background:var(--surface);border:1px solid var(--line);border-radius:var(--r);padding:0 10px;height:34px;transition:border-color .12s,box-shadow .12s}
textarea{height:auto;padding:8px 10px;width:100%;resize:vertical;line-height:1.5}
input:focus,select:focus,textarea:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--ring)}
select{appearance:none;-webkit-appearance:none;padding-right:28px;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 10px center}
input[disabled]{background:var(--surface-2);color:var(--muted)}
.search{position:relative;display:inline-flex;align-items:center;min-width:280px}
.search svg{position:absolute;left:10px;width:14px;height:14px;stroke:var(--faint);fill:none;stroke-width:2;pointer-events:none}
.search input{padding-left:30px;width:100%}
form.filters{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin:0 0 14px}
form.filters .status-strip{width:100%}
.status-strip{display:inline-flex;gap:2px;padding:3px;background:var(--surface-3);border-radius:var(--r);flex-wrap:wrap;margin-bottom:8px}
.chip{position:relative;display:inline-flex;align-items:center;gap:6px;padding:5px 11px;border:1px solid transparent;border-radius:var(--r-sm);color:var(--muted);font-size:var(--fs-sm);font-weight:500;cursor:pointer;user-select:none;transition:background .12s,color .12s}
/* A tab is a label around a real radio, hidden the way .swatch hides its own: out of sight but in the
   layout, so Tab reaches the group and the arrow keys move through it. */
.chip input{position:absolute;opacity:0;width:1px;height:1px}
.chip:has(input:focus-visible){outline:2px solid var(--focus);outline-offset:2px}
.chip:hover{color:var(--ink);text-decoration:none}
.chip.on{background:var(--surface);color:var(--ink);box-shadow:var(--sh);border:1px solid var(--line)}
.chip b{font-weight:600;color:var(--faint)}.chip.on b{color:var(--accent)}
.stack{display:flex;flex-direction:column;gap:10px}
.stack label{display:flex;flex-direction:column;gap:4px;font-size:var(--fs-sm);color:var(--muted);font-weight:500}
.stack label input,.stack label select,.stack label textarea{font-size:var(--fs-md);color:var(--ink);font-weight:400}
.row{display:flex;gap:8px;align-items:flex-end;flex-wrap:wrap}.inline{display:inline}
.danger-zone{border-color:var(--bad-line)}.danger-zone h2{color:var(--bad-ink)}

/* spacing classes, so a template never carries a margin of its own (style= is for data-driven values only) */
.note{margin:0 0 10px}                /* a short explanation that introduces what follows */
.note.after{margin:10px 0 0}          /* one that follows content */
.card>.note:last-child{margin-bottom:0}
.after{margin-top:10px}               /* a form, a list or a details block that follows other content */
.stack>p{margin:0}                    /* the stack's gap spaces a paragraph */
.page-head .meta-line{margin:6px 0 0}
.quick .meta-line{margin:0 0 6px}
.change .after{margin-top:4px}
.picker-vals .note{margin:6px 10px}
.empty h1{margin-bottom:6px}
.card.narrow{max-width:680px}
.two-col.even{grid-template-columns:1fr 1fr}
.main-col>.progress{margin-bottom:16px}   /* the bar under an epic's title */
input.short{width:180px}input.wide{min-width:260px}
.uppercase{text-transform:uppercase}
.stack label.check{flex-direction:row;align-items:center;gap:8px}.stack label.check input{height:auto}
table.grid td.col-label{width:180px}

/* inline editing */
/* inline editing: .editable says a cell edits in place; the affordance depends on what it holds.
   A text cell and a badge get a dashed underline and a soft ground on hover, an avatar a ring on
   its circle, a bounded field (.field.editable, below) its own border and ring. */
.editable{cursor:text;transition:background .12s,border-color .12s,box-shadow .12s}
.editable:focus-visible{outline:2px solid var(--focus);outline-offset:2px;border-radius:var(--r-xs)}
.editable-text{border-bottom:1px dashed transparent}
.editable-text:hover{border-bottom-color:var(--accent);background:var(--accent-soft)}
.editable-badge:hover{background:var(--accent-soft)}
/* Editable text says so: a pencil after the value on hover or focus. The icon is a mask over the
   text's own colour, and its space is reserved so nothing shifts when it appears. */
.editable-text::after{content:"";display:inline-block;width:11px;height:11px;margin-left:5px;vertical-align:-1px;background:currentColor;opacity:0;-webkit-mask:var(--pencil) center/contain no-repeat;mask:var(--pencil) center/contain no-repeat;transition:opacity .12s ease}
.editable-text:hover::after,.editable-text:focus-visible::after{opacity:.7}
.editable-text.editing::after{display:none}
.editable-badge{cursor:pointer}
.editable-avatar{display:inline-flex;border-radius:var(--r-pill);cursor:pointer}
.editable-avatar:hover .av{box-shadow:0 0 0 3px var(--ring)}
.editable-avatar.editing{display:inline-block}
.editable.editing:not(.menu-open){border-bottom:0;background:transparent;cursor:default}  /* the input path; a cell whose menu is open keeps its badge */
.inline-input{font:inherit;padding:4px 8px;border:1px solid var(--accent);border-radius:var(--r-sm);background:var(--surface);color:var(--ink);box-shadow:0 0 0 3px var(--ring);height:auto}
h1 .inline-input,.inline-title{font-size:var(--fs-xl);font-weight:600;width:100%}
.inline-description{width:100%;font-family:inherit}

/* ---------------------------------------------------------------- content blocks */
.prose p{margin:0 0 8px}.prose ul,.prose ol{margin:0 0 8px 18px;padding:0}.prose h1,.prose h2,.prose h3{font-size:var(--fs);color:var(--ink);margin:12px 0 6px}.prose code{background:var(--surface-3)}.prose table{border-collapse:collapse}.prose td,.prose th{border:1px solid var(--line);padding:3px 6px}
.meta-line{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin:6px 0 16px}
blockquote.evidence{margin:6px 0 0;padding:8px 12px;border-left:3px solid var(--violet);background:var(--violet-soft);color:var(--ink-2);font-style:italic;border-radius:0 var(--r-sm) var(--r-sm) 0}
pre.json,pre.body{background:var(--code-bg);color:var(--code-ink);padding:14px;border-radius:var(--r);overflow:auto;font:var(--fs-sm)/1.55 var(--mono);margin:0;white-space:pre-wrap;word-break:break-word}
pre.body{max-height:320px;transition:max-height .2s}pre.body.expanded{max-height:none}
.body-head{display:flex;justify-content:space-between;align-items:center;margin:12px 0 6px}
.body-head h2{margin:0}
.brief{font:var(--fs-sm)/1.6 var(--mono);white-space:pre-wrap;background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r);padding:14px 16px;color:var(--ink-2)}
.comment-head{display:flex;gap:8px;align-items:center;margin-bottom:4px;flex-wrap:wrap}.comment-head>.remove{margin-left:auto}
ul.timeline{list-style:none;margin:0;padding:0}ul.timeline li{padding:8px 0;border-top:1px solid var(--line-2)}ul.timeline li:first-child{border-top:0;padding-top:0}
ul.plain{list-style:none;margin:0;padding:0}ul.plain li{padding:4px 0}
table.transcript{width:100%;border-collapse:collapse}table.transcript td{padding:5px 8px;vertical-align:top;border-bottom:1px solid var(--line-2)}
table.transcript td.ts{width:76px;font-family:var(--mono);font-size:var(--fs-xs);color:var(--muted)}table.transcript td.spk{width:150px;font-weight:600;color:var(--ink-2)}
table.transcript tr.hl td{background:var(--warn-soft)}table.transcript tr:target td{background:var(--warn-line)}
.context-line{display:grid;grid-template-columns:70px 130px 1fr;gap:8px;padding:5px 0;border-top:1px solid var(--line-2);font-size:var(--fs-md)}
.context-line.hl{background:var(--warn-soft)}.context-line .ts{font-family:var(--mono);color:var(--muted);font-size:var(--fs-xs)}.context-line .spk{font-weight:600}
.cand{display:flex;justify-content:space-between;padding:6px 0;border-top:1px solid var(--line-2)}.cand:first-of-type{border-top:0}
.timeline-bar{display:flex;gap:18px;font-size:var(--fs-sm);color:var(--muted);flex-wrap:wrap}.timeline-bar b{color:var(--ink);font-weight:500}
.original{background:var(--warn-soft);border:1px solid var(--warn-line);border-radius:var(--r-sm);padding:8px 10px;font-size:var(--fs-sm);margin-top:8px}
/* The Complete column on the projects list: the same figure the project page leads with. The flex
   box sits inside the cell rather than being the cell: a td made flex stops being a table cell, no
   longer fills the row's height, and the row's hover shows through around it. */
.complete{display:flex;align-items:center;gap:8px;min-width:120px}
.complete .bar{flex:1;height:6px;border-radius:3px}.complete .bar>span{border-radius:3px}
.complete .n{font-variant-numeric:tabular-nums;color:var(--muted);font-size:var(--fs-sm)}
/* A team as a row of faces, each with a hover box (.tip) naming the person and their role. The
   circles overlap slightly with a rim of the surface between them; the hovered one comes forward. */
.av-stack{display:inline-flex;align-items:center}
.av-stack .tip+.tip{margin-left:-5px}
.av-stack .av{box-shadow:0 0 0 2px var(--surface)}
.av-stack .tip:hover{z-index:2}
.tip{position:relative;display:inline-flex}
.tip::after{content:attr(data-tip);position:absolute;left:50%;bottom:calc(100% + 7px);transform:translateX(-50%);padding:5px 9px;border-radius:var(--r-sm);background:var(--ink);color:var(--surface);font-size:var(--fs-sm);font-weight:500;white-space:nowrap;box-shadow:var(--sh-lg);opacity:0;pointer-events:none;transition:opacity .12s ease;z-index:30}
.tip:hover::after,.tip:focus-within::after{opacity:1}
.who{font-weight:600}

/* change preview */
.change{margin:6px 0 8px;padding:10px 12px;background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r)}
.change-target{font-weight:600;margin-bottom:4px}.change-target .key{margin-right:6px}
.change-diff{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:var(--fs-md)}
.change-diff .arrow{color:var(--faint)}
.change-label{font-size:var(--fs-xs);color:var(--muted);font-weight:600;margin-bottom:4px}
/* the previews render Markdown (`md`, nl2br) like the ticket page, so no pre-wrap: it would double every line break */
.comment-preview{background:var(--surface);border-left:3px solid var(--accent);padding:6px 10px;border-radius:0 var(--r-sm) var(--r-sm) 0}
.ticket-preview{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-sm);padding:8px 10px}
.comment-preview p:last-child,.ticket-preview .prose p:last-child{margin-bottom:0}

/* ---------------------------------------------------------------- review: dense rows */
.call-group{margin-bottom:22px}
.call-group-head{display:flex;justify-content:space-between;align-items:center;padding:0 2px 8px;gap:12px}
.call-group-head .title{font-weight:600;font-size:var(--fs);color:var(--ink)}
.sug-list{background:var(--surface);border:1px solid var(--line);border-radius:var(--r);box-shadow:var(--sh-sm);overflow:hidden}
.sug-row{display:grid;grid-template-columns:96px minmax(0,1fr) 150px auto;gap:14px;align-items:center;padding:10px 14px;border-top:1px solid var(--line-2)}
.sug-row:first-child{border-top:0}
.sug-row:hover{background:var(--hover)}
.sug-row.is-rejected,.sug-row.is-reverted{opacity:.7}
.sug-row.is-failed{background:var(--bad-soft)}
.sug-main{min-width:0}
.sug-line1{display:flex;gap:8px;align-items:baseline;flex-wrap:wrap;line-height:1.35}
.sug-title{font-weight:600;color:var(--ink)}
.sug-delta{color:var(--ink-2);font-size:var(--fs-md);display:inline-flex;gap:6px;align-items:center;flex-wrap:wrap}
.sug-delta .arrow{color:var(--faint)}
.sug-quote{font-size:var(--fs-sm);color:var(--muted);margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sug-quote em{color:var(--ink-2)}
.sug-stat{font-size:var(--fs-sm);color:var(--muted);line-height:1.35}
.sug-stat .badge{margin-bottom:2px}
.sug-actions{display:flex;gap:6px;justify-content:flex-end;flex-wrap:wrap}
.sug-actions form{display:inline}

/* ---------------------------------------------------------------- activity: trace timeline */
.trace{position:relative;padding-left:34px}
.trace::before{content:"";position:absolute;left:11px;top:6px;bottom:6px;width:2px;background:var(--line)}
.trace-step{position:relative;margin-bottom:18px}
.trace-step .dot{position:absolute;left:-34px;top:2px;width:24px;height:24px;border-radius:12px;background:var(--surface);border:2px solid var(--line);display:grid;place-items:center;font-size:var(--fs-xs);font-weight:700;color:var(--muted)}
.trace-step.done .dot{border-color:var(--ok);color:var(--ok)}
.trace-step h3{font-size:var(--fs);margin-bottom:2px}
.trace-step .blurb{color:var(--muted);font-size:var(--fs-sm);margin:0 0 8px}
.trace-step .pending{color:var(--faint);font-size:var(--fs-sm)}
.req-list{display:flex;flex-direction:column;gap:4px;margin:0 0 8px}
.req-line{display:flex;gap:10px;align-items:center;font-size:var(--fs-sm);padding:6px 10px;background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r-sm)}
.req-line .mono{flex:1;color:var(--muted)}
.sub-list{display:flex;flex-direction:column;gap:3px}
.sub-line{display:flex;gap:10px;align-items:baseline;font-size:var(--fs-md);padding:4px 0;border-top:1px solid var(--line-2)}
.sub-line:first-child{border-top:0}
.sub-line .grow{flex:1;min-width:0}
.gate{font-size:var(--fs-sm);color:var(--muted)}
.call-block{border:1px solid var(--line);border-radius:var(--r);padding:16px 18px;margin-bottom:14px;background:var(--surface)}
.call-block-head{display:flex;justify-content:space-between;align-items:center;gap:12px;margin-bottom:12px}


/* ---------------------------------------------------------------- home, epics, team */
.progress{display:flex;align-items:center;gap:10px;font-size:var(--fs-sm);color:var(--muted)}
/* One progress bar for every page: a track that stays visible on white cards and on the page ground
   (--track sits well below both; the inset ring marks the edge), and a filled span sized by the template. */
.bar{height:8px;background:var(--track);border-radius:4px;overflow:hidden;box-shadow:inset 0 0 0 1px var(--line)}
.bar>span{display:block;height:100%;background:var(--accent);border-radius:4px}
.progress .bar{flex:1}
/* The project page. The head names the project and who is on it; `standing` is the progress block,
   where a piece's bar is drawn to its share of the project so width reads as size and fill as
   progress. `queue-strip` is an access point to Review, deliberately not a list of suggestions. */
.project-head .page-head{margin:0}
.project-head .page-head .key{font-size:var(--fs-sm);letter-spacing:.06em}
.project-head .goal{margin:10px 0 0;font-size:var(--fs);max-width:62ch}
/* A grid, not a wrapped row: as many equal columns as fit, so the people line up whatever the width. */
.roster{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:12px 18px;margin-top:14px;padding-top:14px;border-top:1px solid var(--line-2);align-items:start}
/* The circle labels the name, so it aligns to the name's line rather than centring on the two-line
   block, where it reads as sitting a half-line low. */
.roster-person{display:flex;align-items:flex-start;gap:7px;color:inherit}
.roster-person a{color:inherit;text-decoration:none}
.roster-person a:hover b{text-decoration:underline}
.roster-who{display:flex;flex-direction:column;line-height:1.3;min-width:0}
.roster-who b{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.roster-remove{opacity:0;transition:opacity .12s ease;margin-left:2px}
.roster-person:hover .roster-remove,.roster-remove:focus-within{opacity:1}
/* .icon-btn is a 32px pill with side padding; this one is a bare 20px circle, so the padding goes
   or the 14px icon has no room and never shows. */
.roster-remove .icon-btn{width:20px;height:20px;padding:0;justify-content:center;color:var(--muted);box-shadow:none}
.roster-remove .icon-btn svg{width:12px;height:12px;stroke:currentColor;fill:none;stroke-width:2.4;stroke-linecap:round}
.roster-remove .icon-btn:hover{color:var(--bad-ink);border-color:var(--bad-line);background:var(--bad-soft)}
.roster-remove.confirming{opacity:1}
.roster-add{align-self:center;justify-self:start}
.row-foot .roster-add{margin:0}
/* The figure, the bar and the button share one line: the bar centres on the percentage's own line and
   the note sits under it beside "complete", so nothing floats between rows. */
.headline-progress{display:flex;align-items:flex-start;gap:18px;margin-bottom:6px}
.headline-progress .grow .bar.lg{margin-top:6px}
.headline-progress .figure{display:flex;flex-direction:column;align-items:flex-start;line-height:1.1}
.headline-progress .figure b{font-size:var(--fs-xl);font-weight:700}
.headline-progress .grow{flex:1;min-width:0}
.headline-progress>.btn{flex:none;align-self:flex-start;margin-top:-2px}
.bar.lg{height:12px;border-radius:6px}.bar.lg>span{border-radius:6px}
.breakdown{display:flex;flex-direction:column;margin-top:6px}
.piece{padding:12px 0;border-top:1px solid var(--line-2)}
.piece-head{display:flex;align-items:center;justify-content:space-between;gap:12px;font-size:var(--fs-md)}
.piece-name{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.piece-meta{display:flex;align-items:center;gap:8px;flex:none}
.piece-meta .n{font-variant-numeric:tabular-nums;color:var(--muted)}
/* Width is data-driven (the share), so the track needs a floor or a one-ticket piece disappears. */
.piece-bar{margin-top:7px;min-width:44px;max-width:100%}
.piece-bar .bar{height:7px;border-radius:4px}
.piece.loose .piece-bar .bar>span{background:var(--muted)}
.piece-note{margin:6px 0 0;max-width:70ch}
/* The project page's rows: a <details> per section, full width, its summary a heading and a chevron.
   Native, so the keyboard and no-JavaScript both work. */
.row-section{padding:0}
.row-section>summary{display:flex;align-items:baseline;gap:12px;padding:14px 18px;cursor:pointer;list-style:none}
.row-section>summary::-webkit-details-marker{display:none}
.row-section>summary::before{content:"";width:8px;height:8px;border-right:2px solid var(--muted);border-bottom:2px solid var(--muted);transform:rotate(-45deg);align-self:center;margin-right:2px;transition:transform .15s ease;flex:none}
.row-section[open]>summary::before{transform:rotate(45deg)}
.row-section>summary h2{margin:0;font-size:var(--fs);}
.row-section>summary:hover{background:var(--hover)}
.row-section[open]>summary{border-bottom:1px solid var(--line-2)}
.row-section .row-body{padding:14px 18px 18px}
.row-section .row-body .narrow{max-width:520px}
.row-foot{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-top:14px;padding-top:14px;border-top:1px solid var(--line-2)}
/* Manage epics: what exists, for reference above the form that adds the next one. */
.epic-refs{list-style:none;margin:0 0 16px;padding:0;display:flex;flex-direction:column;gap:6px}
.epic-refs li{font-size:var(--fs-md);min-width:0}
.epic-refs .n{margin-left:auto;color:var(--muted);font-variant-numeric:tabular-nums}
/* Each epic is a bordered row with a chevron, so it reads as expandable at a glance; open, it gets a
   deeper ground and a stronger edge. Inside, an editable value carries its underline and pencil at rest,
   not only on hover, and Remove is a button in the bad ink. */
.epic-item{border:1px solid var(--line);border-radius:var(--r-sm);background:var(--surface)}
.epic-item>summary{display:flex;align-items:center;gap:8px;padding:8px 10px;cursor:pointer;list-style:none}
.epic-item>summary::-webkit-details-marker{display:none}
.epic-item>summary::before{content:"";width:7px;height:7px;border-right:2px solid var(--muted);border-bottom:2px solid var(--muted);transform:rotate(-45deg);flex:none;margin:0 4px 0 2px;transition:transform .15s ease}
.epic-item[open]>summary::before{transform:rotate(45deg)}
.epic-item>summary:hover{background:var(--hover)}
.epic-item>summary b{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.epic-item[open]{border-color:var(--line-strong);box-shadow:var(--sh-sm)}
.epic-item[open]>summary{background:var(--surface-3);border-bottom:1px solid var(--line)}
.epic-body{display:flex;flex-direction:column;gap:10px;padding:12px 12px 14px 29px}
.epic-body .editable-text{border-bottom-color:var(--line-strong)}
.epic-body .editable-text::after{opacity:.55}
.epic-body .editable-text:hover::after,.epic-body .editable-text:focus-visible::after{opacity:1}
.epic-body .epic-remove{align-self:flex-start;margin-top:4px}
.epic-body .epic-remove .btn{color:var(--bad-ink);border-color:var(--bad-line)}
.row-foot>a:last-child{margin-left:auto}
.epic-list{display:flex;flex-direction:column}
.epic-line{display:grid;grid-template-columns:minmax(0,1fr) auto;grid-template-areas:"title count" "meta bar";gap:6px 12px;align-items:center;font-size:var(--fs-md);padding:9px 0;border-top:1px solid var(--line-2)}
.epic-line:first-child{border-top:0;padding-top:2px}
.epic-title{grid-area:title;font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.epic-line .n{grid-area:count}
.epic-meta{grid-area:meta;display:flex;align-items:center;gap:7px;white-space:nowrap}
.epic-line .bar{grid-area:bar;width:88px;height:6px;border-radius:3px}
.epic-line .n{text-align:right;color:var(--muted);font-size:var(--fs-sm);font-variant-numeric:tabular-nums}
/* people: initials in their own color, the same circle everywhere */
.av{display:inline-grid;place-items:center;width:26px;height:26px;border-radius:50%;background:var(--av,var(--surface-3));border:1px solid color-mix(in srgb,var(--ink) 38%,transparent);color:#fff;-webkit-text-stroke:1.3px color-mix(in srgb,var(--ink) 72%,transparent);paint-order:stroke fill;text-shadow:0 0 1px color-mix(in srgb,var(--ink) 30%,transparent);font-size:10.5px;font-weight:700;letter-spacing:.03em;line-height:1;flex:none;vertical-align:middle;font-family:var(--font)}
.av.sm{width:20px;height:20px;font-size:8.5px}
.av.lg{width:36px;height:36px;font-size:var(--fs)}
.av.none{background:transparent;border:1.5px dashed var(--faint)}  /* its own border: no ring */
.av-name{display:inline-flex;align-items:center;gap:7px;vertical-align:middle;min-width:0}
.av-name>span:last-child{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
a.av-link{color:var(--ink);font-weight:600}a.av-link:hover{text-decoration:none;color:var(--accent-ink)}
h1.av-name{gap:10px}
.swatches{border:0;padding:0;margin:0;display:flex;flex-wrap:wrap;gap:8px}
.swatches legend{font-size:var(--fs-sm);color:var(--muted);font-weight:500;padding:0;margin-bottom:6px;width:100%}
.swatch{position:relative;cursor:pointer}
.swatch input{position:absolute;opacity:0;width:1px;height:1px}
.swatch input:checked+.av{box-shadow:0 0 0 2px var(--surface),0 0 0 4px var(--av)}
.swatch input:focus-visible+.av{outline:2px solid var(--focus);outline-offset:3px}
.section-title{font-size:var(--fs-md);font-weight:600;color:var(--ink-2);margin:8px 0 10px;display:flex;align-items:center;gap:8px}
.section-title .muted{font-weight:400}


/* ---------------------------------------------------------------- home tiles */
.tile{background:var(--surface);border:1px solid var(--line);border-radius:var(--r);box-shadow:var(--sh-sm);margin-bottom:18px;overflow:hidden}
.tile-head{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center;gap:16px;padding:18px 22px 14px;border-bottom:1px solid var(--line-2)}
.tile-head h2{font-size:18px;font-weight:600;color:var(--ink);margin:0 0 4px;display:flex;align-items:baseline;gap:10px}
.tile-head .goal{flex:1 1 100%;margin:4px 0 0 44px;color:var(--muted);font-size:var(--fs-md);max-width:900px}
.tile-actions{display:flex;gap:8px;flex:none}
.tile-grid{display:grid;grid-template-columns:1.2fr 1fr 1.3fr 1.5fr;gap:0}
.tile-col{padding:16px 20px;border-left:1px solid var(--line-2);min-width:0}
.tile-col:first-child{border-left:0}
.tile-col h3{font-size:var(--fs-sm);font-weight:600;color:var(--muted);text-transform:uppercase;letter-spacing:.5px;margin:0 0 10px;display:flex;justify-content:space-between;align-items:center}
.tile-col h3 a{font-weight:500;text-transform:none;letter-spacing:0;font-size:var(--fs-sm)}
.tile-foot{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:10px 22px;border-top:1px solid var(--line-2);background:var(--surface-2);font-size:var(--fs-sm);color:var(--muted);flex-wrap:wrap}
.tile-foot details{flex:1 1 100%}
.mini-list{display:flex;flex-direction:column;gap:8px;font-size:var(--fs-md)}
.member-line{display:flex;justify-content:space-between;gap:8px;font-size:var(--fs-md)}
.member-line .muted{font-size:var(--fs-sm)}
.member-line>.muted:last-child{white-space:nowrap;flex:none}
.event-line{font-size:var(--fs-sm);color:var(--ink-2);line-height:1.4}
.event-line .when{color:var(--faint);font-size:var(--fs-xs)}
.sug-mini{display:flex;gap:8px;align-items:center;font-size:var(--fs-md);min-width:0}
.sug-mini a{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.proj-chip{display:inline-flex;align-items:center;gap:4px;padding:1px 7px;border-radius:var(--r-xs);background:var(--surface-3);color:var(--ink-2);font-size:var(--fs-xs);font-weight:600;font-family:var(--mono)}
a.proj-chip:hover{text-decoration:none;background:var(--accent-soft);color:var(--accent-ink)}

/* ---------------------------------------------------------------- settings */
.settings{display:grid;grid-template-columns:220px minmax(0,1fr);gap:24px;align-items:start}
.settings-nav{display:block;position:sticky;top:76px;background:var(--surface);border:1px solid var(--line);border-radius:var(--r);padding:8px;box-shadow:var(--sh-sm)}
.settings-nav a{display:block;padding:8px 12px;border-radius:var(--r-sm);color:var(--ink-2);font-weight:500}
.settings-nav a:hover{background:var(--surface-3);text-decoration:none}
.settings-nav a.on{background:var(--accent-soft);color:var(--accent-ink)}
.settings-nav .group{font-size:var(--fs-xs);text-transform:uppercase;letter-spacing:.5px;color:var(--faint);padding:10px 12px 4px}
.settings-body>.page-head:first-child{margin-top:0}


/* collapsible tiles */
.tile-summary{color:var(--muted);font-size:var(--fs-md);font-weight:400}
.tile-body{display:block}
.tile.collapsed .tile-body{display:none}
.tile.collapsed .tile-head{border-bottom:0}
.tile-toggle{width:32px;padding:0;justify-content:center}
.tile-toggle svg{width:14px;height:14px;stroke:currentColor;fill:none;stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round;transition:transform .15s}
.tile.collapsed .tile-toggle svg{transform:rotate(-90deg)}
.tile-body .progress{padding:14px 22px;max-width:460px}
.tile-body .tile-grid{border-top:1px solid var(--line-2)}
.tiles-controls{display:flex;gap:10px;align-items:center;font-size:var(--fs-sm);color:var(--muted);margin:0 0 10px}
.tiles-controls .link{color:var(--muted);text-decoration-color:var(--line)}
.inline-form{display:flex;gap:8px;flex-wrap:wrap;align-items:flex-end}
.inline-form label{display:flex;flex-direction:column;gap:4px;font-size:var(--fs-sm);color:var(--muted);font-weight:500}
.inline-form label input{font-size:var(--fs-md);color:var(--ink);font-weight:400;min-width:180px}


/* ---------------------------------------------------------------- ticket list: filter bar, picker, chips */
.filter-bar{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin:0 0 14px;position:relative}
.filter-bar .search{margin-left:auto}
.picker{position:relative}
.picker>summary{list-style:none}
.picker>summary::-webkit-details-marker{display:none}
.picker[open]>summary{background:var(--accent-soft);border-color:var(--accent-line);color:var(--accent-ink)}
.picker-panel{position:absolute;top:calc(100% + 6px);left:0;z-index:25;display:grid;grid-template-columns:150px minmax(260px,320px);background:var(--surface);border:1px solid var(--line);border-radius:var(--r);box-shadow:var(--sh-lg);overflow:hidden}
.picker-dims{display:flex;flex-direction:column;padding:6px;border-right:1px solid var(--line);background:var(--surface-2)}
.picker-dims button{display:flex;justify-content:space-between;align-items:center;gap:8px;padding:7px 10px;border:0;border-radius:var(--r-sm);background:transparent;color:var(--ink-2);font:inherit;font-size:var(--fs-md);font-weight:500;text-align:left;cursor:pointer}
.picker-dims button:hover{background:var(--surface-3);color:var(--ink)}
.picker-dims button.on{background:var(--surface);color:var(--ink);box-shadow:var(--sh);border:1px solid var(--line);padding:6px 9px}
.picker-dims .pill{background:var(--accent);min-width:18px}
.picker-vals{padding:8px 6px;max-height:360px;overflow:auto}
.picker-vals-head{display:flex;justify-content:space-between;align-items:baseline;gap:8px;padding:4px 10px 8px;font-size:var(--fs-sm);font-weight:600;color:var(--ink-2)}
.picker-vals .opt{display:flex;align-items:center;gap:9px;padding:6px 10px;border-radius:var(--r-sm);cursor:pointer;font-size:var(--fs-md);color:var(--ink)}
.picker-vals .opt:hover{background:var(--surface-3)}
.picker-vals .opt input{width:15px;height:15px;margin:0;accent-color:var(--accent);flex:none}
.picker-vals .opt .opt-text{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.picker-vals .opt .hint{color:var(--faint);font-size:var(--fs-xs);white-space:nowrap}
.picker-vals .range{display:flex;flex-direction:column;gap:6px;padding:10px 10px 4px;border-top:1px solid var(--line-2);margin-top:6px}
.picker-vals .range label{display:flex;align-items:center;justify-content:space-between;gap:8px;font-size:var(--fs-sm);color:var(--muted)}
.picker-vals .range input{height:30px;font-size:var(--fs-sm);width:160px}
.chips{display:flex;gap:6px;flex-wrap:wrap;align-items:center}
.fchip{display:inline-flex;align-items:stretch;border:1px solid var(--accent-line);border-radius:var(--r);background:var(--accent-soft);color:var(--accent-ink);font-size:var(--fs-sm);overflow:hidden;box-shadow:var(--sh-sm)}
.fchip button{border:0;background:transparent;color:inherit;font:inherit;cursor:pointer;padding:5px 8px;display:inline-flex;align-items:center;gap:5px;max-width:420px}
.fchip button>span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fchip button:hover{background:var(--accent-soft-hover)}
.fchip b{font-weight:600}
.fchip b::after{content:":"}
.fchip .x{padding:0 8px;border-left:1px solid var(--accent-line);font-size:15px;line-height:1}
.fchip .x:hover{background:var(--accent-line)}
.clear-all{color:var(--muted);text-decoration:underline;text-decoration-color:var(--line)}
.results-head{display:flex;gap:10px;align-items:baseline;margin:0 2px 8px;font-size:var(--fs-md);color:var(--ink-2)}
.results-head .count b{font-weight:600;color:var(--ink)}

/* sortable headings */
table.grid th.sortable{cursor:pointer}
table.grid th.sortable>span{display:inline-flex;align-items:center;gap:4px}
table.grid th.sortable>span::after{content:"";width:0;height:0;border-left:4px solid transparent;border-right:4px solid transparent;border-top:5px solid var(--faint);opacity:0;transition:opacity .12s}
table.grid th.sortable:hover>span::after{opacity:.5}
table.grid th.sorted>span{color:var(--accent-ink)}
table.grid th.sorted>span::after{opacity:1;border-top-color:var(--accent)}
table.grid th.sorted.asc>span::after{border-top:0;border-bottom:5px solid var(--accent)}
table.grid th.sortable:focus-visible{outline:2px solid var(--focus);outline-offset:-2px}
table.grid th[draggable=true].sortable{cursor:pointer}

/* target dates: a calm cue, never an alarm */
.target{white-space:nowrap;font-variant-numeric:tabular-nums}
.target.past{color:var(--warn-ink);font-weight:500}
.target.past::before{content:"";display:inline-block;width:6px;height:6px;border-radius:3px;background:var(--warn);margin-right:6px;vertical-align:1px}
.target-wrap{display:inline-flex;gap:5px;align-items:baseline}
input.inline-target_date{height:28px;padding:2px 6px;font-size:var(--fs-sm)}

/* ---------------------------------------------------------------- fields: bounded text areas on ticket views
   A label sits above, the box marks exactly where the text (and the click-to-edit area) is. */
.field{display:block;border:1px solid var(--line-strong);border-radius:var(--r);padding:10px 13px;background:var(--surface);margin:0;transition:border-color .12s,background .12s,box-shadow .12s}
.field.editable{cursor:text;border-bottom:1px solid var(--line-strong)}
.field.editable:hover{border-color:var(--accent-line-strong);background:var(--accent-soft);border-bottom-color:var(--accent-line-strong);box-shadow:0 0 0 3px var(--ring)}
.field.editing{padding:0;border-color:transparent;background:transparent;box-shadow:none}
.field.static{background:var(--surface-2);cursor:default}
h1.field{padding:8px 13px;line-height:1.35}
h2.field.quick-title{margin:2px 0 10px}
.field.prose p:last-child,.field.prose ul:last-child,.field.prose ol:last-child{margin-bottom:0}
ul.timeline.field li{padding:6px 0}
.comment{border:1px solid var(--line-strong);border-radius:var(--r);padding:10px 13px;margin:0 0 8px;background:var(--surface)}
.comment.from-pipeline{background:var(--violet-soft);border-color:var(--violet-line)}

/* ---------------------------------------------------------------- @mentions */
.mention{display:inline-block;padding:0 6px;border-radius:var(--r-sm);background:var(--accent-soft);color:var(--accent-ink);font-weight:600;text-decoration:none;line-height:1.5}
a.mention:hover{text-decoration:none;background:var(--accent-soft-hover)}
/* the app's own menu: the option list under an editable cell and the @mention picker */
.menu{position:absolute;z-index:40;min-width:180px;background:var(--surface);border:1px solid var(--line);border-radius:var(--r);box-shadow:var(--sh-lg);padding:5px;max-height:280px;overflow:auto}
.menu-row{display:flex;align-items:center;gap:9px;padding:6px 9px;border-radius:var(--r-sm);cursor:pointer;font-size:var(--fs-md);white-space:nowrap}
.menu-row.on,.menu-row:hover{background:var(--accent-soft)}
.menu-row b{font-weight:600}
.menu-row .muted{font-size:var(--fs-sm)}
.menu-row .badge{pointer-events:none}
.menu-tick{margin-left:auto;padding-left:12px;color:var(--accent);font-weight:600}
/* A second look before an irreversible post (form[data-confirm]): a small box beside the button. It never
   outgrows the viewport: the question wraps, the buttons (.btn is flex:none) keep their width. */
.popover{position:absolute;z-index:40;display:flex;align-items:center;gap:10px;padding:9px 12px;background:var(--surface);border:1px solid var(--line);border-radius:var(--r);box-shadow:var(--sh-lg);font-size:var(--fs-md);white-space:normal;max-width:min(360px,calc(100vw - 32px))}
.editable.menu-open{outline:2px solid var(--focus);outline-offset:2px;border-radius:var(--r-xs)}  /* the cell a menu is open under */

/* ---------------------------------------------------------------- modal: quick view and create forms */
dialog.modal{border:0;padding:0;background:transparent;width:min(880px,94vw);max-width:none;max-height:none;overflow:visible;color:var(--ink)}
dialog.modal::backdrop{background:color-mix(in srgb,var(--ink) 42%,transparent);backdrop-filter:blur(2px)}
dialog.modal .flash.js{position:absolute;top:12px;right:12px;left:auto;z-index:2}
.modal-body{background:var(--surface);border:1px solid var(--line);border-radius:14px;box-shadow:var(--sh-lg);max-height:88vh;overflow:auto;overscroll-behavior:contain;padding:18px 24px 24px}
html:has(dialog.modal[open]){overflow:hidden} /* the page stays put while a modal is open; the modal body scrolls on its own */
.modal-body:empty{display:none}
.modal-head{display:flex;justify-content:space-between;align-items:center;gap:12px;margin-bottom:8px}
.modal-title{font-size:var(--fs-lg);font-weight:600;margin:0}
.modal-crumbs{display:flex;gap:8px;align-items:baseline;flex-wrap:wrap}
.modal-actions{display:flex;gap:8px;align-items:center;flex:none}
.modal-close{width:32px;padding:0;justify-content:center;font-size:20px;line-height:1}
.quick-title{font-size:19px;font-weight:600;line-height:1.3;margin:2px 0 8px;letter-spacing:-.01em}
/* The ticket, on its page and in the quick view: one head, then the same rows (_components.html). */
.ticket-head .page-head{margin:0 0 8px}.ticket-head .page-head .key{display:block;font-size:var(--fs-sm);letter-spacing:.06em;margin-bottom:4px}
.ticket-head h1{display:inline-block;padding:2px 4px;margin:0 -4px;border-radius:var(--r-xs)}
.quick .meta-line.where,.ticket-head .meta-line.where{gap:14px;margin:0}.ticket-head .meta-line{margin:8px 0 0}
.where-item{display:inline-flex;gap:5px;align-items:baseline}.where-item .editable-text{padding:0 2px;border-radius:var(--r-xs)}
.quick .quick-title{display:inline-block;padding:2px 4px;margin:2px -4px 6px;border-radius:var(--r-xs)}
.quick .meta-line.where{margin-bottom:14px}
.quick .card{box-shadow:none;margin-bottom:10px}.quick .card:last-child{margin-bottom:0}
/* A record's own actions (archive, delete) read as buttons on their grounds; the list's archive control stays bare so it wears its row. */
.record-actions{display:flex;gap:6px;align-items:center}.record-actions.modal-foot{justify-content:flex-end;margin-top:14px}
.record-actions .btn.archive{background:var(--surface-3)}.record-actions .btn.archive:hover{background:var(--track)}
.btn.danger-text{color:var(--bad-ink)}.record-actions .btn.danger-text{background:var(--bad-soft)}.record-actions .btn.danger-text:hover{background:var(--tint-canceled)}
.ticket-head .meta-line:not(.where),.quick .meta-line:not(.where){gap:18px}
.quick-field{display:flex;flex-direction:column;gap:3px;font-size:var(--fs-sm)}
.quick-field .editable{align-self:flex-start;font-size:var(--fs-md);color:var(--ink);font-weight:500;padding:1px 0}
.create-form .row>label{flex:1 1 140px}
.form-actions{align-items:center;margin-top:4px}
.form-error{background:var(--bad-soft);border:1px solid var(--bad-line);color:var(--bad-ink);padding:8px 12px;border-radius:var(--r-sm);font-size:var(--fs-md)}


/* ---------------------------------------------------------------- three widths
   Wide (to 1100px): the home tile's four columns become two. Medium (to 900px): two-column pages
   stack, the review row and the settings sidebar too. Narrow (to 640px): one column everywhere, the
   header wraps, the page loses its margins, and a table becomes its own scroll box. Above 640px the
   holder is what scrolls a wide table (`.main-col` and the rule beside it), at every width. */
@media(max-width:1100px){.tile-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.tile-col:nth-child(3){border-left:0}.tile-col:nth-child(n+3){border-top:1px solid var(--line-2)}}
@media(max-width:900px){
  .two-col{grid-template-columns:1fr}
  .sug-row{grid-template-columns:1fr;gap:8px}.sug-actions{justify-content:flex-start}
  .settings{grid-template-columns:minmax(0,1fr)}.settings-nav{position:static}
}
@media(max-width:640px){
  header.top{height:auto;flex-wrap:wrap;gap:8px 12px;padding:8px 14px}nav{flex-wrap:wrap;gap:4px}
  main{padding:16px 14px 48px}footer.bottom{padding:0 14px 20px}
  .tile-grid{grid-template-columns:1fr}.tile-col{border-left:0;border-top:1px solid var(--line-2)}.tile-col:first-child{border-top:0}
  .modal-body{padding:14px 16px 18px}
  .picker-panel{grid-template-columns:1fr;width:min(92vw,360px)}.picker-dims{flex-direction:row;flex-wrap:wrap;border-right:0;border-bottom:1px solid var(--line)}
  table.grid{display:block;overflow-x:auto;-webkit-overflow-scrolling:touch}
}

/* ---------------------------------------------------------------- quiet movement
   Things settle rather than appear: a refreshed list, the modal. Off when the system asks for less motion. */
@keyframes settle{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
@keyframes fade{from{opacity:0}to{opacity:1}}
.settle{animation:settle .22s ease-out}
dialog.modal[open] .modal-body{animation:settle .18s ease-out}
dialog.modal[open]::backdrop{animation:fade .18s ease-out}
@media(prefers-reduced-motion:reduce){*,*::before,*::after{animation-duration:0s!important;transition-duration:0s!important}}

/* The login page: one card in the middle of an otherwise empty page (login.html, E1). */
.login{max-width:420px;margin:56px auto 0}
.login h1{margin:0 0 6px}
.login input{width:100%;box-sizing:border-box}
.top nav .me{display:inline-flex;align-items:center;padding:0 2px}
.top nav .me .av{width:26px;height:26px;font-size:11px}
.top nav .signout{display:inline-flex;margin:0}

/* a short numeric input in an inline form (the token form's days) */
.inline-form input.narrow{width:6em}
#tokens h3.others{margin-top:14px}
