:root{
  /* E42 — the density scale. Dimensions and var() references only:
     every colour remains an Astryx token, so themes and theme: overrides
     pass through untouched. */
  --dj-text-ui:13px;          /* operating text: cells, card titles, menu items, inputs, buttons */
  --dj-text-ui-2:12.5px;      /* secondary operating text: rail labels, quiet empty lines, hints */
  --dj-text-meta:11.5px;      /* metadata: counts, timestamps, badge/chip text, kbd hints */
  --dj-text-micro:10.5px;     /* uppercase micro-labels: table headers, eyebrows, section labels */
  --dj-track:.07em;           /* letter-spacing that always accompanies --dj-text-micro uppercase */
  --dj-cell-y:7px;            /* list cell vertical padding  → ~36px rows (7+21+7+1 border) */
  --dj-cell-x:10px;           /* list cell horizontal padding */
  --dj-control-h:var(--size-element-sm);   /* 28px — dense inputs and small buttons */
  --dj-clamp-w:52ch;          /* the max width a clamped list cell contributes to table layout */
  --dj-hover:var(--color-overlay-hover);   /* the one row/card/item hover wash */
  --dj-card-pad:10px 12px;    /* board-card padding */
  --dj-rail-label:110px;      /* record/peek properties-rail label column */
}
*{box-sizing:border-box}html,body{height:100%}
body{margin:0;background:var(--color-background-body);color:var(--color-text-primary);font-family:var(--font-family-body);font-size:15px;line-height:1.55;-webkit-font-smoothing:antialiased}
#root{display:flex;min-height:100%;width:100%}
#side{width:266px;flex:none;background:var(--color-background-surface);border-right:1px solid var(--color-border);display:flex;flex-direction:column;height:100vh;position:sticky;top:0}
.brand{display:flex;align-items:center;gap:12px;padding:20px 20px 16px}
.brand .mark{width:28px;height:28px;border-radius:8px;background:var(--color-text-orange);flex:none;display:grid;place-items:center;color:#fff;font-weight:700;font-size:13px}
.brand h1{font-size:15px;font-weight:600;margin:0;letter-spacing:-.01em}.brand .sub{font-size:11px;color:var(--color-text-disabled);margin-top:1px}
.side-tools{padding:0 16px 12px;display:flex;gap:8px}
#q{flex:1;min-width:0;background:var(--color-background-body);border:1px solid var(--color-border);color:var(--color-text-primary);border-radius:var(--radius-element);padding:8px 11px;font:inherit;font-size:13px}
#q:focus{outline:none;border-color:var(--color-accent)}
.icon-btn{width:36px;height:36px;flex:none;border:1px solid var(--color-border);background:var(--color-background-body);color:var(--color-text-secondary);border-radius:var(--radius-element);cursor:pointer;display:grid;place-items:center;font-size:14px}
#nav{flex:1;overflow-y:auto;padding:8px 12px 24px}
.nav-sec{font-size:10.5px;text-transform:uppercase;letter-spacing:.09em;color:var(--color-text-disabled);font-weight:600;padding:16px 12px 8px}
.nav-item{display:flex;align-items:center;gap:12px;padding:7px 12px;border-radius:10px;font-size:13.5px;color:var(--color-text-secondary);cursor:pointer;user-select:none;transition:background var(--duration-fast) var(--ease-standard)}
.nav-item:hover{background:var(--color-background-muted);color:var(--color-text-primary)}
.nav-item.on{background:var(--color-background-muted);color:var(--color-text-primary);font-weight:600}.nav-item.on .dot{background:var(--color-text-orange)}
.nav-item .dot{width:6px;height:6px;border-radius:var(--radius-full);background:var(--color-text-disabled);flex:none}
.nav-item .n{margin-left:auto;font-size:11.5px;color:var(--color-text-disabled);font-variant-numeric:tabular-nums}
.nav-item.sub{padding-left:24px}.nav-head{font-size:12.5px;font-weight:600;color:var(--color-text-primary);padding:12px 12px 2px}
.side-foot{padding:12px 20px;border-top:1px solid var(--color-border);font-size:11.5px;color:var(--color-text-disabled)}
#main{flex:1;min-width:0;overflow-y:auto;height:100vh}
.wrap{max-width:1080px;margin:0 auto;padding:32px 32px 96px}
.crumb{font-family:var(--font-family-code);font-size:12px;color:var(--color-text-disabled);margin-bottom:8px}
h2.title{font-size:27px;line-height:1.2;letter-spacing:-.022em;font-weight:700;margin:0}
.lede{color:var(--color-text-secondary);font-size:14.5px;margin-top:8px;max-width:64ch}
.sh{font-size:11px;text-transform:uppercase;letter-spacing:.09em;color:var(--color-text-disabled);font-weight:600;margin:32px 0 12px}
.card{background:var(--color-background-surface);border:1px solid var(--color-border);border-radius:var(--radius-container);padding:20px;box-shadow:var(--shadow-low)}
.card.flush{padding:0;overflow:hidden}
.card.link{cursor:pointer;transition:border-color var(--duration-fast) var(--ease-standard),box-shadow var(--duration-fast) var(--ease-standard)}
.card.link:hover{border-color:var(--color-border-emphasized);box-shadow:var(--shadow-high)}
.grid{display:grid;gap:16px}.grid.g4{grid-template-columns:repeat(auto-fit,minmax(190px,1fr))}
.grid.g2{grid-template-columns:repeat(auto-fit,minmax(330px,1fr))}
.stat .k{font-size:11px;text-transform:uppercase;letter-spacing:.08em;color:var(--color-text-disabled);font-weight:600}
.stat .v{font-size:30px;font-weight:700;letter-spacing:-.03em;margin-top:6px;font-variant-numeric:tabular-nums}
.stat .d{font-size:12.5px;color:var(--color-text-secondary);margin-top:2px}
.bar{height:6px;border-radius:var(--radius-full);background:var(--color-background-card);display:flex;overflow:hidden;margin:12px 0}
.bar i{display:block;height:100%}
.chips{display:flex;gap:6px;flex-wrap:wrap}
.chip{font-size:var(--dj-text-meta);padding:3px 9px;border-radius:var(--radius-full);background:var(--color-background-muted);color:var(--color-text-secondary);white-space:nowrap}
.chip b{font-weight:700;font-variant-numeric:tabular-nums}
.cov-head{display:flex;align-items:baseline;justify-content:space-between}
.cov-head h3{margin:0;font-size:15px;font-weight:600}
.cov-note{font-size:12.5px;color:var(--color-text-secondary)}
/* E41 — a chart's honest footnote (a distribution's median, every record the
   answer could not count) and the placeholder a history chart draws while it
   has no answer: the slot says what it reads instead of going blank. */
.chartw-note{font-size:12.5px;color:var(--color-text-secondary);margin:6px 0 0}
.chartw-pending{min-height:64px;display:flex;align-items:center}
.badge{font-family:var(--font-family-code);font-size:var(--dj-text-meta);padding:2px 8px;border-radius:6px;background:var(--color-background-muted);color:var(--color-text-secondary);max-width:100%;overflow-wrap:anywhere}
.list{display:flex;flex-direction:column;gap:12px}
.li-head{display:flex;align-items:baseline;gap:6px 12px;flex-wrap:wrap;min-width:0}
.li-head h3{margin:0;font-size:15px;font-weight:600}
.li-desc{font-size:13px;color:var(--color-text-secondary);margin-top:3px}
.li-meta{display:flex;gap:6px;flex-wrap:wrap;margin-top:8px}
.mono{font-family:var(--font-family-code);font-size:var(--dj-text-meta)}.muted{color:var(--color-text-disabled)}
.back{display:inline-block;font-size:13px;color:var(--color-text-orange);cursor:pointer;margin-bottom:12px;user-select:none}
table.det{width:100%;border-collapse:collapse;font-size:var(--dj-text-ui)}
table.det th{text-align:left;font-size:var(--dj-text-micro);text-transform:uppercase;letter-spacing:var(--dj-track);color:var(--color-text-disabled);font-weight:600;padding:5px var(--dj-cell-x);border-bottom:1px solid var(--color-border);background:none;white-space:nowrap}
table.det td{padding:var(--dj-cell-y) var(--dj-cell-x);border-bottom:1px solid var(--color-border);vertical-align:top;font-size:var(--dj-text-ui);line-height:1.6}
/* E42 §4.3 — the row hover wash, TABLE MODE ONLY (card modes carry the lift
   hover; the two never stack — see the card-mode cancels below/at 760px) */
table.det tbody tr:not(.frow-tr):not(.fbrow-tr):hover>td{background:var(--dj-hover)}
/* E42 §4.4 — the one clamping mechanism: max-width on the inner block caps a
   prose column's contribution to auto table layout; the full text stays in the
   DOM (and on title=, rows.tsx §4.5). .relcell is a chips row — excluded by
   class per spec, never by loosening the clamp. */
table.det td>span:not(.relcell):not(.flopts-wrap){display:block;max-width:var(--dj-clamp-w);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* E42 §8.1 — an empty optional shows NOTHING: in table mode the baked muted
   dash hides and the blank cell in an aligned grid is the information. The
   payload bytes are untouched — filters, facets and the unset lane keep
   reading the same mark off the same cells. */
table.det td.c-empty .muted{display:none}
.tblwrap{overflow-x:auto;border:1px solid var(--color-border);border-radius:var(--radius-element);margin:10px 0}
.doc{font-size:14.5px}
.doc .sec-h,.sec-h{font-size:16.5px;font-weight:700;letter-spacing:-.01em;margin:28px 0 8px}
.doc p{margin:0 0 10px}
.doc h4{font-size:13.5px;font-weight:700;margin:16px 0 6px}
.doc h5{font-size:12.5px;font-weight:700;margin:14px 0 4px}
.doc h6{font-size:11.5px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--color-text-secondary);margin:14px 0 4px}
.doc hr{border:none;border-top:1px solid var(--color-border);margin:18px 0}
.doc del{color:var(--color-text-disabled)}
.doc img{max-width:100%;border-radius:var(--radius-element);border:1px solid var(--color-border)}
.doc ul,.doc ol{margin:0 0 10px;padding-left:22px}
.doc li{margin:2px 0}
.doc code,table.det code{font-family:var(--font-family-code);font-size:.85em;background:var(--color-background-muted);padding:1px 5px;border-radius:6px}
.doc .fence{background:var(--color-background-muted);border:1px solid var(--color-border);border-radius:var(--radius-element);padding:12px 14px;overflow-x:auto;font-size:12.5px;line-height:1.5;margin:0 0 10px}
.doc .fence code{background:none;padding:0;font-size:inherit}
.callout{border-left:3px solid var(--color-text-blue);background:var(--color-background-blue);border-radius:0 var(--radius-element) var(--radius-element) 0;padding:10px 14px;margin:0 0 10px}
.callout.c-important,.callout.c-warning{border-color:var(--color-warning);background:var(--color-warning-muted)}
.callout.c-danger,.callout.c-error{border-color:var(--color-error);background:var(--color-error-muted)}
.callout p{margin:0 0 4px}.callout p:last-child{margin:0}
.clink{color:var(--color-text-orange);cursor:pointer}
.clink:hover{text-decoration:underline}
.clink-dead{color:var(--color-text-secondary)}
.doc a{color:var(--color-text-orange)}
.uri{font-family:var(--font-family-code);font-size:.85em;padding:1px 5px;border-radius:6px;word-break:break-all}
.uri.ok{background:var(--color-success-muted);color:var(--color-success)}
.uri.bad{background:var(--color-error-muted);color:var(--color-error)}
.uri.unknown{background:var(--color-background-muted);color:var(--color-text-secondary)}
.rid{position:relative;padding-left:12px}
.rid::before{content:"";position:absolute;left:0;top:6px;width:6px;height:6px;border-radius:99px;background:var(--dot,var(--color-background-card))}
pre.mermaid{background:transparent;border:none;text-align:center;margin:12px 0;overflow-x:auto}
pre.mermaid svg{max-width:100%}
.chip.on-sel{background:var(--color-accent);color:var(--color-on-accent)}
#fx svg{display:block;background:var(--color-background-surface)}
#fx text{user-select:none}
.meta-fx .meta-list .kv,.card .meta-list .kv{display:flex;gap:16px;padding:6px 0;border-bottom:1px solid var(--color-border);font-size:13px}
.meta-list .kv>*{min-width:0;overflow-wrap:anywhere}
.card .meta-list .kv:last-child{border-bottom:none}
.card .meta-list .k{width:110px;flex:none;color:var(--color-text-disabled);font-size:11px;text-transform:uppercase;letter-spacing:.06em;font-weight:600;padding-top:2px}
.chip.on-type .adot{outline:none}
#gviz svg{display:block;background:var(--color-background-surface)}
#gviz text{user-select:none}
.vfilter{width:100%;background:var(--color-background-surface);border:1px solid var(--color-border);color:var(--color-text-primary);border-radius:var(--radius-element);padding:10px 14px;font:inherit;font-size:13.5px}
.vfilter:focus{outline:none;border-color:var(--color-accent)}
.seg-label{font-size:11px;text-transform:uppercase;letter-spacing:.08em;color:var(--color-text-disabled);font-weight:600;margin-right:10px}
.facet-ctl{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.facet-ctl .seg-label{margin-right:0}
.seg{display:inline-flex;border:1px solid var(--color-border);border-radius:10px;overflow:hidden;vertical-align:middle}
.seg button{font:inherit;font-size:12px;background:transparent;color:var(--color-text-secondary);border:none;padding:6px 12px;cursor:pointer}
.seg button:hover{color:var(--color-text-primary)}
.seg button.on{background:var(--color-accent);color:var(--color-on-accent)}
.grp{display:flex;align-items:center;gap:10px;padding:10px 12px;border-radius:10px;cursor:pointer;user-select:none;font-size:13.5px}
.grp:hover{background:var(--color-background-muted)}
.grp .gname{font-weight:500}
.grp .chev{color:var(--color-text-disabled);font-size:15px;display:inline-block;transition:transform var(--duration-fast) var(--ease-standard)}
.grp .chev.open{transform:rotate(90deg)}
.arts{padding:2px 12px 10px 34px}
.art-row{display:flex;align-items:center;gap:10px;padding:5px 0;font-size:12.5px;border-bottom:1px solid var(--color-border)}
.art-row:last-child{border-bottom:none}
.adot{width:7px;height:7px;border-radius:99px;background:var(--color-background-card);flex:none;display:inline-block}
.adot.ok{background:var(--color-success)}
.lg{display:flex;gap:14px;flex-wrap:wrap;margin:10px 2px 0;font-size:12px;color:var(--color-text-secondary)}
.lg-item{display:inline-flex;align-items:center;gap:6px}
.lg .sw{width:10px;height:10px;border-radius:3px;display:inline-block;background:var(--color-background-card)}
.warnslot{font-size:12px;color:var(--color-error);background:var(--color-error-muted);padding:2px 8px;border-radius:6px}
/* E32 t2 — placement. The span grid mounts ONLY when a child declares span:
   (no spans keeps today's stacked DOM untouched); 12 columns because span is
   declared in twelfths, and min-width:0 on cells because a grid child's
   default min-width:auto lets one wide table blow the whole row open. Below
   the narrow breakpoint (760px, the same line the card layouts break on) the
   grid collapses to stacked flow — display:block makes every grid-column
   moot at once, which is the entire collapse. */
.place-grid{display:grid;grid-template-columns:repeat(12,1fr);gap:16px;margin-top:16px}
.place-grid>.place-cell{min-width:0}
@media(max-width:760px){.place-grid{display:block}}
/* the unresolved slot is MUTED, not error-toned: the warn-level finding
   already carries the mistake to the author, and the reader-facing hole
   should read as "absent, explained" rather than "broken" */
.unresolved-slot{margin-top:16px;padding:10px 14px;border:1px dashed var(--color-border);border-radius:var(--radius-container);color:var(--color-text-secondary);font-size:13px;background:var(--color-background-muted)}
/* E42 §8.4 — the empty state is ONE quiet left-aligned line, never a box:
   the copy keeps its words, the treatment stops announcing them */
.empty{display:block;color:var(--color-text-disabled);text-align:left;padding:6px 0;font-size:var(--dj-text-ui-2)}
.fa-btn{border:0;background:none;padding:0;font:inherit;font-size:var(--dj-text-ui-2);color:var(--color-text-orange);cursor:pointer;user-select:none;white-space:nowrap}
.fa-btn.fa-more{color:var(--color-text-secondary);font-size:15px;line-height:1;padding:2px 8px;border-radius:var(--radius-element)}
.fa-btn.fa-more:hover{background:var(--dj-hover, var(--color-background-surface));color:var(--color-text-primary)}
.fcell{text-align:right}
.frow-tr{display:none}
.frow-tr>td{background:var(--color-background-surface)}
.fform{padding:12px}
.flabel{display:block;font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--color-text-disabled);font-weight:600;margin:8px 0 4px}
.fform input,.fform textarea{width:100%;border:1px solid var(--color-border);background:var(--color-background-body);color:var(--color-text-primary);border-radius:8px;padding:8px 10px;font:inherit;font-size:13.5px}
.fform textarea{min-height:70px;resize:vertical}
/* MENTIONS AS TAGS (E34). The mirror carries the SAME box as the control it
   sits behind — same padding, border width, font, wrapping — because the two
   are read as one surface: any divergence shows up as text that drifts off
   its own highlight. The control keeps a transparent background so the tags
   show through, and the mirror never takes a pointer or a screen reader. */
.mfield{position:relative;display:block;width:100%}
.mfield input,.mfield textarea{position:relative;background:transparent;z-index:1}
.mmirror{position:absolute;inset:0;z-index:0;overflow:hidden;pointer-events:none;
  white-space:pre-wrap;overflow-wrap:break-word;color:transparent;
  border:1px solid transparent;border-radius:8px;padding:8px 10px;
  font:inherit;font-size:13.5px;line-height:inherit}
.mfield.area .mmirror{white-space:pre-wrap}
.mtag{border-radius:var(--radius-element);background:var(--color-background-muted);
  box-shadow:0 0 0 1px var(--color-border) inset;padding:1px 0;margin:0 -1px}
.fimg{display:flex;flex-direction:column;gap:6px}
.fimg input[type=file]{font-size:12.5px;border:none;background:transparent;padding:0}
.fimg-hint{font-size:11.5px;color:var(--color-text-disabled)}
.fimg-prev{max-width:280px;max-height:200px;border:1px solid var(--color-border);border-radius:var(--radius-element);object-fit:contain;background:var(--color-background-body)}
.fbimg{max-width:240px;max-height:180px;border:1px solid var(--color-border);border-radius:var(--radius-element);display:block;margin-top:4px}
.fhint{font-size:11.5px;color:var(--color-text-disabled);margin:-2px 0 4px}
.fsect{margin:14px 0 2px;border-top:1px solid var(--color-border);padding-top:10px}
.fsect-t{font-size:13px;font-weight:600}
.fsect-h{font-size:11.5px;color:var(--color-text-disabled);margin-top:1px}
.frate{display:flex;gap:2px}
.fstar input{display:none}
.fstar span{font-size:22px;color:var(--color-border-emphasized);cursor:pointer;transition:color var(--duration-fast) var(--ease-standard)}
.fstar.on span{color:var(--color-warning)}
.fform input[type=date],.fform input[type=number]{max-width:220px}
.fdia-wrap textarea{font-family:var(--font-family-code);font-size:12px;min-height:90px}
.fdia-prev{margin-top:6px}
.fdia-prev svg{max-width:100%;height:auto}
.fconcepts .fgraph{border:1px solid var(--color-border);border-radius:var(--radius-element);background:var(--color-background-body);min-height:120px}
.fconcepts .fgraph svg{display:block;width:100%;height:300px}
.fchips{display:flex;gap:6px;flex-wrap:wrap;margin-top:8px}
.badd-row{display:flex;flex-wrap:wrap;gap:2px 16px;margin-top:6px}
.fchips .chip{cursor:pointer}
.rowsv-h{display:flex;align-items:center;gap:8px;margin-top:28px;cursor:pointer;user-select:none}
.rowsv-h .chev{color:var(--color-text-disabled);font-size:15px;display:inline-block;
  transition:transform var(--duration-fast) var(--ease-standard)}
.rowsv-h .chev.open{transform:rotate(90deg)}
.rowsv-h:hover{color:var(--color-text-secondary)}
.rowsv-go{font:inherit;font-size:10px;letter-spacing:.08em;text-transform:uppercase;font-weight:600;
  border:none;background:none;cursor:pointer;color:var(--color-text-disabled);padding:2px 6px;
  border-radius:var(--radius-full);opacity:0}
.rowsv-h:hover .rowsv-go,.rowsv-go:focus{opacity:1}
.rowsv-go:hover{background:var(--color-overlay-hover);color:var(--color-text-accent)}
.linkbtn{font:inherit;font-size:inherit;border:none;background:none;padding:0;cursor:pointer;
  color:var(--color-text-accent);text-decoration:underline;text-underline-offset:2px}
.rowsv-n{background:var(--color-background-muted);color:var(--color-text-secondary);border-radius:var(--radius-full);padding:1px 8px;font-size:11px;font-weight:700}
.fform .frow{display:flex;align-items:center;gap:12px;margin-top:10px}
.fbtn{border:none;background:var(--color-accent);color:var(--color-on-accent);border-radius:8px;padding:7px 14px;font:inherit;font-size:13px;font-weight:600;cursor:pointer}
.fbtn:disabled{opacity:.5}
.ferr{font-size:12px;color:var(--color-error)}
.doc img.med{max-width:100%;height:auto;border-radius:var(--radius-element);border:1px solid var(--color-border);margin:10px 0;display:block}
.med-note{font-size:12.5px;color:var(--color-warning);background:var(--color-warning-muted);padding:3px 9px;border-radius:var(--radius-full)}
.fbwrap{margin:14px 0}
/* an answer captured against a row sits directly under it, visually tied to
   the row rather than floating as a separate list */
.fbrow-tr>td{padding:0 10px 10px!important;border-top:none!important;background:var(--color-background-surface)}
tr.has-answer>td{border-bottom:none}
/* inline control + dropdown menu — mirrors Astryx's DropdownMenu: same
   tokens, same anatomy (trigger → floating menuitem rows), same treatment.
   Positioned fixed on <body> rather than with CSS anchor positioning, which
   is Chromium-only and would undo the browser floor the tokens were chosen for. */
.ctl{display:inline-flex;align-items:center;gap:5px;font:inherit;font-size:var(--dj-text-meta);font-weight:600;
  border:1px solid var(--color-border);border-radius:var(--radius-full);padding:2px 7px 2px 9px;cursor:pointer}
.ctl:hover{border-color:var(--color-border-emphasized)}
.ctl:focus-visible{outline:2px solid var(--color-accent);outline-offset:1px}
.ctl-chev{flex:none;opacity:.7}
.menu{position:fixed;z-index:200;display:flex;flex-direction:column;gap:var(--spacing-0-5);
  max-height:300px;overflow-y:auto;padding:var(--spacing-1);border-radius:var(--radius-container);
  background:var(--color-background-popover);border:1px solid var(--color-border);box-shadow:var(--shadow-high);
  transition:opacity var(--duration-fast) var(--ease-standard)}
/* E42 §7 — menu items on the density scale: 13px, 4px item radius, tighter
   padding, so a picker reads at the same metrics as the row it opened from.
   Anatomy (icon · label · ✓ · kbd) and keyboard grammar untouched. */
.menu-item{display:flex;align-items:center;gap:var(--spacing-2);width:100%;box-sizing:border-box;
  padding:5px var(--spacing-2);border:none;background:transparent;cursor:pointer;text-align:left;outline:none;
  border-radius:var(--radius-inner);
  font:inherit;font-size:var(--dj-text-ui);color:var(--color-text-primary);white-space:nowrap}
.menu-item:hover,.menu-item:focus{background:var(--color-overlay-hover)}
.menu-item.on{font-weight:600}
.menu-check{flex:none;width:12px;color:var(--color-accent)}
/* asking the corpus: a button, and the modal it opens */
.ask-btn{display:flex;align-items:center;gap:8px;width:calc(100% - 32px);margin:0 16px 4px;
  font:inherit;font-size:13px;font-weight:600;cursor:pointer;padding:9px 12px;
  border:1px solid var(--color-border);border-radius:var(--radius-element);
  background:var(--color-background-surface);color:var(--color-text-secondary)}
.ask-btn:hover{border-color:var(--color-accent);color:var(--color-text-primary)}
.ask-star{color:var(--color-accent);font-size:14px}
#ask{display:none}
#ask.open{display:block;position:fixed;inset:0;z-index:90;background:var(--color-overlay);
  padding:clamp(16px,8vh,96px) 16px 16px}
