/*
 * board.css — the public feedback board's entire visual design.
 *
 * This page is the first thing a Crestron integrator sees after googling a problem and
 * landing on our roadmap (see the plan's §7.1) — it represents a paid product to a
 * professional audience, so it needs to read as considered, not as an unstyled HTML
 * document and not as a startup marketing page either. The palette below is drawn from
 * the desktop app's own editor chrome (src/renderer/styles.css: #0f141a background,
 * #2868d9 accent) so the board and the product it represents feel like the same thing,
 * without literally reusing editor-only classes that don't belong on a public web page.
 *
 * No framework, no build step: this file is served as-is (see boardRoutes.tsx for how a
 * Worker with no static-asset binding gets a literal .css file into a response). Written
 * for zero JavaScript — every state a script might otherwise toggle (vote pressed, nav
 * current page) is expressed with `:root` custom properties, `[aria-pressed]`, and
 * `[aria-current]`, which board.js can set but this stylesheet never requires it to.
 */

:root {
  /* Light palette — the default. Dark tokens are redefined, never introduced fresh, in
     the media-query and [data-theme] blocks below (this page has no in-page theme toggle,
     but every token still follows the same "define once, override consistently" rule so
     that adding one later is a CSS-only change). */
  --bg: #ffffff;
  --bg-subtle: #f5f6f8;
  --surface: #ffffff;
  --border: #e1e4e9;
  --border-strong: #c7cdd6;
  --text: #1a2129;
  --text-muted: #5b6672;
  --text-faint: #838d99;
  --accent: #2868d9;
  --accent-hover: #1f54b3;
  --accent-contrast: #ffffff;
  --focus-ring: #2868d9;
  --danger: #b3261e;

  --status-open-bg: #eef0f3;
  --status-open-fg: #4b5563;
  --status-planned-bg: #e3ecfc;
  --status-planned-fg: #1d4ed8;
  --status-in_progress-bg: #fdf1da;
  --status-in_progress-fg: #92660a;
  --status-shipped-bg: #dff3e6;
  --status-shipped-fg: #167a42;
  --status-declined-bg: #f4e4e3;
  --status-declined-fg: #9c3a32;

  --content-width: 42rem;
  --radius: 10px;
  --radius-sm: 6px;

  color-scheme: light;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #0f141a;
    --bg-subtle: #10171f;
    --surface: #141c25;
    --border: #26313d;
    --border-strong: #34465a;
    --text: #e8edf4;
    --text-muted: #9ea9b6;
    --text-faint: #71808f;
    --accent: #5b9dff;
    --accent-hover: #82b6ff;
    --accent-contrast: #0b1016;
    --focus-ring: #5b9dff;
    --danger: #f2867d;

    --status-open-bg: #1c242d;
    --status-open-fg: #a7b1bd;
    --status-planned-bg: #17253d;
    --status-planned-fg: #8fb4f7;
    --status-in_progress-bg: #332714;
    --status-in_progress-fg: #ecbc65;
    --status-shipped-bg: #123324;
    --status-shipped-fg: #6fd39a;
    --status-declined-bg: #351f1d;
    --status-declined-fg: #e8938b;

    color-scheme: dark;
  }
}

:root[data-theme="dark"] {
  --bg: #0f141a;
  --bg-subtle: #10171f;
  --surface: #141c25;
  --border: #26313d;
  --border-strong: #34465a;
  --text: #e8edf4;
  --text-muted: #9ea9b6;
  --text-faint: #71808f;
  --accent: #5b9dff;
  --accent-hover: #82b6ff;
  --accent-contrast: #0b1016;
  --focus-ring: #5b9dff;
  --danger: #f2867d;

  --status-open-bg: #1c242d;
  --status-open-fg: #a7b1bd;
  --status-planned-bg: #17253d;
  --status-planned-fg: #8fb4f7;
  --status-in_progress-bg: #332714;
  --status-in_progress-fg: #ecbc65;
  --status-shipped-bg: #123324;
  --status-shipped-fg: #6fd39a;
  --status-declined-bg: #351f1d;
  --status-declined-fg: #e8938b;

  color-scheme: dark;
}

* {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

img,
svg {
  max-width: 100%;
}

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

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

:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
  border-radius: 4px;
}

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

.site-header {
  border-bottom: 1px solid var(--border);
  background: var(--bg);
}

