/* SPDX-License-Identifier: GPL-3.0-or-later */

/* Colours are variables so that the dark scheme only has to change them. */
:root {
	--bg: #f6f7f9;
	--surface: #ffffff;
	--text: #1c2330;
	--muted: #5b6577;
	--border: #d3d8e0;
	--accent: #0b5fff;
	--accent-text: #ffffff;
	--error-bg: #fdecec;
	--error-text: #8a1f1f;
	--focus: #0b5fff;
	--note-bg: #fff8e1;
	--note-border: #d9b73a;
	--in-bg: #eef4ff;
	--out-bg: #f1f8f1;
	--overdue: #b3261e;
	--badge-new: #0b5fff;
	--badge-assigned: #00796b;
	--badge-waiting: #a15c00;
	--badge-resolved: #2e7d32;
	--badge-closed: #5b6577;
	--badge-spam: #b3261e;
	--badge-priority-1: #5b6577;
	--badge-priority-2: #0b5fff;
	--badge-priority-3: #a15c00;
	--badge-priority-4: #b3261e;
	--font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
	color-scheme: light dark;
}

@media (prefers-color-scheme: dark) {
	:root {
		--bg: #12161d;
		--surface: #1b212b;
		--text: #e6e9ef;
		--muted: #a0a9b8;
		--border: #333c4a;
		--accent: #6c9bff;
		--accent-text: #0b1220;
		--error-bg: #3a1d1d;
		--error-text: #ffb4b4;
		--focus: #9db9ff;
		--note-bg: #3a331a;
		--note-border: #8a7425;
		--in-bg: #1c2740;
		--out-bg: #1d2f22;
		--overdue: #ff8a80;
		--badge-new: #8fb3ff;
		--badge-assigned: #5fd0c2;
		--badge-waiting: #ffc266;
		--badge-resolved: #8fd694;
		--badge-closed: #a0a9b8;
		--badge-spam: #ff8a80;
		--badge-priority-1: #a0a9b8;
		--badge-priority-2: #8fb3ff;
		--badge-priority-3: #ffc266;
		--badge-priority-4: #ff8a80;
	}
}

*,
*::before,
*::after {
	box-sizing: border-box;
}

body {
	margin: 0;
	background: var(--bg);
	color: var(--text);
	font-family: var(--font);
	font-size: 1rem;
	line-height: 1.5;
}

a {
	color: var(--accent);
}

:focus-visible {
	outline: 3px solid var(--focus);
	outline-offset: 2px;
}

h1 {
	font-size: 1.5rem;
	line-height: 1.25;
	margin: 0 0 1rem;
}

main {
	max-width: 60rem;
	margin: 0 auto;
	padding: 1.5rem 1rem 3rem;
}

main:focus {
	outline: none;
}

.skip-link {
	position: absolute;
	left: 0.5rem;
	top: -4rem;
	padding: 0.5rem 0.75rem;
	background: var(--surface);
	border: 1px solid var(--border);
	z-index: 10;
}

.skip-link:focus {
	top: 0.5rem;
}

/* Header and navigation */
.site-header {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 0.5rem 1.5rem;
	padding: 0.75rem 1rem;
	background: var(--surface);
	border-bottom: 1px solid var(--border);
	border-top: 4px solid var(--accent);
}

.site-name {
	font-weight: 700;
}

/* The brand links to the default ticket list. */
a.site-name {
	color: var(--text);
	text-decoration: none;
}

a.site-name:hover,
a.site-name:focus-visible {
	text-decoration: underline;
}

.site-header nav {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.25rem 1rem;
}

.nav-list {
	display: flex;
	flex-wrap: wrap;
	gap: 0.25rem 1rem;
	list-style: none;
	margin: 0;
	padding: 0;
}

.nav-soon {
	color: var(--muted);
}

.nav-signout {
	margin: 0;
}

/* Forms and buttons */
.narrow {
	max-width: 26rem;
	margin: 2rem auto 0;
	padding: 1.5rem;
	background: var(--surface);
	border: 1px solid var(--border);
	border-radius: 0.5rem;
}

label {
	display: block;
	margin: 0 0 0.25rem;
	font-weight: 600;
}

input[type="email"],
input[type="text"],
input[type="search"],
select,
textarea {
	display: block;
	width: 100%;
	margin: 0 0 1rem;
	padding: 0.6rem 0.7rem;
	border: 1px solid var(--border);
	border-radius: 0.35rem;
	background: var(--bg);
	color: var(--text);
	font: inherit;
}

button {
	padding: 0.6rem 1rem;
	border: 1px solid var(--accent);
	border-radius: 0.35rem;
	background: var(--accent);
	color: var(--accent-text);
	font: inherit;
	font-weight: 600;
	cursor: pointer;
}

button:disabled {
	opacity: 0.6;
	cursor: default;
}

