/* plugins/boards/assets/css/boards.css */
/**
 * Boards app.
 *
 * Loaded on every page while the plugin is active (plugin.json "styles"), so every
 * rule is scoped to .jy-boards, .jy-boards-* or .jy-boards-dialog and stays inert
 * until Boards markup opts in. Colours come from the .jy-ui kit's --jy-* tokens, so
 * light and dark follow the site; the label and board-background colours are fixed
 * palettes chosen to read on either.
 *
 * @version 1.0.0
 */

/* ─── Shell ─────────────────────────────────────────────── */

.jy-boards { color: var(--jy-color-text); }
.jy-boards [hidden],
.jy-boards-dialog [hidden] { display: none !important; }

/* The list, My cards and Import pages are ordinary scrolling content inside the app frame. */
.jy-boards:not([data-page="board"]) {
	flex: 1 1 0;
	min-height: 0;
	overflow-y: auto;
	padding: var(--jy-space-4);
}
/* The board fills the viewport under the title bar; its lists scroll sideways inside it. */
.jy-boards[data-page="board"] {
	display: flex;
	flex-direction: column;
	flex: 1 1 0;
	min-height: 420px;
	overflow: hidden;
}

.jy-boards-muted { color: var(--jy-color-text-muted); font-size: var(--jy-text-sm); }
.jy-boards-live { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.jy-boards.jy-boards h2 { margin: 0 0 var(--jy-space-3); font-size: var(--jy-text-xl); }

.jy-boards-section { margin-bottom: var(--jy-space-6); }
.jy-boards-section > summary { cursor: pointer; font-weight: 600; margin-bottom: var(--jy-space-3); }

.jy-boards-chip {
	display: inline-flex;
	align-items: center;
	padding: 2px var(--jy-space-2);
	border-radius: var(--jy-radius-full);
	font-size: var(--jy-text-xs);
	background: var(--jy-color-surface-alt);
	color: var(--jy-color-text-muted);
	white-space: nowrap;
}

.jy-boards-iconbtn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 32px;
	min-height: 32px;
	border: 0;
	border-radius: var(--jy-radius-md);
	background: transparent;
	color: inherit;
	cursor: pointer;
}
.jy-boards-iconbtn:hover { background: var(--jy-color-surface-alt); }

.jy-boards-input {
	width: 100%;
	box-sizing: border-box;
	min-height: var(--jy-control-h-md);
	padding: var(--jy-space-2) var(--jy-space-3);
	border: 1px solid var(--jy-color-border-strong);
	border-radius: var(--jy-radius-md);
	background: var(--jy-color-bg);
	color: var(--jy-color-text);
	font: inherit;
}
textarea.jy-boards-input { resize: vertical; }
.jy-boards-input:focus-visible,
.jy-boards-card:focus-visible,
.jy-boards-addbtn:focus-visible,
.jy-boards-tile:focus-visible { outline: 2px solid var(--jy-color-primary); outline-offset: 2px; }

.jy-boards-field { display: flex; flex-direction: column; gap: var(--jy-space-1); margin-bottom: var(--jy-space-3); }
.jy-boards-field > span, .jy-boards-fieldlabel { font-size: var(--jy-text-sm); font-weight: 600; }
.jy-boards-inline { display: flex; gap: var(--jy-space-2); }
.jy-boards-checkline { display: inline-flex; align-items: center; gap: var(--jy-space-2); min-height: 32px; }

/* ─── Board colours ─────────────────────────────────────── */