.site-header__inner {
  max-width: 52rem;
  margin: 0 auto;
  padding: 1.1rem 1.25rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.site-title {
  /* A little larger and heavier than it was when the wordmark read "Ouro Feedback": one
     short word at 1.05rem reads as a label rather than as the name of the product, and
     this is now the only place on the page that says what site you are on. */
  font-size: 1.15rem;
  font-weight: 700;
  letter-spacing: -0.015em;
  color: var(--text);
  text-decoration: none;
  /* The nav items beside it wrap on a narrow viewport; the wordmark itself never should. */
  white-space: nowrap;
}

.site-title:hover {
  color: var(--text);
  opacity: 0.85;
}

/* Wraps the whole wordmark now that it is a single word (see Layout.tsx) — so this is the
   accent colour of the name itself, not of a first word with a plain second one after it. */
.site-title__mark {
  color: var(--accent);
}

.site-nav {
  display: flex;
  align-items: center;
  gap: 1.1rem;
  font-size: 0.9rem;
}

/* Sits immediately after the wordmark and pushes the account nav to the far right, so the
   header reads as "the site's pages" on the left and "you" on the right rather than as
   three evenly-spaced groups with no hierarchy. */
.site-nav--primary {
  margin-right: auto;
  /* Two navs on one row on a phone will not fit; wrapping is better than a horizontal
     scroll or a truncated item. */
  flex-wrap: wrap;
  gap: 0.9rem;
}

.site-nav a {
  color: var(--text-muted);
  text-decoration: none;
}

.site-nav a:hover {
  color: var(--text);
}

/* "You are here", set by Layout.tsx from the same value the page passes for its own title.
   Styled off [aria-current] rather than a `.is-active` class for the same reason the sort
   tabs are: the accessible state and the visible state are then the same fact, and one
   cannot be updated without the other. */
.site-nav a[aria-current="page"] {
  color: var(--text);
  font-weight: 650;
}

.site-nav__logout-form {
  display: inline;
}

.button--small {
  padding: 0.3rem 0.7rem;
  font-size: 0.85rem;
}

.site-main {
  max-width: var(--content-width);
  margin: 0 auto;
  padding: 2.25rem 1.25rem 4rem;
}

.site-main--wide {
  max-width: 52rem;
}

.site-footer {
  border-top: 1px solid var(--border);
  margin-top: 2rem;
}

.site-footer__inner {
  max-width: 52rem;
  margin: 0 auto;
  padding: 1.5rem 1.25rem;
  color: var(--text-faint);
  font-size: 0.82rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.25rem;
}

.site-footer a {
  color: var(--text-faint);
}

.site-footer a:hover {
  color: var(--text-muted);
}

/* Page heading ---------------------------------------------------------------------------*/

.page-heading {
  margin-bottom: 1.75rem;
}

.page-heading h1 {
  font-size: 1.6rem;
  font-weight: 650;
  letter-spacing: -0.015em;
  margin: 0 0 0.35rem;
}

.page-heading p {
  color: var(--text-muted);
  margin: 0;
  font-size: 0.98rem;
}

/* Sort tabs --------------------------------------------------------------------------------*/

.sort-tabs {
  display: flex;
  gap: 0.25rem;
  margin-bottom: 1.5rem;
  border-bottom: 1px solid var(--border);
}

.sort-tabs a {
  display: inline-block;
  padding: 0.55rem 0.85rem;
  font-size: 0.9rem;
  text-decoration: none;
  color: var(--text-muted);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}

.sort-tabs a:hover {
  color: var(--text);
}

.sort-tabs a[aria-current="page"] {
  color: var(--text);
  border-bottom-color: var(--accent);
  font-weight: 600;
}

/* Ticket list --------------------------------------------------------------------------- */

.ticket-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.ticket-card {
  display: flex;
  gap: 1rem;
  align-items: flex-start;
  padding: 1.1rem 1.15rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
}

.ticket-card__body {
  flex: 1;
  min-width: 0;
}

.ticket-card__title {
  margin: 0 0 0.3rem;
  font-size: 1.02rem;
  font-weight: 600;
  line-height: 1.35;
}

.ticket-card__title a {
  color: var(--text);
  text-decoration: none;
}

.ticket-card__title a:hover {
  color: var(--accent);
}

.ticket-card__excerpt {
  margin: 0 0 0.6rem;
  color: var(--text-muted);
  font-size: 0.92rem;
  overflow-wrap: anywhere;
}

.ticket-card__meta {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  font-size: 0.82rem;
  color: var(--text-faint);
}

.ticket-card__meta .comment-count {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
}

/* Status badge -----------------------------------------------------------------------------*/

.status-badge {
  display: inline-flex;
  align-items: center;
  padding: 0.18rem 0.55rem;
  border-radius: 999px;
  font-size: 0.76rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  white-space: nowrap;
}

.status-badge--open {
  background: var(--status-open-bg);
  color: var(--status-open-fg);
}

.status-badge--planned {
  background: var(--status-planned-bg);
  color: var(--status-planned-fg);
}

.status-badge--in_progress {
  background: var(--status-in_progress-bg);
  color: var(--status-in_progress-fg);
}

.status-badge--shipped {
  background: var(--status-shipped-bg);
  color: var(--status-shipped-fg);
}

.status-badge--declined {
  background: var(--status-declined-bg);
  color: var(--status-declined-fg);
}

/* Vote button ------------------------------------------------------------------------------*/

.vote-form {
  flex-shrink: 0;
}

.vote-button {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.15rem;
  min-width: 3.1rem;
  padding: 0.5rem 0.4rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: var(--text-muted);
  font: inherit;
  font-size: 0.78rem;
  font-weight: 600;
  cursor: pointer;
  line-height: 1;
}

.vote-button:hover {
  border-color: var(--accent);
  color: var(--accent);
}

.vote-button__count {
  font-size: 0.95rem;
  font-weight: 700;
}

.vote-button__arrow {
  font-size: 0.7rem;
}

.vote-button[aria-pressed="true"] {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-contrast);
}