.ask-card{max-width:760px;margin:0 auto;display:flex;flex-direction:column;max-height:80vh;
  background:var(--color-background-popover);border:1px solid var(--color-border);
  border-radius:var(--radius-container);box-shadow:var(--shadow-high);overflow:hidden}
.ask-top{display:flex;align-items:center;gap:8px;padding:6px 8px 6px 16px;border-bottom:1px solid var(--color-border)}
#askq{flex:1;font:inherit;font-size:15px;padding:12px 0;border:none;outline:none;
  background:transparent;color:var(--color-text-primary)}
.ask-x{font:inherit;font-size:13px;border:none;background:none;cursor:pointer;
  color:var(--color-text-secondary);padding:8px 10px;border-radius:var(--radius-full)}
.ask-x:hover{background:var(--color-overlay-hover);color:var(--color-text-primary)}
.ask-filters{display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:10px 16px;
  border-bottom:1px solid var(--color-border);background:var(--color-background-body)}
.ask-filters .ped-sel select{font-size:12.5px;padding:6px 30px 6px 12px;min-width:0}
.ask-body{padding:14px 16px 18px;overflow-y:auto}
.ask-body .lede{margin:6px 0}
body.ask-open{overflow:hidden}

/* the way in, and the results either backend returns */
.ask-btn.wide{width:100%;margin:14px 0 0;padding:12px 14px;font-size:13.5px}
.ask-scope{margin-left:auto;font-size:11px;text-transform:uppercase;letter-spacing:.08em;
  color:var(--color-text-disabled)}