/* A button that looks like a link, for Sign out in the navigation. */
.button-link {
	padding: 0;
	border: 0;
	background: none;
	color: var(--accent);
	font-weight: 400;
	text-decoration: underline;
}

.error {
	margin: 0 0 1rem;
	padding: 0.6rem 0.8rem;
	border-radius: 0.35rem;
	background: var(--error-bg);
	color: var(--error-text);
}

.sections {
	padding-left: 1.25rem;
}

/* htmx adds this class to an element while its request is running. */
.htmx-request {
	opacity: 0.6;
}

/* ------------------------------------------------------------------------
   Chunk 4b: ticket list and ticket page
   ------------------------------------------------------------------------ */

main.wide {
	max-width: 90rem;
}

[x-cloak] {
	display: none !important;
}

.visually-hidden {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip: rect(0 0 0 0);
	white-space: nowrap;
}

.muted {
	color: var(--muted);
	font-weight: 400;
}

h2 {
	font-size: 1.1rem;
	margin: 0 0 0.75rem;
}

select,
textarea {
	width: 100%;
	margin: 0 0 1rem;
	font: inherit;
}

textarea {
	resize: vertical;
}

.check {
	display: flex;
	align-items: flex-start;
	gap: 0.5rem;
	margin: 0 0 0.75rem;
	font-weight: 400;
}

.check input {
	margin-top: 0.3rem;
}

button.secondary,
.button-secondary {
	border-color: var(--border);
	background: var(--surface);
	color: var(--text);
}

.button-secondary {
	display: inline-block;
	padding: 0.6rem 1rem;
	border: 1px solid var(--border);
	border-radius: 0.35rem;
	text-decoration: none;
	font-weight: 600;
}

.page-alert:empty {
	display: none;
}

.page-alert {
	max-width: 90rem;
	margin: 0.75rem auto 0;
	padding: 0 1rem;
}

.form-error:empty {
	display: none;
}

.form-error .error {
	margin: 0.75rem 0 0;
}

.notices {
	margin: 0 0 1rem;
	padding: 0.6rem 0.8rem 0.6rem 1.6rem;
	border: 1px solid var(--border);
	border-radius: 0.35rem;
	background: var(--surface);
}

.empty {
	padding: 1.5rem 0;
	color: var(--muted);
}

/* Badges */
.badge {
	display: inline-block;
	padding: 0.05rem 0.55rem;
	border: 1px solid currentColor;
	border-radius: 999px;
	font-size: 0.8rem;
	font-weight: 600;
	line-height: 1.5;
	white-space: nowrap;
}

.badge-new {
	color: var(--badge-new);
}
.badge-assigned {
	color: var(--badge-assigned);
}
.badge-waiting {
	color: var(--badge-waiting);
}
.badge-resolved {
	color: var(--badge-resolved);
}
.badge-closed,
.badge-other,
.badge-type {
	color: var(--badge-closed);
}
.badge-spam {
	color: var(--badge-spam);
}
.badge-priority-1 {
	color: var(--badge-priority-1);
}
.badge-priority-2 {
	color: var(--badge-priority-2);
}
.badge-priority-3 {
	color: var(--badge-priority-3);
}
.badge-priority-4 {
	color: var(--badge-priority-4);
}
.badge-flag {
	color: var(--badge-waiting);
}

.overdue,
.overdue-flag {
	color: var(--overdue);
}

.overdue-flag {
	font-size: 0.8rem;
}

/* Filters */
.filters {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
	gap: 0.5rem 0.75rem;
	align-items: end;
	margin: 0 0 1rem;
	padding: 0.75rem;
	border: 1px solid var(--border);
	border-radius: 0.5rem;
	background: var(--surface);
}

.filter-field {
	min-width: 0;
}

.filter-field select,
.filter-field input {
	margin-bottom: 0;
}

.filter-search {
	grid-column: span 2;
}

.filter-buttons {
	display: flex;
	gap: 0.5rem;
}

/* Tabs */
.tabs ul {
	display: flex;
	flex-wrap: wrap;
	gap: 0.25rem;
	margin: 0 0 0.75rem;
	padding: 0;
	list-style: none;
	border-bottom: 1px solid var(--border);
}

.tabs a {
	display: block;
	padding: 0.5rem 0.9rem;
	border: 1px solid transparent;
	border-bottom: 0;
	border-radius: 0.35rem 0.35rem 0 0;
	color: var(--text);
	text-decoration: none;
}

.tabs a.current {
	background: var(--surface);
	border-color: var(--border);
	font-weight: 700;
	box-shadow: 0 2px 0 var(--surface);
}

.count {
	display: inline-block;
	min-width: 1.4rem;
	padding: 0 0.35rem;
	border-radius: 999px;
	background: var(--border);
	font-size: 0.8rem;
	text-align: center;
}