a.vote-button {
  text-decoration: none;
}

/* Pagination -------------------------------------------------------------------------------*/

.pagination {
  display: flex;
  justify-content: space-between;
  margin-top: 1.75rem;
  font-size: 0.9rem;
}

.pagination a {
  text-decoration: none;
  padding: 0.5rem 0.9rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
}

.pagination a:hover {
  border-color: var(--accent);
  color: var(--accent);
}

.pagination__spacer {
  flex: 1;
}

/* Empty state --------------------------------------------------------------------------- */

.empty-state {
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius);
  padding: 2.5rem 1.5rem;
  text-align: center;
  color: var(--text-muted);
}

.empty-state p {
  margin: 0;
}

/* Closed note --------------------------------------------------------------------------- */

/* The plain, visible "showing the N most recently closed" line — see queries.ts's
   `listClosedTickets` header for why this is never a silent cap. */
.closed-note {
  margin: 0.9rem 0 0;
  color: var(--text-faint);
  font-size: 0.85rem;
}

/* Download ---------------------------------------------------------------------------------- */

/* The first screen has one job: tell someone who has never heard of this product what it is
   and give them the right installer, without scrolling. Everything below the hero (the full
   artifact table, the release notes) is for the smaller audience who needs a specific build.
   See DownloadPage.tsx. */
.download-hero {
  margin-bottom: 2.75rem;
}

.download-hero h1 {
  font-size: 1.9rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  margin: 0 0 0.75rem;
}

.download-hero__lead {
  /* Narrower than the surrounding --wide column: this is a paragraph of prose in a page
     that is otherwise a table, and prose past ~34rem is measurably harder to read. */
  max-width: 34rem;
  margin: 0 0 1.75rem;
  color: var(--text-muted);
  font-size: 1.02rem;
}

.download-hero__cta {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.7rem;
}

.button--large {
  padding: 0.8rem 1.6rem;
  font-size: 1rem;
}

.download-hero__note {
  margin: 0;
  color: var(--text-faint);
  font-size: 0.88rem;
}

.download-meta {
  margin: 0 0 1rem;
  color: var(--text-muted);
  font-size: 0.9rem;
}

/* The table can genuinely not fit a phone — six columns, one of them a base64 digest — so it
   scrolls inside its own box rather than widening the page body. A page that scrolls
   sideways is broken; a table that does is a table. */
.table-scroll {
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  margin-bottom: 2.5rem;
}

.download-table {
  border-collapse: collapse;
  width: 100%;
  font-size: 0.9rem;
}

.download-table th,
.download-table td {
  padding: 0.6rem 0.85rem;
  text-align: left;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}