.ask-filters .ptok{font-size:12px}
.sres{display:flex;flex-direction:column;gap:6px}
.sres-i{display:flex;flex-direction:column;gap:4px;text-align:left;font:inherit;cursor:pointer;
  padding:10px 12px;border:1px solid var(--color-border);border-radius:var(--radius-element);
  background:var(--color-background-surface);color:var(--color-text-primary)}
.sres-i:hover{border-color:var(--color-border-emphasized);background:var(--color-overlay-hover)}
.sres-h{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:13px}
.sres-x{font-size:12.5px;color:var(--color-text-secondary);line-height:1.5}
.sres-x b{color:var(--color-text-primary)}

/* tabs — one panel at a time, the bar carrying each one's count */
.tabs{display:flex;gap:2px;margin:24px 0 0;border-bottom:1px solid var(--color-border);overflow-x:auto}
.tab{font:inherit;font-size:13px;font-weight:600;white-space:nowrap;border:none;background:none;cursor:pointer;
  color:var(--color-text-secondary);padding:9px 12px;border-bottom:2px solid transparent;margin-bottom:-1px;
  display:inline-flex;align-items:center;gap:7px}
.tab:hover{color:var(--color-text-primary);background:var(--color-overlay-hover);
  border-top-left-radius:8px;border-top-right-radius:8px}
.tab.on{color:var(--color-text-accent);border-bottom-color:var(--color-accent)}
.tab-n{font-size:11px;font-weight:600;font-variant-numeric:tabular-nums;padding:1px 6px;border-radius:var(--radius-full);
  background:var(--color-background-muted);color:var(--color-text-secondary)}
.tab.on .tab-n{background:var(--color-accent-muted);color:var(--color-text-accent)}
.tabpanel > .psearch-wrap:first-child{margin-top:14px}

/* power search — the token bar and the filter editor attached under it */
.psearch-wrap{margin-top:14px}
.psearch{display:flex;flex-wrap:wrap;align-items:center;gap:6px;padding:7px 10px;
  border:1px solid var(--color-border);border-radius:var(--radius-container);
  background:var(--color-background-surface)}
.psearch:focus-within{border-color:var(--color-border-emphasized)}
.ptok{display:inline-flex;align-items:center;gap:6px;font-size:13px;padding:4px 6px 4px 11px;
  border-radius:var(--radius-full);background:var(--color-background-muted);color:var(--color-text-primary)}
.ptok-l{color:var(--color-text-secondary)}
.ptok b{font-weight:640}
/* a filter that cannot match — @me where the host names no reader */
.ptok-warn{display:inline-flex;align-items:center;justify-content:center;width:14px;height:14px;
  border-radius:var(--radius-full);background:var(--color-warning-muted);color:var(--color-warning);
  font-size:10px;font-weight:700;cursor:help}
.ptok-x,.ptok-clear{font:inherit;font-size:12px;line-height:1;border:none;background:none;cursor:pointer;
  color:var(--color-text-secondary);padding:3px;border-radius:var(--radius-full)}
.ptok-x:hover,.ptok-clear:hover{background:var(--color-overlay-hover);color:var(--color-text-primary)}
.ptok-clear{margin-left:auto}
.ptok-add{font:inherit;font-size:13px;border:none;background:none;cursor:pointer;
  color:var(--color-text-secondary);padding:4px 8px;border-radius:var(--radius-full)}
.ptok-add:hover{background:var(--color-overlay-hover);color:var(--color-text-primary)}
.ptok-add[aria-expanded=true]{background:var(--color-overlay-hover);color:var(--color-text-primary)}
.peditor{margin-top:8px;padding:var(--spacing-3);border:1px solid var(--color-border);
  border-radius:var(--radius-container);background:var(--color-background-surface);
  box-shadow:var(--shadow-low)}
.ped-row{display:flex;flex-wrap:wrap;align-items:center;gap:var(--spacing-2)}
.ped-sel{position:relative;display:inline-flex;align-items:center}
.ped-sel .ctl-chev{position:absolute;right:12px;pointer-events:none;color:var(--color-text-secondary)}
.ped-sel select,.peditor input.ped-in{font:inherit;font-size:13px;color:var(--color-text-primary);
  background:var(--color-background-body);border:1px solid var(--color-border);
  border-radius:var(--radius-full);padding:7px 34px 7px 14px;
  -webkit-appearance:none;-moz-appearance:none;appearance:none;cursor:pointer;min-width:112px}
.peditor input.ped-in{padding-right:14px;cursor:text;min-width:180px}
.ped-sel select:focus,.peditor input.ped-in:focus{outline:none;border-color:var(--color-accent);
  box-shadow:0 0 0 1px var(--color-accent)}
.ped-list{display:flex;flex-direction:column;gap:2px;max-height:190px;overflow-y:auto;
  border:1px solid var(--color-border);border-radius:var(--radius-element);padding:4px;min-width:180px}
.ped-opt{display:flex;align-items:center;gap:8px;font-size:13px;padding:5px 8px;
  border-radius:calc(var(--radius-element) - 2px);cursor:pointer}
.ped-opt:hover{background:var(--color-overlay-hover)}
.ped-act{display:flex;justify-content:flex-end;align-items:center;gap:var(--spacing-2);margin-top:var(--spacing-3)}
.ped-btn{font:inherit;font-size:13px;font-weight:600;border:none;background:none;cursor:pointer;
  color:var(--color-text-primary);padding:7px 16px;border-radius:var(--radius-full)}
.ped-btn:hover{background:var(--color-overlay-hover)}
.ped-btn.on{background:var(--color-accent);color:var(--color-on-accent)}
.ped-btn.on:hover{opacity:.9}
.ped-btn[disabled]{background:var(--color-background-muted);color:var(--color-text-disabled);cursor:default}
#toast{position:fixed;left:50%;bottom:24px;transform:translateX(-50%) translateY(12px);z-index:60;opacity:0;pointer-events:none;
  transition:opacity var(--duration-fast) var(--ease-standard),transform var(--duration-fast) var(--ease-standard);
  background:var(--color-background-inverted,#222);color:var(--color-background-surface);font-size:13px;padding:9px 14px;border-radius:var(--radius-element);box-shadow:var(--shadow-high)}
#toast.on{opacity:1;transform:translateX(-50%) translateY(0);pointer-events:auto}
#toast button{font:inherit;font-size:13px;background:none;border:none;color:inherit;text-decoration:underline;cursor:pointer;margin-left:8px;padding:0}
#pending{position:fixed;left:50%;bottom:24px;transform:translateX(-50%) translateY(12px);z-index:55;opacity:0;pointer-events:none;
  transition:opacity var(--duration-fast) var(--ease-standard),transform var(--duration-fast) var(--ease-standard);
  display:flex;align-items:center;gap:10px;background:var(--color-background-surface);border:1px solid var(--color-border);
  box-shadow:var(--shadow-high);border-radius:var(--radius-full);padding:8px 10px 8px 16px;font-size:13px}
#pending.on{opacity:1;transform:translateX(-50%) translateY(0);pointer-events:auto}
#pending button{font:inherit;font-size:13px;border:none;border-radius:var(--radius-full);padding:6px 12px;cursor:pointer;background:var(--color-accent);color:var(--color-on-accent)}
#pending button.ghost{background:none;color:var(--color-text-secondary)}
/* tree view: a row per document, children disclosed under their parent */
.tree{border:1px solid var(--color-border);border-radius:var(--radius-element);background:var(--color-background-surface);overflow:hidden}
.tnode{display:flex;align-items:center;gap:8px;padding:7px 12px;border-bottom:1px solid var(--color-border);font-size:13.5px}
.tnode:last-child{border-bottom:none}
.tnode:hover{background:var(--color-background-muted)}
.tdim{opacity:.55}
.tcaret{flex:none;width:14px;text-align:center;color:var(--color-text-disabled);cursor:pointer;transition:transform var(--duration-fast) var(--ease-standard);display:inline-block}
.tcaret.open{transform:rotate(90deg)}
.tcaret.empty{cursor:default;opacity:.25}
.tname{cursor:pointer;font-weight:560;color:var(--color-text-primary);overflow-wrap:anywhere}
.tname:hover{color:var(--color-accent)}
.tcount{font-family:var(--font-family-code);font-size:10.5px;color:var(--color-text-disabled)}
.tchips{margin-left:auto;display:flex;gap:4px;flex-wrap:wrap}
@media(max-width:760px){.tchips{display:none}}
/* concept tree: one surface frame, hairline-separated rows — the item's
   content control drops its boxed default so title + description + chips read
   as ONE row, consistent with the app's list style */
.tree-host{border:1px solid var(--color-border);border-radius:var(--radius-element);background:var(--color-background-surface);overflow:hidden;padding:2px 10px}
.tree-host li[role=treeitem]{border-top:1px solid var(--color-border)}
.tree-host>div>ul>li[role=treeitem]:first-child,.tree-host ul ul>li[role=treeitem]:first-child{border-top:none}
.tree-host .astryx-tree-list-item{width:auto;padding:9px 4px;border-radius:var(--radius-element)}
.tree-host .astryx-tree-list-item:hover{background:var(--color-background-muted)}
.tree-host .astryx-tree-list-item>button{background:none;border:none;border-radius:0;text-align:left}
.tree-host .astryx-tree-list-item>button:not(.astryx-tree-list-chevron){flex:1 1 0;min-width:0;padding:0 6px;font:inherit}
.tree-host .astryx-tree-list-item-label{font-weight:600;font-size:14px}
.tree-host .astryx-tree-list-item>button:not(.astryx-tree-list-chevron)>span:not(.astryx-tree-list-item-label){display:block;font-size:12.5px;color:var(--color-text-secondary);line-height:1.45;margin-top:1px}
.tree-host .astryx-tree-list-item>span:last-child{flex:0 0 42%;display:flex;flex-wrap:wrap;justify-content:flex-end;align-items:center;gap:8px;row-gap:4px}
.tree-host .tree-end{display:contents}
.fbstack{margin:0}
.fbf{margin:0 0 8px}
.fbf:last-child{margin-bottom:0}
.fbk{display:block;margin-bottom:2px}
.fbv{overflow-wrap:anywhere}
.fbd{margin-top:2px;font-size:12px;line-height:1.5;color:var(--color-text-secondary)}
/* stacked under its row the record is a continuation, not a card: the left
   rule already ties it to the row, so the box chrome only adds noise */
.fbstack .fbitem{margin-bottom:4px;background:none;border:none;border-radius:0;padding:2px 0;font-size:12.5px}
.fbstack .fbitem:last-child{margin-bottom:0}
.fnote{font-size:11.5px;color:var(--color-text-secondary);background:var(--color-background-muted);border-radius:8px;padding:6px 9px;margin-bottom:10px}
.fbf.fbrej .fbv{color:var(--color-text-disabled);font-size:12px}
.fbstack .fbitem:last-child{margin-bottom:0}
.fbitem{background:var(--color-background-surface);border:1px solid var(--color-border);border-radius:var(--radius-element);padding:10px 12px;margin-bottom:8px;font-size:13px}
.fbmeta{font-size:11.5px;color:var(--color-text-disabled);margin-left:8px}
/* card layouts: row header line (identity left, comments trigger right), a
   JS-rendered column label that can carry a link (beside:), and the per-row
   comments panel the header opens */
