/* Vikunja-inspired theme — light gray/blue canvas, dark gray/blue in dark mode.
   All colors route through these variables; the dark block below only swaps values. */

:root {
	color-scheme: light dark;

	--bg:              #e2e7f0;
	--surface:         #ffffff;
	--surface-2:       #eef1f6;
	--surface-2-hover: #e2e7ee;
	--row-hover:       #f4f7fb;
	--column-bg:       #d8dee9;
	--border:          #c8d0dd;
	--input-border:    #b3bdcd;
	--text:            #2f333b;
	--text-muted:      #78818f;
	--primary:         #1973ff;
	--primary-dim:     #1260d6;
	--primary-soft:    #dce9ff;
	--primary-soft-hover: #c9ddff;
	--danger:          #eb5757;
	--danger-bg:       #fdeeee;
	--danger-text:     #b03434;
	--success:         #27ae60;
	--success-bg:      #e9f9ef;
	--success-text:    #1e7e46;
	--radius:          8px;
	--shadow:          0 1px 3px rgba(20, 30, 60, .10), 0 1px 2px rgba(20, 30, 60, .06);
}

@media (prefers-color-scheme: dark) {
	:root {
		--bg:              #1e232d;
		--surface:         #2a313d;
		--surface-2:       #353d4c;
		--surface-2-hover: #3f4858;
		--row-hover:       #323a48;
		--column-bg:       #171b23;
		--border:          #414b5e;
		--input-border:    #505c72;
		--text:            #d8dde5;
		--text-muted:      #949dae;
		--primary:         #3f88ff;
		--primary-dim:     #5d9aff;
		--primary-soft:    rgba(63, 136, 255, .18);
		--primary-soft-hover: rgba(63, 136, 255, .30);
		--danger-bg:       rgba(235, 87, 87, .14);
		--danger-text:     #f0908f;
		--success:         #2fbe6d;
		--success-bg:      rgba(47, 190, 109, .14);
		--success-text:    #5ecd92;
		--shadow:          0 1px 3px rgba(0, 0, 0, .45), 0 1px 2px rgba(0, 0, 0, .30);
	}
}

* { box-sizing: border-box; }

body {
	margin: 0;
	background: var(--bg);
	color: var(--text);
	font: 15px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}

/* ---------- Top bar ---------- */

.topbar {
	display: flex;
	align-items: center;
	gap: 24px;
	height: 56px;
	padding: 0 24px;
	background: var(--surface);
	box-shadow: var(--shadow);
	position: sticky;
	top: 0;
	z-index: 10;
}

.brand {
	display: flex;
	align-items: center;
	gap: 10px;
	font-weight: 700;
	font-size: 17px;
	color: var(--text);
	text-decoration: none;
}

.topbar nav {
	display: flex;
	gap: 4px;
}

.topbar nav a {
	padding: 6px 14px;
	border-radius: 6px;
	color: var(--text-muted);
	text-decoration: none;
	font-weight: 600;
}

.topbar nav a:hover  { background: var(--surface-2); color: var(--text); }
.topbar nav a.active { background: var(--primary-soft); color: var(--primary); }

.user-chip {
	padding: 4px 12px;
	border-radius: 20px;
	background: var(--primary-soft);
	color: var(--primary);
	font-weight: 700;
	font-size: 13px;
	white-space: nowrap;
	text-decoration: none;
}

.user-chip:hover { background: var(--primary-soft-hover); }

.user-chip .chip-icon { display: none; }

.spacer { flex: 1; }

/* ---------- Buttons, inputs ---------- */

.btn {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 7px 16px;
	border: 1px solid transparent;
	border-radius: 6px;
	background: var(--surface-2);
	color: var(--text);
	font-weight: 600;
	font-size: 14px;
	text-decoration: none;
	cursor: pointer;
}