.download-table thead th {
  background: var(--bg-subtle);
  color: var(--text-muted);
  font-size: 0.78rem;
  font-weight: 650;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.download-table tbody tr:last-child th,
.download-table tbody tr:last-child td {
  border-bottom: none;
}

.download-table tbody th {
  font-weight: 600;
}

/* The digest cell is the one column that WRAPS. A base64 SHA-512 is 88 characters and will
   never fit any viewport on one line, so left as nowrap it either clips at the table's edge
   (looking broken) or pushes the whole table into a long sideways scroll for the sake of one
   column. Wrapped, the full checksum is visible in two or three lines and every other column
   stays where a reader expects it. */
.download-table td.download-table__digest-cell {
  white-space: normal;
  max-width: 22rem;
}

/* Reference data, not prose — monospaced and dimmed so it doesn't compete with the row's
   actual content, and `user-select: all` so verifying a download is one click and a copy
   rather than a careful drag across 88 characters. */
.download-table__digest {
  display: inline-block;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.75rem;
  line-height: 1.4;
  color: var(--text-faint);
  overflow-wrap: anywhere;
  user-select: all;
}

/* The same cell when the manifest carried no usable digest. Italic rather than monospaced,
   and deliberately NOT `user-select: all` — there is nothing here worth copying, and making
   the word "unavailable" one-click selectable would invite pasting it somewhere that expects
   a checksum. */
.download-table__digest-missing {
  font-size: 0.75rem;
  font-style: italic;
  color: var(--text-faint);
}

/* Release notes. The elements inside are emitted by DownloadPage's ReleaseNotes from the
   manifest's markdown source — block shapes only, with every piece of the author's text
   escaped as a JSX child (see that component for why that specific line is where the safety
   lives). Styled as a quiet panel rather than as page prose so it reads as "what changed in
   this release" and not as more of the page's own copy. */
.release-notes {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-subtle);
  padding: 1.1rem 1.25rem;
  color: var(--text);
  font-size: 0.94rem;
  overflow-wrap: anywhere;
}

.release-notes > :first-child {
  margin-top: 0;
}

.release-notes > :last-child {
  margin-bottom: 0;
}

.release-notes__heading {
  font-size: 0.95rem;
  font-weight: 650;
  margin: 1.35rem 0 0.5rem;
}

.release-notes__paragraph {
  margin: 0 0 0.75rem;
}

.release-notes__list {
  margin: 0 0 0.75rem;
  padding-left: 1.25rem;
}

.release-notes__list li {
  margin-bottom: 0.25rem;
}

/* Roadmap ---------------------------------------------------------------------------------- */

/* One lane per status (RoadmapPage.tsx). Stacked rather than laid out as parallel columns:
   a three-column kanban needs all three to be roughly the same height to read well, and
   these three are routinely 1, 3 and 12 cards — which as columns looks like two of them are
   broken. Stacked, an empty lane is just a short one. */
.roadmap-lane {
  margin-bottom: 2.5rem;
}

.roadmap-lane:last-child {
  margin-bottom: 0;
}

/* Reuses .section-heading's small-caps treatment; the flex is only here to sit the count
   beside the label without a gap the size of a space character. */
.roadmap-lane .section-heading {
  display: flex;
  align-items: center;
  gap: 0.55rem;
}

.roadmap-lane__count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.4rem;
  padding: 0 0.35rem;
  border-radius: 999px;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  color: var(--text-muted);
  font-size: 0.78rem;
  /* The heading is uppercased; a number should not inherit letter-spacing meant for
     small-caps text or the digits drift apart. */
  letter-spacing: 0;
}

.roadmap-lane__empty {
  margin: 0;
  color: var(--text-muted);
  font-size: 0.92rem;
}

/* Ticket detail ----------------------------------------------------------------------------*/

.ticket-detail__header {
  display: flex;
  gap: 1.1rem;
  align-items: flex-start;
  margin-bottom: 1.5rem;
}

.ticket-detail__title {
  font-size: 1.5rem;
  font-weight: 650;
  letter-spacing: -0.015em;
  margin: 0 0 0.5rem;
  line-height: 1.3;
}

.ticket-detail__meta {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  font-size: 0.85rem;
  color: var(--text-faint);
}

.ticket-detail__body {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  font-size: 1rem;
  color: var(--text);
  margin-bottom: 2.25rem;
}

.section-heading {
  font-size: 0.85rem;
  font-weight: 650;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-faint);
  margin: 0 0 0.9rem;
}

