/* Ticket detail page */ /* * Page layout. * * Desktop: two columns that both start at the top - the header and the * conversation on the left, the sidebar (Details, Contact, Tasks, Linked, * History) on the right, so the ticket's properties sit beside its title * instead of in a strip that wrapped onto a second row. * * Phone: one column. Left alone, the whole sidebar would land under the * conversation and put status and priority at the bottom of a long page. The * sidebar wrapper steps aside (display: contents) so its cards become items of * the column, and `order` lifts Details up between the header and the * conversation while the other sidebar cards stay below it. */ .ticket-layout { display: flex; flex-direction: column; } .ticket-layout-header { order: 0; } .ticket-layout-main { order: 2; min-width: 0; } .ticket-layout-side { display: contents; } .ticket-layout-side > * { order: 3; } .ticket-layout-side > .ticket-details { order: 1; } @media (min-width: 992px) { .ticket-layout { display: grid; grid-template-columns: minmax(0, 1fr) 300px; /* The second row soaks up the height, so the header row is only as tall as the header */ grid-template-rows: auto 1fr; grid-template-areas: "header side" "main side"; column-gap: 1rem; align-items: start; } .ticket-layout-header { grid-area: header; } .ticket-layout-main { grid-area: main; } .ticket-layout-side { display: block; grid-area: side; min-width: 0; } } @media (min-width: 1400px) { .ticket-layout { grid-template-columns: minmax(0, 1fr) 340px; } } /* Header */ /* The subject is the page's real heading, so let it breathe */ .ticket-subject { font-weight: 600; word-break: break-word; } /* The pencil next to the subject shouldn't drag the heading's line height around */ .ticket-subject .btn-tool { font-size: 0.9rem; vertical-align: middle; } .ticket-meta { font-size: 0.85rem; color: var(--bs-secondary-color); word-break: break-word; } /* * Details panel - one property per row, label on the left, value on the right. * * A value that can be changed is a full-width button: it highlights on hover and * shows a small pencil, which is how the page says "click to change" without a * column of blue links. Values that can't be changed get the same box with no * hover, so every row lines up whether it is editable or not. */ .ticket-prop { display: grid; grid-template-columns: 6.25rem minmax(0, 1fr); align-items: center; min-height: 2.4rem; } .ticket-prop + .ticket-prop { border-top: 1px solid var(--bs-border-color-translucent); } .ticket-prop dt { margin: 0; padding-left: 0.5rem; font-size: 0.8rem; font-weight: 500; color: var(--bs-secondary-color); } .ticket-prop dd { margin: 0; min-width: 0; } .ticket-prop-edit, .ticket-prop-static { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; width: 100%; min-width: 0; padding: 0.3rem 0.5rem; border: 0; border-radius: var(--bs-border-radius); background: transparent; color: var(--bs-body-color); font: inherit; text-align: left; text-decoration: none; } .ticket-prop-edit:hover, .ticket-prop-edit:focus-visible, .ticket-prop-edit[aria-expanded="true"] { background-color: var(--bs-tertiary-bg); color: var(--bs-body-color); } .ticket-prop-edit-icon { flex: 0 0 auto; font-size: 0.7rem; color: var(--bs-secondary-color); opacity: 0; transition: opacity 0.15s; } .ticket-prop-edit:hover .ticket-prop-edit-icon, .ticket-prop-edit:focus-visible .ticket-prop-edit-icon, .ticket-prop-edit[aria-expanded="true"] .ticket-prop-edit-icon { opacity: 1; } /* Touch screens have no hover, so the pencil stays faintly visible there */ @media (hover: none) { .ticket-prop-edit-icon { opacity: 0.6; } } /* A second line under a value - the SLA plan name, Onsite/Remote */ .ticket-prop-sub { display: block; font-size: 0.8rem; color: var(--bs-secondary-color); } .ticket-prop .badge { font-size: 0.78rem; font-weight: 600; /* Badges never wrap by default, and an SLA countdown can be wider than a narrow column */ white-space: normal; text-align: left; } /* Small uppercase headings inside the Linked and History cards */ .ticket-link-heading { font-size: 0.72rem; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--bs-secondary-color); } /* Tasks - the progress count lives in the card heading, the one place it is shown */ .ticket-task-count { display: inline-flex; align-items: center; gap: 0.4rem; font-size: 0.8rem; font-weight: 400; color: var(--bs-secondary-color); vertical-align: middle; } .ticket-task-progress { width: 48px; height: 5px; } .ticket-task-table td { vertical-align: top; padding-top: 0.45rem; padding-bottom: 0.45rem; } .ticket-task-check { width: 1.75rem; } .ticket-task-table .drag-handle { cursor: grab; opacity: 0.4; } .ticket-task-table tr:hover .drag-handle { opacity: 1; } /* History - label/value pairs in two columns */ .ticket-history-facts { display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: 0.75rem; row-gap: 0.4rem; font-size: 0.875rem; } .ticket-history-facts dt { font-weight: 500; color: var(--bs-secondary-color); } .ticket-history-facts dd { margin: 0; } /* Conversation - the coloured edge says who wrote it and who can see it */ .ticket-reply.border-start { border-left-width: 4px !important; } /* * Dark mode: Bootstrap's "dark" is the page colour there, so the ticket reference, * the Internal badge and an internal note's edge would all vanish into the card. * Lift them to a mid grey that still reads as the dark/neutral one. */ [data-bs-theme="dark"] .ticket-ref, [data-bs-theme="dark"] .ticket-badge-internal { background-color: #495057 !important; color: #fff !important; } /* A public note - seen in the portal, not emailed - is the quieter of the two public badges */ .ticket-badge-note { background-color: var(--bs-info-bg-subtle); color: var(--bs-info-text-emphasis); border: 1px solid var(--bs-info-border-subtle); } /* "Emailed to ..." on a reply, and who each one went to */ .ticket-reply-emailed { text-decoration: none; } .ticket-reply-emailed:hover, .ticket-reply-emailed:focus-visible { text-decoration: underline; } .ticket-reply-recipients { padding: 0.5rem 0.75rem; border-radius: var(--bs-border-radius); background-color: var(--bs-tertiary-bg); } [data-bs-theme="dark"] .ticket-reply.border-dark { border-left-color: #6c757d !important; } /* The "who will see this" line under the reply type buttons */ .ticket-reply-audience { padding: 0.5rem 0.75rem; border-radius: var(--bs-border-radius); background-color: var(--bs-tertiary-bg); color: var(--bs-secondary-color); } .ticket-reply-audience strong { color: var(--bs-body-color); } /* * Bootstrap cancels hover on any .btn following a .btn-check (twbs #31149 / PR #37026): * a checked outline toggle and an unchecked one looked identical while hovered, so you * could not read the control's state without moving the pointer away. Correct, but the * selector also catches the UNCHECKED buttons, and with nothing preselected here that * leaves the whole strip with no feedback at all. * * Give the unchecked ones a NEUTRAL tint - not the variant fill, which is what checked * looks like and would reintroduce exactly the ambiguity #31149 was about. Upstream's * color and border-color still apply, so only the background moves. */ #replyTypePicker .btn-check:not(:checked) + .btn:hover { background-color: var(--bs-secondary-bg); } /* Paper gets one column, conversation first */ @media print { .ticket-layout { display: block; } .ticket-layout-side { display: block; } }