.btn:hover        { background: var(--surface-2-hover); }
.btn.primary      { background: var(--primary); color: #fff; }
.btn.primary:hover{ background: var(--primary-dim); }
.btn.subtle       { background: transparent; border-color: var(--border); }
.btn.subtle:hover { background: var(--surface-2); }
.btn.danger       { background: transparent; border-color: var(--danger); color: var(--danger); }
.btn.danger:hover { background: var(--danger-bg); }

input[type="text"], input[type="search"], input[type="email"], input[type="password"], select, textarea {
	padding: 8px 10px;
	border: 1px solid var(--input-border);
	border-radius: 6px;
	background: var(--surface);
	color: var(--text);
	font: inherit;
}

input:focus, select:focus, textarea:focus {
	outline: none;
	border-color: var(--primary);
	box-shadow: 0 0 0 3px rgba(25, 115, 255, .15);
}

textarea { width: 100%; resize: vertical; }

/* Auto-grows with typed content (see issue.js) instead of a fixed rows count —
   resize:none since manual dragging would just fight the next keystroke's
   auto-grow; overflow:hidden since scrollHeight-based growth means a
   scrollbar should never actually be needed. */
#details { min-height: 180px; resize: none; overflow: hidden; }

/* ---------- Layout ---------- */

main { padding: 24px; max-width: 1400px; margin: 0 auto; }

/* List and Board pages: full available width (content still centers itself). */
main.wide { max-width: none; }

.page-head {
	display: flex;
	align-items: center;
	gap: 16px;
	margin-bottom: 16px;
}

.page-head h1 { margin: 0; font-size: 24px; }

.card {
	background: var(--surface);
	border: 1px solid var(--border);
	border-radius: var(--radius);
	box-shadow: var(--shadow);
}

.muted  { color: var(--text-muted); font-size: 13px; }
.hidden { display: none !important; }

.error-banner {
	margin-bottom: 16px;
	padding: 10px 16px;
	border-radius: 6px;
	background: var(--danger-bg);
	border: 1px solid var(--danger);
	color: var(--danger-text);
}

.success-banner {
	margin-bottom: 16px;
	padding: 10px 16px;
	border-radius: 6px;
	background: var(--success-bg);
	border: 1px solid var(--success);
	color: var(--success-text);
}

.profile-card { max-width: 480px; }
.profile-card input { width: 100%; }
.profile-actions {
	display: flex;
	align-items: center;
	gap: 10px;
	margin-top: 20px;
}

/* ---------- List view ---------- */

/* View tabs (#viewTabs) reuse the .segmented control below — same look as
   Board's By Status/By Priority toggle. The .view-tab class carries no styling
   of its own; it's just what list.js uses to find/wire up the buttons. */

/* A plain text-link-styled <button>, for actions that shouldn't look like a
   full .btn (e.g. the Filters expand/collapse toggle). */
.link-btn {
	appearance: none;
	-webkit-appearance: none;
	border: none;
	background: none;
	margin: 0;
	padding: 0;
	color: var(--primary);
	font: inherit;
	font-weight: 700;
	vertical-align: baseline;
	cursor: pointer;
}

.link-btn:hover { text-decoration: underline; }

/* ---------- Filter panel (collapsible; presets management) ---------- */

.filter-panel { margin-bottom: 16px; }

.filter-panel-bar {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 12px 16px;
}

.filter-panel-body {
	padding: 0 16px 14px;
	border-top: 1px solid var(--border);
}

/* Always-visible multi-select listboxes, side by side — one native <select
   multiple> per facet, matching how e.g. Mouser's part filters work, rather
   than a click-to-open popover per facet. */
.filter-columns {
	display: flex;
	flex-wrap: wrap;
	gap: 16px;
	padding-top: 14px;
}

.filter-column {
	display: flex;
	flex-direction: column;
	gap: 6px;
	flex: 1;
	min-width: 180px;
}

.filter-column .field-label { margin: 0; }

.filter-column select[multiple] {
	flex: 1;
	padding: 4px;
}

.filter-row-extra {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
	margin-top: 14px;
}

.preset-row { margin-top: 12px; }

/* Two deliberate rows, not a flex-wrap accident: the name field/Shared checkbox
   always sit above the solid divider, the preset actions always below it. The
   negative margin bleeds the divider out past .filter-panel-body's own padding
   so it spans the full card width, same as the table's row separators. */
.preset-row-fields {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
	margin: 0 -16px;
	padding: 0 16px 12px;
	border-bottom: 1px solid var(--border);
}

.preset-row-fields .grow { flex: 1; min-width: 140px; }

.preset-row-actions {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin-top: 12px;
}

/* Tighter than the standard .btn — these live in an already-dense filter panel
   row alongside a growing name field, not out on their own like page-level actions. */
.preset-row .btn {
	padding: 5px 12px;
}

/* Search is its own card, deliberately outside .filter-panel — see the
   comment on the markup in Index.cshtml for why. */
.search-bar {
	display: flex;
	padding: 12px 16px;
	margin-bottom: 16px;
}

.search-bar .grow { flex: 1; }

.table-wrap { overflow-x: auto; }

table {
	width: 100%;
	border-collapse: collapse;
	font-size: 14px;
}

th, td {
	padding: 10px 14px;
	text-align: left;
	border-bottom: 1px solid var(--border);
	white-space: nowrap;
}

/* The title-block cell acts like a mini-card: title+number on its own line,
   author/created beneath it (muted), keywords beneath that — stacked, not
   competing with Priority/Status/Modified for horizontal room. */
td.title-cell { white-space: normal; width: 100%; }

/* Shared issue "card body" (see issueCardHtml() in site.js) — used identically
   by List's title-block cell, List's mobile card, and Board's kanban card, so
   all three render the same structure instead of drifting apart. */
.issue-title-line { font-weight: 600; font-size: 14px; margin-bottom: 4px; }

.issue-meta-line {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 6px;
	font-size: 12px;
	color: var(--text-muted);
}

/* Keywords get their OWN row, visually separated from the single-value
   Priority/Status badge above — mixing them in one row is what made a colored
   keyword tag read as "maybe that's the status?" */
.issue-keywords-line { margin-top: 5px; }

/* Priority/Status/Modified stay content-width so Title gets everything else. */
#issueTable th:not(:nth-child(2)),
#issueTable td:not(.title-cell) { white-space: nowrap; width: 1%; }

th {
	font-size: 12px;
	text-transform: uppercase;
	letter-spacing: .04em;
	color: var(--text-muted);
	user-select: none;
}

th[data-sort] { cursor: pointer; }
th[data-sort]:hover { color: var(--text); }
th .sort-arrow { margin-left: 4px; }

tbody tr { cursor: pointer; }
tbody tr:hover { background: var(--row-hover); }
tbody tr:last-child td { border-bottom: none; }

/* Admin tables (Keywords/Statuses/Priorities/Users): rows aren't clickable-to-navigate
   like List's, and the trailing "add new" row is its own tfoot, visually set
   apart with a top divider instead of blending into the editable rows above. */
#keywordTable tbody tr, #statusTable tbody tr, #priorityTable tbody tr, #userTable tbody tr { cursor: default; }
#keywordTable tbody tr:hover, #statusTable tbody tr:hover, #priorityTable tbody tr:hover, #userTable tbody tr:hover { background: none; }
#keywordTable tfoot tr, #statusTable tfoot tr, #priorityTable tfoot tr, #userTable tfoot tr { border-top: 2px solid var(--border); }

.user-pw-cell { white-space: nowrap; }
.user-pw-cell .user-new-password { width: 140px; }

.empty { padding: 40px; text-align: center; color: var(--text-muted); }

/* Phone rendering of the list: stacked cards (hidden on desktop; CSS swaps below). */
.issue-cards { display: none; }

.issue-card { padding: 12px 14px; cursor: pointer; }

/* ---------- Badges & chips ---------- */

.status-not-set {
	color: var(--text-muted);
	font-style: italic;
	font-size: 13px;
}

.triage-status { font-size: 13px; padding: 5px 8px; }

.badge {
	display: inline-block;
	padding: 2px 10px;
	border-radius: 4px;
	font-size: 12px;
	font-weight: 700;
	color: #fff;
}

.chip {
	display: inline-block;
	padding: 2px 10px;
	margin: 1px 2px 1px 0;
	border-radius: 20px;
	background: var(--surface-2);
	color: var(--text-muted);
	font-size: 12px;
	font-weight: 600;
}

.chip .chip-x {
	margin-left: 6px;
	cursor: pointer;
	color: var(--text-muted);
}

.chip .chip-x:hover { color: var(--danger); }

/* Read-only keyword tags (list/board/detail chip rows) — rounded rect, not a
   pill, so horizontal padding stays tight. Neutral text by default; only gets a
   background when an admin explicitly colored that keyword (see keywordChip()
   in site.js) — keywords are zero-or-many descriptive metadata, not an alert,
   so most shouldn't compete visually with Priority. */
.tag {
	display: inline-block;
	padding: 0 3px;
	margin: 1px 4px 1px 0;
	border-radius: 4px;
	border: 1px solid transparent;
	font-size: 11px;
	font-weight: normal;
	line-height: 1.3;
	color: var(--text-muted);
	background: transparent;
}

/* Priority/Status badges look similar enough (both single colored labels)
   that the field name has to be spelled out, or the reader can't tell which
   one they're looking at without extra context (e.g. which board mode). */
.badge-label {
	font-size: 10px;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: .03em;
	color: var(--text-muted);
	margin-right: 4px;
}

/* Status: plain colored text, no background — structural (drives Board
   columns) but doesn't need to shout in a list; Priority is the one field
   that gets a loud badge. */
.status-text { font-weight: 600; font-size: 13px; }

/* ---------- Board controls ---------- */

.board-controls {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 12px 20px;
	padding: 10px 14px;
	margin-bottom: 16px;
}

.segmented {
	display: flex;
	flex-wrap: wrap;
	border: 1px solid var(--border);
	border-radius: 6px;
	overflow: hidden;
}

.segmented button {
	border: none;
	border-right: 1px solid var(--border);
	background: transparent;
	padding: 4px 10px;
	font: inherit;
	font-weight: 600;
	color: var(--text-muted);
	cursor: pointer;
}

.segmented button:last-child { border-right: none; }

.segmented button.active { background: var(--primary); color: #fff; }
.segmented button:not(.active):hover { background: var(--surface-2); color: var(--text); }

/* ---------- Admin ---------- */

.admin-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
	gap: 16px;
}

.admin-card {
	padding: 24px;
	text-decoration: none;
	color: var(--text);
	transition: box-shadow .1s, transform .1s;
}

.admin-card:hover {
	box-shadow: 0 4px 14px rgba(20, 30, 60, .14);
	transform: translateY(-1px);
}

.admin-card-icon { font-size: 28px; margin-bottom: 10px; }
.admin-card-title { font-size: 17px; font-weight: 700; margin-bottom: 4px; }

.admin-edit-link {
	font-size: 12px;
	font-weight: 700;
	/* Ratio, not a fixed px value — when this class lands on a <button> (see
	   .link-btn), the button's own `font: inherit` shorthand otherwise pulls
	   line-height as an already-computed PIXEL value from its parent (a much
	   bigger font context) instead of letting the ratio recompute against
	   this element's own 12px, which is what visibly threw it out of
	   alignment with an adjacent sibling label. */
	line-height: 1.5;
	color: var(--primary);
	text-decoration: none;
}

.admin-edit-link:hover { text-decoration: underline; }

.admin-toolbar {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 12px;
	padding: 12px 16px;
	margin-bottom: 16px;
}

.admin-toolbar input[type="text"] { flex: 1; min-width: 200px; }

.admin-defaults {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 10px;
	padding: 12px 16px;
	margin-bottom: 16px;
}

.admin-add-row {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 10px;
	padding: 14px 16px;
	margin-top: 16px;
}

.admin-add-row input[type="text"],
.admin-add-row input[type="email"],
.admin-add-row input[type="password"] { flex: 1; min-width: 140px; }

#keywordTable input[type="text"],
#priorityTable input[type="text"],
#statusTable input[type="text"] { width: 100%; }

/* Native <input type="color"> sizing/appearance is unreliable across browsers
   even with appearance:none (some ignore explicit width/height on the input
   itself and shrink to a sliver) — a fixed-size wrapper is what actually pins
   the visible box, with the input filling it and just its OWN chrome (the
   color swatch/border it draws internally) suppressed via the pseudo-elements. */
.color-swatch-wrap {
	display: inline-block;
	width: 28px;
	height: 28px;
	border: 1px solid var(--border);
	border-radius: 4px;
	overflow: hidden;
	flex: 0 0 auto;
}

.color-swatch {
	display: block;
	width: 100%;
	height: 100%;
	padding: 0;
	border: none;
	cursor: pointer;
	appearance: none;
	-webkit-appearance: none;
}

.color-swatch::-webkit-color-swatch-wrapper { padding: 0; }
.color-swatch::-webkit-color-swatch { border: none; }
.color-swatch::-moz-color-swatch { border: none; }

/* Each color is a swatch + a typed hex value side by side, under one shared
   <th colspan="2">, so the two columns should read as one paired control —
   tight gap between them, normal gap to whatever comes next. */
.swatch-cell, .hex-cell { width: 1%; white-space: nowrap; }
.swatch-cell { padding-right: 4px; }
.hex-cell    { padding-left: 4px; }

/* Beats the #keywordTable/#statusTable/#priorityTable input[type=text]{width:100%}
   rule above on specificity (ID + type there vs. a plain class here would lose). */
#keywordTable input.hex-input,
#statusTable input.hex-input,
#priorityTable input.hex-input {
	width: 88px;
	padding: 6px 8px;
	font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
	text-transform: lowercase;
}