.jy-boards-bg-blue   { background-color: #0079bf; }
.jy-boards-bg-green  { background-color: #519839; }
.jy-boards-bg-orange { background-color: #b9772c; }
.jy-boards-bg-red    { background-color: #b04632; }
.jy-boards-bg-purple { background-color: #89609e; }
.jy-boards-bg-pink   { background-color: #cd5a91; }
.jy-boards-bg-sky    { background-color: #0a8aa8; }
.jy-boards-bg-lime   { background-color: #3d9a5a; }
.jy-boards-bg-gray   { background-color: #6b7479; }
.jy-boards-bg-image  { background-size: cover; background-position: center; }

/* ─── Board list page ───────────────────────────────────── */

.jy-boards-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: var(--jy-space-3); }
.jy-boards-tilewrap { display: flex; flex-direction: column; gap: var(--jy-space-2); }
.jy-boards-tile {
	display: flex;
	flex-direction: column;
	justify-content: space-between;
	gap: var(--jy-space-2);
	min-height: 96px;
	padding: var(--jy-space-3);
	border-radius: var(--jy-radius-lg);
	color: #fff;
	text-decoration: none;
	box-shadow: var(--jy-shadow-sm);
	background-size: cover;
	background-position: center;
	overflow-wrap: anywhere;
}
.jy-boards a.jy-boards-tile, .jy-boards a.jy-boards-tile:hover, .jy-boards a.jy-boards-tile:visited { color: #fff; }
.jy-boards-tile-name, .jy-boards-tile-desc, .jy-boards-tile-meta { color: inherit; }
.jy-boards-tile:hover { filter: brightness(1.08); }
.jy-boards-tile-name { font-weight: 700; font-size: var(--jy-text-lg); text-shadow: 0 1px 2px rgba(0,0,0,.35); }
.jy-boards-tile-desc { font-size: var(--jy-text-sm); opacity: .92; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.jy-boards-tile-meta { display: flex; justify-content: space-between; align-items: center; gap: var(--jy-space-2); font-size: var(--jy-text-xs); }
.jy-boards-tile .jy-boards-chip { background: rgba(0,0,0,.35); color: #fff; }

/* My cards */
.jy-boards-mylist { list-style: none; margin: 0; padding: 0; border: 1px solid var(--jy-color-border); border-radius: var(--jy-radius-lg); overflow: hidden; }
.jy-boards-mylist li + li { border-top: 1px solid var(--jy-color-border); }
.jy-boards-myrow {
	display: flex; flex-wrap: wrap; align-items: center; gap: var(--jy-space-2) var(--jy-space-4);
	padding: var(--jy-space-3); color: inherit; text-decoration: none; min-height: 44px;
}
.jy-boards-myrow:hover { background: var(--jy-color-surface-alt); }
.jy-boards-myrow-title { flex: 1 1 260px; font-weight: 600; display: flex; gap: var(--jy-space-2); align-items: center; flex-wrap: wrap; }
.jy-boards-myrow-where { color: var(--jy-color-text-muted); font-size: var(--jy-text-sm); }
.jy-boards-section.is-overdue h2 { color: var(--jy-color-danger); }

/* Import */
.jy-boards-import { max-width: 640px; }
.jy-boards-importlist { padding-left: var(--jy-space-5); }
.jy-boards-importpeople h3 { font-size: var(--jy-text-base); margin: var(--jy-space-4) 0 var(--jy-space-2); }

/* ─── The board ─────────────────────────────────────────── */

.jy-boards-board {
	display: flex;
	flex-direction: column;
	flex: 1 1 0;
	min-height: 0;
	background-size: cover;
	background-position: center;
}

.jy-boards-bar {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--jy-space-2);
	padding: var(--jy-space-2) var(--jy-space-3);
	background: rgba(0, 0, 0, 0.32);
	color: #fff;
}
.jy-boards .jy-boards-bar-name {
	margin: 0 !important;
	font-size: var(--jy-text-lg) !important;
	color: #fff !important;
	cursor: default;
}
.jy-boards-bar-name[tabindex] { cursor: pointer; }
.jy-boards-bar-spacer { flex: 1 1 auto; }
.jy-boards-bar .jy-boards-chip { background: rgba(255,255,255,.22); color: #fff; }
.jy-boards-bar .btn {
	background: rgba(255,255,255,.2);
	color: #fff;
	border-color: transparent;
	min-height: 36px;
}
.jy-boards-bar .btn:hover { background: rgba(255,255,255,.32); }
.jy-boards-bar .btn-primary { background: var(--jy-color-primary); }
.jy-boards-bar-people { display: flex; align-items: center; cursor: pointer; }
.jy-boards-bar-people .jy-boards-avatar { margin-left: -6px; border: 2px solid rgba(255,255,255,.7); }
.jy-boards-bar-people .jy-boards-avatar:first-child { margin-left: 0; }

.jy-boards-filterbar {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--jy-space-2);
	padding: var(--jy-space-2) var(--jy-space-3);
	background: var(--jy-color-surface);
	border-bottom: 1px solid var(--jy-color-border);
}
.jy-boards-filterbar .jy-boards-input { width: auto; min-width: 150px; }

.jy-boards-banner {
	display: flex; align-items: center; gap: var(--jy-space-3);
	padding: var(--jy-space-2) var(--jy-space-3);
	background: var(--jy-color-warning-bg);
	color: var(--jy-color-text);
}

.jy-boards-scroller {
	flex: 1 1 0;
	min-height: 0;
	overflow-x: auto;
	overflow-y: hidden;
	scroll-snap-type: x proximity;
	-webkit-overflow-scrolling: touch;
}
.jy-boards-lists {
	display: flex;
	align-items: flex-start;
	gap: var(--jy-space-3);
	height: 100%;
	padding: var(--jy-space-3);
	box-sizing: border-box;
	width: max-content;
	min-width: 100%;
}

.jy-boards-list {
	display: flex;
	flex-direction: column;
	flex: 0 0 288px;
	width: 288px;
	max-height: 100%;
	box-sizing: border-box;
	background: var(--jy-color-surface);
	border: 1px solid var(--jy-color-border);
	border-radius: var(--jy-radius-lg);
	scroll-snap-align: start;
}
.jy-boards-list-head {
	display: flex;
	align-items: center;
	gap: var(--jy-space-2);
	padding: var(--jy-space-2) var(--jy-space-3);
	cursor: grab;
	touch-action: pan-x pan-y;
	-webkit-user-select: none;
	user-select: none;
}
.is-readonly .jy-boards-list-head { cursor: default; }
.jy-boards-list-name { flex: 1 1 auto; margin: 0 !important; font-size: var(--jy-text-base) !important; font-weight: 700; overflow-wrap: anywhere; cursor: text; }
.jy-boards-list-count { color: var(--jy-color-text-muted); font-size: var(--jy-text-xs); }
.jy-boards-list-rename { flex: 1 1 auto; }
.jy-boards-cards {
	flex: 1 1 auto;
	min-height: 8px;
	overflow-y: auto;
	padding: 0 var(--jy-space-2) var(--jy-space-1);
	display: flex;
	flex-direction: column;
	gap: var(--jy-space-2);
}
.jy-boards-list-foot { padding: var(--jy-space-2); }

.jy-boards-addbtn {
	display: inline-flex;
	align-items: center;
	gap: var(--jy-space-1);
	min-height: 40px;
	padding: var(--jy-space-2) var(--jy-space-3);
	border: 0;
	border-radius: var(--jy-radius-md);
	background: transparent;
	color: var(--jy-color-text-muted);
	font: inherit;
	cursor: pointer;
}
.jy-boards-addbtn:hover { background: var(--jy-color-surface-alt); color: var(--jy-color-text); }
.jy-boards-addbtn--alt { font-size: var(--jy-text-sm); }
.jy-boards-addlist {
	flex: 0 0 288px;
	width: 288px;
	box-sizing: border-box;
	padding: var(--jy-space-2);
	border-radius: var(--jy-radius-lg);
	background: rgba(255, 255, 255, 0.22);
}
.jy-boards-addlist .jy-boards-addbtn { color: #fff; width: 100%; }
.jy-boards-addlist .jy-boards-addbtn:hover { background: rgba(255,255,255,.2); color: #fff; }
.jy-boards-composer-actions { display: flex; gap: var(--jy-space-2); margin-top: var(--jy-space-2); }

/* ─── Cards ─────────────────────────────────────────────── */

.jy-boards-card {
	position: relative;
	display: flex;
	flex-direction: column;
	gap: var(--jy-space-1);
	padding: var(--jy-space-2) var(--jy-space-3);
	background: var(--jy-color-bg);
	border: 1px solid var(--jy-color-border);
	border-radius: var(--jy-radius-md);
	box-shadow: var(--jy-shadow-sm);
	cursor: pointer;
	overflow-wrap: anywhere;
	-webkit-user-select: none;
	user-select: none;
	-webkit-touch-callout: none;
}
.jy-boards-card:hover { border-color: var(--jy-color-border-strong); }
.jy-boards-card.is-done .jy-boards-card-title { text-decoration: line-through; color: var(--jy-color-text-muted); }
.jy-boards-card.is-dim { opacity: 0.3; }
.jy-boards-card-cover { margin: calc(var(--jy-space-2) * -1) calc(var(--jy-space-3) * -1) var(--jy-space-1); width: calc(100% + var(--jy-space-3) * 2); max-height: 160px; object-fit: cover; border-radius: var(--jy-radius-md) var(--jy-radius-md) 0 0; pointer-events: none; }
.jy-boards-card-title { font-size: var(--jy-text-sm); line-height: var(--jy-leading-base); }
.jy-boards-card-labels { display: flex; flex-wrap: wrap; gap: 4px; }
.jy-boards-card-badges { display: flex; flex-wrap: wrap; align-items: center; gap: var(--jy-space-2); color: var(--jy-color-text-muted); font-size: var(--jy-text-xs); }
.jy-boards-card-members { display: flex; justify-content: flex-end; gap: 2px; flex-wrap: wrap; }
.jy-boards-badge { display: inline-flex; align-items: center; gap: 3px; }
.jy-boards-badge.is-complete { color: var(--jy-color-success); }
.jy-boards-badge.is-template { background: var(--jy-color-surface-alt); border-radius: var(--jy-radius-sm); padding: 0 var(--jy-space-1); }

.jy-boards-due {
	display: inline-flex; align-items: center; gap: 3px;
	padding: 0 var(--jy-space-1);
	border: 0; border-radius: var(--jy-radius-sm);
	background: transparent; color: inherit; font: inherit; font-size: var(--jy-text-xs);
}
button.jy-boards-due { cursor: pointer; padding: 4px var(--jy-space-2); font-size: var(--jy-text-sm); background: var(--jy-color-surface-alt); }
.jy-boards-due.is-soon { background: var(--jy-color-warning-bg); color: var(--jy-color-text); }
.jy-boards-due.is-overdue { background: var(--jy-color-danger); color: #fff; }
.jy-boards-due.is-done { background: var(--jy-color-success); color: #fff; }

/* Labels: a fixed palette; the dark text on the pale ones keeps them readable. */
.jy-boards-label {
	display: inline-block;
	min-width: 36px;
	min-height: 8px;
	max-width: 100%;
	padding: 0 var(--jy-space-2);
	border: 0;
	border-radius: var(--jy-radius-sm);
	font: inherit;
	font-size: var(--jy-text-xs);
	font-weight: 600;
	line-height: 18px;
	color: #fff;
	text-align: left;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
button.jy-boards-label { cursor: pointer; padding-top: 2px; padding-bottom: 2px; }
.jy-boards-label-green  { background: #3f8f2f; }
.jy-boards-label-yellow { background: #f2d600; color: #3a3300; }
.jy-boards-label-orange { background: #ff9f1a; color: #3d2600; }
.jy-boards-label-red    { background: #d93f2b; }
.jy-boards-label-purple { background: #9a4fc0; }
.jy-boards-label-blue   { background: #0b6cb0; }
.jy-boards-label-sky    { background: #00c2e0; color: #00323b; }
.jy-boards-label-lime   { background: #51e898; color: #0a3a20; }
.jy-boards-label-pink   { background: #ff78cb; color: #4a0a33; }
.jy-boards-label-gray   { background: #6f787d; }

/* People */
.jy-boards-avatar { width: 24px; height: 24px; border-radius: var(--jy-radius-full); object-fit: cover; background: var(--jy-color-surface-alt); flex: 0 0 auto; }
.jy-boards-avatar--initials { display: inline-flex; align-items: center; justify-content: center; font-size: 10px; font-weight: 700; color: var(--jy-color-text-muted); }
.jy-boards-person { display: inline-flex; align-items: center; gap: var(--jy-space-1); }

/* ─── Dragging ──────────────────────────────────────────── */

body.jy-boards-dragging { cursor: grabbing; -webkit-user-select: none; user-select: none; }
.jy-boards-ghost {
	position: fixed !important;
	z-index: 10000;
	margin: 0;
	pointer-events: none;
	opacity: 0.92;
	transform: rotate(2.5deg);
	box-shadow: var(--jy-shadow-lg);
}
.jy-boards-list.jy-boards-ghost { transform: rotate(1.5deg); }
/* The picked-up item stays in the tree (so pointer capture holds) but takes no room. */
.is-drag-source { height: 0 !important; min-height: 0 !important; padding: 0 !important; margin: 0 !important; border: 0 !important; overflow: hidden !important; opacity: 0; flex: 0 0 0 !important; }
.jy-boards-placeholder { box-sizing: border-box; border: 2px dashed var(--jy-color-primary); border-radius: var(--jy-radius-md); background: color-mix(in srgb, var(--jy-color-primary) 12%, transparent); flex: 0 0 auto; }
.jy-boards-placeholder--list { border-radius: var(--jy-radius-lg); }

/* ─── Dialogs ───────────────────────────────────────────── */

.jy-boards-dialog.jy-boards-dialog {
	max-width: none;
	padding: 0;
	border: 1px solid var(--jy-color-border);
	border-radius: var(--jy-radius-lg);
	box-shadow: var(--jy-shadow-lg);
	color: var(--jy-color-text);
	background: var(--jy-color-bg);
	width: min(520px, 94vw);
	max-height: calc(100vh - 32px);
}
.jy-boards-dialog[open] { display: flex; flex-direction: column; }
.jy-boards-dialog::backdrop { background: rgba(20, 25, 35, 0.45); }
.jy-boards-dialog.jy-boards-dialog--small { width: min(420px, 94vw); }
.jy-boards-dialog.jy-boards-dialog--medium { width: min(520px, 94vw); }
.jy-boards-dialog.jy-boards-dialog--menu { width: min(600px, 96vw); }
.jy-boards-dialog.jy-boards-dialog--card { width: min(980px, 97vw); max-height: calc(100vh - 24px); }
.jy-boards-dialog-head { display: flex; align-items: center; gap: var(--jy-space-2); padding: var(--jy-space-3) var(--jy-space-4); border-bottom: 1px solid var(--jy-color-border); }
.jy-boards-dialog .jy-boards-dialog-head h3 { margin: 0; flex: 1 1 auto; font-size: var(--jy-text-lg); }
.jy-boards-dialog-body { padding: var(--jy-space-4); overflow-y: auto; flex: 1 1 auto; min-height: 0; }
.jy-boards-dialog--card .jy-boards-dialog-body { padding: 0; }
.jy-boards-dialog-foot { display: flex; justify-content: flex-end; gap: var(--jy-space-2); padding: var(--jy-space-3) var(--jy-space-4); border-top: 1px solid var(--jy-color-border); }
.jy-boards-dialog--card .jy-boards-dialog-foot { display: none; }
.jy-boards-dialog-body h4:not(.jy-boards-cl-title) { margin: var(--jy-space-3) 0 var(--jy-space-2); font-size: var(--jy-text-sm); color: var(--jy-color-text-muted); text-transform: uppercase; letter-spacing: .03em; }

.jy-boards-picklist { list-style: none; margin: var(--jy-space-2) 0; padding: 0; }
.jy-boards-pickrow {
	display: flex; align-items: center; gap: var(--jy-space-3);
	width: 100%; min-height: 40px; padding: var(--jy-space-1) var(--jy-space-2);
	border: 0; border-radius: var(--jy-radius-md); background: transparent; color: inherit;
	font: inherit; text-align: left; cursor: pointer; box-sizing: border-box;
}
.jy-boards-pickrow:hover { background: var(--jy-color-surface-alt); }
.jy-boards-pickrow > span:not(.jy-boards-avatar):not(.jy-boards-label) { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.jy-boards-pickrow select { width: auto; }
.jy-boards-labelrow { display: flex; align-items: center; gap: var(--jy-space-2); }
.jy-boards-labelrow .jy-boards-pickrow { flex: 1 1 auto; }
.jy-boards-labelrow > .jy-boards-label { flex: 1 1 auto; line-height: 28px; }

.jy-boards-swatches { display: flex; flex-wrap: wrap; gap: var(--jy-space-2); margin: var(--jy-space-2) 0; }
.jy-boards-swatch { width: 40px; height: 32px; border: 2px solid transparent; border-radius: var(--jy-radius-md); cursor: pointer; padding: 0; }
.jy-boards-swatch.is-selected { border-color: var(--jy-color-text); box-shadow: 0 0 0 2px var(--jy-color-bg) inset; }

.jy-boards-menusec { padding-bottom: var(--jy-space-3); margin-bottom: var(--jy-space-3); border-bottom: 1px solid var(--jy-color-border); }
.jy-boards-menusec:last-child { border-bottom: 0; }
.jy-boards-dialog .jy-boards-menusec h3 { margin: 0 0 var(--jy-space-2); font-size: var(--jy-text-base); }
.jy-boards-menuactions { display: flex; flex-wrap: wrap; gap: var(--jy-space-2); }

.jy-boards-shortcuts { display: grid; grid-template-columns: auto 1fr; gap: var(--jy-space-2) var(--jy-space-4); margin: 0; }
.jy-boards-shortcuts dt, .jy-boards-shortcuts dd { margin: 0; }
.jy-boards-shortcuts kbd { padding: 2px var(--jy-space-2); border: 1px solid var(--jy-color-border-strong); border-radius: var(--jy-radius-sm); background: var(--jy-color-surface-alt); font-family: var(--jy-font-mono); font-size: var(--jy-text-sm); }

.jy-boards-uploads { list-style: none; margin: var(--jy-space-2) 0; padding: 0; font-size: var(--jy-text-sm); }

.jy-boards-covergrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); gap: var(--jy-space-2); margin-bottom: var(--jy-space-3); }
.jy-boards-coverpick { padding: 0; border: 2px solid transparent; border-radius: var(--jy-radius-md); overflow: hidden; cursor: pointer; background: none; }
.jy-boards-coverpick img { display: block; width: 100%; height: 80px; object-fit: cover; }
.jy-boards-coverpick.is-selected { border-color: var(--jy-color-primary); }

/* ─── Card back ─────────────────────────────────────────── */

.jy-boards-cb-cover { display: block; width: 100%; max-height: 220px; object-fit: cover; }
.jy-boards-cb-head { display: flex; align-items: flex-start; gap: var(--jy-space-3); padding: var(--jy-space-4) var(--jy-space-4) var(--jy-space-2); }
.jy-boards-cb-headtext { flex: 1 1 auto; min-width: 0; }
.jy-boards-dialog .jy-boards-cb-title { margin: 0 !important; font-size: var(--jy-text-2xl) !important; overflow-wrap: anywhere; cursor: text; }
.jy-boards-cb-titleinput { font-size: var(--jy-text-xl); font-weight: 700; }
.jy-boards-cb-grid { display: grid; grid-template-columns: minmax(0, 1fr) 190px; gap: var(--jy-space-4); padding: 0 var(--jy-space-4) var(--jy-space-4); }
.jy-boards-cb-main { min-width: 0; }
.jy-boards-cb-side {
	display: flex; flex-direction: column; gap: var(--jy-space-2);
	align-self: start; position: sticky; top: var(--jy-space-2);
}
.jy-boards-dialog .jy-boards-cb-side h4 { margin: var(--jy-space-2) 0 0; }
.jy-boards-sidebtn { width: 100%; justify-content: flex-start; min-height: 40px; text-align: left; }

.jy-boards-cb-meta { display: flex; flex-wrap: wrap; gap: var(--jy-space-4); margin-bottom: var(--jy-space-3); }
.jy-boards-dialog .jy-boards-cb-metagroup h4 { margin: 0 0 var(--jy-space-1) !important; }
.jy-boards-cb-chips { display: flex; flex-wrap: wrap; align-items: center; gap: var(--jy-space-2); }
.jy-boards-cb-section { margin-bottom: var(--jy-space-5); }
.jy-boards-dialog .jy-boards-cb-section > h3 { font-size: var(--jy-text-base); margin: 0 0 var(--jy-space-2); }

.jy-boards-md { overflow-wrap: anywhere; line-height: var(--jy-leading-base); }
.jy-boards-md p { margin: 0 0 var(--jy-space-2); }
.jy-boards-md img { max-width: 100%; }
.jy-boards-md pre { overflow-x: auto; padding: var(--jy-space-2); background: var(--jy-color-surface-alt); border-radius: var(--jy-radius-sm); }
.jy-boards-md.is-editable { cursor: text; padding: var(--jy-space-1); border-radius: var(--jy-radius-md); }
.jy-boards-md.is-editable:hover { background: var(--jy-color-surface-alt); }
.jy-boards-placeholder-btn { width: 100%; min-height: 64px; text-align: left; padding: var(--jy-space-3); border: 0; border-radius: var(--jy-radius-md); background: var(--jy-color-surface-alt); color: var(--jy-color-text-muted); font: inherit; cursor: pointer; }

.jy-boards-cl-head { display: flex; align-items: center; gap: var(--jy-space-3); }
.jy-boards-dialog .jy-boards-cl-title { flex: 1 1 auto; margin: 0; font-size: var(--jy-text-base); cursor: text; }
.jy-boards-progress { height: 6px; margin: var(--jy-space-2) 0; border-radius: var(--jy-radius-full); background: var(--jy-color-surface-alt); overflow: hidden; }
.jy-boards-progress > span { display: block; height: 100%; background: var(--jy-color-success); }
.jy-boards-cl-items { list-style: none; margin: 0; padding: 0; }
.jy-boards-cl-item { display: flex; flex-wrap: wrap; align-items: center; gap: var(--jy-space-2); min-height: 36px; padding: 2px 0; }
.jy-boards-cl-text { flex: 1 1 160px; overflow-wrap: anywhere; cursor: text; }
.jy-boards-cl-text.is-done { text-decoration: line-through; color: var(--jy-color-text-muted); }
.jy-boards-cl-add { display: flex; gap: var(--jy-space-2); margin-top: var(--jy-space-2); }

.jy-boards-attachments { list-style: none; margin: 0; padding: 0; }
.jy-boards-att { display: flex; align-items: center; gap: var(--jy-space-3); padding: var(--jy-space-2) 0; flex-wrap: wrap; }
.jy-boards-att-thumb { width: 72px; height: 54px; object-fit: cover; border-radius: var(--jy-radius-sm); background: var(--jy-color-surface-alt); flex: 0 0 auto; }
.jy-boards-att-icon { display: inline-flex; align-items: center; justify-content: center; }
.jy-boards-att-body { flex: 1 1 160px; min-width: 0; display: flex; flex-direction: column; overflow-wrap: anywhere; }
.jy-boards-att-actions { display: flex; gap: var(--jy-space-2); }

.jy-boards-comments, .jy-boards-activity { list-style: none; margin: var(--jy-space-3) 0 0; padding: 0; }
.jy-boards-comment { display: flex; gap: var(--jy-space-3); margin-bottom: var(--jy-space-3); }
.jy-boards-comment-main { flex: 1 1 auto; min-width: 0; }
.jy-boards-comment-main .jy-boards-md { padding: var(--jy-space-2) var(--jy-space-3); border: 1px solid var(--jy-color-border); border-radius: var(--jy-radius-md); background: var(--jy-color-surface); }
.jy-boards-comment-actions { display: flex; gap: var(--jy-space-2); margin-top: var(--jy-space-1); }
.jy-boards-activity li { padding: 3px 0; font-size: var(--jy-text-sm); }

.jy-boards-mentionmenu {
	position: absolute; z-index: 5; left: 0; right: 0; margin: 2px 0 0; padding: var(--jy-space-1); list-style: none;
	background: var(--jy-color-bg); border: 1px solid var(--jy-color-border-strong); border-radius: var(--jy-radius-md); box-shadow: var(--jy-shadow-md);
}
.jy-boards-mentionmenu li { display: flex; align-items: center; gap: var(--jy-space-2); padding: var(--jy-space-2); border-radius: var(--jy-radius-sm); cursor: pointer; min-height: 36px; }
.jy-boards-mentionmenu li.is-active, .jy-boards-mentionmenu li:hover { background: var(--jy-color-surface-alt); }

.jy-boards-gone { padding: var(--jy-space-8); text-align: center; }

/* ─── Toast ─────────────────────────────────────────────── */

.jy-boards-toast {
	position: fixed; left: 50%; bottom: var(--jy-space-5); transform: translateX(-50%); z-index: 20000;
	max-width: min(520px, 92vw); padding: var(--jy-space-3) var(--jy-space-4);
	border-radius: var(--jy-radius-md); box-shadow: var(--jy-shadow-lg);
	background: var(--jy-color-text); color: var(--jy-color-bg); font-size: var(--jy-text-sm);
}
.jy-boards-toast.is-error { background: var(--jy-color-danger); color: #fff; }

/* ─── Phones ────────────────────────────────────────────── */

@media (max-width: 720px) {
	.jy-boards-list, .jy-boards-addlist { flex-basis: 84vw; width: 84vw; }
	.jy-boards-scroller { scroll-snap-type: x mandatory; }
	.jy-boards-bar .btn, .jy-boards-addbtn, .jy-boards-sidebtn { min-height: 44px; }
	.jy-boards-iconbtn { min-width: 44px; min-height: 44px; }
	.jy-boards-dialog.jy-boards-dialog--card { width: 100vw; max-width: 100vw; height: 100vh; max-height: 100vh; border-radius: 0; border: 0; }
	.jy-boards-dialog { max-height: 96vh; }
	.jy-boards-cb-grid { grid-template-columns: minmax(0, 1fr); }
	.jy-boards-cb-side { position: static; order: -1; flex-direction: row; flex-wrap: nowrap; overflow-x: auto; padding-bottom: var(--jy-space-2); }
	.jy-boards-dialog .jy-boards-cb-side h4 { display: none; }
	.jy-boards-sidebtn { width: auto; flex: 0 0 auto; white-space: nowrap; }
	.jy-boards-filterbar .jy-boards-input { flex: 1 1 140px; }
}

@media (prefers-reduced-motion: reduce) {
	.jy-boards-ghost { transform: none; }
	.jy-boards-scroller { scroll-behavior: auto; }
}

/* ---- email to this board (board menu) ---- */
.jy-boards-row { display: flex; flex-wrap: wrap; gap: 8px; align-items: flex-end; margin: 8px 0; }
.jy-boards-row > .jy-boards-input { flex: 1 1 14rem; min-width: 0; }
.jy-boards-menusec h4 { margin: 14px 0 4px; font-size: 0.9rem; }
.jy-boards-frompage { max-width: 36rem; }

/* plugins/joinery_ai/assets/css/joinery_ai.css */
/* joinery_ai plugin styles. Distinctive .joai-* prefix.
   Public dashboard rules are scoped under .jy-ui (the view opts in);
   admin run-detail utilities are plain .joai-* (admin theme, not .jy-ui)
   and carry the exact values lifted from former inline styles. */

/* --- Admin recipe edit: built-in prompt display ---
   A pipeline job ships its own instructions and rcp_prompt only overrides them,
   so the edit form shows the real text rather than an empty box. Reads as prose,
   not as a disabled input, because it is not a field. */
.joai-prompt-builtin { white-space: pre-wrap; word-break: break-word; font-family: inherit;
    font-size: 0.9rem; line-height: 1.5; margin: 0; padding: 0.85rem 1rem; max-height: 22rem;
    overflow-y: auto; background: #f7f8fa; border: 1px solid #dfe3e8; border-radius: 6px;
    color: #33393f; }

/* --- Public dashboard (/joinery_ai) --- */
.jy-ui .joai-wrap { max-width: 900px; margin: 2rem auto; padding: 0 1rem; }
.jy-ui .joai-wrap h1 { margin-bottom: 0.5rem; }
.jy-ui .joai-card { border: 1px solid #ddd; border-radius: 8px; margin-bottom: 1.5rem;
              background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,0.04); }
.jy-ui .joai-card-header { padding: 1rem 1.25rem; border-bottom: 1px solid #eee;
                    display: flex; justify-content: space-between; align-items: center; }
.jy-ui .joai-card-header h2 { margin: 0; font-size: 1.25rem; }
.jy-ui .joai-card-header .joai-meta { font-size: 0.85rem; color: #666; }
.jy-ui .joai-card-body { padding: 1.25rem; }
.jy-ui .joai-empty { padding: 1.25rem; color: #888; font-style: italic; }
.jy-ui .joai-actions a { font-size: 0.85rem; margin-left: 0.5rem; }
.jy-ui .joai-intro { color: #666; margin-bottom: 2rem; }

/* --- Admin run detail (/admin/joinery_ai/run) --- */
.joai-pre-wrap { white-space: pre-wrap; }
.joai-trace { font-size: 0.85em; }
.joai-trace-wrap { font-size: 0.85em; white-space: pre-wrap; }
.joai-toolcall { border-color: #0d6efd !important; }
.joai-toolcall.is-error { border-color: #dc3545 !important; }

/* --- Admin chat (/admin/joinery_ai/chat) --- */
.joai-chat-wrap { display: flex; gap: 1rem; height: calc(100vh - 220px); min-height: 420px; }
.joai-chat-list { flex: 0 0 240px; display: flex; flex-direction: column; gap: 0.5rem;
                  border: 1px solid #ddd; border-radius: 8px; background: #fff; padding: 0.75rem; overflow-y: auto; }
.joai-chat-newbtn { width: 100%; }
.joai-chat-search { width: 100%; box-sizing: border-box; padding: 0.4rem 0.6rem; font: inherit;
                    font-size: 0.85rem; border: 1px solid #ddd; border-radius: 6px; }
.joai-chat-search:focus { outline: none; border-color: #0d6efd; box-shadow: 0 0 0 2px rgba(13,110,253,0.15); }
.joai-chat-threads { display: flex; flex-direction: column; gap: 0.25rem; }
.joai-chat-item { position: relative; }
.joai-chat-list-item { display: flex; align-items: center; gap: 0.35rem;
                       padding: 0.5rem 1.7rem 0.5rem 0.6rem; border-radius: 6px; color: #222;
                       text-decoration: none; font-size: 0.9rem; }
.joai-chat-list-item:hover { background: #f1f3f5; }
.joai-chat-list-item.is-active { background: #e7f1ff; font-weight: 600; }
.joai-chat-item-title { flex: 1 1 auto; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.joai-chat-pin { display: none; flex: 0 0 auto; color: #6c757d; line-height: 0; }
.joai-chat-item.is-pinned .joai-chat-pin { display: inline-flex; }

/* Three-dots trigger: hidden until row hover or menu open. */
.joai-chat-item-menu-btn { position: absolute; top: 50%; right: 0.2rem; transform: translateY(-50%);
                           border: 0; background: transparent; color: #888; cursor: pointer;
                           font-size: 1.15rem; line-height: 1; padding: 0.05rem 0.35rem; border-radius: 4px;
                           opacity: 0; }
.joai-chat-item:hover .joai-chat-item-menu-btn,
.joai-chat-item-menu-btn[aria-expanded="true"] { opacity: 1; }
.joai-chat-item-menu-btn:hover { background: rgba(0,0,0,0.08); color: #333; }

.joai-chat-item-menu { position: absolute; top: 100%; right: 0.2rem; z-index: 30; min-width: 130px;
                       background: #fff; border: 1px solid #ddd; border-radius: 6px;
                       box-shadow: 0 4px 14px rgba(0,0,0,0.14); padding: 0.25rem; }
.joai-chat-item-menu.open-up { top: auto; bottom: 100%; }
.joai-chat-item-menu button { display: block; width: 100%; text-align: left; border: 0;
                              background: transparent; padding: 0.4rem 0.6rem; border-radius: 4px;
                              font: inherit; font-size: 0.85rem; color: #222; cursor: pointer; }
.joai-chat-item-menu button:hover { background: #f1f3f5; }
.joai-chat-menu-danger { color: #dc3545; }
.joai-chat-menu-danger:hover { background: #fdecea; }

.joai-chat-rename { width: 100%; box-sizing: border-box; padding: 0.45rem 0.5rem; font: inherit;
                    font-size: 0.9rem; border: 1px solid #0d6efd; border-radius: 6px; }

/* Export dialog (rendered inside the system JoineryModal). */
.joai-export-title { margin: 0 0 0.75rem; font-weight: 600; font-size: 1rem; }
.joai-export-formats { border: 0; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.6rem; }
.joai-export-formats label { display: flex; align-items: baseline; gap: 0.4rem; font-size: 0.9rem; cursor: pointer; }
.joai-export-hint { color: #6c757d; font-size: 0.8rem; }
.joai-chat-main { flex: 1 1 auto; display: flex; flex-direction: column; border: 1px solid #ddd;
                  border-radius: 8px; background: #fff; overflow: hidden; }
/* Control strip above the transcript: a single line summarizing the active
   settings, with every control tucked behind the ⚙ Settings disclosure. Same
   on desktop and mobile. */
.joai-chat-status { display: flex; align-items: stretch; position: relative;
                    border-bottom: 1px solid #e6e8eb; background: #f7f8fa;
                    font-size: 0.8rem; color: #555; }

/* Selects + inputs in the settings panel share one look. */
.joai-chat-control { padding: 0.32rem 0.5rem; border: 1px solid #cdd3da; border-radius: 6px;
                     background: #fff; color: #222; font: inherit; font-size: 0.8rem; }
.joai-chat-control:focus { outline: none; border-color: #0d6efd;
                           box-shadow: 0 0 0 2px rgba(13,110,253,0.15); }
select.joai-chat-control { cursor: pointer; }

/* Settings disclosure. The summary IS the one-line control bar: a live summary
   of the active settings on the left, the gear affordance on the right.
   Clicking it drops the full-width settings drawer over the top of the chat. */
.joai-chat-settings { flex: 1 1 auto; min-width: 0; }
.joai-chat-settings > summary { list-style: none; cursor: pointer; user-select: none;
    display: flex; align-items: center; gap: 0.75rem; padding: 0.5rem 0.85rem; }
.joai-chat-settings > summary::-webkit-details-marker { display: none; }
.joai-chat-settings > summary::marker { content: ''; }
.joai-chat-settings > summary:hover { background: #eef1f5; }
.joai-chat-settings[open] > summary { background: #eef1f5; }
.joai-chat-settings-summary { flex: 1 1 auto; min-width: 0; overflow: hidden;
    text-overflow: ellipsis; white-space: nowrap; color: #333; font-weight: 500; }
.joai-chat-settings-gear { flex: none; color: #0d6efd; font-weight: 600; white-space: nowrap; }

/* The panel: a full-width drawer that slides down under the summary line and
   overlays the top of the chat. */
.joai-chat-settings-body { position: absolute; top: 100%; left: 0; right: 0; z-index: 40;
    background: #fff; border: 1px solid #d8dde3; border-top: none;
    border-radius: 0 0 10px 10px; box-shadow: 0 12px 32px rgba(0,0,0,0.16); padding: 0.95rem 1rem;
    display: flex; flex-direction: column; gap: 0.85rem;
    transform-origin: top center; animation: joai-settings-in 0.16s ease-out; }
@keyframes joai-settings-in {
    from { opacity: 0; transform: translateY(-8px); }
    to   { opacity: 1; transform: translateY(0); }
}
.joai-chat-settings-title { font-size: 0.7rem; font-weight: 700; letter-spacing: 0.04em;
    text-transform: uppercase; color: #99a1ab; margin-top: 0.15rem; }
.joai-chat-settings-body label { display: flex; flex-direction: column; gap: 0.3rem;
    font-size: 0.76rem; font-weight: 600; color: #555; }
.joai-chat-settings-body .joai-chat-control { width: 100%; box-sizing: border-box; font-weight: 400; }
.joai-chat-settings-body textarea.joai-chat-control { resize: vertical; min-height: 60px; }
.joai-chat-settings-row { display: flex; gap: 0.7rem; }
.joai-chat-settings-row label { flex: 1; min-width: 0; }
/* Capability toggles read as a horizontal row inside the column-stacked panel. */
.joai-chat-settings-toggles { display: flex; flex-wrap: wrap; gap: 0.4rem 1.2rem; }
.joai-chat-settings-body .joai-chat-toggle { flex-direction: row; align-items: center;
    font-weight: 500; }
/* Extra protection: the add-on switches shown under the Private level. */
.joai-chat-addons { display: flex; flex-direction: column; gap: 0.3rem;
    padding: 0.55rem 0.7rem; border-left: 3px solid #d8dde3; background: #f7f8fa; border-radius: 4px; }
.joai-chat-addons[hidden] { display: none; }
.joai-chat-addons-heading { font-size: 0.7rem; font-weight: 700; letter-spacing: 0.04em;
    text-transform: uppercase; color: #99a1ab; }
.joai-chat-addon-note { margin: 0; font-size: 0.74rem; color: #666; line-height: 1.4; }
.joai-chat-transcript { flex: 1 1 auto; overflow-y: auto; padding: 1.25rem 1.5rem; display: flex;
                        flex-direction: column; gap: 1rem; }
/* Send button morphs into an active Cancel while a turn streams (setBusy). */
.joai-btn.joai-chat-cancel-active { background: #dc3545; border-color: #dc3545; color: #fff; }
.joai-btn.joai-chat-cancel-active:hover { background: #c0392b; }
/* Waiting-for-you cards: this conversation's pending queued actions. The
   facts are the card's substance; the model's note renders as collapsed
   quotation, visibly its voice. */
.joai-chat-queued { padding: 0 1rem 0.5rem; }
.joai-queued-card { margin-top: 0.6rem; padding: 0.7rem 0.85rem 0.8rem; border: 1px solid #dfe3e8;
                    border-left: 3px solid #1d63d1; background: #fff; border-radius: 8px;
                    min-width: 0; overflow-wrap: anywhere; }
.joai-queued-head { font-size: 0.72rem; font-weight: 700; text-transform: uppercase;
                    letter-spacing: 0.05em; color: #1d63d1; margin-bottom: 0.35rem; }
.joai-queued-fact { font-size: 0.9rem; margin: 0 0 0.25rem; color: #1f2933; }
.joai-queued-headline { font-weight: 600; }
.joai-queued-kicker { font-size: 0.75rem; font-weight: 600; margin: 0 0 0.1rem; color: #667085; }
/* Labelled fields: a muted label column beside the values. A link stays on
   one line until clicked; a note shows three lines, then 'more'. */
.joai-queued-fields { display: grid; grid-template-columns: max-content minmax(0, 1fr);
                      column-gap: 0.75rem; row-gap: 0.3rem; margin: 0.4rem 0 0; }
.joai-queued-field { display: contents; }
.joai-queued-label { margin: 0; padding-top: 0.1rem; font-size: 0.75rem; font-weight: 600; color: #667085; }
.joai-queued-value { margin: 0; min-width: 0; font-size: 0.9rem; line-height: 1.4; color: #1f2933; }
.joai-queued-line { display: block; width: 100%; padding: 0; border: 0; background: none; font: inherit;
                    text-align: left; color: inherit; cursor: pointer; white-space: nowrap;
                    overflow: hidden; text-overflow: ellipsis; }
.joai-queued-line.is-open { white-space: normal; overflow-wrap: anywhere; }
.joai-queued-clamp { white-space: pre-line; display: -webkit-box; -webkit-box-orient: vertical;
                     -webkit-line-clamp: 3; line-clamp: 3; overflow: hidden; }
.joai-queued-clamp.is-open { display: block; -webkit-line-clamp: unset; line-clamp: none; overflow: visible; }
.joai-queued-more { padding: 0; border: 0; background: none; font: inherit; font-size: 0.8rem;
                    color: #2563eb; cursor: pointer; }
.joai-queued-more[hidden] { display: none; }
.joai-queued-note { margin: 0.4rem 0 0; font-size: 0.82rem; color: #667085; }
.joai-queued-note blockquote { margin: 0.3rem 0 0 0.25rem; padding-left: 0.6rem;
                               border-left: 3px solid #dfe3e8; font-style: italic; }
.joai-queued-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.7rem; }
/* Event chips: platform-written transcript facts (a queued action's
   resolution) — neutral, centered, neither voice. */
.joai-chat-event { margin: 0.75rem auto; max-width: 85%; text-align: center;
                   font-size: 0.8rem; color: #777; }
.joai-chat-event-time { margin-left: 0.5rem; color: #aaa; font-size: 0.72rem; }
/* Long event content (an approved fetch carries its whole result): head shown
   inline, the rest behind a toggle, scrolling in place. */
.joai-chat-event-more { margin-top: 0.35rem; text-align: left; }
.joai-chat-event-more summary { cursor: pointer; color: #999; font-size: 0.75rem;
                                text-align: center; }
.joai-chat-event-more pre { max-height: 20rem; overflow: auto; margin: 0.35rem 0 0;
                            padding: 0.5rem; background: #f7f7f7; border-radius: 6px;
                            font-size: 0.75rem; white-space: pre-wrap;
                            word-break: break-word; color: #555; }
.joai-chat-thinking { padding: 0 1rem 0.5rem; font-size: 0.82rem; color: #888; font-style: italic; }
.joai-chat-composer { display: flex; gap: 0.5rem; padding: 0.75rem; border-top: 1px solid #eee;
                      align-items: flex-end; }
.joai-chat-composer textarea { flex: 1 1 auto; resize: none; border: 1px solid #ccc; border-radius: 8px;
                               padding: 0.5rem 0.7rem; font: inherit; }
.joai-chat-composer.joai-chat-dragover { outline: 2px dashed #0d6efd; outline-offset: -4px; }
.joai-chat-empty { color: #888; font-style: italic; padding: 0.5rem; }

/* Attachments: the file input is hidden (the attach button proxies it); the button
   centers its upload glyph and matches the composer button height. */
.joai-chat-file-input { display: none; }
.joai-chat-attach-btn { flex: 0 0 auto; display: inline-flex; align-items: center;
                        justify-content: center; line-height: 1; padding: 0.4rem 0.55rem; }
.joai-chat-attach-btn svg { width: 22px; height: 22px; display: block; }

/* Pending-file strip above the composer, and rendered attachment chips inside a
   sent user bubble. */
.joai-chat-attach-strip { display: flex; flex-wrap: wrap; gap: 0.4rem; padding: 0.4rem 0.75rem 0; }
.joai-chat-attachments { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.4rem; }
.joai-chat-attach { display: inline-flex; align-items: center; gap: 0.3rem; max-width: 220px;
                    padding: 0.25rem 0.5rem; border-radius: 6px; background: rgba(0,0,0,0.06);
                    font-size: 0.78rem; }
.joai-chat-mine .joai-chat-attach { background: rgba(255,255,255,0.2); color: #fff; }
.joai-chat-attach-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.joai-chat-attach-icon { flex: 0 0 auto; }
.joai-chat-attach-image { padding: 0; background: none; }
.joai-chat-attach-image img { max-width: 120px; max-height: 120px; border-radius: 6px; display: block; }
.joai-chat-attach-remove { border: none; background: none; cursor: pointer; font-size: 1rem;
                           line-height: 1; color: inherit; padding: 0 0.1rem; }
.joai-chat-attach-remove:hover { color: #dc3545; }

/* Conversation meta bar under the composer — the toolbar strip. Holds the
   running token/cost total today; room for more controls later. */
.joai-chat-meta { display: flex; justify-content: flex-end; align-items: center;
                  padding: 0.2rem 0.75rem 0.5rem; font-size: 0.72rem; color: #999; }
.joai-chat-meta-usage { white-space: nowrap; }
.joai-btn { display: inline-block; padding: 0.45rem 0.9rem; border: 1px solid #ccc; border-radius: 8px;
            background: #fff; color: #222; cursor: pointer; font: inherit; }
.joai-btn:hover { background: #f1f3f5; }
.joai-btn:disabled { opacity: 0.6; cursor: default; }
.joai-btn-primary { background: #0d6efd; border-color: #0d6efd; color: #fff; }
.joai-btn-primary:hover { background: #0b5ed7; }

/* chat capability toggles in the status strip */
.joai-chat-toggle { display: inline-flex; align-items: center; gap: 0.3rem; font-size: 0.8rem;
                    color: #444; cursor: pointer; user-select: none; }
.joai-chat-toggle input { margin: 0; cursor: pointer; }
.joai-chat-toggle.is-disabled { color: #aaa; cursor: not-allowed; }
.joai-chat-toggle.is-disabled input { cursor: not-allowed; }

/* --- Mobile: a bar atop the chat pane with the Conversations drawer toggle and
   the maximize/minimize control. The whole bar is hidden on desktop. --- */
.joai-chat-mobilebar { display: none; }
.joai-chat-list-toggle { display: flex; align-items: center; gap: 0.4rem; flex: 1 1 auto; min-width: 0;
    padding: 0.55rem 0.85rem; border: 0; border-bottom: 1px solid #e6e8eb; background: #f7f8fa;
    color: #0d6efd; font: inherit; font-weight: 600; text-align: left; cursor: pointer; }
/* Maximize/minimize control, pinned to the right of the ⚙ Settings summary.
   Mobile-only (desktop has the room); shows the Minimize label while maximized. */
.joai-chat-fullscreen-toggle { display: none; align-items: center; justify-content: center;
    flex: none; padding: 0 0.85rem; border: 0; border-left: 1px solid #e6e8eb;
    background: #f7f8fa; color: #0d6efd; font-weight: 600; cursor: pointer; }
.joai-chat-fullscreen-toggle .joai-icon-max,
.joai-chat-fullscreen-toggle .joai-icon-min { align-items: center; }
.joai-chat-fullscreen-toggle .joai-icon-max { display: inline-flex; }
.joai-chat-fullscreen-toggle .joai-icon-min { display: none; }
.joai-chat-wrap.joai-fullscreen .joai-chat-fullscreen-toggle .joai-icon-max { display: none; }
.joai-chat-wrap.joai-fullscreen .joai-chat-fullscreen-toggle .joai-icon-min { display: inline-flex; }
/* While maximized, the control reads as an explicit, labeled way back. */
.joai-chat-fullscreen-toggle .joai-fs-label { display: none; margin-left: 0.4rem; font-weight: 600; }
.joai-chat-wrap.joai-fullscreen .joai-chat-fullscreen-toggle .joai-fs-label { display: inline; }
/* Background scroll lock while maximized. */
body.joai-fullscreen-lock { overflow: hidden; }

@media (max-width: 767px) {
    .joai-chat-wrap { position: relative; gap: 0; height: calc(100vh - 175px); min-height: 360px; }
    .joai-chat-list { position: absolute; top: 0; left: 0; bottom: 0; z-index: 40; width: 82%;
        max-width: 290px; transition: transform 0.22s ease;
        /* The wrap is inset from the viewport by the page/card padding, so clear the
           element's own width plus an extra margin to push it fully off-screen. */
        transform: translateX(calc(-100% - 4rem)); }
    .joai-chat-wrap.list-open .joai-chat-list { transform: translateX(0);
        box-shadow: 4px 0 18px rgba(0,0,0,0.18); }
    .joai-chat-list-backdrop { position: absolute; inset: 0; z-index: 35; background: rgba(0,0,0,0.4); }
    .joai-chat-main { width: 100%; min-width: 0; }
    .joai-chat-mobilebar { display: flex; }
    .joai-chat-fullscreen-toggle { display: inline-flex; }
    /* Icon-only on mobile: drop the "Settings" and "Minimize" words. */
    .joai-chat-settings-gear-label,
    .joai-chat-wrap.joai-fullscreen .joai-chat-fullscreen-toggle .joai-fs-label { display: none; }

    /* Maximized: the chat fills the viewport, above the site header/footer.
       100dvh tracks the dynamic viewport so the composer clears the mobile
       browser's address bar. */
    .joai-chat-wrap.joai-fullscreen { position: fixed; inset: 0; z-index: 2000;
        height: 100vh; height: 100dvh; min-height: 0; margin: 0; border-radius: 0;
        background: #fff; }
}

/* plugins/mailbox/assets/mailbox_reader.css */
/*
 * Mailbox Reader styles — two-pane Gmail layout: a left rail plus a single main
 * pane that swaps between the conversation list and an opened conversation.
 * Vanilla CSS, no framework. @version 2.53 — contacts pane: .mbx-contact-edit pencils, .mbx-contacts-locked;
 *   the add/import controls and the delete button are gone (the Contacts page has them)
 * @version 2.52 — .mbx-thread-purge removed (Trash rows show the received date)
 * @version 2.51 — .mbx-context-waiting (a slot held below a still-loading docked panel)
 * @version 2.50 — .mbx-device-search-btn (Rebuild / Remove on the device-search note)
 * @version 2.49 — .mbx-dai-link (Change / Test again in the one-line ready state)
 * @version 2.48 — .mbx-dai-ondemand (Summarize, Scan now)
 * @version 2.47 — .mbx-danger-banner-model, .mbx-dai-info
 * @version 2.46 — .mbx-dai ("Your AI, your model" in the AI panel)
 * @version 2.45 — the Fortress list banner reuses the setup banner
 * @version 2.44 — .mbx-level-fortress (the Fortress chip)
 * @version 2.43 — .mbx-addcontact (header add-to-contacts icon)
 */

/* Every size the reader renders text at, in one ladder. Nothing in this file
 * states a font-size literal — a rule picks the rung that matches its role, so
 * making the whole surface a step larger or smaller is an edit to these eight
 * values and nothing else. Declared at :root because the reader's modals mount
 * on the body, outside .mbx-reader. */
:root {
	--mbx-text-micro: 11px;   /* pills and tags */
	--mbx-text-xs:    12px;   /* rail labels, counts, timestamps */
	--mbx-text-sm:    13px;   /* secondary metadata, small controls */
	--mbx-text-base:  14px;   /* conversation rows, menus, buttons */
	--mbx-text-md:    15px;   /* message bodies, compose fields */
	--mbx-text-lg:    16px;   /* compose title, panel headings */
	--mbx-text-xl:    18px;   /* icon glyphs, modal close */
	--mbx-text-2xl:   20px;   /* open conversation subject, kebab glyph */
}

.mbx-reader {
	display: flex;
	gap: 0;
	overflow: hidden;
	background: #fff;
	height: calc(100vh - 220px);
	min-height: 420px;
}

/* Inside a kit app page (.page-content--app, e.g. /profile/mailbox/mailbox)
 * the host is a flex column sized to the viewport — grow to fill it instead
 * of guessing chrome height. */
.page-content--app .mbx-reader {
	height: auto;
	/* basis 0 so the reader's (internally scrolled) content doesn't inflate the
	 * page's intrinsic height — it takes whatever the viewport leaves over. */
	flex: 1 1 0;
	min-height: 420px;
}

.mbx-reader * { box-sizing: border-box; }

/* The conversation row's column geometry, stated once so the list header and the
 * rows below space themselves the same way. The sender width is in base-text
 * units rather than em so a rule with a different font-size can still use it. */
.mbx-reader {
	--mbx-row-gap:  10px;
	--mbx-check-w:  18px;
	--mbx-check-hit: 32px;
	--mbx-star-w:   18px;
	--mbx-from-w:   calc(13 * var(--mbx-text-base));
}

/* ---- Left rail ---- */
.mbx-rail {
	flex: 0 0 264px;
	border-right: 1px solid #e4e7eb;
	background: #f7f9fb;
	overflow-y: auto;
	padding: 12px 0;
}
.mbx-rail-section { padding: 0 12px 16px; }
/* Scoped under .mbx-reader so the reader's own heading sizing wins over a host
 * theme's bare h1/h2 defaults (e.g. the kit's `body.jy-default h2`), which would
 * otherwise blow these labels up to a page-title size. */
.mbx-reader .mbx-rail-title {
	font-size: var(--mbx-text-xs);
	text-transform: uppercase;
	letter-spacing: .05em;
	color: #6b7280;
	margin: 0 0 8px;
	font-weight: 600;
}
.mbx-mailbox-list { list-style: none; margin: 0; padding: 0; }
/* The rail's title row also carries the drawer's close button on a phone. */
.mbx-rail-head { display: flex; align-items: center; justify-content: space-between; }
.mbx-rail-close {
	display: none;
	border: none; background: none; cursor: pointer; color: #6b7280;
	font-size: var(--mbx-text-xl); line-height: 1; padding: 2px 6px; margin: -6px -6px 0 0;
	border-radius: 4px;
}
.mbx-rail-close:hover { background: #e9eef3; color: #111827; }
/* Scrim behind the phone drawer; nothing on a desktop, where there is no drawer. */
.mbx-scrim { display: none; }
/* Scope bar (specs/mailbox_reader_phone_layout.md): phone-only, above the
 * list header — the mailbox and folder the list is showing, and the way into
 * the drawer. On a desktop the rail highlight says the same thing, so the bar
 * does not exist there. */
.mbx-scope-row {
	display: none;
	align-items: center;
	border-bottom: 1px solid #e4e7eb;
	background: #f7f9fb;
}
.mbx-scope {
	display: flex;
	flex: 1 1 auto;
	min-width: 0;
	align-items: center;
	gap: 10px;
	padding: 10px 14px;
	border: none;
	background: none;
	color: #1f2933;
	font-size: var(--mbx-text-base);
	text-align: left;
	cursor: pointer;
}
/* The page's app-bar actions (AI, Actions) live here on a phone, as icons. */
.mbx-scope-actions { display: flex; align-items: center; gap: 4px; padding-right: 8px; flex: 0 0 auto; }
/* Monochrome, and one look for all three whatever class the host gave them:
 * white, a hairline border, a dark glyph. */
.mbx-scope-actions .btn {
	padding: 4px 6px; line-height: 1;
	background: #fff; border: 1px solid #cfd6dd; color: #1f2933; border-radius: 6px;
}
.mbx-scope-actions .btn:hover { background: #f1f3f5; color: #111827; }
.mbx-scope-actions .btn svg { width: 20px; height: 20px; display: block; }
.mbx-reader.search-open .mbx-scope-search { background: #e5e7eb; border-color: #9ca3af; }
/* The scope row's unread count is monochrome too. */
#mbx-scope-unread { background: #374151; }
.mbx-scope-caret { flex: 0 0 auto; color: #6b7280; font-size: var(--mbx-text-sm); }
.mbx-scope-text { flex: 1 1 auto; min-width: 0; display: flex; align-items: baseline; gap: 6px; overflow: hidden; }
.mbx-scope-mailbox { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mbx-scope-folder { flex: 0 0 auto; color: #6b7280; font-size: var(--mbx-text-sm); }
.mbx-scope-folder::before { content: '\203A\00a0'; }

.mbx-mailbox {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 6px;
	padding: 7px 9px;
	border-radius: 5px;
	cursor: pointer;
	font-size: var(--mbx-text-base);
	color: #1f2933;
}
.mbx-mailbox:hover { background: #e9eef3; }
.mbx-mailbox.active { background: #d7e7fb; font-weight: 600; }
.mbx-mailbox-addr { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Folder rail — the membership-driven folders under the active mailbox. */
.mbx-folders { list-style: none; margin: 0 0 4px 0; padding: 0; }
/* Same flex geometry as the mailbox rows above, so a folder's count (Drafts)
 * sits at the right edge with breathing room instead of butting the name. */
.mbx-folder {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 6px;
	padding: 5px 9px 5px 22px;
	border-radius: 5px;
	cursor: pointer;
	font-size: var(--mbx-text-sm);
	color: #3b4754;
}
.mbx-folder:hover { background: #eef2f6; }
.mbx-folder.active { background: #e3eefb; font-weight: 600; }
.mbx-folder-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mbx-badge {
	flex: 0 0 auto;
	min-width: 20px;
	text-align: center;
	background: #2563eb;
	color: #fff;
	font-size: var(--mbx-text-xs);
	font-weight: 600;
	border-radius: 10px;
	padding: 1px 6px;
}
.mbx-badge.zero { display: none; }
/* Protection-level chip (specs/mailbox_protection_ceremony.md) — trailing the
 * list toolbar, naming the protection of the mailbox being read. */
.mbx-level-badge {
	flex: 0 0 auto; font-size: var(--mbx-text-micro); font-weight: 600; border-radius: 8px;
	padding: 1px 7px;
}
.mbx-level-private { background: #d7e7fb; color: #1e40af; }
.mbx-level-fortress { background: #e4dcfa; color: #4c1d95; }

/* ---- Main pane (swaps between list view and reading view) ---- */
.mbx-main {
	flex: 1;
	min-width: 0;
	display: flex;
	flex-direction: column;
	overflow: hidden;
}
.mbx-list-view {
	display: flex;
	flex-direction: column;
	flex: 1;
	min-height: 0;
}
.mbx-read-view {
	display: none;
	flex: 1;
	min-height: 0;
	overflow-y: auto;
}
/* When reading, the list is replaced by the conversation (Gmail-style). */
.mbx-reader.reading .mbx-list-view { display: none; }
.mbx-reader.reading .mbx-read-view { display: flex; flex-direction: column; }

.mbx-list-header {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: var(--mbx-row-gap);
	padding: 10px 14px;
	border-bottom: 1px solid #eef1f4;
}
/* The toolbar takes the width it needs and never gives it up — a clipped bulk
 * action is a control the reader silently loses. The search box takes the
 * leftover width up to its own maximum, and its auto margins keep it centred in
 * whatever is left; when a selection's icons crowd it out, the header wraps and
 * search drops to its own line rather than squeezing anything off the row. */
.mbx-list-tools {
	flex: 0 0 auto;
	display: flex;
	align-items: center;
	gap: 2px;
	min-width: 0;
}
/* Select-all box and its caret menu, sharing the row's checkbox column so the
 * box sits directly above the ones on the rows below it. */
.mbx-selectall {
	position: relative;
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	gap: 0;
	padding-left: 2px;
}
.mbx-check-input {
	width: 15px; height: 15px; margin: 0; cursor: pointer;
	accent-color: #2563eb;
}
.mbx-check-input:disabled { cursor: default; opacity: .5; }
.mbx-select-caret {
	border: none; background: none; cursor: pointer; color: #6b7280;
	font-size: var(--mbx-text-xs); line-height: 1; padding: 4px 2px; border-radius: 4px;
}
.mbx-select-caret:hover { background: #eef1f4; color: #111827; }
.mbx-select-panel {
	position: absolute; z-index: 20; top: calc(100% + 6px); left: 0;
	min-width: 140px;
	background: #fff; border: 1px solid #cfd6dd; border-radius: 6px;
	box-shadow: 0 6px 18px rgba(16,24,40,.12); padding: 4px;
}
.mbx-select-opt {
	padding: 6px 10px; border-radius: 5px; cursor: pointer;
	font-size: var(--mbx-text-sm); color: #374151; white-space: nowrap;
}
.mbx-select-opt:hover { background: #f1f3f5; }

/* Toolbar icon buttons — one square hit area each, the icon sized inside it. */
.mbx-toolbtn {
	flex: 0 0 auto;
	display: inline-flex; align-items: center; justify-content: center;
	width: 32px; height: 32px;
	border: none; background: none; border-radius: 50%;
	color: #5f6368; cursor: pointer; padding: 0;
}
.mbx-toolbtn svg { width: 18px; height: 18px; display: block; }
.mbx-toolbtn:hover { background: #eef1f4; color: #111827; }
.mbx-toolbtn.danger:hover { background: #fee4e2; color: #b42318; }
.mbx-toolbtn:disabled { opacity: .4; cursor: default; background: none; }
/* Refresh in flight: the icon spins while the check-mail pull + re-read run. */
.mbx-toolbtn.mbx-refreshing svg { animation: mbx-spin .8s linear infinite; }
@keyframes mbx-spin { to { transform: rotate(360deg); } }
/* The bulk group appears only with a selection; it shares the toolbar's line. */
.mbx-bulk { display: flex; align-items: center; gap: 2px; }
.mbx-bulk[hidden] { display: none; }
.mbx-tool-sep {
	flex: 0 0 auto; width: 1px; height: 20px; margin: 0 5px; background: #e0e3e7;
}
.mbx-tool-sep[hidden] { display: none; }
.mbx-select-count {
	flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
	margin-left: 6px; font-size: var(--mbx-text-sm); color: #5f6368;
}
.mbx-select-count[hidden] { display: none; }
.mbx-list-header-actions {
	flex: 1 1 0;
	display: flex;
	align-items: center;
	justify-content: flex-end;
	gap: 6px;
}
.mbx-searchbar { flex: 1 1 200px; min-width: 0; max-width: 380px; margin: 0 auto; }
.mbx-search {
	width: 100%;
	border: 1px solid #cfd6dd;
	border-radius: 16px;
	padding: 6px 12px;
	font-size: var(--mbx-text-sm);
	background: #f3f5f8;
}
.mbx-search:focus {
	outline: none;
	border-color: #2563eb;
	background: #fff;
	box-shadow: 0 0 0 3px rgba(37, 99, 235, .15);
}
.mbx-new-btn {
	border: 1px solid #2563eb; background: #2563eb; color: #fff;
	border-radius: 16px; padding: 6px 14px; cursor: pointer;
	font-size: var(--mbx-text-sm); font-weight: 600;
}
.mbx-new-btn:hover { background: #1d4ed8; }
.mbx-new-btn[hidden] { display: none; }
.mbx-iconbtn {
	border: none; background: none; cursor: pointer;
	font-size: var(--mbx-text-xl); color: #6b7280; padding: 2px 6px; border-radius: 4px;
}
.mbx-iconbtn:hover { background: #eef1f4; color: #111827; }

.mbx-threads { list-style: none; margin: 0; padding: 0; overflow-y: auto; flex: 1; }

/* Gmail-style section heading (Unread / Starred / Everything else). */
.mbx-section {
	padding: 14px 14px 6px;
	background: #fff;
	font-size: var(--mbx-text-sm);
	font-weight: 700;
	letter-spacing: .02em;
	color: #5f6368;
	position: sticky;
	top: 0;
	z-index: 1;
}
.mbx-section:first-child { padding-top: 10px; }

.mbx-thread-item {
	display: flex;
	align-items: baseline;
	gap: var(--mbx-row-gap);
	padding: 9px 14px;
	border-bottom: 1px solid #f1f3f5;
	cursor: pointer;
	font-size: var(--mbx-text-base);
	background: #f6f8fb;          /* read rows sit on a faint grey, like Gmail */
}
.mbx-thread-item:hover {
	background: #fff;
	box-shadow: inset 1px 0 0 #d7e7fb, 0 1px 2px rgba(16,24,40,.08);
}
.mbx-thread-item.active { background: #eaf1fb; }
.mbx-thread-item.unread { background: #fff; }     /* unread rows pop on white */
/* A ticked row stays visibly picked under hover — the selection outlives the
 * pointer, so hover must not be able to hide it. */
.mbx-thread-item.selected,
.mbx-thread-item.selected:hover { background: #fdf3d6; }
/* Select box, first column, above-baseline with the rest of the row.
 *
 * The box is small; the target around it is not. A circle the size of a toolbar
 * button is centred on the box and takes the click, so ticking a row does not
 * ask for pointer precision — and it shows itself on hover, the way Gmail's
 * does. The circle is drawn out of flow, so it adds no column width and no row
 * height: it fits inside the row's own padding and never overlaps the row above
 * or below, and the checkbox stays painted on top of it. */
.mbx-thread-check {
	flex: 0 0 var(--mbx-check-w);
	position: relative;
	display: flex;
	align-items: center;
	justify-content: center;
	align-self: center;
	cursor: pointer;
}
.mbx-thread-check::before {
	content: '';
	position: absolute;
	left: 50%;
	top: 50%;
	width: var(--mbx-check-hit);
	height: var(--mbx-check-hit);
	margin: calc(var(--mbx-check-hit) / -2) 0 0 calc(var(--mbx-check-hit) / -2);
	border-radius: 50%;
}
.mbx-thread-check:hover::before { background: rgba(32, 33, 36, .09); }
.mbx-thread-check .mbx-check-input { position: relative; z-index: 1; }
/* Fixed width, not the glyph's own, so stars line up down the column. */
.mbx-thread-star {
	flex: 0 0 var(--mbx-star-w);
	text-align: center;
	color: #c4c9d0;
	font-size: var(--mbx-text-lg);
	cursor: pointer;
	line-height: 1.2;
}
.mbx-thread-star.on { color: #f5b400; }

/* Sender — fixed left column so subjects line up across rows. Sized off the
 * row's own text size, so a step up the ladder widens it instead of clipping
 * more of every name. */
.mbx-thread-from {
	flex: 0 0 var(--mbx-from-w);
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	color: #1f2933;
}
/* Subject + snippet share one clipped line. */
.mbx-thread-mid {
	flex: 1 1 auto;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.mbx-thread-subject { color: #1f2933; }
.mbx-thread-snippet { color: #6b7280; }
.mbx-thread-ai { font-style: italic; }
.mbx-thread-item.unread .mbx-thread-from,
.mbx-thread-item.unread .mbx-thread-subject { font-weight: 700; }
/* On an unread row the AI summary is the line worth reading — it says what the
   mail wants — so it carries the subject's colour rather than the muted snippet
   grey, a step darker still. A read row keeps the quiet grey either way. */
.mbx-thread-item.unread .mbx-thread-ai { color: #111827; }
.mbx-thread-time { flex: 0 0 auto; color: #9097a1; font-size: var(--mbx-text-xs); white-space: nowrap; }
/* The Trash view's one line about itself: the retention window, plus the
   source-server caveat on a mailbox that pulls from one. A note, not a row —
   it must never scan as mail. */
.mbx-trash-note {
	padding: 0.6rem 0.9rem;
	margin: 0.5rem 0.5rem 0.25rem;
	background: #f8fafc;
	border: 1px solid #e5e7eb;
	border-radius: 8px;
	font-size: var(--mbx-text-sm);
	color: #4b5563;
	line-height: 1.4;
}
/* Paperclip marker, sitting just left of the time. */
.mbx-thread-clip {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	color: #9097a1;
	margin-right: 4px;
}
.mbx-thread-clip svg { width: 13px; height: 13px; }
.mbx-thread-item.unread .mbx-thread-clip { color: #4b5563; }
.mbx-thread-count {
	display: inline-block;
	background: #e4e7eb;
	color: #4b5563;
	border-radius: 9px;
	font-size: var(--mbx-text-xs);
	padding: 0 6px;
	margin-left: 6px;
}
/* AI security scan badge (specs/joinery_ai_email_security_scan.md) — silent
   below score 5, since an unremarkable inbox is the common case. */
.mbx-danger-badge {
	display: inline-block;
	border-radius: 9px;
	font-size: var(--mbx-text-xs);
	font-weight: 700;
	padding: 0 6px;
	margin-left: 6px;
	white-space: nowrap;
}
.mbx-danger-badge.amber { background: #fef3c7; color: #92400e; }
.mbx-danger-badge.red   { background: #fee2e2; color: #991b1b; }

/* Verified-direct mark (docs/joinery_direct.md § The social signal).
   Deliberately quiet: one small glyph in the accent colour, no pill, no badge
   background, no borrowed blue check. It appears on a minority of messages, so
   restraint is what makes it read as meaningful rather than as decoration —
   and a mark that shouted would read as promotional, or as a phishing tell. */
.mbx-direct-mark {
	color: #0b7285;
	font-size: var(--mbx-text-sm);
	line-height: 1;
	margin-right: 4px;
	flex: 0 0 auto;
}
.mbx-direct-line {
	color: #0b7285;
}
/* A hairline on the message block, not a coloured panel behind it. */
.mbx-message-direct {
	border-left: 2px solid #0b7285;
	padding-left: 10px;
}
/* Compose-time indicator: one quiet line under the To field. It appears only
   when there is something to say — a message going by ordinary email says
   nothing, because the absence of the mark is the signal and a per-message
   "this is ordinary" would be noise. */
.mbx-direct-hint {
	color: #0b7285;
	font-size: var(--mbx-text-xs);
	margin: -6px 0 8px;
}

.mbx-list-footer { padding: 10px 14px; text-align: center; }
/* With nothing to load the footer is a blank strip under the list; it goes. */
.mbx-list-footer:has(> .mbx-more[hidden]) { display: none; }
.mbx-more {
	border: 1px solid #cfd6dd; background: #fff; border-radius: 5px;
	padding: 6px 14px; cursor: pointer; font-size: var(--mbx-text-base);
}

/* ---- Reading view ---- */
.mbx-thread { padding: 16px 20px; max-width: 900px; }
.mbx-thread-back {
	display: inline-flex; align-items: center; gap: 6px;
	border: none; background: none; cursor: pointer;
	color: #374151; font-size: var(--mbx-text-base); padding: 4px 6px; border-radius: 4px;
	margin-bottom: 10px;
}
.mbx-thread-back:hover { background: #eef1f4; color: #111827; }
.mbx-thread-back .mbx-back-arrow { font-size: var(--mbx-text-xl); line-height: 1; }
.mbx-thread-header { margin-bottom: 14px; }
/* Subject line: the subject takes the width it needs, the star sits at the far
 * right of the same line (Gmail), staying put as the subject wraps. */
.mbx-thread-title { display: flex; align-items: flex-start; gap: 10px; }
.mbx-thread-title h1 { flex: 1 1 auto; min-width: 0; }
.mbx-reader .mbx-thread-header h1 { font-size: var(--mbx-text-2xl); margin: 0 0 6px; color: #111827; }
/* The open conversation's star — the list column's glyph and colours, in a
 * round hit area the size of a toolbar button. */
.mbx-thread-starbtn {
	flex: 0 0 auto;
	display: inline-flex; align-items: center; justify-content: center;
	width: 32px; height: 32px; padding: 0;
	border: none; background: none; border-radius: 50%;
	color: #c4c9d0; font-size: var(--mbx-text-2xl); line-height: 1; cursor: pointer;
}
.mbx-thread-starbtn:hover { background: #eef1f4; }
.mbx-thread-starbtn.on { color: #f5b400; }
/* The open conversation's actions are the list toolbar's icon buttons, so the
 * row spaces them the way the toolbar does. */
.mbx-thread-actions { display: flex; align-items: center; gap: 2px; flex-wrap: wrap; margin-top: 8px; }
.mbx-action {
	border: 1px solid #cfd6dd; background: #fff; color: #374151;
	border-radius: 5px; padding: 5px 11px; cursor: pointer; font-size: var(--mbx-text-sm);
	text-decoration: none;
}
.mbx-action:hover { background: #f1f3f5; }
.mbx-action.danger { color: #b42318; border-color: #f1c4bf; }
.mbx-action.danger:hover { background: #fef0ee; }

/* Move / Labels control (open-thread toolbar). */
.mbx-folder-ctl { position: relative; display: inline-block; }
.mbx-folder-panel {
	position: absolute; z-index: 20; top: calc(100% + 4px); left: 0;
	min-width: 180px; max-height: 260px; overflow-y: auto;
	background: #fff; border: 1px solid #cfd6dd; border-radius: 6px;
	box-shadow: 0 6px 18px rgba(16,24,40,.12); padding: 4px;
}
.mbx-folder-opt {
	display: flex; align-items: center; gap: 6px;
	padding: 6px 9px; border-radius: 5px; cursor: pointer; font-size: var(--mbx-text-sm); color: #374151;
}
.mbx-folder-opt:hover { background: #f1f3f5; }
.mbx-folder-opt.current { font-weight: 600; background: #e3eefb; }
/* The trash can on a label row: right-aligned, quiet until the row is hovered or
 * the button focused. Low contrast rather than disabled — it is live, just not
 * competing with the tick that the row is for. A touch screen has no hover, so
 * there it simply shows. */
.mbx-label-trash {
	margin-left: auto; flex: 0 0 auto;
	display: inline-flex; align-items: center; justify-content: center;
	width: 22px; height: 22px; padding: 0;
	border: none; background: none; border-radius: 4px;
	color: #98a2ad; cursor: pointer; opacity: 0;
}
.mbx-label-trash svg { width: 14px; height: 14px; display: block; }
.mbx-folder-opt:hover .mbx-label-trash, .mbx-label-trash:focus-visible { opacity: 1; }
.mbx-label-trash:hover { color: #b42318; background: #fee4e2; }
@media (hover: none) { .mbx-label-trash { opacity: 1; } }
.mbx-folder-newrow { display: flex; gap: 4px; padding: 6px; border-top: 1px solid #eef0f2; margin-top: 2px; }
/* On a mailbox with no labels yet the field is the whole panel, so the rule that
 * separates it from the list above has nothing to separate. */
.mbx-folder-newrow:first-child { border-top: none; margin-top: 0; }
.mbx-folder-newinput {
	flex: 1 1 auto; min-width: 0; border: 1px solid #cfd6dd; border-radius: 5px;
	padding: 5px 8px; font-size: var(--mbx-text-sm);
}
.mbx-folder-newbtn {
	flex: 0 0 auto; border: 1px solid #cfd6dd; background: #fff; border-radius: 5px;
	padding: 4px 10px; cursor: pointer; font-size: var(--mbx-text-md); line-height: 1; color: #2563eb;
}
.mbx-folder-newbtn:hover { background: #f1f3f5; }
.mbx-folder-newbtn:disabled { opacity: .5; cursor: default; }

.mbx-message {
	border: 1px solid #e4e7eb;
	border-radius: 6px;
	margin-bottom: 12px;
	overflow: hidden;
}
.mbx-message-head {
	display: flex;
	justify-content: space-between;
	gap: 8px;
	padding: 10px 12px;
	background: #f7f9fb;
	cursor: pointer;
	font-size: var(--mbx-text-base);
}
/* The sender block yields before the time and menu do: a flex child will not
 * shrink below its longest word by default, and on a phone that word is a full
 * address — the head would push its right side out of the card and hand the
 * whole reading pane a sideways scroll. */
.mbx-message-left { flex: 1 1 auto; min-width: 0; }
.mbx-message-from { font-weight: 600; color: #1f2933; overflow-wrap: anywhere; }
.mbx-message-meta { color: #6b7280; font-size: var(--mbx-text-sm); overflow-wrap: anywhere; }

/* The add-to-contacts icon beside each header address: small and muted so a
 * header naming many people stays readable; it takes colour only on hover. */
.mbx-addcontact {
	display: inline-flex; align-items: center; justify-content: center;
	width: 18px; height: 18px; padding: 0; margin-left: 3px;
	border: 0; border-radius: 4px; background: transparent;
	color: #9097a1; cursor: pointer; vertical-align: -4px;
}
.mbx-addcontact[hidden] { display: none; }
.mbx-addcontact-tail { white-space: nowrap; }
.mbx-addcontact svg { width: 13px; height: 13px; }
.mbx-addcontact:hover { color: #2563eb; background: #e5edfb; }
.mbx-addcontact[disabled] { cursor: default; opacity: .6; }
.mbx-addcontact.mbx-addcontact-done { color: #3f7c53; background: transparent; opacity: 1; }
.mbx-addcontact.mbx-addcontact-failed { color: #b23c3c; }

/* Authentication line. A message nothing checked is the ordinary case for
   imported and IMAP-collected mail, so it stays neutral grey — only a verdict
   that actually FAILED earns colour, or the warning stops meaning anything. */
.mbx-auth { cursor: help; }
.mbx-auth-verified { color: #3f7c53; }
.mbx-auth-failed { color: #b23c3c; font-weight: 600; }
.mbx-auth-partial { color: #8a6d3b; }
.mbx-message-time { color: #9097a1; font-size: var(--mbx-text-sm); white-space: nowrap; }
.mbx-message-right { display: flex; align-items: center; gap: 4px; flex: 0 0 auto; }

/* Per-message kebab (⋮) menu — Gmail-style "more" affordance. */
.mbx-kebab-wrap { position: relative; }
.mbx-kebab {
	border: none; background: none; cursor: pointer;
	font-size: var(--mbx-text-2xl); line-height: 1; color: #6b7280;
	padding: 2px 6px; border-radius: 4px;
}
.mbx-kebab:hover { background: #e9eef3; color: #111827; }
.mbx-kebab-menu {
	position: absolute; right: 0; top: 100%; margin-top: 4px;
	background: #fff; border: 1px solid #d9dde2; border-radius: 6px;
	box-shadow: 0 4px 12px rgba(0, 0, 0, .12);
	min-width: 160px; padding: 4px 0; z-index: 10;
}
.mbx-kebab-menu[hidden] { display: none; }
/* An item is an <a> when it navigates and a <button> when it acts; both read as
 * one menu row, so the button's chrome is reset rather than restyled. */
.mbx-kebab-item {
	display: block; width: 100%; box-sizing: border-box;
	padding: 8px 14px; font-size: var(--mbx-text-base); font-family: inherit;
	color: #1f2933; text-decoration: none; white-space: nowrap;
	border: none; background: none; text-align: left; cursor: pointer;
}
.mbx-kebab-item:hover { background: #f1f6fd; }
.mbx-message-body { padding: 12px; font-size: var(--mbx-text-md); }
.mbx-message-body pre {
	white-space: pre-wrap; word-break: break-word; margin: 0;
	font-family: inherit;
}
/* The HTML body frame can't size to its (sandboxed, cross-origin) content, so
 * it takes 40% of the viewport where the screen affords it, never under 360px. */
.mbx-message-body iframe {
	width: 100%; height: max(360px, 40vh); border: 1px solid #e4e7eb; background: #fff;
}
.mbx-collapsed .mbx-message-body { display: none; }

/* AI security scan banner (specs/joinery_ai_email_security_scan.md). Sits
   between the head and the body as its own sibling, so a dangerous verdict
   stays visible even when the message is collapsed (mbx-collapsed only
   hides .mbx-message-body). */
.mbx-danger-banner {
	padding: 10px 12px;
	font-size: var(--mbx-text-base);
	border-bottom: 1px solid #e4e7eb;
}
.mbx-danger-banner-head { font-weight: 700; margin-bottom: 4px; }
.mbx-danger-banner-flags { margin: 4px 0 0; padding-left: 18px; }
.mbx-danger-banner.safe {
	background: #f0fdf4; color: #166534; border-bottom-color: #dcfce7;
	font-size: var(--mbx-text-sm); padding: 6px 12px;
}
.mbx-danger-banner.caution   { background: #fffbeb; color: #92400e; }
.mbx-danger-banner.dangerous { background: #fef2f2; color: #991b1b; }

/* Why a message is in Spam, plus the one deliberate way past it
   (specs/mailbox_contact_spam_bypass.md). A sibling of the body like the scan
   banner above, so the explanation survives a collapsed message. Deliberately
   informational rather than alarming — the message is already filed, and the
   banner exists to explain and offer, not to warn. */
.mbx-spam-reason {
	padding: 10px 12px;
	font-size: var(--mbx-text-sm);
	background: #fffbeb;
	color: #92400e;
	border-bottom: 1px solid #fde68a;
}
.mbx-spam-reason-head { font-weight: 700; margin-bottom: 4px; }
.mbx-spam-reason-actions {
	margin-top: 8px;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
}
.mbx-spam-reason-btn {
	display: inline-flex; align-items: center; gap: 6px;
	border: 1px solid #b45309; background: #fff; color: #92400e;
	border-radius: 18px; padding: 6px 14px; cursor: pointer;
	font-size: var(--mbx-text-sm); font-weight: 600;
}
.mbx-spam-reason-btn:hover { background: #fef3c7; }
.mbx-spam-reason-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.mbx-spam-reason-note { font-size: var(--mbx-text-xs); opacity: 0.85; }

/* ---- Attachment chips (Gmail-style, below the content area) ---- */
.mbx-attachments {
	padding: 4px 12px 14px;
	border-top: 1px solid #f1f3f5;
}
.mbx-collapsed .mbx-attachments { display: none; }
.mbx-attachments-label {
	font-size: var(--mbx-text-sm); color: #6b7280; font-weight: 600;
	margin: 8px 0 6px;
}
.mbx-attachments-note {
	font-size: var(--mbx-text-sm); color: #6b7280;
	margin: 0 0 8px;
}
.mbx-attachment-grid {
	display: flex; flex-wrap: wrap; gap: 8px;
}
/* The chip is a container: a download link, plus an optional preview button
 * beside it. A button cannot nest inside a link, which is why the bordered
 * chip is a div and the link sits inside it. */
.mbx-attachment {
	display: flex; align-items: stretch;
	max-width: 300px;
	border: 1px solid #d7dee6; border-radius: 8px;
	background: #fbfcfd;
	color: #1f2933; transition: background .12s, border-color .12s, box-shadow .12s;
}
.mbx-attachment:hover {
	background: #eef4fd; border-color: #a9c6f2;
	box-shadow: 0 1px 3px rgba(16,24,40,.10);
}
.mbx-attachment-open {
	display: flex; align-items: center; gap: 10px;
	min-width: 0; flex: 1 1 auto;
	padding: 8px 12px 8px 10px;
	text-decoration: none; color: inherit;
	border-radius: 8px 0 0 8px;
}
.mbx-attachment-preview {
	flex: 0 0 auto;
	display: inline-flex; align-items: center; justify-content: center;
	width: 34px;
	border: 0; border-left: 1px solid #dde4ec;
	border-radius: 0 8px 8px 0;
	background: transparent; color: #52606d;
	cursor: pointer; padding: 0;
	transition: background .12s, color .12s;
}
.mbx-attachment-preview:hover { background: #dbe8fb; color: #1d4ed8; }
.mbx-attachment-preview:focus-visible { outline: 2px solid #2563eb; outline-offset: -2px; }
.mbx-attachment-icon {
	flex: 0 0 auto; width: 30px; height: 30px;
	object-fit: contain;
	display: inline-flex; align-items: center; justify-content: center;
}
.mbx-attachment-icon--generic svg { width: 26px; height: 26px; }
.mbx-attachment-meta { min-width: 0; }
.mbx-attachment-name {
	font-size: var(--mbx-text-base); font-weight: 600;
	white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.mbx-attachment-size { font-size: var(--mbx-text-xs); color: #6b7280; margin-top: 1px; }

/* Outbound (sent) messages read as the right-hand side of the dialog. */
.mbx-message.mbx-outbound { border-color: #cfe0fb; }
.mbx-message.mbx-outbound .mbx-message-head { background: #eef5ff; }
.mbx-sent-tag {
	display: inline-block; margin-left: 8px;
	background: #2563eb; color: #fff;
	font-size: var(--mbx-text-micro); font-weight: 700; letter-spacing: .03em;
	border-radius: 9px; padding: 1px 7px; vertical-align: middle;
}

.mbx-loading { color: #9097a1; font-size: var(--mbx-text-base); padding: 14px; }

/* ---- Reply / Forward (Gmail-style: chips at the bottom of the conversation) ---- */
.mbx-reply-actions { display: flex; gap: 8px; flex-wrap: wrap; margin: 4px 0 20px; }
.mbx-reply-btn {
	display: inline-flex; align-items: center; gap: 6px;
	border: 1px solid #cfd6dd; background: #fff; color: #1f2933;
	border-radius: 18px; padding: 7px 16px; cursor: pointer; font-size: var(--mbx-text-base);
}
.mbx-reply-btn:hover { background: #f1f6fd; border-color: #9fc2f5; }

/* ---- Compose box (rendered once, moved to the bottom of the open thread) ---- */
/* Inline card in the conversation flow — not an overlay. */
.mbx-compose {
	display: flex;
	flex-direction: column;
	background: #fff;
	border: 1px solid #cfe0fb;
	border-radius: 8px;
	margin: 4px 0 20px;
	box-shadow: 0 1px 3px rgba(0, 0, 0, .06);
}
/* An explicit display: above defeats the [hidden] attribute's display:none, so
   restore it for the hidden (default / discarded) state. */
.mbx-compose[hidden] { display: none; }
/* Opened from the list (New message) the panel has no conversation to sit
 * under and lands in the main pane itself, a flex sibling of the list. Left
 * as a card there it squeezes the list to nothing — whose header then paints
 * over the compose title — and is clipped at the pane's foot, Send and all.
 * So in the pane it IS the pane: it scrolls inside itself and the list steps
 * aside until it closes (which also takes the phone's New-message pill with
 * it). Inside an open conversation none of this applies; that pane scrolls. */
.mbx-main > .mbx-compose:not([hidden]) {
	flex: 1 1 0;
	min-height: 0;
	overflow-y: auto;
	margin: 0;
	border: none;
	border-radius: 0;
	box-shadow: none;
}
.mbx-main:has(> .mbx-compose:not([hidden])) .mbx-list-view { display: none; }
.mbx-main > .mbx-compose:not([hidden]) .mbx-compose-head {
	position: sticky;
	top: 0;
	z-index: 1;
	background: #fff;
}
.mbx-compose-head {
	display: flex; align-items: center; gap: 4px;
	padding: 12px 16px; border-bottom: 1px solid #eef1f4;
}
/* The title pushes both icon buttons (discard, close) to the right edge as one
 * group — space-between would strand the trash can in the middle of the bar. */
.mbx-compose-title { font-weight: 600; font-size: var(--mbx-text-lg); color: #111827; margin-right: auto; }
.mbx-compose-error {
	margin: 12px 16px 0;
	background: #fef0ee; border: 1px solid #f1c4bf; color: #b42318;
	border-radius: 5px; padding: 8px 11px; font-size: var(--mbx-text-base);
}
/* The send-capability preflight: amber, not red — nothing has failed yet,
   the mailbox simply cannot send until its connected account is put right. */
.mbx-compose-preflight {
	margin: 12px 16px 0;
	background: #fef0c7; border: 1px solid #f5d38a; color: #93370d;
	border-radius: 5px; padding: 8px 11px; font-size: var(--mbx-text-base);
}
/* The FormWriter form lives inside the panel. */
.mbx-compose form { padding: 14px 16px 20px; }
.mbx-compose .form-group { margin-bottom: 12px; }
.mbx-compose label.form-label { display: block; font-size: var(--mbx-text-sm); color: #6b7280; margin-bottom: 4px; }
.mbx-compose input[type="text"],
.mbx-compose input[type="file"],
.mbx-compose select,
.mbx-compose textarea {
	width: 100%;
	border: 1px solid #cfd6dd;
	border-radius: 5px;
	padding: 8px 10px;
	font-size: var(--mbx-text-md);
	font-family: inherit;
}
.mbx-compose textarea { resize: vertical; min-height: 160px; }
.mbx-compose button[type="submit"] {
	background: #2563eb; border: 1px solid #2563eb; color: #fff;
	border-radius: 5px; padding: 8px 18px; cursor: pointer; font-size: var(--mbx-text-md); font-weight: 600;
}
.mbx-compose button[type="submit"]:hover { background: #1d4ed8; }
.mbx-compose button[type="submit"]:disabled { opacity: .6; cursor: default; }

/* ---- Compose attachments: pending chips + paperclip + drag-and-drop ---- */
.mbx-attach-strip {
	display: flex; flex-wrap: wrap; gap: 6px;
	padding: 0 16px 10px;
}
.mbx-attach-chip {
	display: inline-flex; align-items: center; gap: 6px;
	max-width: 220px;
	background: #eef1f4; border-radius: 14px;
	padding: 4px 6px 4px 10px; font-size: var(--mbx-text-sm); color: #1f2933;
}
.mbx-attach-chip-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mbx-attach-chip-size { color: #6b7280; flex: 0 0 auto; }
.mbx-attach-chip-remove {
	border: none; background: none; cursor: pointer; font-size: var(--mbx-text-base);
	color: #6b7280; line-height: 1; padding: 2px 4px; border-radius: 50%;
}
.mbx-attach-chip-remove:hover { color: #b42318; background: #fff; }

.mbx-compose-actions {
	display: flex; align-items: center; gap: 8px;
	padding: 0 16px 16px;
}
.mbx-file-input { display: none; }
.mbx-attach-btn {
	flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
	width: 32px; height: 32px; color: #6b7280;
}
.mbx-attach-btn svg { width: 20px; height: 20px; display: block; }
.mbx-attach-btn:hover { background: #eef1f4; color: #111827; }
.mbx-compose-actions button[type="submit"] { margin-left: auto; }

/* Drag-and-drop affordance while a file is dragged over the open compose panel. */
.mbx-compose.mbx-compose-dragover {
	outline: 2px dashed #2563eb; outline-offset: -4px;
}

/* ---- Responsive: rail moves above the main pane on narrow screens ---- */
/* ---- Phone layout (specs/mailbox_reader_phone_layout.md) ----
 * Below the kit's header breakpoint the reader shows one pane at a time: the
 * list by default, an opened conversation in its place, and the rail only on
 * request, as a drawer over the list. The reader keeps filling the viewport
 * and scrolling inside itself; only what lives inside that height changes. */
@media (max-width: 768px) {
	/* The rail leaves the flex row and becomes a drawer: off-canvas until
	 * .rail-open, then full height with its own scroll. In the row it is
	 * content-sized and cannot shrink, which is what squeezed the list to
	 * nothing on a phone. */
	.mbx-rail {
		position: fixed;
		top: 0; left: 0; bottom: 0;
		height: 100vh;
		height: 100dvh;
		width: min(320px, 85vw);
		flex: none;
		overflow-y: auto;
		box-shadow: 0 0 24px rgba(16, 24, 40, .18);
		z-index: 1000;
		transform: translateX(-100%);
		visibility: hidden;
		transition: transform .2s ease, visibility 0s linear .2s;
	}
	.mbx-reader.rail-open .mbx-rail {
		transform: none;
		visibility: visible;
		transition: transform .2s ease;
	}
	.mbx-scrim {
		display: block;
		position: fixed;
		inset: 0;
		background: rgba(16, 24, 40, .4);
		z-index: 999;
		opacity: 0;
		visibility: hidden;
		transition: opacity .2s ease, visibility 0s linear .2s;
	}
	.mbx-reader.rail-open .mbx-scrim { opacity: 1; visibility: visible; transition: opacity .2s ease; }
	.mbx-rail-close { display: inline-flex; }

	/* The scope row stands in for the rail highlight and carries the page's
	 * actions, so the app bar above the reader has nothing left to say and
	 * goes (the reader JS moves the actions and marks the bar). Hidden while
	 * reading: the conversation header names its own context. */
	.mbx-scope-row { display: flex; }
	.mbx-reader.reading .mbx-scope-row { display: none; }
	.jy-app-bar.mbx-app-bar-moved { display: none; }

	/* Too narrow for three things on one row: search drops to its own full-width
	 * line under the toolbar and the buttons, which then take only the width
	 * they need instead of half the row each. */
	.mbx-list-header .mbx-searchbar { order: 3; flex: 1 1 100%; max-width: none; margin: 0; }
	.mbx-list-header .mbx-list-tools { flex: 1 1 auto; }
	.mbx-list-header .mbx-list-header-actions { flex: 0 0 auto; }
	/* The search line is hidden until the scope row's search icon reveals it. */
	.mbx-list-header .mbx-searchbar { display: none; }
	.mbx-reader.search-open .mbx-list-header .mbx-searchbar { display: block; }
	/* No section headings (Unread / Starred / Everything else): the order is
	 * the same, the labels cost rows. */
	.mbx-section { display: none; }

	/* The list header only exists for a selection's tools or an open search;
	 * otherwise the rows start straight under the scope row. Select-all and
	 * Refresh are gone (rows tick individually; pull-to-refresh reloads). */
	.mbx-list-header { display: none; }
	.mbx-reader.search-open .mbx-list-header,
	.mbx-list-header:has(#mbx-bulk:not([hidden])) { display: flex; }
	.mbx-selectall, #mbx-refresh { display: none; }
	/* New message floats over the foot of the list as a pill (the reader JS
	 * moves it out of the header). It lives inside the list view, so it is
	 * gone while reading. */
	.mbx-new-btn.mbx-fab {
		position: fixed;
		right: 16px;
		bottom: 16px;
		z-index: 50;
		padding: 12px 18px;
		border-radius: 999px;
		font-size: var(--mbx-text-base);
		background: #fff; color: #111827; border: 1px solid #cfd6dd;
		box-shadow: 0 4px 14px rgba(16, 24, 40, .28);
	}
	.mbx-new-btn.mbx-fab:hover { background: #f1f3f5; }
	.mbx-scope-text .mbx-level-badge { margin-left: 4px; }

	/* Two-line rows. The desktop row's fixed sender column leaves nothing for
	 * the subject at phone width, so sender and time take line one, subject and
	 * snippet line two; the checkbox, star and verified mark span both. The
	 * markup is the desktop row's — each piece is placed by name. */
	.mbx-thread-item {
		display: grid;
		grid-template-columns: auto auto auto minmax(0, 1fr) auto auto;
		grid-template-areas:
			"check star mark from clip time"
			"check star mark mid  mid  mid";
		column-gap: 0;
		row-gap: 2px;
		align-items: center;
		padding: 9px 12px;
	}
	.mbx-thread-check { grid-area: check; margin-right: var(--mbx-row-gap); }
	.mbx-thread-star  { grid-area: star;  margin-right: var(--mbx-row-gap); }
	.mbx-direct-mark  { grid-area: mark; }
	.mbx-thread-from  { grid-area: from; flex: none; }
	.mbx-thread-mid   { grid-area: mid; }
	.mbx-thread-clip  { grid-area: clip; margin-left: var(--mbx-row-gap); }
	.mbx-thread-time  { grid-area: time; margin-left: var(--mbx-row-gap); }

	.mbx-thread { padding: 12px 14px; }

	/* Floating panels never run past the screen edge. */
	.mbx-select-panel, .mbx-folder-panel, .mbx-kebab-menu { max-width: calc(100vw - 2rem); }
}
}

/* Locked-state unlock affordances (specs/mailbox_security_levels.md § 4.1):
   a one-tap prompt shown when sealed content or search needs an open vault. */
.mbx-unlock-banner {
	display: flex;
	align-items: center;
	gap: 0.75rem;
	padding: 0.625rem 0.875rem;
	margin: 0.5rem 0;
	background: #fff7ed;
	border: 1px solid #fed7aa;
	border-radius: 8px;
	font-size: var(--mbx-text-base);
}
.mbx-unlock-text { color: #7c2d12; }
.mbx-unlock-btn {
	margin-left: auto;
	padding: 0.35rem 0.85rem;
	border: none;
	border-radius: 6px;
	background: #2563eb;
	color: #fff;
	font-size: var(--mbx-text-sm);
	cursor: pointer;
}
.mbx-unlock-btn:disabled { opacity: 0.6; cursor: default; }

/* A search from the Inbox tab covers All Mail — one quiet line above the
   results explains hits from outside the Inbox. */
.mbx-search-scope-note {
	padding: 0.375rem 0.875rem;
	margin: 0.25rem 0;
	color: var(--mbx-text-muted, #6b7280);
	font-size: var(--mbx-text-sm);
}
/* A search over Fortress mail ran on this device: the line says how far the
   index has got, with two quiet controls for this browser's copy. */
.mbx-device-search-btn {
	background: none;
	border: none;
	padding: 0;
	margin-right: 0.75rem;
	font: inherit;
	color: var(--jy-color-primary, #2563eb);
	text-decoration: underline;
	cursor: pointer;
}
.mbx-device-search-btn:disabled { opacity: 0.6; cursor: default; }

/* Search over an index still catching up on a backlog: informational, not an
   error and not actionable — the fold continues in the background. */
.mbx-indexing-banner {
	display: flex;
	align-items: center;
	gap: 0.75rem;
	padding: 0.625rem 0.875rem;
	margin: 0.5rem 0;
	background: #eff6ff;
	border: 1px solid #bfdbfe;
	border-radius: 8px;
	font-size: var(--mbx-text-base);
}
.mbx-indexing-text { color: #1e40af; }

/* A read that failed. Distinct from the empty state beside it: an empty
   mailbox is a fact about the mail, this is a fact about the request. */
.mbx-load-error {
	display: flex;
	align-items: center;
	gap: 0.75rem;
	padding: 0.625rem 0.875rem;
	margin: 0.5rem 0;
	background: #fef2f2;
	border: 1px solid #fecaca;
	border-radius: 8px;
	font-size: var(--mbx-text-base);
}
.mbx-load-error-text { color: #991b1b; }

/* Catch-up prompt (specs/in_window_deferred_work.md § Catching up): shown only
   when enough unsummarized mail has piled up that background batches will not
   clear it promptly. Deliberately quieter than the unlock banner — nothing is
   wrong, there is just a backlog. */
.mbx-catchup-banner {
	display: flex;
	align-items: center;
	gap: 0.75rem;
	padding: 0.5rem 0.875rem;
	margin: 0.5rem 0;
	background: #f8fafc;
	border: 1px solid #e2e8f0;
	border-radius: 8px;
	font-size: var(--mbx-text-sm);
}
.mbx-catchup-text { color: #475569; }
.mbx-catchup-progress { color: #64748b; }
.mbx-catchup-btn {
	margin-left: auto;
	padding: 0.3rem 0.8rem;
	border: 1px solid #cbd5e1;
	border-radius: 6px;
	background: #fff;
	color: #334155;
	font-size: var(--mbx-text-sm);
	cursor: pointer;
}
.mbx-catchup-btn:hover { background: #f1f5f9; }
.mbx-catchup-btn:disabled { opacity: 0.6; cursor: default; }

/* Setup banner (specs/mailbox_setup_verdicts.md): shown in place of the first
   conversation when the open mailbox looks unfinished, and absent entirely
   otherwise. It reads as a card, not a row, so it never scans as mail. */
.mbx-setup-banner {
	display: flex;
	align-items: center;
	gap: 1rem;
	padding: 0.875rem 1rem;
	margin: 0.5rem 0.5rem 0.75rem;
	background: #fffbeb;
	border: 1px solid #fcd34d;
	border-left: 4px solid #f59e0b;
	border-radius: 8px;
}
.mbx-setup-banner-body { display: flex; flex-direction: column; gap: 0.2rem; min-width: 0; }
.mbx-setup-banner-title {
	font-weight: 600;
	font-size: var(--mbx-text-md);
	color: #78350f;
}
.mbx-setup-banner-reason { font-size: var(--mbx-text-sm); color: #92400e; }
.mbx-setup-banner-btn {
	margin-left: auto;
	flex: 0 0 auto;
	padding: 0.45rem 0.95rem;
	border-radius: 6px;
	background: #b45309;
	color: #fff;
	font-size: var(--mbx-text-sm);
	font-weight: 600;
	text-decoration: none;
	white-space: nowrap;
}
.mbx-setup-banner-btn:hover { background: #92400e; color: #fff; }
/* The Fortress banner's action is a button, not a link. */
button.mbx-setup-banner-btn { border: 0; cursor: pointer; font-family: inherit; line-height: inherit; }
button.mbx-setup-banner-btn:disabled { opacity: 0.6; cursor: default; }

/* ── compose maturity: rich-text editor + Bcc toggle (§ Phase 1) ───────────── */
.mbx-bcc-toggle-row { display: flex; gap: 14px; margin: -0.25rem 0 0.35rem; }
.mbx-bcc-toggle {
	background: none;
	border: none;
	padding: 0;
	color: #2563eb;
	font-size: var(--mbx-text-sm);
	cursor: pointer;
}
.mbx-bcc-toggle:hover { text-decoration: underline; }

.mbx-richwrap { margin: 0.5rem 0; }
.mbx-rich-label {
	display: block;
	font-size: var(--mbx-text-sm);
	font-weight: 600;
	color: #374151;
	margin-bottom: 0.25rem;
}
.mbx-toolbar {
	display: flex;
	align-items: center;
	gap: 2px;
	flex-wrap: wrap;
	padding: 4px 6px;
	border: 1px solid #cfd6dd;
	border-bottom: none;
	border-radius: 6px 6px 0 0;
	background: #f7f9fb;
}
.mbx-tb {
	min-width: 28px;
	height: 26px;
	padding: 0 7px;
	border: 1px solid transparent;
	border-radius: 4px;
	background: none;
	color: #374151;
	font-size: var(--mbx-text-base);
	line-height: 1;
	cursor: pointer;
}
.mbx-tb:hover { background: #e9eef3; border-color: #cfd6dd; }
.mbx-tb:active { background: #d7e7fb; }
.mbx-tb-sep {
	width: 1px;
	height: 18px;
	margin: 0 4px;
	background: #d7dde3;
}
.mbx-rich {
	min-height: 320px;
	max-height: 60vh;
	overflow-y: auto;
	padding: 0.6rem 0.7rem;
	border: 1px solid #cfd6dd;
	border-radius: 0 0 6px 6px;
	background: #fff;
	font-size: var(--mbx-text-md);
	line-height: 1.5;
	color: #1f2933;
}
.mbx-rich:focus { outline: none; border-color: #2563eb; box-shadow: 0 0 0 2px rgba(37,99,235,.15); }
.mbx-rich img { max-width: 100%; height: auto; }
.mbx-rich blockquote {
	margin: 0 0 0 .8ex;
	padding-left: 1ex;
	border-left: 2px solid #cfd6dd;
	color: #52606d;
}
.mbx-rich.mbx-rich-empty::before {
	content: attr(data-placeholder);
	color: #9aa5b1;
	pointer-events: none;
}

/* ── compose maturity: drafts (§ Phase 2) ──────────────────────────────────── */
.mbx-drafts-entry .mbx-mailbox-addr { font-style: italic; }
.mbx-attach-chip.mbx-attach-saved {
	background: #eef2f6;
	border-color: #d7dde3;
	opacity: 0.85;
}
.mbx-attach-chip.mbx-attach-saved .mbx-attach-chip-name::before {
	content: "📎 ";
}

/* ── compose maturity: signatures (§ Phase 3) ──────────────────────────────── */
.mbx-mailbox { position: relative; }
/* The signature as it sits in a composed message. */
.mbx-sig-block { color: #52606d; }

.mbx-modal-overlay {
	position: fixed;
	inset: 0;
	background: rgba(16, 24, 40, .45);
	display: flex;
	align-items: center;
	justify-content: center;
	z-index: 1000;
}
.mbx-modal {
	background: #fff;
	border-radius: 10px;
	box-shadow: 0 10px 40px rgba(16, 24, 40, .25);
	width: min(560px, 92vw);
	max-height: 88vh;
	overflow-y: auto;
	padding: 1.1rem 1.25rem 1rem;
}
.mbx-modal-title { margin: 0 0 .15rem; font-size: var(--mbx-text-lg); color: #111827; }
.mbx-modal-help { margin: 0 0 .75rem; font-size: var(--mbx-text-sm); color: #6b7280; }
/* A confirmation that takes a typed name before it will act (delete a label). */
.mbx-confirm-modal { width: min(440px, 92vw); }
.mbx-confirm-field { display: block; margin: .25rem 0 .5rem; }
.mbx-confirm-prompt { display: block; font-size: var(--mbx-text-sm); color: #374151; margin-bottom: 4px; }
.mbx-confirm-input {
	width: 100%; box-sizing: border-box;
	border: 1px solid #cfd6dd; border-radius: 6px; padding: 7px 10px;
	font-size: var(--mbx-text-base); font-family: inherit;
}
.mbx-confirm-error { color: #b42318; }
.mbx-action:disabled { opacity: .5; cursor: default; }
.mbx-action:disabled:hover { background: #fff; }
.mbx-sig-editor { min-height: 120px; max-height: 300px; }

/* ---------------------------------------------------------------------------
   The Email settings section (/profile/mailbox/settings) — one signature card
   per mailbox, outside .mbx-reader, borrowing the reader's editor styling so a
   signature is written in the same box it will be shown in.
   --------------------------------------------------------------------------- */
.mbx-settings-links { list-style: none; margin: 0; padding: 0; }
.mbx-settings-links li { margin: 0 0 .75rem; }
.mbx-settings-links li:last-child { margin-bottom: 0; }
.mbx-settings-links a { font-weight: 600; }
.mbx-settings-links span { display: block; font-size: var(--mbx-text-sm); }

.mbx-sig-card { margin: 1.25rem 0 .5rem; }
/* Two classes deep, because the page is inside a theme that has its own idea
   of what an h2 and a p look like. */
.mbx-sig-card .mbx-sig-address {
	margin: 0 0 .4rem;
	font-size: var(--mbx-text-md);
	font-weight: 600;
	color: #111827;
}
.mbx-sig-card .mbx-sig-note { margin: .4rem 0 0; font-size: var(--mbx-text-sm); }
.mbx-sig-card .mbx-sig-note.is-ok { color: #067647; }
.mbx-sig-card .mbx-sig-note.is-error { color: #b42318; }

/* "Show logs": the message timeline — a time column and a body column per
 * event, the column collapsing to stacked lines at phone width. Kinds colour
 * the marker only: a failure reads red, a delivery green, everything else the
 * neutral dot. */
.mbx-timeline-modal { width: min(760px, 94vw); }
.mbx-timeline {
	list-style: none;
	margin: 0;
	padding: 0;
	max-height: 60vh;
	overflow: auto;
	border-left: 2px solid #e4e7eb;
}
.mbx-timeline-item {
	position: relative;
	display: grid;
	grid-template-columns: 11.5rem 1fr;
	gap: .25rem .9rem;
	padding: .45rem 0 .45rem 1.1rem;
}
.mbx-timeline-item::before {
	content: '';
	position: absolute;
	left: -6px;
	top: .8rem;
	width: 10px;
	height: 10px;
	border-radius: 50%;
	background: #9aa3ae;
	border: 2px solid #fff;
}
.mbx-timeline-item.kind-attempt_failed::before { background: #b42318; }
.mbx-timeline-item.kind-delivery::before,
.mbx-timeline-item.kind-sent::before,
.mbx-timeline-item.kind-receipt::before { background: #067647; }
.mbx-timeline-item.kind-auth::before,
.mbx-timeline-item.kind-spam::before { background: #4f6bed; }
.mbx-timeline-time {
	font-size: var(--mbx-text-sm);
	color: #6b7280;
	font-variant-numeric: tabular-nums;
	white-space: nowrap;
	padding-top: .1rem;
}
.mbx-timeline-time.is-timeless::after { content: '—'; color: #c4c9d0; }
.mbx-timeline-title { font-weight: 600; color: #1f2933; }
.mbx-timeline-detail { font-size: var(--mbx-text-sm); color: #4b5563; overflow-wrap: anywhere; }
.mbx-timeline-detail.is-muted { color: #9aa3ae; }
.mbx-timeline-notes {
	margin: .75rem 0 0;
	padding: .6rem .8rem;
	list-style: none;
	background: #f7f8fa;
	border: 1px solid #e4e7eb;
	border-radius: 6px;
	font-size: var(--mbx-text-sm);
	color: #4b5563;
}
.mbx-timeline-notes li + li { margin-top: .3rem; }
@media (max-width: 640px) {
	.mbx-timeline-item { grid-template-columns: 1fr; gap: .1rem; }
}

/* "Show original": raw RFC822, so it is read as code — monospace, wrapped at
 * word boundaries (headers run long), and scrolled inside the modal rather
 * than growing it. Wider than the default modal because header lines are. */
.mbx-source-modal { width: min(860px, 94vw); }
.mbx-source {
	margin: 0;
	padding: .6rem .7rem;
	background: #f7f8fa;
	border: 1px solid #e4e7eb;
	border-radius: 6px;
	max-height: 60vh;
	overflow: auto;
	font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
	font-size: var(--mbx-text-sm);
	line-height: 1.45;
	color: #1f2933;
	white-space: pre-wrap;
	word-break: break-word;
	-webkit-user-select: text;
	user-select: text;
}
/* Attachment preview: the document's words, never the document. Extracted
 * prose reads as prose (proportional, wrapped); spreadsheets, archive
 * manifests and raw XML keep their columns (monospace). */
.mbx-preview-modal { width: min(820px, 94vw); }
.mbx-preview-text {
	margin: 0;
	padding: .7rem .8rem;
	background: #f7f8fa;
	border: 1px solid #e4e7eb;
	border-radius: 6px;
	max-height: 62vh;
	overflow: auto;
	font-family: inherit;
	font-size: var(--mbx-text-base);
	line-height: 1.5;
	color: #1f2933;
	white-space: pre-wrap;
	word-break: break-word;
	-webkit-user-select: text;
	user-select: text;
}
/* A picture preview: sized to the modal, never scaled up past its own
 * resolution, on a neutral field so a transparent PNG is still legible. */
.mbx-preview-image {
	display: block;
	max-width: 100%;
	max-height: 62vh;
	margin: 0 auto;
	border: 1px solid #e4e7eb;
	border-radius: 6px;
	background: #f7f8fa;
	object-fit: contain;
}
.mbx-preview-text.mbx-preview-mono {
	font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
	font-size: var(--mbx-text-sm);
	white-space: pre;
	word-break: normal;
}
.mbx-modal-actions {
	display: flex;
	justify-content: flex-end;
	gap: .5rem;
	margin-top: .9rem;
}
/* The Download action is an anchor; it must sit level with the buttons. */
.mbx-modal-actions a.mbx-action { display: inline-flex; align-items: center; text-decoration: none; }
.mbx-action.mbx-primary { background: #2563eb; border-color: #2563eb; color: #fff; }
.mbx-action.mbx-primary:hover { background: #1d4ed8; }
.mbx-action.mbx-primary:disabled { opacity: .6; cursor: default; }

/* ── compose maturity: contacts autocomplete + manager (§ Phase 4) ─────────── */
.mbx-contacts-entry .mbx-mailbox-addr { font-style: italic; }
.mbx-ac-dropdown {
	position: absolute;
	left: 0;
	right: 0;
	top: 100%;
	z-index: 50;
	background: #fff;
	border: 1px solid #cfd6dd;
	border-radius: 0 0 6px 6px;
	box-shadow: 0 6px 18px rgba(16, 24, 40, .12);
	max-height: 240px;
	overflow-y: auto;
}
.mbx-ac-item {
	display: flex;
	flex-direction: column;
	padding: .35rem .6rem;
	cursor: pointer;
}
.mbx-ac-item.active, .mbx-ac-item:hover { background: #e3eefb; }
.mbx-ac-name { font-size: var(--mbx-text-base); color: #1f2933; }
.mbx-ac-addr { font-size: var(--mbx-text-xs); color: #6b7280; }

.mbx-contacts-list { display: flex; flex-direction: column; }
.mbx-contact-row {
	display: flex;
	align-items: center;
	gap: .5rem;
	padding: .45rem .25rem;
	border-bottom: 1px solid #f1f3f5;
}
.mbx-contact-info { display: flex; flex-direction: column; flex: 1; }
.mbx-contact-name { font-size: var(--mbx-text-base); color: #1f2933; }
.mbx-contact-addr { font-size: var(--mbx-text-sm); color: #6b7280; }
/* The pencil beside each contact, and in the pane's header: both open the
   Contacts page (the header's on the mailbox, a row's on that contact). */
.mbx-contact-edit {
	display: inline-flex;
	flex: 0 0 auto;
	width: 1.5rem;
	height: 1.5rem;
	padding: .2rem;
	border-radius: 4px;
	color: #9aa5b1;
}
.mbx-contact-edit:hover { color: #2563eb; background: #f1f5f9; }
.mbx-contact-edit svg { width: 100%; height: 100%; }
.mbx-context-head .mbx-contact-edit { margin-left: auto; }
.mbx-contacts-empty { padding: .25rem 0; font-size: var(--mbx-text-sm); color: #6b7280; }

/* A sealed store with the vault shut: a quiet note and a small button, in the
   column's own colours — locked is a normal state, not a fault. */
.mbx-contacts-locked {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: .5rem;
	padding: .75rem;
	border: 1px solid #e4e7eb;
	border-radius: 8px;
	background: #f8fafc;
}
.mbx-contacts-locked-text {
	margin: 0;
	font-size: var(--mbx-text-sm);
	line-height: 1.45;
	color: #52606d;
}
.mbx-contacts-locked-btn {
	padding: .3rem .8rem;
	border: 1px solid #cbd2d9;
	border-radius: 6px;
	background: #fff;
	color: #1f2933;
	font-size: var(--mbx-text-sm);
	font-weight: 500;
	cursor: pointer;
}
.mbx-contacts-locked-btn:hover { border-color: #2563eb; color: #2563eb; }

/* ── contact panel (§ Phase 5) ─────────────────────────────────────────────────
   One aside, two jobs: the open conversation's counterparty card, and — on the
   list view — the selected mailbox's contact manager, collapsed to a spine by
   default. Collapsed still shows the header, so the panel announces itself
   instead of disappearing. */
.mbx-context {
	flex: 0 0 260px;
	border-left: 1px solid #e4e7eb;
	background: #f7f9fb;
	padding: .75rem .85rem;
	overflow-y: auto;
	font-size: var(--mbx-text-base);
	transition: flex-basis .15s ease;
}
.mbx-context.mbx-context-collapsed {
	flex-basis: 2.4rem;
	padding: .75rem .35rem;
	overflow: hidden;
}
.mbx-context-head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: .35rem;
	margin-bottom: .5rem;
}
/* A header that leads with its collapse control reads left-to-right: the caret,
   then what it opens. Space-between is for the counterparty card's header,
   whose close button belongs at the far edge. */
.mbx-context-head:has(.mbx-context-toggle) { justify-content: flex-start; }
/* One slot per panel. A rule between them, never above the first or below the
   last, so the column reads as stacked panels rather than boxed ones. */
.mbx-context-slot + .mbx-context-slot {
	margin-top: .75rem;
	padding-top: .75rem;
	border-top: 1px solid #e4e7eb;
}
/* Below a docked panel that is still loading its first content: out of the
   layout until it settles (syncContextColumn), so its growth moves nothing. */
.mbx-context-slot.mbx-context-waiting { display: none; }
.mbx-context.mbx-context-collapsed .mbx-context-slot + .mbx-context-slot {
	margin-top: .5rem;
	padding-top: .5rem;
}
/* Spine mode belongs to the COLUMN, not to a panel: one collapsed panel beside
   an open one is just a header row. Only when every panel is collapsed does the
   column narrow, and then each title turns on its side so the spine reads as a
   labelled edge rather than a blank gutter. */
.mbx-context.mbx-context-collapsed .mbx-context-head {
	flex-direction: column;
	justify-content: flex-start;
	margin-bottom: 0;
}
.mbx-context.mbx-context-collapsed .mbx-context-title {
	writing-mode: vertical-rl;
	margin-top: .5rem;
	font-size: var(--mbx-text-sm);
	color: #52606d;
	white-space: nowrap;
}
/* Matches the disclosure control a docked plugin panel draws in this same
   column (.aip-head-toggle): a plain triangle, no box. */
.mbx-context-toggle {
	border: 0;
	background: none;
	/* The same token the docked panel's own toggle resolves, so the two
	   triangles are the same grey under any theme. */
	color: var(--jy-color-text-muted, #667085);
	cursor: pointer;
	font-size: .85rem;
	line-height: 1;
	padding: 0 .15rem;
}
.mbx-context-toggle:hover { color: #2563eb; }
.mbx-context-title { font-weight: 600; color: #111827; }
.mbx-context-card {
	background: #fff;
	border: 1px solid #e4e7eb;
	border-radius: 8px;
	padding: .6rem .7rem;
	margin-bottom: .75rem;
}
.mbx-context-name { font-weight: 600; color: #1f2933; }
.mbx-context-email { color: #52606d; font-size: var(--mbx-text-sm); margin-top: .1rem; }
.mbx-context-since { color: #6b7280; font-size: var(--mbx-text-xs); margin-top: .25rem; }
/* The "also on this message" cards: same card, tighter, with a To/Cc marker. */
.mbx-context-card-minor { padding: .45rem .6rem; margin-bottom: .5rem; }
.mbx-context-field {
	display: inline-block;
	margin-left: .2rem;
	padding: 0 .3rem;
	border-radius: 4px;
	background: #f0f3f6;
	color: #6b7280;
	font-size: var(--mbx-text-micro);
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: .03em;
	vertical-align: middle;
}
.mbx-context-link {
	display: inline-block;
	margin-top: .5rem;
	color: #2563eb;
	text-decoration: none;
	font-size: var(--mbx-text-sm);
}
.mbx-context-link:hover { text-decoration: underline; }
.mbx-context-note { color: #6b7280; font-style: italic; font-size: var(--mbx-text-sm); }
/* Saved-contact marker, and the one-click add offered when there is none. */
.mbx-context-badge {
	display: inline-block;
	margin-top: .35rem;
	padding: .1rem .4rem;
	border-radius: 999px;
	background: #e8f5ee;
	color: #1b7a4b;
	font-size: var(--mbx-text-micro);
	font-weight: 600;
}
.mbx-context-addrow {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: .4rem;
	margin-top: .35rem;
}
.mbx-context-add {
	border: 1px solid #cbd2d9;
	background: #fff;
	color: #2563eb;
	border-radius: 6px;
	padding: .1rem .45rem;
	font-size: var(--mbx-text-xs);
	font-weight: 600;
	cursor: pointer;
	white-space: nowrap;
}
.mbx-context-add:hover { background: #eef2ff; border-color: #2563eb; }
.mbx-context-add[disabled] { opacity: .6; cursor: default; }
.mbx-context-section {
	font-weight: 600;
	font-size: var(--mbx-text-xs);
	text-transform: uppercase;
	letter-spacing: .03em;
	color: #9aa5b1;
	margin: .6rem 0 .3rem;
}
.mbx-context-row {
	display: flex;
	justify-content: space-between;
	gap: .5rem;
	padding: .2rem 0;
	color: #3b4754;
	border-bottom: 1px solid #eef1f4;
}
.mbx-context-muted { color: #6b7280; }

/* The contacts list inside the panel scrolls on its own, so a long list does not
   push the panels below it off the column. */
.mbx-context .mbx-contacts-list {
	max-height: 55vh;
	overflow-y: auto;
}
.mbx-context .mbx-contact-row { padding: .3rem 0; }
/* The address under the name wraps rather than overflowing a narrow column. */
.mbx-context .mbx-contact-info { min-width: 0; }
.mbx-context .mbx-contact-addr { overflow-wrap: anywhere; }

/* Hidden below a width breakpoint — the two panes take priority on narrow screens. */
@media (max-width: 1100px) {
	.mbx-context { display: none !important; }
}

/* ---------------------------------------------------------------------------
   The mailbox gear — the page-chrome settings menu, which lives outside
   .mbx-reader. The kit's app-bar buttons show a label on a desktop and their
   icon only on a phone; a gear IS the label, so it shows at every width and
   carries no caret.
   --------------------------------------------------------------------------- */
.mbx-gear > summary .jy-btn-icon { display: inline-flex; }
.mbx-gear > summary .jy-btn-label { display: none; }
.mbx-gear > summary::after { content: none; }

/* "Your AI, your model" — the AI panel section for an end-to-end encrypted
   mailbox (mailbox_device_ai.js). */
.mbx-dai { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--jy-border, #e2e2e2); }
.mbx-dai[hidden] { display: none; }
.mbx-dai-note { margin: 0 0 8px; font-size: 0.85em; color: var(--jy-muted, #666); overflow-wrap: anywhere; }
.mbx-dai-link { background: none; border: none; padding: 0; font: inherit; color: var(--jy-color-primary, #2563eb); text-decoration: underline; cursor: pointer; }
.mbx-dai-fields[hidden] { display: none; }
.mbx-dai-field { display: block; margin: 0 0 8px; }
.mbx-dai-label { display: block; font-size: 0.8em; font-weight: 600; margin-bottom: 2px; }
.mbx-dai-input { width: 100%; box-sizing: border-box; }
.mbx-dai-actions { display: flex; gap: 8px; flex-wrap: wrap; margin: 4px 0 8px; }
.mbx-dai-status { margin: 0; font-size: 0.85em; overflow-wrap: anywhere; }
.mbx-dai-info { margin: 0 0 6px; font-size: 0.85em; overflow-wrap: anywhere; }
.mbx-dai-warn { margin: 0 0 6px; font-size: 0.85em; color: var(--jy-danger, #b42318); overflow-wrap: anywhere; }
.mbx-danger-banner-model { margin-top: 4px; font-size: 0.8em; opacity: 0.8; }
.mbx-dai-ondemand { margin: 8px 0; }
.mbx-dai-bar { display: flex; gap: 8px; flex-wrap: wrap; }
.mbx-dai-result { margin-top: 6px; font-size: 0.9em; overflow-wrap: anywhere; }
.mbx-dai-result:empty { display: none; }

/* plugins/mailbox/assets/css/mailbox.css */
/* inbound_email plugin — admin UI styles. Admin pages render in the admin
   theme (not .jy-ui), so these use distinctive prefixes (.iea-*, .iem-*,
   .fix-toggle) unscoped. Values lifted verbatim from former <style> blocks
   and inline styles. (The reader UI lives in mailbox_reader.css.) */

/* --- Setup page: collapsible fix toggles --- */
summary.fix-toggle { cursor: pointer; color: #6c757d; }
summary.fix-toggle:hover { color: #0d6efd; text-decoration: underline; }

/* --- Accounts page --- */
.iea-acct { max-width: 1000px; }
.iea-domain {
	border: 1px solid #d9dde2; border-radius: 8px; margin-bottom: 14px; background: #fff; overflow: hidden;
}
.iea-domain-head {
	display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
	padding: 12px 14px; background: #f7f9fb; border-bottom: 1px solid #eef1f4;
}
.iea-domain-name { font-size: 15px; font-weight: 600; color: #111827; }
.iea-domain-head .iea-spacer { flex: 1; }
.iea-mailboxes { list-style: none; margin: 0; padding: 0; }
.iea-mailbox {
	display: flex; align-items: flex-start; gap: 12px;
	padding: 11px 14px; border-bottom: 1px solid #f1f3f5;
}
.iea-mailbox:last-child { border-bottom: none; }
.iea-mb-main { min-width: 0; flex: 1; }
.iea-mb-addr { font-weight: 600; color: #1f2933; font-size: 14px; }
.iea-mb-route { color: #4b5563; font-size: 13px; margin-top: 3px; }
.iea-mb-imap { color: #374151; font-size: 12px; margin-top: 5px; }
.iea-mb-imap-attention { color: #92400e; }
.iea-mb-imap-attention form { display: inline; margin-left: 6px; }
.iea-mb-actions { flex: 0 0 auto; display: flex; gap: 5px; flex-wrap: wrap; align-items: center; }
.iea-empty-mb { padding: 11px 14px; color: #9097a1; font-size: 13px; }
.iea-tag {
	display: inline-block; font-size: 11px; font-weight: 600; border-radius: 9px;
	padding: 1px 8px; vertical-align: middle;
}
.iea-tag-store { background: #d7e7fb; color: #1e40af; }
.iea-tag-fwd { background: #e4e7eb; color: #374151; }
.iea-badge {
	display: inline-block; font-size: 11px; font-weight: 600; border-radius: 9px; padding: 1px 8px;
}
.iea-badge-on { background: #dcfce7; color: #166534; }
.iea-badge-off { background: #e4e7eb; color: #6b7280; }
.iea-badge-imapsrc { background: #dcfce7; color: #166534; }
.iea-badge-conn { background: #dcfce7; color: #166534; }
.iea-badge-noconn { background: #fde68a; color: #92400e; }
/* Protection-level badges (specs/mailbox_protection_ceremony.md): links to the
   domain editor, so anchor specificity pins the pill colors like -warn above. */
a.iea-badge-level, a.iea-badge-level:link, a.iea-badge-level:visited { text-decoration: none; }
.iea-badge-level-standard { background: #e4e7eb; color: #374151; }
.iea-badge-level-private { background: #d7e7fb; color: #1e40af; }
a.iea-badge-level-standard:link, a.iea-badge-level-standard:visited { color: #374151; }
a.iea-badge-level-private:link, a.iea-badge-level-private:visited { color: #1e40af; }
/* Real warning pill (an anchor) — amber fill + border, and an explicit color at
   anchor specificity so the theme's a:link blue doesn't bleed through. */
a.iea-badge-warn, a.iea-badge-warn:link, a.iea-badge-warn:visited {
	background: #fef3c7; color: #92400e; border: 1px solid #f59e0b; text-decoration: none;
}
a.iea-badge-warn:hover { background: #fde68a; color: #92400e; }
.iea-page-actions { margin: 4px 0 18px; }
.iea-trash { margin: 8px 0 24px; border: 1px solid #e4e7eb; border-radius: 8px; background: #fff; }
.iea-trash > summary { cursor: pointer; padding: 10px 14px; color: #6b7280; font-size: 13px; }
.iea-trash .iea-mailboxes { border-top: 1px solid #eef1f4; }
.iem-imap-status { color: #9097a1; }

/* --- Shared admin utilities (former inline styles) --- */
.iem-inline-form { display: inline; }
.iem-table-760 { max-width: 760px; }
.iem-table-900 { max-width: 900px; }
.iem-code-break { word-break: break-all; }
.iem-msg-iframe { width: 100%; min-height: 500px; border: 1px solid #ccc; background: #fff; }
.iem-msg-plain { white-space: pre-wrap; word-break: break-word; }

/* plugins/messenger/assets/css/messenger.css */
/**
 * Messages app layout.
 *
 * The bubbles, composer and reactions come from the shared chat kit
 * (.jy-chat-* in the platform stylesheet). What is here is this app's own
 * arrangement: a conversation rail beside an open thread on a wide screen, one
 * pane at a time on a narrow one.
 *
 * @version 1.1.0
 * @changelog 1.1.0 - level chip marks an active add-on (.msgr-level-chip--sealed-exits)
 */

/* A self-scrolling app component: flex-basis 0 plus an explicit min-height is
   how the app page lets it shrink to the fold instead of growing the page
   (the same opt-in the mailbox reader uses). */
.msgr {
    display: flex;
    align-items: stretch;
    flex: 1 1 0;
    min-height: 420px;
    background: var(--jy-color-bg);
    border: 1px solid var(--jy-color-border);
    border-radius: var(--jy-radius-lg);
    overflow: hidden;
}

/* ─── The conversation rail ─────────────────────────────── */

/* Several parts of the app are flex containers that spend time hidden (the
   thread header before a conversation is open, the composer, the reply bar).
   A `display` rule outranks the hidden attribute, so state it once here rather
   than remembering it at every rule. */
.msgr [hidden] { display: none !important; }

.msgr-rail {
    display: flex;
    flex-direction: column;
    flex: 0 0 320px;
    min-width: 0;
    border-right: 1px solid var(--jy-color-border);
    background: var(--jy-color-surface);
}

.msgr-rail-head {
    display: flex;
    align-items: center;
    gap: var(--jy-space-2);
    padding: var(--jy-space-3);
    border-bottom: 1px solid var(--jy-color-border);
}
.msgr-rail-head input[type="search"] {
    flex: 1 1 auto;
    min-width: 0;
    height: var(--jy-control-h-sm);
    padding: 0 var(--jy-space-3);
    border: 1px solid var(--jy-color-border-strong);
    border-radius: var(--jy-radius-full);
    font: inherit;
    font-size: var(--jy-text-sm);
    background: var(--jy-color-bg);
    color: var(--jy-color-text);
}

.msgr-list {
    flex: 1 1 auto;
    overflow-y: auto;
    list-style: none;
    margin: 0;
    padding: 0;
}
.msgr-list-empty {
    padding: var(--jy-space-6) var(--jy-space-4);
    text-align: center;
    color: var(--jy-color-text-muted);
    font-size: var(--jy-text-sm);
}

.msgr-item {
    display: flex;
    align-items: center;
    gap: var(--jy-space-3);
    width: 100%;
    padding: var(--jy-space-3);
    border: 0;
    border-bottom: 1px solid var(--jy-color-border);
    background: none;
    text-align: left;
    cursor: pointer;
    color: inherit;
    font: inherit;
}
.msgr-item:hover { background: var(--jy-color-surface-alt); }
.msgr-item--open { background: var(--jy-color-bg); box-shadow: inset 3px 0 0 var(--jy-color-primary); }

.msgr-item-avatar {
    position: relative;
    flex: 0 0 40px;
    width: 40px;
    height: 40px;
    border-radius: var(--jy-radius-full);
    object-fit: cover;
    background: var(--jy-color-surface-alt);
}
.msgr-item-initials {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 40px;
    width: 40px;
    height: 40px;
    border-radius: var(--jy-radius-full);
    background: var(--jy-color-surface-alt);
    color: var(--jy-color-text-muted);
    font-size: var(--jy-text-sm);
    font-weight: 600;
}

.msgr-item-body { flex: 1 1 auto; min-width: 0; }
.msgr-item-title {
    display: flex;
    align-items: baseline;
    gap: var(--jy-space-2);
}
.msgr-item-name {
    flex: 1 1 auto;
    min-width: 0;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.msgr-item-time {
    flex: 0 0 auto;
    font-size: var(--jy-text-xs);
    color: var(--jy-color-text-subtle);
}
.msgr-item-preview {
    display: flex;
    align-items: center;
    gap: var(--jy-space-2);
    font-size: var(--jy-text-sm);
    color: var(--jy-color-text-muted);
}
.msgr-item-excerpt {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.msgr-item--unread .msgr-item-excerpt { color: var(--jy-color-text); font-weight: 500; }

.msgr-badge {
    flex: 0 0 auto;
    min-width: 20px;
    padding: 0 6px;
    border-radius: var(--jy-radius-full);
    background: var(--jy-color-primary);
    color: var(--jy-color-primary-text);
    font-size: var(--jy-text-xs);
    line-height: 20px;
    text-align: center;
}
.msgr-mute { color: var(--jy-color-text-subtle); font-size: var(--jy-text-xs); }

/* ─── The open thread ───────────────────────────────────── */

.msgr-thread {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-width: 0;
    min-height: 0;
}

.msgr-thread-head {
    display: flex;
    align-items: center;
    gap: var(--jy-space-3);
    padding: var(--jy-space-3) var(--jy-space-4);
    border-bottom: 1px solid var(--jy-color-border);
    background: var(--jy-color-bg);
}
.msgr .msgr-thread-head h2 {
    margin: 0;
    font-size: var(--jy-text-lg);
    font-weight: 600;
    line-height: var(--jy-leading-tight);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.msgr-thread-headings { flex: 1 1 auto; min-width: 0; }
.msgr-thread-sub {
    font-size: var(--jy-text-xs);
    color: var(--jy-color-text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.msgr-level-chip {
    flex: 0 0 auto;
    padding: 1px var(--jy-space-2);
    border-radius: var(--jy-radius-full);
    border: 1px solid var(--jy-color-border);
    font-size: var(--jy-text-xs);
    color: var(--jy-color-text-muted);
}
.msgr-level-chip--private {
    border-color: var(--jy-color-success);
    color: var(--jy-color-success);
    background: var(--jy-color-success-bg);
}
/* An add-on is on: the chip text names it, and the heavier border marks it. */
.msgr-level-chip--sealed-exits {
    border-width: 2px;
    font-weight: 600;
}

.msgr-log { flex: 1 1 auto; min-height: 0; }

.msgr-empty {
    display: flex;
    flex: 1 1 auto;
    align-items: center;
    justify-content: center;
    padding: var(--jy-space-6);
    text-align: center;
    color: var(--jy-color-text-muted);
}

.msgr-earlier { align-self: center; margin-bottom: var(--jy-space-3); }

.msgr-receipt {
    padding: 0 var(--jy-space-4) var(--jy-space-1);
    text-align: right;
    font-size: var(--jy-text-xs);
    color: var(--jy-color-text-subtle);
}

/* Per-bubble actions, revealed on hover or keyboard focus. */
.msgr-bubble-actions {
    display: flex;
    gap: var(--jy-space-1);
    opacity: 0;
    transition: opacity 0.12s ease;
}
.jy-chat-row:hover .msgr-bubble-actions,
.jy-chat-row:focus-within .msgr-bubble-actions { opacity: 1; }
@media (hover: none) {
    .msgr-bubble-actions { opacity: 1; }
}
.msgr-bubble-action {
    display: inline-flex;
    align-items: center;
    border: 0;
    background: none;
    padding: 2px;
    cursor: pointer;
    color: var(--jy-color-text-subtle);
    line-height: 1;
}
.msgr-bubble-action:hover { color: var(--jy-color-text); }

/* What the composer is replying to. */
.msgr-reply-bar {
    display: flex;
    align-items: center;
    gap: var(--jy-space-2);
    padding: var(--jy-space-2) var(--jy-space-4);
    border-top: 1px solid var(--jy-color-border);
    background: var(--jy-color-surface);
    font-size: var(--jy-text-sm);
}
.msgr-reply-bar-body { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ─── Dialogs ───────────────────────────────────────────── */

.msgr-dialog {
    border: 1px solid var(--jy-color-border);
    border-radius: var(--jy-radius-lg);
    box-shadow: var(--jy-shadow-lg);
    padding: 0;
    width: min(460px, 92vw);
    color: var(--jy-color-text);
    background: var(--jy-color-bg);
}
.msgr-dialog::backdrop { background: rgba(20, 25, 35, 0.35); }
.msgr-dialog-head {
    display: flex;
    align-items: center;
    gap: var(--jy-space-2);
    padding: var(--jy-space-4);
    border-bottom: 1px solid var(--jy-color-border);
}
.msgr-dialog-head h3 { margin: 0; flex: 1 1 auto; font-size: var(--jy-text-lg); }
.msgr-dialog-body { padding: var(--jy-space-4); max-height: 60vh; overflow-y: auto; }
.msgr-dialog-foot {
    display: flex;
    justify-content: flex-end;
    gap: var(--jy-space-2);
    padding: var(--jy-space-3) var(--jy-space-4);
    border-top: 1px solid var(--jy-color-border);
}

.msgr-people { list-style: none; margin: var(--jy-space-3) 0 0; padding: 0; }
.msgr-person {
    display: flex;
    align-items: center;
    gap: var(--jy-space-3);
    width: 100%;
    padding: var(--jy-space-2);
    border: 0;
    border-radius: var(--jy-radius-md);
    background: none;
    text-align: left;
    cursor: pointer;
    color: inherit;
    font: inherit;
}
.msgr-person:hover { background: var(--jy-color-surface-alt); }
.msgr-person img { width: 32px; height: 32px; border-radius: var(--jy-radius-full); object-fit: cover; }
.msgr-person-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msgr-person-address { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--jy-color-text-muted); font-size: var(--jy-text-sm); }

.msgr-chips { display: flex; flex-wrap: wrap; gap: var(--jy-space-2); margin-bottom: var(--jy-space-2); }
.msgr-chip {
    display: inline-flex;
    align-items: center;
    gap: var(--jy-space-1);
    padding: 2px var(--jy-space-2);
    border-radius: var(--jy-radius-full);
    background: var(--jy-color-surface-alt);
    font-size: var(--jy-text-sm);
}
.msgr-chip button { border: 0; background: none; cursor: pointer; color: var(--jy-color-text-muted); }

.msgr-emoji-grid {
    display: grid;
    grid-template-columns: repeat(8, 1fr);
    gap: var(--jy-space-1);
}
.msgr-emoji-grid button {
    border: 0;
    background: none;
    font-size: 1.4rem;
    line-height: 1.6;
    cursor: pointer;
    border-radius: var(--jy-radius-sm);
}
.msgr-emoji-grid button:hover { background: var(--jy-color-surface-alt); }

.msgr-field { display: block; margin-bottom: var(--jy-space-3); }
.msgr-field > span { display: block; font-size: var(--jy-text-sm); font-weight: 600; margin-bottom: var(--jy-space-1); }
.msgr-field input[type="text"],
.msgr-field input[type="search"] {
    width: 100%;
    height: var(--jy-control-h-md);
    padding: 0 var(--jy-space-3);
    border: 1px solid var(--jy-color-border-strong);
    border-radius: var(--jy-radius-md);
    font: inherit;
    background: var(--jy-color-bg);
    color: var(--jy-color-text);
}

.msgr-members { list-style: none; margin: 0; padding: 0; }
.msgr-member {
    display: flex;
    align-items: center;
    gap: var(--jy-space-3);
    padding: var(--jy-space-2) 0;
    border-bottom: 1px solid var(--jy-color-border);
}
.msgr-member img { width: 32px; height: 32px; border-radius: var(--jy-radius-full); object-fit: cover; }
.msgr-member-name { flex: 1 1 auto; min-width: 0; }
.msgr-member-role { font-size: var(--jy-text-xs); color: var(--jy-color-text-subtle); }

.msgr-error {
    padding: var(--jy-space-2) var(--jy-space-4);
    background: var(--jy-color-danger-bg);
    color: var(--jy-color-danger);
    font-size: var(--jy-text-sm);
}
.msgr-error:empty { display: none; }

/* ─── One pane at a time on a narrow screen ─────────────── */

.msgr-back { display: none; }

@media (max-width: 760px) {
    .msgr-rail { flex: 1 1 auto; border-right: 0; }
    .msgr-thread { display: none; }
    .msgr[data-pane="thread"] .msgr-rail { display: none; }
    .msgr[data-pane="thread"] .msgr-thread { display: flex; }
    .msgr-back { display: inline-flex; }
    .jy-chat-stack { max-width: 88%; }
}

/* Protection */

.msgr-level-picker { margin-top: var(--jy-space-4); }
.msgr-level-picker[hidden] { display: none; }
.msgr-protect-note {
    margin: 0 0 var(--jy-space-3);
    font-size: var(--jy-text-sm);
    color: var(--jy-color-text-muted);
}
.jy-chat-bubble--locked {
    display: flex;
    align-items: center;
    gap: var(--jy-space-2);
    background: transparent;
    border: 1px dashed var(--jy-color-border-strong);
    color: var(--jy-color-text-muted);
    font-style: italic;
}
.jy-chat-row--mine .jy-chat-bubble--locked {
    background: transparent;
    color: var(--jy-color-text-muted);
}

/* Cross-site chat — inline resolution in the unified picker */

.msgr-pick-status {
    margin: var(--jy-space-2) 0 0;
    font-size: var(--jy-text-sm);
    color: var(--jy-color-text-muted);
}
.msgr-pick-status a { margin-left: 2px; }
.msgr-site-notice {
    margin: var(--jy-space-2) 0 0;
    font-size: var(--jy-text-xs);
    color: var(--jy-color-text-muted);
}
.msgr-remote-level-note {
    margin: var(--jy-space-3) 0 0;
    font-size: var(--jy-text-sm);
    color: var(--jy-color-text-muted);
}
.msgr-person--blocked { opacity: 0.5; cursor: not-allowed; }
.msgr-person-blocked-line {
    display: block;
    padding: 0 var(--jy-space-2) var(--jy-space-1);
    font-size: var(--jy-text-xs);
    color: var(--jy-color-text-muted);
}
.msgr-chip-address { color: var(--jy-color-text-muted); font-size: var(--jy-text-xs); }

/* Delivery ticks — only ever on a message that has to cross to another site. */
.msgr-tick { display: inline-flex; align-items: center; }
.msgr-tick--delivered { color: var(--jy-color-success); }
.msgr-tick--failed { color: var(--jy-color-danger); }

/* plugins/vault/assets/css/vault.css */
/* Password manager (client-custody Sealed Vault consumer).
   Everything is scoped under .jy-vault so these rules never leak to the rest of
   the site (the sheet loads globally while the plugin is active). */

.jy-vault { --vlt-bg:#fff; --vlt-fg:#1c2430; --vlt-muted:#66748a; --vlt-line:#e2e7ef;
	--vlt-accent:#2f6df6; --vlt-accent-fg:#fff; --vlt-danger:#c23b3b; --vlt-sel:#eef3ff;
	color:var(--vlt-fg); }

@media (prefers-color-scheme: dark) {
	.jy-vault { --vlt-bg:#161b22; --vlt-fg:#e6edf3; --vlt-muted:#8b98a9; --vlt-line:#2a323d;
		--vlt-accent:#4f8bff; --vlt-sel:#1d2735; }
}

/* The manager toggles sections/buttons via the hidden attribute, but any rule
   here that sets display (flex on the manager, inline-flex on .jy-btn) would
   out-rank the UA's [hidden]{display:none}. Re-assert it. */
.jy-vault [hidden], .jy-vault[hidden] { display:none !important; }

/* ---- shared controls ---- */
.jy-vault .jy-btn { display:inline-flex; align-items:center; justify-content:center; gap:.4em;
	font:inherit; font-weight:600; padding:.55em 1.1em; border-radius:8px; border:1px solid var(--vlt-line);
	background:var(--vlt-bg); color:var(--vlt-fg); cursor:pointer; line-height:1.2; }
.jy-vault .jy-btn:hover { border-color:var(--vlt-accent); }
.jy-vault .jy-btn:disabled { opacity:.5; cursor:not-allowed; }
.jy-vault .jy-btn-primary { background:var(--vlt-accent); color:var(--vlt-accent-fg); border-color:var(--vlt-accent); }
.jy-vault .jy-btn-danger { color:var(--vlt-danger); border-color:transparent; background:transparent; }
.jy-vault .jy-btn-link { border:none; background:none; color:var(--vlt-accent); padding:.4em .5em; font-weight:600; }
.jy-vault .jy-btn-block { width:100%; }
.jy-vault .jy-input { font:inherit; padding:.55em .75em; border-radius:8px; border:1px solid var(--vlt-line);
	background:var(--vlt-bg); color:var(--vlt-fg); width:100%; }
.jy-vault .jy-input:focus { outline:2px solid var(--vlt-accent); outline-offset:1px; }
.jy-vault .jy-vault-actions { display:flex; flex-wrap:wrap; gap:.6em; align-items:center; margin-top:1em; }
.jy-vault .jy-vault-error { color:var(--vlt-danger); margin-top:.8em; }

/* ---- centered states ---- */
.jy-vault-centered { text-align:center; padding:4em 1em; color:var(--vlt-muted); }
.jy-vault-spinner { width:34px; height:34px; border:3px solid var(--vlt-line); border-top-color:var(--vlt-accent);
	border-radius:50%; margin:0 auto 1em; animation:jy-vault-spin .8s linear infinite; }
@keyframes jy-vault-spin { to { transform:rotate(360deg); } }

/* ---- manager two-pane ---- */
.jy-vault-manager { display:flex; flex-wrap:wrap; gap:0; border:1px solid var(--vlt-line); border-radius:14px; overflow:hidden;
	min-height:520px; background:var(--vlt-bg); }
.jy-vault-decrypt-warning { flex-basis:100%; margin:0; padding:.7em 1em; font-size:.92em;
	color:var(--vlt-danger); border-bottom:1px solid var(--vlt-danger); background:color-mix(in srgb, var(--vlt-danger) 8%, var(--vlt-bg)); }
.jy-vault-list-pane { width:320px; border-right:1px solid var(--vlt-line); display:flex; flex-direction:column; }
.jy-vault-list-toolbar { display:flex; gap:.5em; padding:.8em; border-bottom:1px solid var(--vlt-line); }
.jy-vault-list-toolbar .jy-input { flex:1; }
.jy-vault-list-toolbar .jy-btn { flex:0 0 auto; width:2.6em; font-size:1.2em; padding:.3em; }
.jy-vault-list { list-style:none; margin:0; padding:0; overflow-y:auto; flex:1; }
.jy-vault-list-item { padding:.7em .9em; border-bottom:1px solid var(--vlt-line); cursor:pointer; }
.jy-vault-list-item:hover { background:var(--vlt-sel); }
.jy-vault-list-item.is-selected { background:var(--vlt-sel); box-shadow:inset 3px 0 0 var(--vlt-accent); }
.jy-vault-item-title { font-weight:600; }
.jy-vault-item-sub { font-size:.85em; color:var(--vlt-muted); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.jy-vault-list-empty { padding:1.5em; text-align:center; color:var(--vlt-muted); }
.jy-vault-list-footer { padding:.6em .8em; border-top:1px solid var(--vlt-line); display:flex; flex-direction:column; gap:.5em; }
.jy-vault-autolock { display:flex; align-items:center; gap:.5em; font-size:.85em; color:var(--vlt-muted); }
.jy-vault-autolock .jy-input { width:auto; padding:.3em .5em; }
.jy-vault-tools { display:flex; gap:.3em; flex-wrap:wrap; justify-content:space-between; }
.jy-vault-detail-pane { flex:1; padding:1.5em; overflow-y:auto; }
.jy-vault-empty-detail { color:var(--vlt-muted); text-align:center; padding:4em 1em; }
.jy-vault-detail-head { display:flex; justify-content:space-between; align-items:center; margin-bottom:1em; gap:1em; }
.jy-vault-detail-head h2 { margin:0; word-break:break-word; }
.jy-vault-field { margin-bottom:1.1em; }
.jy-vault-field-label { font-size:.8em; text-transform:uppercase; letter-spacing:.04em; color:var(--vlt-muted); margin-bottom:.25em; }
.jy-vault-field-value { display:flex; align-items:center; gap:.5em; flex-wrap:wrap; }
.jy-vault-field-text { font-family:ui-monospace,SFMono-Regular,Menlo,monospace; word-break:break-all; }
.jy-vault-field-text.is-masked { letter-spacing:.15em; }
.jy-vault-notes { white-space:pre-wrap; word-break:break-word; background:var(--vlt-sel); padding:.8em; border-radius:8px; }
.jy-vault-icon-btn { font-size:.78em; font-weight:600; color:var(--vlt-accent); background:none; border:1px solid var(--vlt-line);
	border-radius:6px; padding:.15em .5em; cursor:pointer; }
.jy-vault-icon-btn:hover { border-color:var(--vlt-accent); }
.jy-vault-totp-code { font-family:ui-monospace,monospace; font-size:1.2em; letter-spacing:.08em; }
.jy-vault-totp-ring { font-size:.8em; color:var(--vlt-muted); }
.jy-vault-generate { margin-top:.3em; }

/* ---- toast ---- */
.jy-vault-toast { position:fixed; bottom:24px; left:50%; transform:translateX(-50%) translateY(10px);
	background:#1c2430; color:#fff; padding:.7em 1.2em; border-radius:10px; opacity:0; transition:opacity .2s, transform .2s;
	z-index:9999; }
.jy-vault-toast.is-visible { opacity:1; transform:translateX(-50%) translateY(0); }

@media (max-width:720px) {
	.jy-vault-manager { flex-direction:column; }
	.jy-vault-list-pane { width:auto; border-right:none; border-bottom:1px solid var(--vlt-line); max-height:40vh; }
}