/* Ticket table */
/*
   The list table never scrolls sideways: the layout is fixed, every column but
   the subject has a set width, and the subject takes what is left. Long text
   is cut with an ellipsis (the full text is in the title attribute). On
   narrower screens the less important columns are hidden (see the media
   queries below), and on a phone the table becomes cards.
*/
.table-wrap {
	overflow: hidden;
	border: 1px solid var(--border);
	border-radius: 0.5rem;
	background: var(--surface);
}

table.tickets {
	width: 100%;
	table-layout: fixed;
	border-collapse: collapse;
}

table.tickets th,
table.tickets td {
	padding: 0.5rem;
	border-bottom: 1px solid var(--border);
	text-align: left;
	vertical-align: top;
	font-size: 0.92rem;
	overflow: hidden;
	overflow-wrap: anywhere;
}

table.tickets th {
	font-size: 0.8rem;
	text-transform: uppercase;
	letter-spacing: 0.03em;
	color: var(--muted);
	white-space: nowrap;
	text-overflow: ellipsis;
}

/* Every row has its own tbody (so a phone can fold one card), hence last-of-type. */
table.tickets tbody:last-of-type td {
	border-bottom: 0;
}

/* Cells that only the phone card uses: the client and the expand button. */
table.tickets .col-client,
table.tickets .col-toggle {
	display: none;
}

/* Column widths. The subject column has none: it gets the rest. */
table.tickets th.col-num {
	width: 3.5rem;
}

table.tickets th.col-requester {
	width: 11rem;
}

table.tickets th.col-status {
	width: 6.5rem;
}

table.tickets th.col-priority {
	width: 5.5rem;
}

table.tickets th.col-type {
	width: 7rem;
}

table.tickets th.col-assignee {
	width: 8rem;
}

table.tickets th.col-activity,
table.tickets th.col-due {
	width: 8.5rem;
}