/* Fixed-width, non-wrapping columns keep every row's Preview/Issues/delete
   cells aligned regardless of how wide a given keyword's colors/name are. */
#keywordTable .kw-preview { width: 160px; white-space: nowrap; }
#keywordTable td.muted { width: 1%; white-space: nowrap; }
#keywordTable th:last-child,
#keywordTable td:last-child { width: 1%; white-space: nowrap; }

#userTable td { vertical-align: middle; }

.check {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	font-size: 14px;
	font-weight: 600;
	color: var(--text);
	cursor: pointer;
	white-space: nowrap;
}

.check input[type="checkbox"] { accent-color: var(--primary); }

/* ---------- Kanban board ---------- */

.board {
	display: flex;
	gap: 16px;
	align-items: flex-start;
	overflow-x: auto;
	padding-bottom: 24px;
}

/* Auto margins center the column set when it fits the viewport, while staying
   compatible with overflow-x scrolling when it doesn't (unlike justify-content). */
.column:first-child { margin-left: auto; }
.column:last-child  { margin-right: auto; }

.column {
	flex: 0 0 300px;
	background: var(--column-bg);
	border: 1px solid var(--border);
	border-radius: var(--radius);
	padding: 10px;
	max-height: calc(100vh - 200px);
	display: flex;
	flex-direction: column;
}