.comment-list {
  list-style: none;
  margin: 0 0 2rem;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.comment {
  padding: 0.9rem 1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
}

.comment__body {
  margin: 0 0 0.4rem;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  font-size: 0.94rem;
}

.comment__meta {
  font-size: 0.78rem;
  color: var(--text-faint);
}

/* Forms ------------------------------------------------------------------------------------*/

.form-field {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin-bottom: 1.1rem;
}

.form-field label {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text);
}

.form-field .field-hint {
  font-size: 0.8rem;
  color: var(--text-faint);
  font-weight: 400;
}

input[type="text"],
input[type="email"],
textarea,
select {
  font: inherit;
  font-size: 0.95rem;
  padding: 0.6rem 0.7rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: var(--text);
  width: 100%;
}

input[type="text"]:focus-visible,
input[type="email"]:focus-visible,
textarea:focus-visible,
select:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 1px;
}

textarea {
  resize: vertical;
  min-height: 6rem;
  font-family: inherit;
}

select {
  /* Unlike textarea/input, a <select> should size to its content, not stretch to fill the
     full ~42rem content column — a five-word status name doesn't need that much width, and
     a full-width dropdown reads oddly next to a same-width text field. */
  width: auto;
  max-width: 100%;
}

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  padding: 0.6rem 1.1rem;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  font: inherit;
  font-size: 0.92rem;
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
}

.button--primary {
  background: var(--accent);
  color: var(--accent-contrast);
}

.button--primary:hover {
  background: var(--accent-hover);
  color: var(--accent-contrast);
}

.button--quiet {
  background: transparent;
  color: var(--text);
  border-color: var(--border-strong);
}

.button--quiet:hover {
  border-color: var(--text-muted);
}

.button--danger {
  background: transparent;
  color: var(--danger);
  border-color: var(--border-strong);
}

.button--danger:hover {
  border-color: var(--danger);
}

.comment-form,
.auth-card,
.admin-item__actions,
.status-form {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.status-form {
  /* Sits between the ticket header and body (see TicketPage.tsx) — admin-only, so it needs
     its own bottom margin rather than relying on .ticket-detail__body's, which is absent
     entirely for a non-admin viewer. */
  align-items: flex-start;
  margin-bottom: 1.75rem;
}

.signin-prompt {
  padding: 1rem 1.1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-subtle);
  color: var(--text-muted);
  font-size: 0.92rem;
  margin-bottom: 2rem;
}

.signin-prompt a {
  font-weight: 600;
}

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

.auth-card {
  max-width: 26rem;
  margin: 2rem auto 0;
  padding: 1.75rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
}

.auth-card h1 {
  font-size: 1.25rem;
  margin: 0 0 0.4rem;
}

.auth-card p {
  color: var(--text-muted);
  font-size: 0.92rem;
  margin: 0 0 0.5rem;
}

.auth-confirmation {
  text-align: center;
}

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

.admin-item {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.25rem;
  margin-bottom: 1.25rem;
  background: var(--surface);
}

.admin-item__meta {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-size: 0.8rem;
  color: var(--text-faint);
  margin-bottom: 0.75rem;
}

.kind-badge {
  display: inline-flex;
  padding: 0.15rem 0.5rem;
  border-radius: 999px;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  font-size: 0.74rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--text-muted);
}

.admin-item__actions {
  flex-direction: row;
  flex-wrap: wrap;
  margin-top: 1rem;
}

/* Direct child only — `.admin-item__button-row` below holds two more `<form>`s (Reject,
   Spam) that must stay their own content width, not get stretched full-width by this rule
   too if it matched every descendant form. */
.admin-item__actions > form {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  flex: 1 1 100%;
}

.admin-item__button-row {
  display: flex;
  gap: 0.6rem;
  flex-wrap: wrap;
}

.admin-item__button-row form {
  flex: 0 0 auto;
}

.admin-empty {
  color: var(--text-muted);
}

/* 404 --------------------------------------------------------------------------------------*/

.not-found {
  text-align: center;
  padding: 3rem 1rem;
}

.not-found h1 {
  font-size: 1.4rem;
  margin-bottom: 0.5rem;
}

.not-found p {
  color: var(--text-muted);
}

/* Responsive ---------------------------------------------------------------------------- */

@media (max-width: 30rem) {
  .site-header__inner {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.6rem;
  }

  .ticket-card {
    padding: 0.9rem;
  }

  .ticket-detail__title {
    font-size: 1.3rem;
  }
}