/* One line, cut with an ellipsis. Used for the subject, requester and assignee. */
.ellipsis {
	display: block;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

table.tickets .badge {
	max-width: 100%;
	overflow: hidden;
	text-overflow: ellipsis;
	vertical-align: top;
}

.pager {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5rem 1rem;
	margin: 0.75rem 0;
}

.pager span {
	margin-right: auto;
	color: var(--muted);
}

/* Ticket page */
.back {
	margin: 0 0 0.5rem;
}

.ticket-header {
	margin: 0 0 1.25rem;
}

.ticket-header h1 {
	margin-bottom: 0.5rem;
	overflow-wrap: anywhere;
}

.ticket-number {
	color: var(--muted);
}

.badges {
	margin: 0 0 0.75rem;
	display: flex;
	flex-wrap: wrap;
	gap: 0.35rem;
}

.facts {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
	gap: 0.5rem 1rem;
	margin: 0 0 0.75rem;
}

.facts div {
	min-width: 0;
}

.facts dt {
	font-size: 0.8rem;
	color: var(--muted);
}

.facts dd {
	margin: 0;
	overflow-wrap: anywhere;
}

.ticket-links {
	margin: 0;
	padding-left: 1.25rem;
}

.ticket-grid {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: 1.25rem;
	margin: 0 0 1.25rem;
}

@media (min-width: 62rem) {
	.ticket-grid {
		grid-template-columns: minmax(0, 1fr) 20rem;
		align-items: start;
	}
}

.panel {
	margin: 0 0 1.25rem;
	padding: 1rem;
	border: 1px solid var(--border);
	border-radius: 0.5rem;
	background: var(--surface);
}

.ticket-side .panel {
	margin-bottom: 1rem;
}

.ticket-grid > *,
.conversation,
.ticket-side {
	min-width: 0;
}

.status-actions {
	display: flex;
	flex-direction: column;
	gap: 0.6rem;
}

.status-form {
	margin: 0;
}

.status-form .check {
	margin-bottom: 0.25rem;
}

.blocked-note {
	margin-top: 0.75rem;
	padding-top: 0.75rem;
	border-top: 1px solid var(--border);
}

/* The keyboard hint is hidden until components.js adds "has-shortcuts" to <html>. */
.shortcut-hint,
.key-mac {
	display: none;
}

html.has-shortcuts .shortcut-hint {
	display: inline;
	align-self: center;
	font-size: 0.85rem;
}

html.is-mac .key-mac {
	display: inline;
}

html.is-mac .key-pc {
	display: none;
}

.buttons {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
}

/* Conversation */
.messages {
	display: flex;
	flex-direction: column;
	gap: 0.85rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.msg {
	padding: 0.75rem 0.9rem;
	border: 1px solid var(--border);
	border-left-width: 5px;
	border-radius: 0.5rem;
	background: var(--surface);
}

.msg-in {
	border-left-color: var(--badge-new);
	background: var(--in-bg);
	margin-right: 1.5rem;
}

.msg-out {
	border-left-color: var(--badge-resolved);
	background: var(--out-bg);
	margin-left: 1.5rem;
}

.msg-note {
	border-style: dashed;
	border-color: var(--note-border);
	background: var(--note-bg);
}

.msg-head {
	display: flex;
	flex-wrap: wrap;
	gap: 0.25rem 0.75rem;
	align-items: baseline;
	margin-bottom: 0.4rem;
}

.msg-label {
	font-weight: 700;
}

.msg-who {
	overflow-wrap: anywhere;
}

.msg-to,
.msg-subject {
	font-size: 0.85rem;
	overflow-wrap: anywhere;
}

.msg-text {
	white-space: pre-wrap;
	overflow-wrap: anywhere;
	margin: 0.4rem 0;
}

.delivery {
	font-size: 0.85rem;
}

.delivery-queued {
	color: var(--badge-waiting);
}

.delivery-failed {
	color: var(--overdue);
}

.attachments {
	margin: 0.5rem 0 0;
	padding-left: 1.25rem;
	overflow-wrap: anywhere;
}

/* Pictures the message itself shows (inline = 1), kept apart in a closed list. */
.inline-images {
	margin: 0.5rem 0 0;
}

.inline-images summary {
	color: var(--muted);
	font-size: 0.85rem;
	cursor: pointer;
}

.inline-images .attachments {
	margin-top: 0.25rem;
}

/* View button and image popover for attachments that are pictures. The popover
   is native (popovertarget), so Escape and a click outside close it. */
.attachment-view {
	padding: 0.1rem 0.5rem;
	border-color: var(--border);
	background: var(--surface);
	color: var(--text);
	font-size: 0.85rem;
}

.image-popover {
	box-sizing: border-box;
	max-width: 92vw;
	max-height: 92vh;
	padding: 0.75rem;
	overflow: auto;
	border: 1px solid var(--border);
	border-radius: 0.35rem;
	background: var(--surface);
	color: var(--text);
}

.image-popover::backdrop {
	background: rgba(0, 0, 0, 0.75);
}

.image-popover img {
	display: block;
	max-width: 100%;
	max-height: 80vh;
	margin: 0 auto;
	object-fit: contain;
}

.image-popover-links {
	margin: 0.5rem 0 0;
	font-size: 0.85rem;
	overflow-wrap: anywhere;
}

.msg-original {
	margin-top: 0.5rem;
}

.html-frame {
	display: block;
	width: 100%;
	height: 28rem;
	margin-top: 0.5rem;
	border: 1px solid var(--border);
	background: #ffffff;
	resize: vertical;
	overflow: auto;
}

.events {
	margin: 0;
	padding-left: 0;
	list-style: none;
}

.events li {
	margin: 0 0 0.35rem;
	overflow-wrap: anywhere;
}

/* Narrower desktop windows: hide the least important columns instead of scrolling. */
@media (min-width: 48.0625rem) and (max-width: 75rem) {
	table.tickets .col-type,
	table.tickets .col-assignee {
		display: none;
	}
}

@media (min-width: 48.0625rem) and (max-width: 56rem) {
	table.tickets .col-requester {
		display: none;
	}
}

/* Phone width: the table turns into cards (see "Phone layout" at the end). */
@media (max-width: 48rem) {
	.table-wrap {
		overflow: visible;
		border: 0;
		background: none;
	}

	table.tickets,
	table.tickets tbody,
	table.tickets tr,
	table.tickets td {
		display: block;
		width: 100%;
	}

	table.tickets thead {
		position: absolute;
		width: 1px;
		height: 1px;
		overflow: hidden;
		clip: rect(0 0 0 0);
	}

	table.tickets tbody {
		margin: 0 0 0.5rem;
	}

	table.tickets td {
		display: grid;
		grid-template-columns: 6.5rem minmax(0, 1fr);
		gap: 0.5rem;
		border-bottom: 0;
		overflow: visible;
	}

	table.tickets td::before {
		content: attr(data-label);
		font-size: 0.8rem;
		color: var(--muted);
	}

	/* In a card the text wraps instead of being cut. */
	.ellipsis {
		white-space: normal;
		overflow-wrap: anywhere;
	}

	.msg-in {
		margin-right: 0;
	}

	.msg-out {
		margin-left: 0;
	}

	.buttons button {
		width: auto;
	}
}

/* ------------------------------------------------------------------------
   Chunk 4c: search, merge, split, new ticket, clients and contacts
   ------------------------------------------------------------------------ */

.site-search {
	display: flex;
	flex: 1 1 14rem;
	max-width: 24rem;
	gap: 0.35rem;
	margin: 0;
}

/* The box takes all the free space and the button is only as wide as its text.
   The 16px font stops phones from zooming in when the box gets focus. */
.site-search input[type="search"] {
	flex: 1 1 auto;
	width: auto;
	min-width: 0;
	min-height: 2.25rem;
	margin: 0;
	padding: 0.35rem 0.6rem;
	font-size: 1rem;
}

.site-search button {
	flex: 0 0 auto;
	width: auto;
	min-height: 2.25rem;
	padding: 0.35rem 0.9rem;
}

.page-head {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 0.5rem 1rem;
	margin: 0 0 1rem;
}

.page-head h1 {
	margin: 0;
}

.inline-search {
	display: flex;
	flex-wrap: wrap;
	align-items: end;
	gap: 0.5rem;
	margin: 0 0 1rem;
}

.inline-search label {
	flex-basis: 100%;
	margin: 0;
}

.inline-search input[type="search"] {
	flex: 1 1 14rem;
	max-width: 24rem;
	margin: 0;
}

.plain-table {
	width: 100%;
	table-layout: fixed;
	border-collapse: collapse;
}

.plain-table th,
.plain-table td {
	padding: 0.5rem;
	border-bottom: 1px solid var(--border);
	text-align: left;
	vertical-align: top;
	overflow: hidden;
	overflow-wrap: anywhere;
}

.plain-table th {
	font-size: 0.8rem;
	text-transform: uppercase;
	letter-spacing: 0.03em;
	color: var(--muted);
}

.plain-list {
	margin: 0 0 0.75rem;
	padding-left: 1.25rem;
	overflow-wrap: anywhere;
}

.plain-list li {
	margin: 0 0 0.35rem;
}

.split-link {
	margin-left: auto;
	font-size: 0.85rem;
}

.merged-panel {
	border-style: dashed;
}

.merge-list {
	margin: 0;
	padding: 0;
	list-style: none;
}

.merge-list li {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 0.25rem 0.75rem;
	padding: 0.5rem 0;
	border-bottom: 1px solid var(--border);
}

.merge-list a {
	overflow-wrap: anywhere;
}

.merge-search input[type="search"] {
	max-width: 30rem;
}

.plan {
	margin: 0 0 1rem;
	padding-left: 1.25rem;
}

.plan li {
	margin: 0 0 0.5rem;
	overflow-wrap: anywhere;
}

.split-excerpt {
	margin: 0 0 1rem;
	padding: 0.5rem 0.9rem;
	border-left: 4px solid var(--border);
	background: var(--surface);
	white-space: pre-wrap;
	overflow-wrap: anywhere;
}

.confirm-form,
.new-ticket,
.record-form {
	max-width: 44rem;
}

.form-row {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
	gap: 0 0.75rem;
}

.form-row > div {
	min-width: 0;
}

/* Admin pages (chunk 4d) */
input[type="url"],
input[type="number"],
input[type="date"],
input[type="time"] {
	display: block;
	width: 100%;
	margin: 0 0 1rem;
	padding: 0.6rem 0.7rem;
	border: 1px solid var(--border);
	border-radius: 0.35rem;
	background: var(--bg);
	color: var(--text);
	font: inherit;
}

.admin-sections {
	padding-left: 1.25rem;
}

.admin-sections li {
	margin: 0 0 0.6rem;
}

/* A date or time that is late, in red text (also readable without colour: the page adds "(late)"). */
.stale {
	color: var(--overdue);
	font-weight: 600;
}

.status-list {
	margin: 0 0 0.75rem;
}

.status-list dt {
	margin-top: 0.5rem;
	font-size: 0.8rem;
	text-transform: uppercase;
	letter-spacing: 0.03em;
	color: var(--muted);
}

.status-list dd {
	margin: 0;
	overflow-wrap: anywhere;
}

.inline-form {
	display: inline-flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.4rem;
	margin: 0;
}

.inline-form input,
.inline-form select {
	width: auto;
	min-width: 0;
	margin: 0;
}

.plain-table input[type="number"] {
	display: inline-block;
	width: 5rem;
	margin: 0;
	padding: 0.35rem 0.5rem;
}

.event-detail {
	max-height: 20rem;
	margin: 0.4rem 0 0;
	padding: 0.5rem 0.7rem;
	overflow: auto;
	border: 1px solid var(--border);
	border-radius: 0.35rem;
	background: var(--bg);
	font-size: 0.8rem;
	white-space: pre-wrap;
	overflow-wrap: anywhere;
}

.plain-preview {
	padding: 0.6rem 0.8rem;
	border: 1px solid var(--border);
	border-radius: 0.35rem;
	background: var(--bg);
	white-space: pre-wrap;
	overflow-wrap: anywhere;
}

.preview-links {
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem 1rem;
	margin: 0 0 0.75rem;
	padding: 0;
	list-style: none;
}

textarea.code {
	font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
	font-size: 0.85rem;
}

.warning {
	margin: 0 0 1rem;
	padding: 0.6rem 0.8rem;
	border: 1px solid var(--note-border);
	border-radius: 0.35rem;
	background: var(--note-bg);
}

fieldset.days {
	margin: 0 0 1rem;
	padding: 0.5rem 0.8rem;
	border: 1px solid var(--border);
	border-radius: 0.35rem;
}

fieldset.days legend {
	font-weight: 600;
}

@media (max-width: 48rem) {
	.plain-table,
	.plain-table tbody,
	.plain-table tr,
	.plain-table td {
		display: block;
		width: 100%;
	}

	.plain-table thead {
		position: absolute;
		width: 1px;
		height: 1px;
		overflow: hidden;
		clip: rect(0 0 0 0);
	}

	.plain-table tr {
		margin: 0 0 0.75rem;
		border: 1px solid var(--border);
		border-radius: 0.5rem;
		background: var(--surface);
	}

	.plain-table td::before,
	.plain-table th[data-label]::before {
		content: attr(data-label) ": ";
		color: var(--muted);
		font-size: 0.8rem;
	}

	/* A row heading (th scope="row") is the first line of its card. */
	.plain-table th[scope="row"] {
		display: block;
		padding: 0.5rem;
		text-transform: none;
		letter-spacing: 0;
	}
}

@media (max-width: 480px) {
	main {
		padding: 1rem 0.75rem 2rem;
	}

	.narrow {
		margin-top: 1rem;
		padding: 1rem;
	}

	button {
		width: 100%;
	}

	.button-link {
		width: auto;
	}
}

/* ------------------------------------------------------------------------
   Phone layout
   Phone = max-width 48rem (the same width components.js tests with
   matchMedia). The page parts that fold away are marked "collapsible"; the
   collapse component adds "is-collapsed" to them on a phone only. Without
   JavaScript no class is added, the toggle buttons stay hidden (x-cloak) and
   everything is shown. All folding rules are inside the phone query, so a wide
   window always shows everything, whatever state a section was left in.
   ------------------------------------------------------------------------ */

/* The toggle buttons exist for phones only. */
.collapse-toggle {
	display: none;
}

.chevron {
	display: inline-block;
	flex: none;
	width: 0.6rem;
	height: 0.6rem;
	margin: -0.25rem 0.2rem 0;
	border-right: 2px solid currentColor;
	border-bottom: 2px solid currentColor;
	transform: rotate(45deg);
}

.collapse-toggle[aria-expanded="true"] .chevron {
	margin: 0.25rem 0.2rem 0;
	transform: rotate(-135deg);
}

.collapse-head h2 {
	margin: 0 0 0.75rem;
}

/* The ticket page is one grid. On a phone it is a single column in the order
   conversation, reply box, note box, side panels, event log. From 62rem named
   areas give the layout the page always had: the conversation beside the side
   column, the boxes full width below. #ticket-view is the part htmx replaces
   as a whole; display: contents lets its children be grid items. */
.ticket-layout {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	column-gap: 1.25rem;
	margin: 0 0 1.25rem;
}

#ticket-view {
	display: contents;
}

.ticket-layout .back,
.ticket-layout .ticket-header,
.ticket-layout .conversation,
.ticket-layout .ticket-side,
.ticket-layout > .panel {
	min-width: 0;
}

.ticket-layout .conversation {
	margin-bottom: 1.25rem;
}

@media (min-width: 62rem) {
	.ticket-layout {
		grid-template-columns: minmax(0, 1fr) 20rem;
		grid-template-areas:
			"back back"
			"head head"
			"conv side"
			"reply reply"
			"note note"
			"events events";
		align-items: start;
	}

	.ticket-layout .back {
		grid-area: back;
	}

	.ticket-layout .ticket-header {
		grid-area: head;
	}

	.ticket-layout .conversation {
		grid-area: conv;
	}

	.ticket-layout .ticket-side {
		grid-area: side;
	}

	#reply-area {
		grid-area: reply;
	}

	#note-area {
		grid-area: note;
	}

	#ticket-events {
		grid-area: events;
	}
}