.column-head {
	display: flex;
	align-items: center;
	gap: 8px;
	padding: 4px 6px 10px;
	font-weight: 700;
}

.column-dot {
	width: 10px;
	height: 10px;
	border-radius: 50%;
}

.column-count {
	color: var(--text-muted);
	font-weight: 600;
	font-size: 13px;
}

.column-cards {
	display: flex;
	flex-direction: column;
	gap: 8px;
	overflow-y: auto;
	min-height: 40px;
	flex: 1;
}

.column.drag-over { outline: 2px dashed var(--primary); outline-offset: -4px; }

.kanban-card {
	background: var(--surface);
	border-radius: 6px;
	box-shadow: var(--shadow);
	padding: 10px 12px;
	cursor: grab;
}

.kanban-card:hover { box-shadow: 0 3px 8px rgba(20, 30, 60, .14); }
.kanban-card.dragging { opacity: .5; }


/* ---------- Dialog ---------- */

dialog {
	border: 1px solid var(--border);
	border-radius: var(--radius);
	box-shadow: 0 10px 40px rgba(0, 0, 20, .35);
	padding: 24px;
	min-width: 440px;
	background: var(--surface);
	color: var(--text);
}

dialog::backdrop { background: rgba(20, 30, 60, .35); }

dialog h2 { margin-top: 0; }