.cardhead{display:flex;align-items:center;justify-content:space-between;gap:8px;min-height:24px}
.cardlbl{display:flex;align-items:center;gap:10px;font-size:10px;text-transform:uppercase;letter-spacing:.08em;color:var(--color-text-disabled);font-weight:600;margin-bottom:1px}
.blkfilters{margin:4px 0 14px}
.fbhist{margin-top:12px;padding:12px 14px;background:var(--color-background-muted);border-radius:var(--radius-element)}
.fbhist-head{font-size:10px;text-transform:uppercase;letter-spacing:.08em;color:var(--color-text-disabled);font-weight:600;margin-bottom:6px}
.fbhist-add{margin-top:10px;display:flex;gap:8px;justify-content:flex-end}
/* record actions read as small buttons: surface pills against the muted panel */
.fbreview{margin-left:10px;display:inline-flex;gap:6px}
.fbreview .fa-btn,.fbdel .fa-btn{background:var(--color-background-surface);border:1px solid var(--color-border);border-radius:var(--radius-element);padding:2px 9px;font:inherit;font-size:12px;line-height:1.5}
.fbdel{margin-left:6px}
.fbdel .fa-btn{color:var(--color-text-disabled)}
.fbdel .fa-btn:hover{color:var(--color-text-orange);border-color:var(--color-border-emphasized)}
.fbreview .fa-btn:hover{border-color:var(--color-border-emphasized)}
.fbbody{margin-top:6px;overflow-wrap:anywhere}
.fbk{font-size:10.5px;text-transform:uppercase;letter-spacing:.06em;color:var(--color-text-disabled);font-weight:600;margin-right:4px}
#mtop{display:none}#scrim{display:none}
/* A block declaring layout.narrow: cards restructures into cards at narrow
   widths — same markup, no second render, labels straight from the declared
   columns. Form and stacked-answer rows keep their own behaviour. */
@media(max-width:760px){
table.det[data-layout=cards],table.det[data-layout=cards] tbody{display:block}
/* in card mode each row carries its own frame, so the wrapper's frame is a
   leftover second border around the whole set */
.tblwrap.cards{border:none;border-radius:0;overflow:visible}
table.det[data-layout=cards] .frow-tr>td{background:none}
table.det[data-layout=cards] tr:not(.frow-tr):not(.fbrow-tr){display:block;border:1px solid var(--color-border);border-top:none;background:var(--color-background-surface);padding:12px 14px;margin:0}
table.det[data-layout=cards] tr:first-child:not(.frow-tr):not(.fbrow-tr){display:none}
/* joined list: the cards share ONE frame — hairlines between them, the top
   card opens it rounded, whatever renders last closes it rounded */
table.det[data-layout=cards] tbody>tr:nth-child(2):not(.frow-tr){border-top:1px solid var(--color-border);border-top-left-radius:var(--radius-element);border-top-right-radius:var(--radius-element)}
table.det[data-layout=cards] tbody>tr:last-child{border-bottom-left-radius:var(--radius-element);border-bottom-right-radius:var(--radius-element)}
table.det[data-layout=cards] tr:not(.frow-tr):not(.fbrow-tr)>td{display:block;border:none;padding:3px 0;width:auto}
table.det[data-layout=cards] td::before{content:attr(data-label);display:block;font-size:10px;text-transform:uppercase;letter-spacing:.08em;color:var(--color-text-disabled);font-weight:600;margin-bottom:1px}
table.det[data-layout=cards] td.c-title::before,table.det[data-layout=cards] td.c-eyebrow::before,table.det[data-layout=cards] td.c-badge::before,table.det[data-layout=cards] td.c-actions::before{display:none}
table.det[data-layout=cards] td.c-eyebrow{font-size:11px;color:var(--color-text-disabled);letter-spacing:.04em}
/* E42 §5 — the title clamps to 2 lines (overflow clamp: the full text stays
   in the DOM, and rides the wrapper span's title=); consecutive badge cells
   flow inline so N badge columns read as ONE badge row. Role rules that set
   display are spelled through the full tr:not() path: the generic card-cell
   rule above is (0,4,3) and silently beat the old td.c-* spellings — the very
   bug that rendered card: hide columns on production cards. */
table.det[data-layout=cards] td.c-title{font-size:15.5px;font-weight:600;line-height:1.4;margin:1px 0 6px}
table.det[data-layout=cards] tr:not(.frow-tr):not(.fbrow-tr)>td.c-title{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden}
table.det[data-layout=cards] tr:not(.frow-tr):not(.fbrow-tr)>td.c-badge{display:inline-flex;gap:4px;margin:4px 6px 0 0;vertical-align:top}
table.det[data-layout=cards] tr:not(.frow-tr):not(.fbrow-tr)>td.c-hide{display:none}
/* E42 §8.2 — on a card an empty cell renders nothing at all: no label, no
   dash, no reserved space (rows.tsx never marks the identity cell c-empty) */
table.det[data-layout=cards] tr:not(.frow-tr):not(.fbrow-tr)>td.c-empty{display:none}
/* E42 — card mode opts out of the table-mode wash and single-line clamp
   (§4 scope: table mode only; §5 gives cards their own treatment); the wash
   TRANSITION's card-mode cancel lives in the motion layer, which sorts later */
table.det[data-layout=cards] tbody tr:not(.frow-tr):not(.fbrow-tr):hover>td{background:none}
table.det[data-layout=cards] td>span:not(.relcell):not(.flopts-wrap){display:inline;max-width:none;overflow:visible;text-overflow:clip;white-space:normal}
table.det[data-layout=cards] tr:not(.frow-tr):not(.fbrow-tr)>td.c-actions{margin-top:8px;padding-top:8px;border-top:1px solid var(--color-border)!important;display:flex;justify-content:flex-end;flex-wrap:wrap;gap:2px 12px}
table.det[data-layout=cards] .fbrow-tr>td,table.det[data-layout=cards] .frow-tr>td{padding-left:0!important}
/* an open panel CONTINUES its card: the card opens its bottom edge, the panel
   closes the segment, and the joined frame carries straight on to the next
   card — no radius here; the tbody last-child rule rounds the true end */
table.det[data-layout=cards] .fbrow-tr{display:block;background:var(--color-background-surface);border:1px solid var(--color-border);border-top:none;margin:0;padding:0 14px 12px}
table.det[data-layout=cards] .fbstack{margin-left:0;padding-left:0}
table.det[data-layout=cards] tr.form-open:not(.frow-tr):not(.fbrow-tr){border-bottom:none;padding-bottom:6px}
table.det[data-layout=cards] tr.frow-tr[style*="table-row"],table.det[data-layout=cards] tr.frow-tr[style*="block"]{display:block!important;background:var(--color-background-surface);border:1px solid var(--color-border);border-top:none;margin:0;padding:0 14px 12px}
table.det[data-layout=cards] .frow-tr>td{display:block;width:auto;border:none!important}
table.det[data-layout=cards] .fform{padding:12px 0}
}

/* layout: { wide: cards } — the SAME card presentation at every width,
   not gated by viewport. MIRRORS the narrow-cards @media block above
   (selector data-layout=cards-wide, wrapper class .wide); keep in sync. */
table.det[data-layout=cards-wide],table.det[data-layout=cards-wide] tbody{display:block}
/* in card mode each row carries its own frame, so the wrapper's frame is a
   leftover second border around the whole set */
.tblwrap.wide{border:none;border-radius:0;overflow:visible}
table.det[data-layout=cards-wide] .frow-tr>td{background:none}
table.det[data-layout=cards-wide] tr:not(.frow-tr):not(.fbrow-tr){display:block;border:1px solid var(--color-border);border-top:none;background:var(--color-background-surface);padding:12px 14px;margin:0}
table.det[data-layout=cards-wide] tr:first-child:not(.frow-tr):not(.fbrow-tr){display:none}
/* joined list: the cards share ONE frame — hairlines between them, the top
   card opens it rounded, whatever renders last closes it rounded */
table.det[data-layout=cards-wide] tbody>tr:nth-child(2):not(.frow-tr){border-top:1px solid var(--color-border);border-top-left-radius:var(--radius-element);border-top-right-radius:var(--radius-element)}
table.det[data-layout=cards-wide] tbody>tr:last-child{border-bottom-left-radius:var(--radius-element);border-bottom-right-radius:var(--radius-element)}
table.det[data-layout=cards-wide] tr:not(.frow-tr):not(.fbrow-tr)>td{display:block;border:none;padding:3px 0;width:auto}
table.det[data-layout=cards-wide] td::before{content:attr(data-label);display:block;font-size:10px;text-transform:uppercase;letter-spacing:.08em;color:var(--color-text-disabled);font-weight:600;margin-bottom:1px}
table.det[data-layout=cards-wide] td.c-title::before,table.det[data-layout=cards-wide] td.c-eyebrow::before,table.det[data-layout=cards-wide] td.c-badge::before,table.det[data-layout=cards-wide] td.c-actions::before{display:none}
table.det[data-layout=cards-wide] td.c-eyebrow{font-size:11px;color:var(--color-text-disabled);letter-spacing:.04em}
/* E42 §5 — mirror of the narrow block: 2-line title clamp, one badge row,
   display-setting role rules through the winning tr:not() path */
table.det[data-layout=cards-wide] td.c-title{font-size:15.5px;font-weight:600;line-height:1.4;margin:1px 0 6px}
table.det[data-layout=cards-wide] tr:not(.frow-tr):not(.fbrow-tr)>td.c-title{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden}
table.det[data-layout=cards-wide] tr:not(.frow-tr):not(.fbrow-tr)>td.c-badge{display:inline-flex;gap:4px;margin:4px 6px 0 0;vertical-align:top}
table.det[data-layout=cards-wide] tr:not(.frow-tr):not(.fbrow-tr)>td.c-hide{display:none}
/* E42 §8.2 — same rule in the always-cards layout (and so on every board) */
table.det[data-layout=cards-wide] tr:not(.frow-tr):not(.fbrow-tr)>td.c-empty{display:none}
/* E42 — card mode opts out of the table-mode wash and single-line clamp
   (§4 scope: table mode only; §5 gives cards their own treatment) */
table.det[data-layout=cards-wide] tbody tr:not(.frow-tr):not(.fbrow-tr):hover>td{background:none}
table.det[data-layout=cards-wide] td>span:not(.relcell):not(.flopts-wrap){display:inline;max-width:none;overflow:visible;text-overflow:clip;white-space:normal}
table.det[data-layout=cards-wide] tr:not(.frow-tr):not(.fbrow-tr)>td.c-actions{margin-top:8px;padding-top:8px;border-top:1px solid var(--color-border)!important;display:flex;justify-content:flex-end;flex-wrap:wrap;gap:2px 12px}
table.det[data-layout=cards-wide] .fbrow-tr>td,table.det[data-layout=cards-wide] .frow-tr>td{padding-left:0!important}
/* an open panel CONTINUES its card: the card opens its bottom edge, the panel
   closes the segment, and the joined frame carries straight on to the next
   card — no radius here; the tbody last-child rule rounds the true end */
table.det[data-layout=cards-wide] .fbrow-tr{display:block;background:var(--color-background-surface);border:1px solid var(--color-border);border-top:none;margin:0;padding:0 14px 12px}
table.det[data-layout=cards-wide] .fbstack{margin-left:0;padding-left:0}
table.det[data-layout=cards-wide] tr.form-open:not(.frow-tr):not(.fbrow-tr){border-bottom:none;padding-bottom:6px}
table.det[data-layout=cards-wide] tr.frow-tr[style*="table-row"],table.det[data-layout=cards-wide] tr.frow-tr[style*="block"]{display:block!important;background:var(--color-background-surface);border:1px solid var(--color-border);border-top:none;margin:0;padding:0 14px 12px}
table.det[data-layout=cards-wide] .frow-tr>td{display:block;width:auto;border:none!important}
table.det[data-layout=cards-wide] .fform{padding:12px 0}
@media(max-width:900px){
html,body{overflow-x:clip}
.chip{white-space:normal;overflow-wrap:anywhere}
.li-head h3{flex:1 1 100%}
.crumb{overflow-wrap:anywhere}
#mtop{display:flex;align-items:center;gap:12px;position:fixed;top:0;left:0;right:0;height:56px;z-index:40;background:var(--color-background-surface);border-bottom:1px solid var(--color-border);padding:0 14px}
#mtop .mtitle{font-size:15px;font-weight:600;letter-spacing:-.01em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
#side{position:fixed;left:0;top:0;bottom:0;width:min(82vw,300px);height:100dvh;z-index:60;transform:translateX(-105%);transition:transform var(--duration-fast) var(--ease-standard)}
body.nav-open #side{transform:none;box-shadow:var(--shadow-high)}
body.nav-open #scrim{display:block;position:fixed;inset:0;z-index:50;background:rgba(0,0,0,.42)}
#main{height:auto;min-height:100dvh;padding-top:56px;overflow-x:hidden}
.wrap{padding:20px 16px 80px}
h2.title{font-size:22px}
.grid.g2{grid-template-columns:1fr}
.cov-head{flex-direction:column;align-items:flex-start;gap:2px}
}
.toast-host{position:fixed;left:50%;bottom:24px;transform:translateX(-50%);z-index:60}
/* Astryx's MediaTheme stamps data-astryx-media on content it renders over an
   inverted surface and expects the HOST THEME's generated CSS to remap the
   text/icon tokens — CSS an Astryx app generates and this engine (which
   vendors the components but serves its own tokens) never shipped, so toast
   text painted --color-text-primary on --color-background-inverted: dark on
   dark. Supply the remap here, keyed on the attribute's PRESENCE, not the
   OS theme: --color-background-surface is inverted's opposite in BOTH
   palettes, so the pair always contrasts. Doubled attribute beats stylex's
   single-class specificity regardless of bundle order. */