@media (max-width: 48rem) {
	/* Tap targets of at least 44px (2.75rem). */
	button,
	.button-secondary,
	.button-link,
	.tabs a,
	.pager a,
	.back a,
	.site-header nav a {
		min-height: 2.75rem;
	}

	.button-link,
	.tabs a,
	.pager a,
	.back a,
	.site-header nav a,
	.button-secondary {
		display: inline-flex;
		align-items: center;
	}

	input[type="email"],
	input[type="text"],
	input[type="search"],
	input[type="url"],
	input[type="number"],
	input[type="date"],
	input[type="time"],
	select {
		min-height: 2.75rem;
		font-size: 1rem;
	}

	.back {
		margin: 0;
	}

	/* Header: brand and navigation on the first line, the search under them. */
	.site-header {
		gap: 0 0.75rem;
		padding: 0.5rem 0.75rem;
	}

	.site-name {
		order: 1;
		display: inline-flex;
		align-items: center;
		min-height: 2.75rem;
	}

	.site-header nav {
		order: 2;
		margin-left: auto;
		gap: 0 0.75rem;
	}

	.nav-list {
		gap: 0 0.75rem;
	}

	.site-search {
		order: 3;
		flex: 1 1 100%;
		max-width: none;
		margin: 0 0 0.25rem;
	}

	.site-search input[type="search"],
	.site-search button {
		min-height: 2.75rem;
	}

	/* The folding itself. */
	.collapse-toggle {
		display: flex;
		align-items: center;
		justify-content: space-between;
		gap: 0.5rem;
		width: 100%;
		min-height: 2.75rem;
		padding: 0 0.25rem;
		border: 0;
		border-radius: 0.35rem;
		background: transparent;
		color: var(--text);
		text-align: left;
	}

	.collapsible.is-collapsed > .collapse-body {
		display: none;
	}

	/* A panel's toggle lies over its whole heading row, so the row is the tap target. */
	.collapse-head {
		position: relative;
		display: flex;
		align-items: center;
		min-height: 2.75rem;
	}

	.collapse-head h2 {
		flex: 1;
		margin: 0;
	}

	.collapse-head .collapse-toggle {
		position: absolute;
		inset: 0;
		justify-content: flex-end;
	}

	.collapsible:not(.is-collapsed) > .collapse-body {
		padding-bottom: 0.5rem;
	}

	/* Side panels, note box and event log: slim when folded. */
	.ticket-side .panel,
	#note-area,
	#ticket-events {
		margin-bottom: 0.5rem;
		padding: 0.25rem 1rem;
	}

	/* The ticket header. */
	.ticket-header {
		margin: 0 0 0.75rem;
	}

	.ticket-header h1 {
		margin-bottom: 0.35rem;
		font-size: 1.15rem;
	}

	.ticket-header .badges {
		gap: 0.25rem;
		margin-bottom: 0.4rem;
	}

	.ticket-header .badge {
		padding: 0 0.45rem;
		font-size: 0.72rem;
	}

	.header-toggle {
		padding: 0 0.75rem;
		border: 1px solid var(--border);
		background: var(--surface);
		font-weight: 600;
	}

	.ticket-header .collapse-body {
		margin-top: 0.5rem;
	}

	.ticket-layout .conversation {
		margin-bottom: 0.75rem;
	}

	.conversation h2 {
		margin-bottom: 0.5rem;
		font-size: 1rem;
	}

	/* The ticket list: filters behind one toggle row. */
	.list-controls-toggle {
		margin: 0 0 0.5rem;
		padding: 0 0.75rem;
		border: 1px solid var(--border);
		background: var(--surface);
		font-weight: 600;
	}

	.list-controls-text {
		min-width: 0;
		overflow: hidden;
		text-overflow: ellipsis;
		white-space: nowrap;
	}

	.page-head {
		margin-bottom: 0.5rem;
	}

	/* The tabs are the main filter: they come first, above the form. */
	.list-controls:not(.is-collapsed) > .collapse-body {
		display: flex;
		flex-direction: column;
	}

	#ticket-tabs {
		order: -1;
	}

	.filter-search {
		grid-column: 1 / -1;
	}

	.filter-buttons button,
	.filter-buttons .button-secondary {
		flex: 1;
		justify-content: center;
	}

	/* The ticket list: each ticket is a compact card. Two lines (number, subject
	   and the expand button; requester and status), then the other fields. The
	   subject link is stretched over the whole card, so the card is one big link;
	   the expand button sits above it. */
	table.tickets tr {
		position: relative;
		display: grid;
		grid-template-columns: auto minmax(0, 1fr) auto auto;
		grid-template-areas:
			"num subject subject toggle"
			"req req status toggle";
		margin: 0;
		border: 1px solid var(--border);
		border-radius: 0.5rem;
		background: var(--surface);
	}

	table.tickets td.col-num,
	table.tickets td.col-subject,
	table.tickets td.col-requester,
	table.tickets td.col-status,
	table.tickets td.col-toggle {
		display: block;
		min-width: 0;
	}

	table.tickets td.col-num::before,
	table.tickets td.col-subject::before,
	table.tickets td.col-requester::before,
	table.tickets td.col-status::before,
	table.tickets td.col-toggle::before {
		content: none;
	}

	table.tickets td.col-num {
		grid-area: num;
		padding: 0.5rem 0 0 0.75rem;
		font-weight: 700;
	}

	table.tickets td.col-num a {
		display: inline-block;
		min-width: 2.2rem;
	}

	table.tickets td.col-subject {
		grid-area: subject;
		padding: 0.5rem 0.25rem 0 0.5rem;
		font-weight: 600;
	}

	table.tickets td.col-subject .ellipsis {
		display: -webkit-box;
		-webkit-line-clamp: 2;
		-webkit-box-orient: vertical;
		overflow: hidden;
		color: var(--text);
		text-decoration: none;
	}

	table.tickets td.col-subject .ellipsis::after {
		content: "";
		position: absolute;
		inset: 0;
	}

	table.tickets td.col-subject .ellipsis:focus-visible {
		outline: none;
	}

	table.tickets td.col-subject .ellipsis:focus-visible::after {
		outline: 3px solid var(--focus);
		outline-offset: 2px;
		border-radius: 0.5rem;
	}

	table.tickets td.col-requester {
		grid-area: req;
		padding: 0.15rem 0.25rem 0.5rem 0.75rem;
		color: var(--muted);
	}

	table.tickets td.col-status {
		grid-area: status;
		padding: 0.15rem 0.25rem 0.5rem 0;
		text-align: right;
	}

	table.tickets td.col-toggle {
		position: relative;
		z-index: 1;
		grid-area: toggle;
		min-width: 2.75rem;
		padding: 0;
	}

	table.tickets td.col-toggle .collapse-toggle {
		height: 100%;
		padding: 0;
		justify-content: center;
	}

	/* The other fields, one label and value per line, shown when the card is open. */
	table.tickets td.col-priority,
	table.tickets td.col-type,
	table.tickets td.col-client,
	table.tickets td.col-assignee,
	table.tickets td.col-activity,
	table.tickets td.col-due {
		display: grid;
		grid-column: 1 / -1;
		padding: 0.3rem 0.75rem;
		border-top: 1px solid var(--border);
	}

	table.tickets td > .badge {
		justify-self: start;
	}

	table.tickets tbody.is-collapsed td.col-priority,
	table.tickets tbody.is-collapsed td.col-type,
	table.tickets tbody.is-collapsed td.col-client,
	table.tickets tbody.is-collapsed td.col-assignee,
	table.tickets tbody.is-collapsed td.col-activity,
	table.tickets tbody.is-collapsed td.col-due,
	table.tickets tbody td:empty {
		display: none;
	}

	/* The event list: one line per event (time, description, ticket, expand
	   button). Open, the entry grows and shows the kind, the actor and the detail. */
	.events-table tr.event-row {
		position: relative;
		display: grid;
		grid-template-columns: minmax(0, 1fr) auto auto;
		grid-template-areas:
			"time ticket toggle"
			"what what what"
			"kind kind kind"
			"actor actor actor";
		margin: 0 0 0.5rem;
	}

	.events-table td {
		min-width: 0;
		padding: 0.15rem 0.75rem;
		border-bottom: 0;
	}

	.events-table td[data-label="Time"] {
		grid-area: time;
		padding-top: 0.5rem;
	}

	.events-table td[data-label="Ticket"] {
		grid-area: ticket;
		padding-top: 0.5rem;
		padding-left: 0;
	}

	.events-table td[data-label="What happened"] {
		grid-area: what;
	}

	.events-table td[data-label="Kind"] {
		grid-area: kind;
	}

	.events-table td[data-label="Actor"] {
		grid-area: actor;
		padding-bottom: 0.5rem;
	}

	.events-table td.event-toggle {
		grid-area: toggle;
		min-width: 2.75rem;
		padding: 0;
	}

	.events-table td.event-toggle .collapse-toggle {
		justify-content: center;
		padding: 0;
	}

	.events-table td[data-label="Time"]::before,
	.events-table td[data-label="Ticket"]::before,
	.events-table td[data-label="What happened"]::before,
	.events-table td.event-toggle::before {
		content: none;
	}

	/* The detail shows as soon as the entry is open, so its own button is not needed. */
	.events-table .event-detail-box button {
		display: none;
	}

	.events-table .event-detail {
		display: block !important;
	}

	.events-table tr.event-row.is-collapsed {
		grid-template-columns: auto minmax(0, 1fr) auto auto;
		grid-template-areas: "time what ticket toggle";
		align-items: center;
	}

	.events-table tr.is-collapsed td {
		padding-top: 0;
		padding-bottom: 0;
	}

	.events-table tr.is-collapsed td[data-label="Kind"],
	.events-table tr.is-collapsed td[data-label="Actor"],
	.events-table tr.is-collapsed .event-detail-box {
		display: none;
	}

	/* Folded, the time is only its short hint, such as "(5 min ago)". */
	.events-table tr.is-collapsed td[data-label="Time"] {
		font-size: 0;
		white-space: nowrap;
	}

	.events-table tr.is-collapsed td[data-label="Time"] .muted {
		font-size: 0.8rem;
	}

	.events-table tr.is-collapsed td[data-label="What happened"] {
		overflow: hidden;
		text-overflow: ellipsis;
		white-space: nowrap;
	}

	/* Cells with nothing in them take no room. */
	.events-table tbody td:empty {
		display: none;
	}
}