.dialog-actions {
	display: flex;
	align-items: center;
	gap: 8px;
	margin-top: 16px;
	padding-top: 16px;
	border-top: 1px solid var(--border);
}

.icon-btn {
	border: none;
	background: none;
	cursor: pointer;
	color: var(--text-muted);
	font-size: 16px;
	padding: 4px 6px;
	border-radius: 6px;
	flex-shrink: 0;
}

.icon-btn:hover { color: var(--primary); background: var(--primary-soft); }

/* ---------- Login ---------- */

.login-body {
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: 100vh;
}

.login-card {
	width: 360px;
	padding: 32px;
}

.login-brand {
	display: flex;
	align-items: center;
	gap: 12px;
	font-size: 20px;
	font-weight: 700;
	margin-bottom: 20px;
}

.login-card input { width: 100%; }

.login-btn {
	width: 100%;
	justify-content: center;
	margin-top: 20px;
}

/* ---------- Issue detail ---------- */

.issue-layout {
	display: flex;
	gap: 20px;
	align-items: flex-start;
}

.issue-main { flex: 1; min-width: 0; }

.issue-side {
	flex: 0 0 300px;
	position: sticky;
	top: 80px;
}

.section { padding: 20px; margin-bottom: 20px; }
.section h2 { margin: 0 0 12px; font-size: 17px; }