[data-astryx-media][data-astryx-media]{
  color:var(--color-background-surface);
  --color-text-primary:var(--color-background-surface);
  --color-text-secondary:var(--color-background-surface);
  --color-icon-primary:var(--color-background-surface);
  --color-icon-secondary:var(--color-background-surface);
}
.toast-host button{color:inherit}

/* ---- modal form host (E19 t6): the SAME panel, dialog chrome --------------
   Astryx Dialog draws the chrome (native <dialog>, browser top layer); the
   engine owns state and placement — the toast-host pattern one layer up.
   Toast lesson applied ahead of shipping: the dialog PANEL sits in the normal
   tree and inherits the engine-served tokens, but ::backdrop historically
   does not inherit custom properties — supply the scrim with the token AND
   its literal per-theme fallback (values from tokens.ts, light and dark).
   The doubled class beats stylex's single-class specificity either way, and
   where the var resolves the computed value is identical to Astryx's own.
   The dialog's inner container supplies its own padding, so the hosted
   .fform drops the stacked 12px — scoped: the pinned global .fform rule
   stays exactly as the render suite expects. */
.fmodal.fmodal::backdrop{background:var(--color-overlay,#01122866);backdrop-filter:blur(2px)}
[data-theme=dark] .fmodal.fmodal::backdrop{background:var(--color-overlay,#11111299)}
/* E42 §7 — the modal states its chrome explicitly (the same surface grammar
   the menu and peek already speak): popover ground, 1px low-contrast border,
   the container radius, the high shadow. Doubled class beats the vendored
   component's single-class specificity, the page.css idiom throughout. */
.fmodal.fmodal{background:var(--color-background-popover);border:1px solid var(--color-border);
  border-radius:var(--radius-container);box-shadow:var(--shadow-high)}
.fmodal-body{overflow-y:auto;min-height:0}
.fmodal-body .fform{padding:2px 0 0}
/* E42 §7 — fields dense IN MODAL SCOPE only (the pinned global .fform rules
   stand): 13px operating text in 28px --dj-control-h boxes. The line-height
   is what MAKES the box 28px: control-h minus the 10px vertical padding and
   2px border below — the inherited 1.55 would compute a 32px box instead.
   The mention MIRROR moves by the same amounts as the control it sits
   behind — the E34 one-surface rule; divergence shows as tags drifting off
   their own text. */
.fmodal .fform input,.fmodal .fform textarea,.fmodal .fform select{font-size:var(--dj-text-ui);line-height:calc(var(--dj-control-h) - 12px);padding:5px 10px}
.fmodal .fform .mfield .mmirror{font-size:var(--dj-text-ui);line-height:calc(var(--dj-control-h) - 12px);padding:5px 10px}
.fmodal .fform .fbtn{font-size:var(--dj-text-ui);height:var(--dj-control-h);padding:0 14px}
/* E19 t7: the modal BODY speaks Astryx too — FormLayout owns the field
   spacing (gap --spacing-4), Astryx Field the labels and hints, so the
   legacy .flabel never renders in here; the button row becomes a
   footer-shaped row (divider, right-aligned Cancel + primary, the error
   text keeping the left edge). The range picker's calendar popover needs
   NO token bridge, checked against the [data-astryx-media] precedent:
   app.css carries the compiled component styles, and every custom
   property they lean on (--color-background-popover, --shadow-low, the
   --spacing-* scale) is served by tokens.ts in BOTH themes — the popover
   also sits in the trigger's subtree, so it inherits the engine-served
   tokens like the dialog panel does, not like ::backdrop. */
.fform .frow-modal{margin-top:16px;padding-top:12px;border-top:1px solid var(--color-border);justify-content:flex-end}
.frow-modal .ferr{margin-right:auto}
.tree-end{display:inline-flex;align-items:center;gap:8px}

/* ---- one collection, two projections (§14): the board's chrome row --------
   The widget's ONE chrome row: the search bar left, the projection toggle
   (.proj-seg) right — margin-left:auto in a shared flex row, never a second
   toolbar. CSS order keeps the filter editor (.peditor) full-width BELOW the
   row while the toggle stays on it; without search the toggle stands alone,
   still right-aligned. */
.wchrome{display:flex;align-items:flex-start;flex-wrap:wrap;gap:10px;margin-top:14px}
.wchrome .psearch-wrap{order:1;flex:1 1 auto;min-width:0;margin-top:0}
.wchrome .proj-seg{order:2;margin-left:auto}
.wchrome .peditor{order:3;flex-basis:100%}

/* ---- board: the rows pipeline fanned into lanes ---------------------------
   Lane colour rides the same chip tones every other value wears; the cards
   inside are the cards layout's own markup (data-layout=cards-wide), so the
   board adds columns, never a second card style. */
.board{display:flex;gap:12px;align-items:flex-start;overflow-x:auto;margin-top:14px;padding-bottom:8px}
.board .lane{flex:1 1 0;min-width:230px;max-width:340px;background:var(--color-background-muted);border:1px solid var(--color-border);border-radius:var(--radius-element);padding:8px}
.board .lane-h{display:flex;align-items:center;gap:8px;padding:2px 4px 8px}
.board .lane-name{font-size:12px;font-weight:600;color:var(--color-text-secondary)}
.board .lane-n{margin-left:auto;font-size:11px;font-weight:600;color:var(--color-text-secondary)}
.board .lane[data-over-wip] .lane-n{color:var(--color-warning)}
.board .lane-about{font-size:11.5px;color:var(--color-text-disabled);margin:2px 4px;padding:0}
.board .lane .tblwrap{margin:0 0 8px}
.board .lane table.det[data-layout=cards-wide] tr:not(.frow-tr):not(.fbrow-tr){border:1px solid var(--color-border);border-radius:var(--radius-element);margin:0 0 8px}
.board .cardhead .ctl{margin-left:auto}

/* swimlanes (rows: — the board's second axis): horizontal bands, each holding
   the full lane strip. The board root goes vertical; each band scrolls its own
   lane strip, so a wide vocabulary never forces the whole page sideways. The
   band header reuses the lane header's chip/count anatomy and the disclosure
   chevron the grouped views wear — same words, same tones, one system. */
.board.bands{display:block;overflow-x:visible}
.board .band{border-top:1px solid var(--color-border);padding-top:2px;margin-bottom:10px}
.board .band:first-child{border-top:none;padding-top:0}
.board .band-h{display:flex;align-items:center;gap:8px;padding:6px 4px;cursor:pointer;user-select:none;-webkit-user-select:none}
.board .band-h .band-name{font-size:12px;font-weight:600;color:var(--color-text-secondary)}
.board .band-h .chip{font-size:11.5px}
.board .band-n{font-size:11px;font-weight:600;color:var(--color-text-secondary)}
.board .band-h .chev{color:var(--color-text-disabled);font-size:15px;display:inline-block;transition:transform var(--duration-fast) var(--ease-standard)}
.board .band-h .chev.open{transform:rotate(90deg)}
.board .band-lanes{display:flex;gap:12px;align-items:flex-start;overflow-x:auto;padding-bottom:8px}

/* drag-and-drop (ui/drag.ts): the gesture layer over the lane control's one
   write path. can-drag is set only when the lane column hosts a control on a
   writable host — a read-only board offers no grab affordance at all. */
.board.can-drag .lane table.det[data-layout=cards-wide] tr:not(.frow-tr):not(.fbrow-tr){cursor:grab}
body.board-dragging{user-select:none;-webkit-user-select:none;cursor:grabbing}
/* the lane the drop would land in */
.board .lane.drop-target{border-color:var(--color-accent);box-shadow:inset 0 0 0 1px var(--color-accent)}
/* the ghost slot the card left behind */
.board .lane table.det[data-layout=cards-wide] tr.drag-ghost{opacity:.35;border-style:dashed}
/* the floating clone: the card's own tr in the cards-wide skeleton, body-
   appended (menu.ts ruling — no ancestor overflow can clip it). Its tbody
   holds ONLY the card, so the hide-the-header first-child rule is re-opened
   and the card border drawn here. */
.drag-clone{position:fixed;z-index:75;pointer-events:none;opacity:.96;box-shadow:0 10px 28px rgba(0,0,0,.28);border-radius:var(--radius-element)}
.drag-clone table.det[data-layout=cards-wide]{display:block}
.drag-clone table.det[data-layout=cards-wide] tr:not(.frow-tr):not(.fbrow-tr),
.drag-clone table.det[data-layout=cards-wide] tr:first-child:not(.frow-tr):not(.fbrow-tr){display:block;border:1px solid var(--color-border);border-radius:var(--radius-element);background:var(--color-background-surface);padding:12px 14px;margin:0}
.drag-clone.drag-wait{opacity:.6}
.drag-clone.snap-back{transition:left .18s ease,top .18s ease,opacity .18s ease;opacity:.4}

/* ---- timeline: bars on the data's own time grid ---------------------------
   Frozen rail on the left (sticky inside the widget's own horizontal
   scroller), tracks share one percentage domain from ../timeline.ts, the
   today line only exists inside that domain. Only a bar whose block declares
   a gesture-shaped date form wears the grab cursor and handles (tl-can-drag,
   set by TimelineView) — concepts-mode and read-only bars stay inert. */
.tl{margin-top:14px;border:1px solid var(--color-border);border-radius:var(--radius-element);overflow-x:auto;background:var(--color-background-surface)}
/* .tl-in: the deps overlay's positioning box. It spans the rows' full laid-out
   width (same min-width), so the overlay's percentage x-space stays the
   tracks' even when .tl scrolls on a narrow screen — sized against the
   scrolling .tl itself the connectors would compress to the viewport while
   the bars kept their min-width, landing arrows inside the wrong bars. */
.tl-in{position:relative;min-width:560px}
.tl-row{display:flex;align-items:stretch;height:32px;border-top:1px solid var(--color-border);min-width:560px}
.tl-row:first-child{border-top:0}
.tl-rail{flex:0 0 200px;max-width:200px;padding:7px 10px;font-size:12.5px;position:sticky;left:0;z-index:2;background:var(--color-background-surface);border-right:1px solid var(--color-border);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tl-track{position:relative;flex:1 1 auto;min-width:360px}
.tl-axis{height:26px}
.tl-tick{position:absolute;top:5px;font-size:10.5px;color:var(--color-text-secondary);border-left:1px solid var(--color-border);padding-left:4px;white-space:nowrap}
.tl-line{position:absolute;top:0;bottom:0;border-left:1px solid var(--color-border);opacity:.45}
.tl-bar{position:absolute;top:9px;height:14px;min-width:4px;border-radius:4px;opacity:.9}
.tl-today{position:absolute;top:0;bottom:0;border-left:2px solid var(--color-error);z-index:1}
.tl-missing{margin-top:10px}
.tl-miss{font-size:12.5px;padding:2px 0}
/* dependency connectors: the overlay shares the tracks' percentage domain on
   x and counts rows on y (viewBox 100 × rows, preserveAspectRatio none); the
   rail offset and axis height below must match .tl-rail / .tl-axis above */
.tl-deps{position:absolute;left:200px;top:26px;width:calc(100% - 200px);height:calc(100% - 26px);pointer-events:none;z-index:1}
.tl-dep{fill:none;stroke:var(--color-text-secondary);stroke-width:1.4;opacity:.65}
/* the drag gesture (tl-drag.ts): handles, live-preview tip, refusal snap-back */
.tl-bar.tl-can-drag{cursor:grab;touch-action:none}
.tl-h{position:absolute;top:0;bottom:0;width:7px;cursor:ew-resize;opacity:0}
.tl-h[data-tl-h=start]{left:0;border-radius:4px 0 0 4px}
.tl-h[data-tl-h=end]{right:0;border-radius:0 4px 4px 0}
.tl-bar.tl-can-drag:hover .tl-h{opacity:.55;background:var(--color-text-primary)}
.tl-bar.tl-lift{opacity:1;z-index:3;cursor:grabbing;box-shadow:var(--shadow-high)}
.tl-bar.tl-wait{opacity:.6}
.tl-bar.tl-snap{transition:left .18s ease,width .18s ease;opacity:.5}
body.tl-dragging{user-select:none;cursor:grabbing}
.tl-tip{position:fixed;z-index:1000;pointer-events:none;font-family:var(--font-family-code);font-size:11px;padding:2px 7px;border-radius:4px;background:var(--color-background-inverted,#222);color:var(--color-background-surface);white-space:nowrap}
.tl-rail .tl-edit{margin-left:6px;border:0;background:none;cursor:pointer;color:var(--color-text-secondary);font-size:11px;padding:0 2px}
.tl-rail .tl-edit:hover{color:var(--color-text-primary)}
.tl-miss .fa-btn{margin-left:8px}
/* board-card dep badges: ref id + the target's derived-state chip */
.cardhead .deps{display:inline-flex;align-items:center;gap:6px;flex-wrap:wrap}
.cardhead .dep{display:inline-flex;align-items:center;gap:4px}
.cardhead .dep-id{font-family:var(--font-family-code);font-size:11px;color:var(--color-text-secondary)}
.cardhead .dep .chip{font-size:10px;padding:1px 7px}

/* ── Motion layer (E30) ─────────────────────────────────────────────────────
   The Astryx duration/ease tokens spent on entrance, view transitions and
   reflow, so the surface feels alive the way Linear's does. Keyed on the
   root's data-motion (the dashboard's declared ceiling: full · reduced · off)
   AND gated by the reader's prefers-reduced-motion (the floor). FLIP reflow
   lives in flip.ts; this is the CSS half — enter, and the transitions the
   board/rows never spelled. Additive: with motion off, or under reduced
   motion, the page is exactly what it was before. */
@keyframes dj-view-in{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
@keyframes dj-rise{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
/* the view swap: content settles up as it appears */
[data-motion=full] .entering #content>*,[data-motion=full] .entering #dash{animation:dj-view-in var(--duration-medium-min) var(--ease-standard) both}
/* entrance stagger — tiles, cards and lanes rise as the view lands; capped at
   six steps so a long list never delays its own tail visibly */
[data-motion=full] .entering .tile,[data-motion=full] .entering .card,[data-motion=full] .entering .board .lane{animation:dj-rise var(--duration-fast-max) var(--ease-standard) both}
[data-motion=full] .entering .tile:nth-child(1),[data-motion=full] .entering .card:nth-child(1),[data-motion=full] .entering .board .lane:nth-child(1){animation-delay:0ms}
[data-motion=full] .entering .tile:nth-child(2),[data-motion=full] .entering .card:nth-child(2),[data-motion=full] .entering .board .lane:nth-child(2){animation-delay:28ms}
[data-motion=full] .entering .tile:nth-child(3),[data-motion=full] .entering .card:nth-child(3),[data-motion=full] .entering .board .lane:nth-child(3){animation-delay:56ms}
[data-motion=full] .entering .tile:nth-child(4),[data-motion=full] .entering .card:nth-child(4),[data-motion=full] .entering .board .lane:nth-child(4){animation-delay:84ms}
[data-motion=full] .entering .tile:nth-child(5),[data-motion=full] .entering .card:nth-child(5),[data-motion=full] .entering .board .lane:nth-child(5){animation-delay:112ms}
[data-motion=full] .entering .tile:nth-child(n+6),[data-motion=full] .entering .card:nth-child(n+6),[data-motion=full] .entering .board .lane:nth-child(n+6){animation-delay:140ms}
/* the interactions the tokens were made for but the base sheet left flat.
   Under full AND reduced — a hover/press cue is feedback, not decoration. */
[data-motion=full] .tile,[data-motion=reduced] .tile{transition:transform var(--duration-fast) var(--ease-standard),box-shadow var(--duration-fast) var(--ease-standard),border-color var(--duration-fast) var(--ease-standard)}
[data-motion=full] .tile.link:hover,[data-motion=reduced] .tile.link:hover{transform:translateY(-1px)}
[data-motion=full] .board.can-drag .lane table.det[data-layout=cards-wide] tr:not(.frow-tr):not(.fbrow-tr),[data-motion=reduced] .board.can-drag .lane table.det[data-layout=cards-wide] tr:not(.frow-tr):not(.fbrow-tr){transition:box-shadow var(--duration-fast) var(--ease-standard),border-color var(--duration-fast) var(--ease-standard)}
[data-motion=full] .board.can-drag .lane table.det[data-layout=cards-wide] tr:not(.frow-tr):not(.fbrow-tr):hover,[data-motion=reduced] .board.can-drag .lane table.det[data-layout=cards-wide] tr:not(.frow-tr):not(.fbrow-tr):hover{border-color:var(--color-border-emphasized);box-shadow:var(--shadow-med)}
[data-motion=full] .chip,[data-motion=reduced] .chip{transition:background var(--duration-fast) var(--ease-standard),color var(--duration-fast) var(--ease-standard)}
/* E42 §4.3 — the list-row hover wash rides the same motion layer; the base
   sheet stays motionless. Scope is TABLE MODE, which includes a
   layout.narrow: cards block above its breakpoint — only cards-wide (cards
   at every width) never renders as a table; the narrow-cards @media block
   carries the card-mode cancel, mirroring its hover/clamp cancels. */
[data-motion=full] table.det:not([data-layout=cards-wide]) td,[data-motion=reduced] table.det:not([data-layout=cards-wide]) td{transition:background var(--duration-fast) var(--ease-standard)}
@media(max-width:760px){
[data-motion=full] table.det[data-layout=cards] td,[data-motion=reduced] table.det[data-layout=cards] td{transition:none}
}
/* the reader's floor beats the author's ceiling: reduced-motion silences
   ENTRANCE and the view swap (flip.ts checks the same query for reflow),
   leaving only the instant feedback above */
@media (prefers-reduced-motion: reduce){
[data-motion=full] .entering #content>*,[data-motion=full] .entering #dash,[data-motion=full] .entering .tile,[data-motion=full] .entering .card,[data-motion=full] .entering .board .lane{animation:none}
}
/* ── The side peek (E38): a record over the board, the board kept ───────────
   A right-side panel above the live view — under the toast (z 60: a write
   made inside the peek must keep its undo visible), under menus (80) and the
   palette (90), above the page. The slide/fade spends the same Astryx motion
   tokens as everything else, keyed on the declared ceiling (data-motion) and
   silenced by the reader's prefers-reduced-motion floor. */
.peek-scrim{position:fixed;inset:0;z-index:56;background:var(--color-overlay)}
.peek{position:fixed;top:0;right:0;bottom:0;z-index:57;width:min(640px,94vw);box-sizing:border-box;
  display:flex;flex-direction:column;background:var(--color-background-surface);
  border-left:1px solid var(--color-border);box-shadow:var(--shadow-high);outline:none}
.peek-top{display:flex;align-items:center;gap:var(--spacing-2);flex:none;
  padding:10px 14px;border-bottom:1px solid var(--color-border)}
.peek-pos{margin-left:auto;font-variant-numeric:tabular-nums;font-family:var(--font-family-code);
  font-size:11px;color:var(--color-text-disabled)}
.peek-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding:8px 26px 44px}
/* the record view's own "← back" is page chrome — inside the peek the panel's
   ✕/scrim/Escape are the way back, and a second, differently-aimed back lies */
.peek .back{display:none}
@keyframes dj-peek-in{from{transform:translateX(24px);opacity:0}to{transform:none;opacity:1}}
[data-motion=full] .peek{animation:dj-peek-in var(--duration-medium-min) var(--ease-standard) both}
[data-motion=full] .peek-scrim{animation:dj-bfade var(--duration-fast-max) var(--ease-standard) both}
@media (prefers-reduced-motion: reduce){
[data-motion=full] .peek,[data-motion=full] .peek-scrim{animation:none}
}
/* palette anatomy (E30): typeahead header, tone dots, numeric shortcuts */
.menu-grp{padding:8px 10px 4px;font-size:10.5px;text-transform:uppercase;letter-spacing:.08em;
  font-weight:600;color:var(--color-text-disabled);user-select:none}
.menu-grp:first-child{padding-top:6px}
.menu-hd{position:sticky;top:calc(-1 * var(--spacing-1));margin:calc(-1 * var(--spacing-1)) calc(-1 * var(--spacing-1)) 0;padding:var(--spacing-1);background:var(--color-background-popover);border-bottom:1px solid var(--color-border);z-index:1}
.menu-q{width:100%;box-sizing:border-box;padding:var(--spacing-2);border:none;outline:none;background:transparent;font:inherit;font-size:var(--text-label-size);color:var(--color-text-primary)}
.menu-q::placeholder{color:var(--color-text-disabled)}
.menu-dot{width:9px;height:9px;border-radius:var(--radius-full);flex:none;border:1px solid var(--color-border)}
.menu-lbl{flex:1 1 auto;overflow:hidden;text-overflow:ellipsis}
.menu-num{margin-left:var(--spacing-3);font-family:var(--font-family-code);font-size:11px;color:var(--color-text-disabled);border:1px solid var(--color-border);border-radius:var(--radius-inner);padding:0 5px;line-height:16px}
.menu-item.hl{background:var(--color-overlay-hover)}
.menu-item .menu-check{width:14px;text-align:center;color:var(--color-text-accent)}
/* progress chips (E30): ring + label, the icon carries the tone */
.pchip{display:inline-flex;align-items:center;gap:6px;font-size:var(--dj-text-ui-2);color:var(--color-text-primary);white-space:nowrap}
.pchip .pring,.menu-ic .pring,.ctl.pctl .pring{display:block;flex:none}
.menu-ic{display:inline-flex;align-items:center;width:14px;flex:none}
.ctl.pctl{background:transparent;border-color:transparent}
.ctl.pctl:hover{border-color:var(--color-border-emphasized);background:var(--color-overlay-hover)}
/* person chips (E34): round initial + display name — an unresolved handle is
   the muted handle itself, a state, not an error */
.person{display:inline-flex;align-items:center;gap:6px;font-size:var(--dj-text-ui-2);color:var(--color-text-primary);white-space:nowrap}
.person+.person{margin-left:var(--spacing-3)}
.person .pini{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;border-radius:var(--radius-full);background:var(--color-background-muted);color:var(--color-text-secondary);font-size:10px;font-weight:600;flex:none}
.person.unres{color:var(--color-text-disabled)}
/* the facepile — several people, one glance: the chip's initial circle,
   stacked with a surface-toned ring so overlapped faces stay countable.
   Names live in the titles/aria-label; +N is the overflow's honest
   arithmetic. Unresolved faces are muted, a state, not an error. */
.facepile{display:inline-flex;align-items:center}
.facepile .face{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;border-radius:var(--radius-full);background:var(--color-background-muted);color:var(--color-text-secondary);font-size:10px;font-weight:600;flex:none;box-shadow:0 0 0 1.5px var(--color-background-surface)}
.facepile .face+.face{margin-left:-5px}
.facepile .face.unres{color:var(--color-text-disabled)}
.facepile .face.more{background:var(--color-background-surface);box-shadow:0 0 0 1px var(--color-border)}
/* board cards, the captured Linear anatomy (E30): separated cards (not a
   joined frame) inside the lane, dim mono eyebrow, tight metrics, chips as
   bordered mini-pills, a lifted hover. Scoped to .board so document views
   and narrow-card layouts keep their joined-frame look. */
.board .lane table.det[data-layout=cards-wide] tr:not(.frow-tr):not(.fbrow-tr){
  border:1px solid var(--color-border);border-radius:var(--radius-element);
  background:var(--color-background-surface);padding:var(--dj-card-pad);margin:0 0 8px;box-shadow:var(--shadow-low)}
.board .lane table.det[data-layout=cards-wide] tbody>tr:nth-child(2):not(.frow-tr){border-top:1px solid var(--color-border)}
.board .lane .cardhead{min-height:20px}
/* E42 §5 — the card: role contract in BOARD scope, full-path selectors so
   these beat the generic cards-wide rules (the old .board .lane td.* spellings
   lost on specificity and never actually applied). Eyebrow: mono identity at
   the meta size; title: THE card text, 13px/500, 2-line clamp. */
.board .lane table.det[data-layout=cards-wide] td.c-eyebrow{font-family:var(--font-family-code);font-size:var(--dj-text-meta);letter-spacing:0;color:var(--color-text-disabled)}
.board .lane table.det[data-layout=cards-wide] td.c-title{font-size:var(--dj-text-ui);font-weight:500;line-height:1.35;margin:0 0 4px;padding:2px 0 0;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden}
/* field on a BOARD card: value only, one quiet clamped line — the data-label
   eyebrow is the document-cards spelling; deliberately compact here but never
   silently dropped (a Linear-pure 3-line card declares card: hide) */
.board .lane table.det[data-layout=cards-wide] td.c-field::before{display:none}
.board .lane table.det[data-layout=cards-wide] td.c-field{font-size:var(--dj-text-ui-2);color:var(--color-text-secondary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* the inner wrapper span must not re-wrap what the cell just clamped (the
   card-mode span cancel sets white-space:normal at lower specificity) */
.board .lane table.det[data-layout=cards-wide] td.c-field>span{white-space:nowrap}
.board .lane .chip{font-size:11px;padding:1px 8px;border:1px solid var(--color-border)}
.board .lane .pchip{font-size:12px}
.board .lane-h .chip{font-size:11.5px}
/* the lane itself: quieter ground, the cards carry the surface */
.board .lane{background:transparent;border:none;padding:0 4px}
.board .lane-h{padding:4px 6px 10px;position:sticky;top:0}
/* ⌘K jump list (E30): navigation + documents above the row results */
.jump{margin-bottom:var(--spacing-3)}
.jump-h{font-size:10.5px;text-transform:uppercase;letter-spacing:.08em;color:var(--color-text-disabled);font-weight:600;padding:2px 4px 6px}
.jump-i{display:flex;align-items:center;gap:var(--spacing-2);width:100%;box-sizing:border-box;padding:7px 10px;border:none;background:transparent;cursor:pointer;text-align:left;border-radius:var(--radius-element);font:inherit;font-size:var(--text-label-size);color:var(--color-text-primary)}
.jump-i:hover,.jump-i.hl{background:var(--color-overlay-hover)}
.jump-l{flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.jump-g{font-size:11px;color:var(--color-text-disabled)}
/* side panel + modal polish (E30): Linear's metrics on the declared nav —
   tighter section labels, tabular counts, calmer dividers; the dialog rises
   and its backdrop fades on the same tokens everything else spends. */
.nav-sec{display:flex;align-items:center;gap:4px;font-size:10.5px;text-transform:uppercase;letter-spacing:.08em;color:var(--color-text-disabled);font-weight:600;padding:14px 12px 4px;cursor:pointer;user-select:none}
.nav-sec:hover{color:var(--color-text-secondary)}
.nav-item{padding:5px 10px;border-radius:8px;font-size:13px;gap:8px;min-height:18px}
.nav-item .n{font-variant-numeric:tabular-nums;font-size:11px}
.nav-item .dot{width:5px;height:5px}
.nav-item.sub{padding-left:30px;font-size:12.5px}
/* the icon slot: Linear's metrics — 15px outline strokes in the sidebar's
   muted ink, warming to full ink with the row. An icon-less child indents
   behind a RAIL instead (the "Upcoming under Cycles" spelling). */
.nav-ic{display:inline-flex;flex:none;width:15px;color:var(--color-text-secondary)}
.nav-item:hover .nav-ic,.nav-item.on .nav-ic{color:var(--color-text-primary)}
.nav-lbl{flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.nav-item.sub.rail{margin-left:17px;padding-left:12px;border-left:1.5px solid var(--color-border);border-top-left-radius:0;border-bottom-left-radius:0}
/* section + parent chevrons: declared position, rotated open, on the motion tokens */
.nav-chev{flex:none;transition:transform var(--duration-fast) var(--ease-standard)}
.nav-chev.open{transform:rotate(90deg)}
.nav-twist{display:inline-flex;align-items:center;justify-content:center;margin-left:auto;width:18px;height:18px;border:none;border-radius:var(--radius-element);background:transparent;color:var(--color-text-disabled);cursor:pointer;padding:0;opacity:0;transition:opacity var(--duration-fast) var(--ease-standard)}
.nav-item.parent:hover .nav-twist,.nav-twist:focus-visible{opacity:1}
.nav-twist:hover{background:var(--color-overlay-hover);color:var(--color-text-primary)}
.nav-item.parent .n{margin-left:auto}
.nav-item.parent:hover .n{display:none}
#side{border-right:1px solid var(--color-border)}
dialog[open]{animation:dj-rise var(--duration-fast-max) var(--ease-standard)}
dialog::backdrop{background:var(--color-overlay);animation:dj-bfade var(--duration-fast-max) var(--ease-standard)}
@keyframes dj-bfade{from{opacity:0}to{opacity:1}}
@media (prefers-reduced-motion: reduce){dialog[open],dialog::backdrop{animation:none}}

/* ---- E32 t4: the report surface -------------------------------------------
   One scrolling, page-headed document ([data-surface=report], stamped by
   main.tsx from the payload's surface key): a centred reading column, the
   title block, a generated TOC, section headings — and, under @media print,
   the print-shaped medium the report KIND declares (§1.4): the TOC, the
   concept overlay and every interactive affordance hidden, sections kept
   whole where the engine can ask for it, chips and links degraded to ink.
   Real Astryx tokens only — the report recolors with the same theme:
   overrides as every other surface. */
[data-surface=report]{background:var(--color-background-body)}
[data-surface=report] #root{display:block}
#report{max-width:840px;margin:0 auto;padding:56px 40px 80px}
.rpt-head h1{font-size:28px;font-weight:700;letter-spacing:-.02em;margin:0}
.rpt-sub{font-size:15px;color:var(--color-text-secondary);margin:8px 0 0;max-width:64ch}
.rpt-date{font-family:var(--font-family-code);font-size:12px;color:var(--color-text-disabled);margin-top:10px}
.rpt-toc{margin:28px 0 8px;padding:16px 20px;background:var(--color-background-surface);border:1px solid var(--color-border);border-radius:var(--radius-container)}
.rpt-toc-head{font-size:11px;text-transform:uppercase;letter-spacing:.09em;color:var(--color-text-disabled);font-weight:600;margin-bottom:8px}
.rpt-toc-item{display:block;padding:3px 0;font-size:13.5px;color:var(--color-text-secondary);cursor:pointer;user-select:none}
.rpt-toc-item:hover{color:var(--color-text-primary)}
.rpt-sec{margin-top:40px;padding-top:8px;border-top:1px solid var(--color-border)}
.rpt-sec-label{font-size:20px;font-weight:650;letter-spacing:-.01em;margin:16px 0 4px}
.rpt-notes{margin:8px 0 4px;max-width:70ch}
.rpt-view{margin-top:12px}
.rpt-view-label{font-size:15px;font-weight:600;margin:20px 0 0}
.rpt-foot{margin-top:56px;padding-top:14px;border-top:1px solid var(--color-border);font-size:11.5px;color:var(--color-text-disabled)}
/* the #/c/ overlay: the document view OVER the report, reader's place kept */
.rpt-overlay{position:fixed;inset:0;z-index:40;overflow-y:auto;background:var(--color-background-body)}
.rpt-overlay-inner{max-width:840px;margin:0 auto;padding:40px}
@media print{
  [data-surface=report] .rpt-toc,[data-surface=report] .rpt-overlay,
  [data-surface=report] #pending,[data-surface=report] .toast-host{display:none!important}
  [data-surface=report] body{background:#fff}
  #report{max-width:none;padding:0}
  .rpt-sec{break-inside:avoid-page}
  /* chips and links degrade to ink: paper has no hover and no palette */
  [data-surface=report] .chip,[data-surface=report] .pchip{background:none;color:inherit;border:1px solid var(--color-border)}
  [data-surface=report] a,[data-surface=report] [data-open],[data-surface=report] [data-path]{color:inherit;text-decoration:none}
}

/* E37 — the record view. The affordance rule is attribute-keyed so it costs
   pre-E37 pages nothing: no record view in the payload, no data-open-record
   in the DOM, no styled element. */
[data-open-record]{cursor:pointer}
[data-open-record]:hover{text-decoration:underline;text-underline-offset:2px}
.rec-crumb-doc{cursor:pointer}
.rec-crumb-doc:hover{color:var(--color-text-primary);text-decoration:underline;text-underline-offset:2px}
.rec-body{margin-top:14px;max-width:70ch}
/* E42 §6 — the record page is Linear's peek widened: a 22px title (record
   view ONLY — document-view h2.title keeps its 27px), the status row under
   it, then a compact properties RAIL that reads as metadata, not a table:
   no box, no hairlines, quiet label column. In the peek the same title
   drops to 17px. */
h2.rec-title{font-size:22px;font-weight:650;letter-spacing:-.02em}
.peek h2.rec-title{font-size:17px;font-weight:600}
.rec-props{margin-top:12px;padding:2px 0}
/* E43 §13.3 — the rail row is icon · label · value/control: a 16px
   mechanics-only icon slot (ring / face / tone dot / empty), the quiet label
   column, then the value — which on a control row is the SAME 28px trigger
   the table cell renders, and its box sets the row height. */
.rec-prop{display:flex;gap:10px;padding:4px 0;font-size:var(--dj-text-ui);align-items:center}
.rec-prop-i{flex:0 0 16px;width:16px;height:16px;display:inline-flex;align-items:center;justify-content:center;color:var(--color-text-secondary)}
.rec-prop-i .pring{display:block;flex:none}
.rec-prop-i .tdot{width:8px;height:8px;border-radius:50%;display:block}
.rec-prop-l{flex:0 0 var(--dj-rail-label);color:var(--color-text-secondary);font-size:var(--dj-text-ui-2)}
.rec-prop-v{min-width:0;font-size:var(--dj-text-ui)}
.rec-prop .ctl{min-height:var(--dj-control-h)}
/* §13.2 — the text rung's trigger: same .ctl anatomy, pencil instead of a
   chevron, quiet until hovered (the pctl treatment — the value is prose, a
   pill background would shout) */
.ctl.tctl{background:transparent;border-color:transparent;font-weight:500;font-size:var(--dj-text-ui);max-width:100%;min-width:0}
.ctl.tctl:hover{border-color:var(--color-border-emphasized);background:var(--color-overlay-hover)}
/* E43 review — the text trigger clamps exactly as the plain cell it replaces
   (§4.4/§4.5): one ellipsized line capped at the same --dj-clamp-w, so §4's
   ~36px rows survive a md column adopting control: (the measured offender:
   208px description pills). The full value stays reachable — the trigger's
   title attr, and the modal it opens holds the whole text. */
.ctl.tctl .ctl-val{min-width:0;max-width:var(--dj-clamp-w);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ctl-pen{flex:none;opacity:.7}
/* §13.4 — the title's ghost pencil: hover/focus-within reveal */
.rec-title-row{display:flex;align-items:center;gap:6px}
.rec-title-row .rec-title-edit{opacity:0;transition:opacity var(--transition-fast)}
.rec-title-row:hover .rec-title-edit,.rec-title-row:focus-within .rec-title-edit{opacity:1}
/* §13.5 — the body's edit affordance, and the empty body's quiet + line */
.rec-bodywrap{position:relative}
.rec-bodywrap .rec-body-edit{position:absolute;top:14px;right:0;font-size:var(--dj-text-ui-2);color:var(--color-text-secondary)}
.rec-body-add{display:block;border:0;background:none;padding:6px 0;margin-top:14px;font:inherit;
  font-size:var(--dj-text-ui-2);color:var(--color-text-disabled);cursor:pointer;text-align:left}
.rec-body-add:hover{color:var(--color-text-secondary)}

/* E36 t5 — dj/comments' thread panel + composer. Attribute/class-keyed like
   the record view above: no installed plugin, no panel in the DOM, no styled
   element — pre-t5 pages cost nothing. */
.cmt-panel{margin-top:12px}
.cmt{padding:10px 0;border-top:1px solid var(--color-border)}
.cmt:first-child{border-top:0}
.cmt.pending{opacity:.55}
.cmt-people{margin-bottom:8px}
.cmt-head{display:flex;align-items:baseline;gap:10px;font-size:12.5px}
.cmt-you{color:var(--color-text-secondary);font-weight:600}
.cmt-at{color:var(--color-text-disabled);font-size:11.5px}
.cmt-acts{margin-left:auto;display:flex;gap:10px;opacity:0}
.cmt:hover .cmt-acts,.cmt:focus-within .cmt-acts{opacity:1}
.cmt-body{margin-top:4px;font-size:13.5px;max-width:70ch}
.cmt-body p{margin:0 0 6px}
.cmt-body p:last-child{margin-bottom:0}
.cmt-resolved{display:flex;align-items:baseline;gap:12px;margin:8px 0;padding:6px 12px;
  border:1px solid var(--color-border);border-radius:var(--radius-element);
  background:var(--color-background-muted);font-size:12.5px;color:var(--color-text-secondary)}
.cmt-thread-acts{margin-top:6px}
.cmt-composer{margin-top:10px}
/* the control's box matches .fform's exactly (border 1px, radius 8, padding
   8/10, 13.5px) because the mention MIRROR is drawn to that box — any
   divergence shows as tags drifting off their own text. The surface colour
   lives on .mfield: the textarea itself stays transparent so tags show
   through (the E34 rule above). */
.cmt-composer .mfield{background:var(--color-background-body);border-radius:8px}
.cmt-composer .mfield textarea{width:100%;min-height:64px;resize:vertical;font:inherit;font-size:13.5px;
  border:1px solid var(--color-border);border-radius:8px;padding:8px 10px;color:var(--color-text-primary)}
.cmt-composer .mfield textarea:focus{outline:none;border-color:var(--color-border-emphasized)}
.cmt-send{display:flex;justify-content:flex-end;gap:8px;margin-top:6px}

/* ---- E39 t1: dj/reactions' bar --------------------------------------------
   One row of small pill buttons — the glyph, its count, and a `mine` ring
   drawn with the SAME emphasis border every selected control in this product
   wears (no new colour vocabulary for a feature that is eight glyphs). The
   resting bar shows only what somebody said; `+` opens the rest. A chip the
   door did not authorise is `disabled` in fact, and reads as inert rather
   than as broken. */
.rx-bar{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-top:8px}
.rx-chip{display:inline-flex;align-items:center;gap:5px;padding:2px 8px;font:inherit;font-size:13px;
  line-height:20px;cursor:pointer;border:1px solid var(--color-border);border-radius:999px;
  background:var(--color-background-body);color:var(--color-text-secondary)}
.rx-chip:hover:not(:disabled){border-color:var(--color-border-emphasized)}
.rx-chip.mine{border-color:var(--color-border-emphasized);background:var(--color-background-muted);
  color:var(--color-text-primary)}
.rx-chip.empty{opacity:.6}
.rx-chip:disabled{cursor:default;opacity:.5}
.rx-emoji{font-size:14px;line-height:1}
.rx-n{font-size:11.5px;font-variant-numeric:tabular-nums}
.rx-more{padding:2px 9px;font:inherit;font-size:13px;line-height:20px;cursor:pointer;
  border:1px dashed var(--color-border);border-radius:999px;background:transparent;
  color:var(--color-text-disabled)}
.rx-more:hover{border-style:solid;color:var(--color-text-secondary)}
.rx-note{font-size:12px}

/* ---- E39 t2: dj/attachments' panel ----------------------------------------
   A list, not a gallery (see the component header: no thumbnails, no drag
   overlay, no guessed progress bar). Each row is name · size · who · when,
   with Remove revealed on hover the way a comment's actions are. The native
   file input is hidden behind a real Button so the control matches every
   other control on the page — the input still exists and still works with a
   keyboard, it just isn't what the reader sees. */
.att-panel{margin-top:12px}
.att{display:flex;align-items:baseline;gap:10px;padding:8px 0;font-size:13px;
  border-top:1px solid var(--color-border)}
.att:first-child{border-top:0}
.att.pending{opacity:.55}
.att-name{font-weight:500;overflow-wrap:anywhere}
.att-meta{color:var(--color-text-disabled);font-size:11.5px}
.att-you{color:var(--color-text-secondary);font-weight:600}
.att-acts{margin-left:auto;opacity:0}
.att:hover .att-acts,.att:focus-within .att-acts{opacity:1}
.att-add{margin-top:10px}
/* clipped rather than display:none — a hidden-by-display input is skipped by
   some assistive tooling, and the label the Button carries is the accessible
   name either way */
.att-input{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* ---- E40 t1: the form surface ---------------------------------------------
   One centred card on an empty page ([data-surface=form], stamped by main.tsx
   from the payload's surface key): the title block, the intro prose, the
   declared form's own fields, one submit — and, after the write lands, the
   thank-you in the card's place. No sidebar, no top bar, no overlay: the
   person this page is built for is not reading the knowledge base.
   Real Astryx tokens only, and every rule is keyed off [data-surface=form] or
   an .fm- class that only this surface renders, so no other page pays a byte
   for it. The FIELD chrome itself is .fform's, unchanged — an intake field
   looks like the same field inside a record panel because it IS one. */
[data-surface=form]{background:var(--color-background-muted)}
[data-surface=form] #root{display:block}
#form-surface{min-height:100vh;display:flex;align-items:flex-start;justify-content:center;padding:56px 20px 80px}
.fm-card{width:100%;max-width:600px;background:var(--color-background-surface);
  border:1px solid var(--color-border);border-radius:var(--radius-container);padding:32px 32px 20px}
.fm-head h1{font-size:23px;font-weight:650;letter-spacing:-.02em;margin:0}
.fm-sub{font-size:14px;color:var(--color-text-secondary);margin:8px 0 0;max-width:60ch}
.fm-intro{margin:16px 0 4px;max-width:64ch;font-size:13.5px;color:var(--color-text-secondary)}
.fm-fields{padding:16px 0 0}
.fm-set{border:0;margin:0;padding:0;min-width:0}
.fm-set[disabled] .flabel{color:var(--color-text-disabled)}
.fm-row{justify-content:flex-start}
.fm-note{font-size:12.5px;color:var(--color-text-secondary);background:var(--color-background-muted);
  border-radius:var(--radius-element);padding:10px 12px;margin-top:14px}
.fm-thanks{padding:24px 0 8px;text-align:center}
.fm-thanks-mark{width:34px;height:34px;margin:0 auto 12px;border-radius:50%;
  background:var(--color-success-muted);color:var(--color-success);
  display:flex;align-items:center;justify-content:center;font-size:17px}
.fm-thanks-msg{font-size:15px;margin:0 0 10px;max-width:48ch;margin-left:auto;margin-right:auto}
.fm-thanks-addr{display:inline-block;font-family:var(--font-family-code);font-size:12.5px;
  color:var(--color-text-secondary);margin-bottom:14px}
a.fm-thanks-addr{color:var(--color-text-blue);text-decoration:none}
a.fm-thanks-addr:hover{text-decoration:underline;text-underline-offset:2px}
.fm-foot{margin-top:22px;padding-top:12px;border-top:1px solid var(--color-border);
  font-size:11px;color:var(--color-text-disabled)}

/* ---- E39 t4: dj/approvals' panel -------------------------------------------
   A list of sign-offs, not a workflow diagram (see the component header: no
   chain drawing, no reminder button, no re-cast affordance). Each row is
   reviewer · verdict · date, with the reviewer drawn by the payload's own
   person-chip ladder so it matches the table cell exactly. The cast row
   appears only on your own open request, and a request the door has taken but
   the payload has no home for yet reads `pending` — the same muted treatment
   an uploading attachment wears, for the same reason. */
.ap-panel{margin-top:10px}
.ap-count{font-size:11.5px;margin:0 0 8px}
.ap{padding:8px 0;border-top:1px solid var(--color-border);font-size:13px}
.ap:first-child{border-top:0}
.ap.pending{opacity:.55}
.ap-line{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap}
.ap-who{font-weight:500}
.ap-verdict{font-size:11.5px;padding:1px 8px;border-radius:999px;
  border:1px solid var(--color-border);color:var(--color-text-secondary)}
.ap-verdict[data-verdict=approved]{border-color:var(--color-success);color:var(--color-success)}
.ap-verdict[data-verdict="changes requested"]{border-color:var(--color-warning);color:var(--color-warning)}
.ap-verdict[data-verdict=declined]{border-color:var(--color-error);color:var(--color-error)}
.ap-verdict.muted{border-style:dashed;color:var(--color-text-disabled)}
.ap-meta{margin-left:auto;font-size:11.5px;color:var(--color-text-disabled);
  font-variant-numeric:tabular-nums}
.ap-noteline{margin:6px 0 0;font-size:12.5px;color:var(--color-text-secondary);max-width:64ch}
.ap-cast,.ap-ask{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:8px}
.ap-note,.ap-handle{flex:1 1 180px;min-width:0;font:inherit;font-size:12.5px;padding:5px 9px;
  border:1px solid var(--color-border);border-radius:var(--radius-element);
  background:var(--color-background-body);color:var(--color-text-primary)}

/* ---- E39 t5: dj/presence' facepile -----------------------------------------
   THE DASHED OUTLINE IS THE COMPLIANCE STORY (ruling P19). A presence handle
   is self-reported and unverifiable, so it must not be mistakable for the
   resolved person chip at a glance — hence a shape that appears nowhere else
   in this product: dashed border, no avatar, no display name, muted text, the
   raw @handle only. Small enough to sit beside a heading, quiet enough to be
   ignored, and distinct enough that nobody ever reads it as identity. */
.pr-pile{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-top:8px}
.pr-face{display:inline-flex;align-items:center;padding:1px 8px;font-size:11.5px;line-height:18px;
  border:1px dashed var(--color-border);border-radius:999px;
  background:transparent;color:var(--color-text-disabled);font-family:var(--font-family-code)}
.pr-more{font-size:11.5px;color:var(--color-text-disabled);font-variant-numeric:tabular-nums}

/* ---- E43 §15: the COMPOSER (modal append forms) — and the options chip ----
   The hero title wears the peek-title scale (17px/600 — the thing being
   composed is a record); the E42 mirror rule stands verbatim: restyle the
   input, move .mfield .mmirror by the SAME amounts. Both are placeholders
   over borderless inputs — the field's own declared label is the prompt. */
.fmodal .fform .composer-title input{border:none;background:transparent;width:100%;
  font-size:17px;font-weight:600;line-height:1.35;padding:4px 0}
.fmodal .fform .composer-title input:focus{outline:none}
.fmodal .fform .composer-title .mfield .mmirror{font-size:17px;font-weight:600;line-height:1.35;padding:4px 0}
.fmodal .fform .composer-desc textarea{border:none;background:transparent;width:100%;resize:vertical;
  font-size:var(--dj-text-ui);line-height:1.5;min-height:4.5em;padding:4px 0}
.fmodal .fform .composer-desc textarea:focus{outline:none}
.fmodal .fform .composer-desc .mfield .mmirror{font-size:var(--dj-text-ui);line-height:1.5;padding:4px 0}
.composer-chips{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-top:12px}
/* §15.3 — the chip: a 28px pill on the shared .ctl anatomy (one trigger,
   restyled — never a styled twin). Required-and-unfilled is an OUTLINE,
   presentation only: enforcement stays exactly where it is, [data-ferr]. */
.fchip.fchip{height:var(--dj-control-h);border-radius:var(--radius-element);
  border:1px solid var(--color-border);background:var(--color-background-surface);
  color:var(--color-text-primary);font-size:var(--dj-text-ui-2);font-weight:500;padding:0 10px}
.fchip.fchip-empty{color:var(--color-text-secondary)}
.fchip.fchip-req{border-color:var(--color-border-emphasized)}
.fchip-wrap{display:inline-flex;align-items:center;gap:6px}
.flopts-wrap{display:block;width:100%;max-width:none;overflow:visible;white-space:normal;text-align:left}
.flopts{display:flex;flex-direction:column;gap:2px;max-width:64ch}
.flopt{display:flex;gap:10px;align-items:flex-start;padding:6px 8px;border-radius:var(--radius-element);cursor:pointer}
.flopt:hover{background:var(--dj-hover, var(--color-background-surface))}
.flopt input[type=radio],.flopt input[type=checkbox]{width:14px;height:14px;flex:none;margin:3px 0 0;padding:0;border:none;background:none;accent-color:var(--color-text-orange)}
.flopt-body{display:flex;flex-direction:column;gap:1px;min-width:0}
.flopt-t{font-size:var(--dj-text-ui);color:var(--color-text-primary)}
.flopt.on .flopt-t{font-weight:500}
.flopt-d{font-size:var(--dj-text-ui-2);color:var(--color-text-secondary);line-height:1.45}
.flopt-other{margin-top:4px}
.fchip-wrap .menu-dot{width:8px;height:8px;border-radius:50%;flex:none}
.fchip-other{max-width:220px;font-size:var(--dj-text-ui-2)}
.fcreate-more{display:inline-flex;align-items:center;font-size:var(--dj-text-ui-2);color:var(--color-text-secondary)}