.section-head {
	display: flex;
	align-items: center;
	gap: 8px;
	margin-bottom: 8px;
}

.section-head .field-label { margin: 0; }

.field-label {
	display: block;
	margin: 14px 0 4px;
	font-size: 12px;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: .04em;
	color: var(--text-muted);
}

.field-label:first-child { margin-top: 0; }

.title-input { width: 100%; font-size: 24px; font-weight: 600; margin-bottom: 14px; }

/* Attachments lives inside the same card as Title/Details now — its heading
   needs real separation from the textarea above it, beating .section h2's
   own margin-top:0 (higher specificity than a bare .attachments-heading). */
#detailsCard .attachments-heading { margin-top: 24px; }

/* Save and Close/Save and New/Discard Changes relocate here on phones (see
   issue.js) — desktop keeps them in .page-head, so this stays empty and
   hidden until the 700px query turns it into the visible stacked group. */
.mobile-actions { display: none; }

.issue-side select, .issue-side input[type="text"] { width: 100%; }

.side-fields {
	display: flex;
	flex-direction: column;
	gap: 16px;
}

.side-fields .field-label { margin: 0 0 4px; }

.chip-editor { margin-bottom: 10px; min-height: 10px; }

/* ---------- Keyword picker modal ---------- */

/* No min-width — the fixed 480px floor here was winning over the phones
   media query's own `dialog { min-width: 0; ... }` reset below (an ID beats
   a type selector regardless of which media query either sits in), which is
   exactly what was forcing this dialog wider than the screen on phones. */
#keywordDialog { width: calc(100vw - 32px); max-width: 560px; }

.keyword-dialog-toolbar {
	display: flex;
	gap: 10px;
	margin-bottom: 12px;
}

.keyword-dialog-toolbar input { flex: 1; }

.keyword-options {
	max-height: 360px;
	overflow-y: auto;
	border: 1px solid var(--border);
	border-radius: 6px;
}

.keyword-option {
	display: flex;
	align-items: center;
	gap: 10px;
	width: 100%;
	padding: 10px 12px;
	border: none;
	border-bottom: 1px solid var(--border);
	background: transparent;
	color: var(--text);
	font: inherit;
	text-align: left;
	cursor: pointer;
}

.keyword-option:last-child { border-bottom: none; }
.keyword-option:hover { background: var(--surface-2); }
.keyword-option.selected { background: var(--primary-soft); }

.keyword-usage { flex: 1; font-size: 12px; }
.keyword-check { color: var(--primary); font-weight: 700; }

.keyword-admin-actions { display: flex; gap: 4px; }
.keyword-admin-actions .icon-btn { padding: 2px 4px; }

.keyword-empty { padding: 16px; text-align: center; }

.keyword-create-row {
	display: flex;
	align-items: center;
	gap: 10px;
	margin-top: 12px;
	padding: 10px 12px;
	border: 1px dashed var(--input-border);
	border-radius: 6px;
}

.created-by { padding: 2px 0 4px; font-weight: 600; }

.meta-dates { margin-top: 18px; line-height: 1.8; }

.attachment-list {
	list-style: none;
	margin: 0 0 12px;
	padding: 0;
}

.attachment-list li {
	display: flex;
	align-items: center;
	gap: 8px;
	padding: 6px 0;
	border-bottom: 1px solid var(--border);
}

.attachment-list li:last-child { border-bottom: none; }
.attachment-list a { color: var(--primary); text-decoration: none; font-weight: 600; }
.attachment-list a:hover { text-decoration: underline; }

.attachment-x {
	cursor: pointer;
	border: none;
	background: none;
	color: var(--text-muted);
	font-size: 15px;
}

.attachment-x:hover { color: var(--danger); }

.file-btn { position: relative; overflow: hidden; }

.history-list { margin-bottom: 16px; }

.history-entry {
	padding: 12px 0;
	border-bottom: 1px solid var(--border);
}

.history-entry:last-child { border-bottom: none; }

.history-head {
	display: flex;
	gap: 10px;
	align-items: baseline;
	margin-bottom: 4px;
}

.history-author { font-weight: 700; }
.history-comment { white-space: pre-wrap; }

.history-attachments { margin-top: 6px; }
.history-attachments a { color: var(--primary); text-decoration: none; font-size: 13px; margin-right: 12px; }
.history-attachments a:hover { text-decoration: underline; }

.comment-form { border-top: 1px solid var(--border); padding-top: 16px; }
.comment-form input[type="text"] { width: 240px; margin-bottom: 8px; }
.comment-form textarea { margin-bottom: 8px; }

.comment-form-actions {
	display: flex;
	align-items: center;
	gap: 10px;
}

/* Narrow screens: single column ordered title → Details → fields → attachments →
   history. display:contents dissolves .issue-main so its cards and the sidebar can
   be interleaved with `order`; align-items must stretch or cards shrink-to-fit. */
@media (max-width: 900px) {

	.issue-layout {
		flex-direction: column;
		align-items: stretch;
		gap: 0;
	}

	.issue-main { display: contents; }

	#detailsCard    { order: 1; }
	.issue-side     { order: 2; position: static; flex: none; width: auto; }
	#historySection { order: 4; }

	/* Status/Priority/Keywords stay single-column, same as the full-size window
	   — side-by-side saved a little vertical room but wasted horizontal room
	   (worse when Status is hidden for non-admins) and its 2-column grid was
	   the actual source of the excess space under Keywords: it sat alone in
	   its own grid row, sized larger than its own content needed. Plain
	   stacking (.side-fields' own base rule, unset here) sidesteps that
	   entirely instead of fighting it. */

	.meta-dates { margin-top: 14px; }
}

/* ---------- Phones ---------- */

@media (max-width: 700px) {

	/* 16px inputs stop iOS Safari from auto-zooming on focus. */
	input[type="text"], input[type="search"], input[type="email"], input[type="password"], select, textarea {
		font-size: 16px;
	}

	/* The brand mark reads as an unlabeled "menu button" at this size and just
	   takes up room a user on their own app doesn't need reminding about —
	   List/Board/Admin plus the profile icon carry the whole top bar instead. */
	.brand { display: none; }

	.topbar {
		flex-wrap: wrap;
		height: auto;
		padding: 10px 12px;
		gap: 8px 14px;
	}

	/* Plain text links, not pill-shaped nav buttons — wraps on its own if
	   List/Board/Admin plus the profile icon can't all fit on one line. */
	.topbar nav { flex-wrap: wrap; gap: 4px 14px; }

	.topbar nav a {
		padding: 4px 2px;
		border-radius: 0;
		background: none !important;
		color: var(--primary);
		text-decoration: underline;
	}

	.topbar nav a.active { color: var(--primary-dim); font-weight: 700; }

	.hide-narrow { display: none; }

	/* Compact user chip: icon only — name stays visible on the Profile page itself. */
	.user-chip .chip-name { display: none; }
	.user-chip .chip-icon { display: inline; }

	/* List view becomes stacked cards; the column table (and its horizontal
	   scrolling) disappears entirely. */
	.table-wrap { display: none; }

	.issue-cards {
		display: flex;
		flex-direction: column;
		gap: 10px;
	}

	main { padding: 12px; }

	.page-head {
		flex-wrap: wrap;
		gap: 10px;
		row-gap: 12px;
		margin-bottom: 10px;
	}

	.page-head h1 { font-size: 18px; }

	.title-input { font-size: 20px; margin-bottom: 10px; }

	/* Smaller, tighter card headings — full desktop-sized headings with
	   generous margins eat too much of a phone's limited vertical room. */
	.section h2 { font-size: 14px; margin-bottom: 6px; }
	#detailsCard .attachments-heading { margin-top: 10px; }

	/* Roughly 4 lines instead of the desktop floor — the auto-grow in issue.js
	   takes it from there as you type, so this is just the empty-state floor. */
	#details { min-height: 100px; }

	/* Same reasoning as the card headings above, applied to the Status/Priority/
	   Keywords sidebar specifically — desktop-sized gaps between each field's
	   own label row and its control add up fast across 3-4 stacked fields. */
	.side-fields { gap: 10px; }
	.section-head { margin-bottom: 4px; }
	.chip-editor { margin-bottom: 4px; min-height: 0; }

	.filter-panel-bar { flex-wrap: wrap; padding: 10px 12px; }
	.filter-panel-body { padding: 0 12px 12px; }
	.preset-row-fields { margin: 0 -12px; padding: 0 12px 12px; }
	.filter-columns { flex-direction: column; }
	.filter-column select[multiple] { min-height: 120px; }
	.preset-row input { flex: 1 1 100%; min-width: 0; }
	.preset-row .grow { min-width: 0; }
	.search-bar { padding: 10px 12px; }

	th, td { padding: 8px 10px; }

	.section { padding: 14px; margin-bottom: 14px; }

	.column { flex: 0 0 260px; }

	dialog { min-width: 0; width: calc(100vw - 32px); padding: 16px; }

	/* Same reasoning as the Issue page's own headings/fields — smaller heading,
	   tighter margins, so the picker doesn't eat more of a phone's screen than
	   its actual content needs. */
	dialog h2 { font-size: 18px; margin-bottom: 10px; }
	.keyword-dialog-toolbar { flex-wrap: wrap; margin-bottom: 8px; }
	.keyword-options { max-height: 300px; }
	.keyword-create-row { margin-top: 8px; }

	.comment-form-actions { flex-wrap: wrap; }

	/* Segmented toggles (Board's By Status/By Priority, the keyword dialog's
	   A–Z/Most Used) read as plain links instead of a bordered button group —
	   same reasoning as the topbar nav above. */
	.segmented {
		border: none;
		border-radius: 0;
		gap: 14px;
	}

	.segmented button {
		border-right: none;
		padding: 4px 0;
		background: none !important;
		color: var(--primary);
		text-decoration: underline;
	}

	.segmented button.active        { color: var(--primary-dim); font-weight: 700; }
	.segmented button:not(.active):hover { background: none; color: var(--primary-dim); }

	/* Action buttons relocate below Status/Priority (see #mobileActions'
	   order in the 900px query above) — full-width and stacked so the input
	   fields stay closest to the top instead of being pushed down by them. */
	.mobile-actions {
		display: flex;
		flex-direction: column;
		gap: 10px;
		order: 3;
		margin-bottom: 20px;
	}

	.mobile-actions .btn { width: 100%; justify-content: center; }

	.page-head #closeBtn, .page-head #saveNewBtn, .page-head #saveCloseBtn { display: none; }
}
