/* ============================================================================
 * Application-specific components.
 *
 * Loaded after the ported shell so it can build on the UKLSH tokens.
 * Only classes without an upstream equivalent live here: the task list header,
 * the table/swimlane switch, swimlanes, the task detail view and status badges.
 *
 * Status colours are defined once as tokens so badges, swimlane headers and
 * future filters stay consistent (ADR-016).
 * ==========================================================================*/

:root {
  /* Six task statuses (ADR-004), each as a readable text/border pair and a
     subtle surface. Chosen to sit inside the UKLSH palette and to meet
     WCAG AA contrast against --bg in light mode. */
  --status-backlog-ink:        #4a4d33;
  --status-backlog-bg:         #e6e3d3;

  --status-todo-ink:           #20384a;
  --status-todo-bg:            #d6e0e6;

  --status-in-progress-ink:    #57592e;
  --status-in-progress-bg:     #e4e4cd;

  --status-feedback-ink:       #6b4a32;
  --status-feedback-bg:        #ede0d6;

  --status-done-ink:           #3d5c3a;
  --status-done-bg:            #dbe4d5;

  --status-obsolete-ink:       #5c5650;
  --status-obsolete-bg:        #e2ded8;
}

[data-theme="dark"] {
  /* Dark equivalents: lighter ink on a darker surface, still AA on --bg. */
  --status-backlog-ink:        #d3d0b4;
  --status-backlog-bg:         #2a2d20;

  --status-todo-ink:           #b8d0dd;
  --status-todo-bg:            #1c2c35;

  --status-in-progress-ink:    #c1c382;
  --status-in-progress-bg:     #2b2d1c;

  --status-feedback-ink:       #dcc0a8;
  --status-feedback-bg:        #33261c;

  --status-done-ink:           #b3cfa8;
  --status-done-bg:            #202b1e;

  --status-obsolete-ink:       #bcb6ad;
  --status-obsolete-bg:        #26241f;
}

/* ---------- page header ---------- */
/* ADR-005 views use the full page width: six lanes and a wide table need it. */
/* ADR-005: the task views use the full available width — six swimlanes and a
   wide table do not fit a reading measure. The layout lifts the max-width on
   the main element when the page sets :full_width; this reduces its horizontal
   padding to a hairline gutter so the board really reaches the edges. */
.admin-main.is-full-width {
  max-width: none;
  padding-inline: 0.75rem;
}

.tasks-header {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  align-items: baseline;
  justify-content: space-between;
  margin-block: 2rem 1.5rem;
}

.tasks-header-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  align-items: center;
}

.tasks-header h1 {
  font-family: var(--serif);
  font-weight: 500;
  font-size: clamp(1.5rem, 1.2rem + 1.2vw, 2rem);
  margin: 0;
}

.tasks-view-switch {
  display: inline-flex;
  gap: 0.25rem;
  border: 1px solid var(--rule);
  border-radius: 0.5rem;
  padding: 0.2rem;
  background: var(--bg-elev);
}

.tasks-view-switch a,
.tasks-view-switch .is-active {
  padding: 0.35rem 0.8rem;
  border-radius: 0.35rem;
  font-size: 0.9rem;
  text-decoration: none;
  color: var(--ink-soft);
}

.tasks-view-switch .is-active {
  background: var(--bg);
  color: var(--ink);
  font-weight: 500;
}

/* The row of links above a page's content. A flex row rather than a plain
   paragraph, so the back link and any sibling page links share it with a gap. */
.tasks-back {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 1.25rem;
  align-items: baseline;
  margin-block: 1.5rem 0;
}

.tasks-back a {
  color: var(--ink-soft);
  text-decoration: none;
}

/* The shell underlines links on hover only (ADR-016); these are links, so they
   follow it. The offset keeps the line clear of descenders. */
.tasks-back a:hover,
.tasks-back a:focus-visible {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

.tasks-empty {
  color: var(--ink-mute);
  font-style: italic;
}

.tasks-description-cell {
  max-width: 24rem;
  color: var(--ink-soft);
}

/* ---------- status badges ---------- */
.status-badge {
  display: inline-block;
  padding: 0.15rem 0.55rem;
  border-radius: 999px;
  font-size: 0.8rem;
  font-weight: 500;
  white-space: nowrap;
  background: var(--status-backlog-bg);
  color: var(--status-backlog-ink);
}

.status-backlog         { background: var(--status-backlog-bg);         color: var(--status-backlog-ink); }
.status-todo            { background: var(--status-todo-bg);            color: var(--status-todo-ink); }
.status-in-progress     { background: var(--status-in-progress-bg);     color: var(--status-in-progress-ink); }
.status-feedback-needed { background: var(--status-feedback-bg);        color: var(--status-feedback-ink); }
.status-done            { background: var(--status-done-bg);            color: var(--status-done-ink); }
.status-obsolete        { background: var(--status-obsolete-bg);        color: var(--status-obsolete-ink); }

/* ---------- overdue ---------- */
.is-overdue {
  color: var(--umber);
  font-weight: 500;
}

[data-theme="dark"] .is-overdue {
  color: var(--umber-light);
}

/* ---------- swimlanes ---------- */
.swimlanes {
  display: grid;
  gap: 1rem;
  grid-template-columns: 1fr;
  margin-bottom: 3rem;
}

@media (min-width: 900px) {
  .swimlanes {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

@media (min-width: 1400px) {
  .swimlanes {
    grid-template-columns: repeat(6, minmax(0, 1fr));
  }
}

.swimlane {
  background: var(--bg-elev);
  border: 1px solid var(--rule-soft);
  border-radius: 0.6rem;
  padding: 0.85rem;
  min-width: 0;
}

/* Each lane takes the background of its status badge in the table, so the two
   views read the same way. Keyed on the lane's own status, which the same
   data-status attribute the drag and drop uses already carries. */
.swimlane[data-status="backlog"]         { background: var(--status-backlog-bg); }
.swimlane[data-status="todo"]            { background: var(--status-todo-bg); }
.swimlane[data-status="in_progress"]     { background: var(--status-in-progress-bg); }
.swimlane[data-status="feedback_needed"] { background: var(--status-feedback-bg); }
.swimlane[data-status="done"]            { background: var(--status-done-bg); }
.swimlane[data-status="obsolete"]        { background: var(--status-obsolete-bg); }

/* The lane title picks up the matching ink, so the header reads as a pair with
   its badge rather than as a separate style. */
.swimlane[data-status="backlog"]         .swimlane-title { color: var(--status-backlog-ink); }
.swimlane[data-status="todo"]            .swimlane-title { color: var(--status-todo-ink); }
.swimlane[data-status="in_progress"]     .swimlane-title { color: var(--status-in-progress-ink); }
.swimlane[data-status="feedback_needed"] .swimlane-title { color: var(--status-feedback-ink); }
.swimlane[data-status="done"]            .swimlane-title { color: var(--status-done-ink); }
.swimlane[data-status="obsolete"]        .swimlane-title { color: var(--status-obsolete-ink); }

/* Cards keep the page surface so they stay legible on the tinted lane. */
.swimlane .swimlane-card-link {
  background: var(--bg);
}

/* Outline for the lane that the ghost is being filled in, so the open lane is
   distinguishable from its neighbours of the same status colour. */
.swimlane:has(.swimlane-form) {
  outline: 2px solid var(--moss-bright);
  outline-offset: 1px;
}

.swimlane-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin: 0 0 0.75rem;
  font-family: var(--sans);
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.swimlane-count {
  font-weight: 400;
  color: var(--ink-mute);
}

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

.swimlane-empty {
  color: var(--ink-faint);
  font-size: 0.85rem;
  font-style: italic;
}

.swimlane-card-link {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  padding: 0.6rem 0.7rem;
  border-radius: 0.45rem;
  background: var(--bg);
  border: 1px solid var(--rule-soft);
  text-decoration: none;
  color: var(--ink);
}

.swimlane-card-link:hover {
  border-color: var(--moss);
}

/* Drag and drop is an enhancement; the move control below is the real path. */
.swimlane-card {
  cursor: grab;
}

.swimlane-card.is-dragging {
  opacity: 0.5;
  cursor: grabbing;
}

.swimlane.is-drop-target {
  border-color: var(--moss);
  box-shadow: inset 0 0 0 1px var(--moss);
}

.swimlane-move {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  align-items: center;
  margin-top: 0.4rem;
}

/* The lane already shows the status, so the move control stays in the
   accessibility tree (ADR-010) without taking visual space. */
.swimlane-move.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Focus must be visible when the hidden control is reached by keyboard, so it
   is revealed rather than left as an invisible focus stop. */
.swimlane-move.visually-hidden:focus-within {
  position: static;
  width: auto;
  height: auto;
  margin: 0.4rem 0 0;
  padding: 0.35rem;
  overflow: visible;
  clip: auto;
  white-space: normal;
  border: 1px solid var(--rule);
  border-radius: 0.4rem;
  background: var(--bg-elev);
}

/* ---------- ghost card and inline form ---------- */
.swimlane-ghost-slot {
  list-style: none;
}

/* Looks like an empty task, so the affordance sits where the card will appear. */
.swimlane-ghost {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.6rem 0.7rem;
  border-radius: 0.45rem;
  border: 1px dashed var(--rule);
  color: var(--ink-mute);
  font-size: 0.85rem;
  text-decoration: none;
  background: none;
}

.swimlane-ghost:hover {
  border-color: var(--moss);
  color: var(--moss-bright);
}

.swimlane-ghost-plus {
  font-size: 1rem;
  line-height: 1;
}

.swimlane-form {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  padding: 0.6rem 0.7rem;
  border-radius: 0.45rem;
  border: 1px solid var(--moss);
  background: var(--bg);
}

.swimlane-form-field {
  display: flex;
  flex-direction: column;
}

.swimlane-form-input {
  width: 100%;
  padding: 0.3rem 0.45rem;
  font: inherit;
  font-size: 0.85rem;
  color: var(--ink);
  background: var(--bg-elev);
  border: 1px solid var(--rule);
  border-radius: 0.35rem;
}

.swimlane-form-input:focus {
  outline: 2px solid var(--moss-bright);
  outline-offset: 1px;
}

.swimlane-form-error {
  margin: 0;
  font-size: 0.8rem;
  color: var(--umber);
}

[data-theme="dark"] .swimlane-form-error {
  color: var(--umber-light);
}

.swimlane-form-actions {
  display: flex;
  gap: 0.35rem;
  margin-top: 0.1rem;
}

.swimlane-new {
  margin: 0 0 0.6rem;
}

.swimlane-new-link {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.8rem;
  color: var(--ink-mute);
  text-decoration: none;
}

.swimlane-new-link:hover {
  color: var(--moss-bright);
}

.swimlane-move select {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 0.8rem;
  padding: 0.15rem 0.3rem;
}

.swimlane-card-title {
  font-size: 0.92rem;
  line-height: 1.35;
}

.swimlane-card-due,
.swimlane-card-assignee {
  font-size: 0.78rem;
  color: var(--ink-mute);
}

/* ---------- account menu ---------- */
.account-menu {
  position: relative;
}

.account-menu-list {
  position: absolute;
  right: 0;
  top: calc(100% + 0.4rem);
  z-index: 40;
  min-width: 12rem;
  margin: 0;
  padding: 0.35rem;
  list-style: none;
  background: var(--bg);
  border: 1px solid var(--rule);
  border-radius: 0.5rem;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
}

.account-menu-list a,
.account-menu-list button {
  display: block;
  width: 100%;
  padding: 0.45rem 0.6rem;
  border: 0;
  border-radius: 0.35rem;
  background: none;
  text-align: left;
  font: inherit;
  color: var(--ink);
  text-decoration: none;
  cursor: pointer;
}

.account-menu-list a:hover,
.account-menu-list button:hover {
  background: var(--bg-elev);
}

/* ---------- task detail ---------- */
.task-detail-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 1.5rem;
}

.task-detail-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-left: auto;
}

.task-detail-header h1 {
  font-family: var(--serif);
  font-weight: 500;
  font-size: clamp(1.5rem, 1.2rem + 1.2vw, 2.1rem);
  margin: 0;
}

.task-meta {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.35rem 1.25rem;
  margin: 0 0 2rem;
  max-width: 32rem;
}

.task-meta dt {
  color: var(--ink-mute);
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

.task-meta dd {
  margin: 0;
}

.task-description {
  margin-bottom: 3rem;
}

.task-description h2 {
  font-family: var(--sans);
  font-size: 0.85rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--ink-soft);
  margin-bottom: 0.5rem;
}

/* ---------- task panel (side overlay) ---------- */
/* ADR-018: task details and editing open here. The frame is always in the DOM
   and is the positioning context for its close button; it only becomes visible
   once Turbo has put content into it, so a page that never opens a task shows
   nothing. */
.task-panel {
  display: none;
  position: relative;
}

.task-panel.is-open {
  display: block;
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 60;
  width: min(42rem, 100vw);
  overflow-y: auto;
  padding: 2rem var(--pad-x) 4rem;
  background: var(--bg);
  border-left: 1px solid var(--rule);
  box-shadow: -12px 0 40px rgba(0, 0, 0, 0.18);
}

/* Dim the board behind the panel, but only while it is open. */
.has-task-panel::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 55;
  background: rgba(20, 24, 15, 0.28);
}

.task-panel-header {
  margin-bottom: 1.5rem;
}

.task-panel-header h1,
.task-panel .task-detail-header h1 {
  font-family: var(--serif);
  font-weight: 500;
  font-size: clamp(1.3rem, 1.1rem + 1vw, 1.8rem);
  margin: 0;
  /* Room for the close button in the top right. */
  padding-right: 2.75rem;
}

.task-panel .task-detail-header {
  align-items: flex-start;
}

.task-panel .task-meta {
  margin-bottom: 1.5rem;
}

.task-panel-close {
  position: absolute;
  top: 0.9rem;
  right: 0.9rem;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* At least 24x24 for a comfortable pointer target (WCAG 2.2 target size). */
  width: 2.25rem;
  height: 2.25rem;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--bg-elev);
  color: var(--ink);
  font-size: 1.35rem;
  line-height: 1;
  text-decoration: none;
}

.task-panel-close:hover {
  background: var(--bg-warm);
  border-color: var(--ink-mute);
  color: var(--ink);
}

.task-panel-close:focus-visible {
  outline: 2px solid var(--moss-bright);
  outline-offset: 2px;
}

/* The card or row whose task is open in the panel (ADR-018). Marked with a
   visible outline and a left bar, so it is perceivable without relying on
   colour alone. */
.swimlane-card.is-panel-source {
  outline: 2px solid var(--moss-bright);
  outline-offset: 2px;
  border-radius: 0.45rem;
}

tr.is-panel-source > * {
  box-shadow: inset 0 2px 0 var(--moss-bright), inset 0 -2px 0 var(--moss-bright);
}

tr.is-panel-source > *:first-child {
  box-shadow: inset 2px 0 0 var(--moss-bright), inset 0 2px 0 var(--moss-bright), inset 0 -2px 0 var(--moss-bright);
}

tr.is-panel-source > *:last-child {
  box-shadow: inset -2px 0 0 var(--moss-bright), inset 0 2px 0 var(--moss-bright), inset 0 -2px 0 var(--moss-bright);
}

.task-panel .task-meta {
  margin-bottom: 1.5rem;
}

/* ---------- comments ---------- */.task-comments {
  margin-bottom: 3rem;
}

.task-comments h2 {
  font-family: var(--sans);
  font-size: 0.85rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--ink-soft);
  margin-bottom: 0.5rem;
}

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

.comment {
  background: var(--bg-elev);
  border: 1px solid var(--rule-soft);
  border-radius: 0.5rem;
  padding: 0.75rem 0.9rem;
}

.comment-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  align-items: baseline;
  margin: 0 0 0.4rem;
  font-size: 0.82rem;
  color: var(--ink-mute);
}

.comment-meta strong {
  color: var(--ink);
  font-weight: 500;
}

.comment-actions {
  display: flex;
  gap: 0.5rem;
  margin-top: 0.5rem;
}

.comment-form-heading {
  font-family: var(--sans);
  font-size: 0.85rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--ink-soft);
  margin: 2rem 0 0.5rem;
}

/* ---------- notification preferences ---------- */
.preference-fieldset {
  border: 1px solid var(--rule-soft);
  border-radius: 0.5rem;
  padding: 1rem 1.1rem;
  margin: 0 0 1.25rem;
}

.preference-fieldset legend {
  font-family: var(--sans);
  font-size: 0.85rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--ink-soft);
  padding-inline: 0.35rem;
}

/* A checkbox and its label on one line. Scoped to `.admin-form` so it beats the
   ported `.admin-form .field` rule, which sets flex-direction: column and would
   otherwise stack the box above its label. */
.admin-form .field.field-checkbox {
  display: flex;
  flex-direction: row;
  align-items: flex-start;
  gap: 0.6rem;
}

.field-checkbox input[type="checkbox"] {
  /* Comfortably clickable, and aligned with the first text line. */
  width: 1.15rem;
  height: 1.15rem;
  margin-top: 0.15rem;
  flex: 0 0 auto;
}

/* Scoped like the rule above, so the label of a checkbox is not styled as a
   field label: those are small uppercase captions, and a preference is a
   sentence to read. */
.admin-form .field.field-checkbox label {
  margin-bottom: 0;
  font-size: 0.95rem;
  letter-spacing: normal;
  text-transform: none;
  color: var(--ink);
}

/* ---------- tiptap editor in a form field ---------- */
.tiptap-editor {
  border: 1px solid var(--rule);
  border-radius: 0.45rem;
  background: var(--bg);
  overflow: hidden;
}

.tiptap-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.15rem;
  padding: 0.35rem;
  background: var(--bg-elev);
  border-bottom: 1px solid var(--rule-soft);
}

.tiptap-btn {
  min-width: 2rem;
  padding: 0.2rem 0.45rem;
  border: 1px solid transparent;
  border-radius: 0.3rem;
  background: none;
  color: var(--ink);
  font: inherit;
  font-size: 0.9rem;
  cursor: pointer;
}

.tiptap-btn:hover {
  background: var(--bg);
  border-color: var(--rule);
}

.tiptap-mount {
  padding: 0.6rem 0.75rem;
  min-height: 8rem;
}

.tiptap-mount .ProseMirror {
  outline: none;
  min-height: 7rem;
}

.tiptap-mount .ProseMirror p {
  margin: 0 0 0.75rem;
}

.tiptap-mount .ProseMirror p:last-child {
  margin-bottom: 0;
}

/* ---------- wide auth-shaped pages (legal, preferences) ---------- */
.auth-card-wide {
  max-width: 44rem;
}
/* ---------- inline editors (ADR-019) ---------- */
/* A cell that edits in place. The editor is a `details` element, so the open
   and closed states and the keyboard interaction come from the browser; this
   only styles them. */
.inline-edit {
  position: relative;
  display: inline-block;
}

.inline-edit-trigger {
  cursor: pointer;
  list-style: none;
  border-radius: 0.35rem;
}

.inline-edit-trigger::-webkit-details-marker {
  display: none;
}

/* A visible focus ring, so the keyboard path through the table is followable. */
.inline-edit-trigger:focus-visible,
.inline-edit[open] > .inline-edit-trigger {
  outline: 2px solid var(--moss-bright);
  outline-offset: 2px;
}

.inline-edit-trigger:hover {
  background: var(--bg-warm);
}

.inline-edit-menu {
  position: absolute;
  top: calc(100% + 0.35rem);
  left: 0;
  z-index: 40;
  min-width: 14rem;
  padding: 0.6rem;
  background: var(--bg);
  border: 1px solid var(--rule);
  border-radius: 0.5rem;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.18);
}

/* In the last columns the menu would run off the page, so it opens inwards. */
.tasks-description-cell ~ td .inline-edit-menu,
td:last-child .inline-edit-menu {
  left: auto;
  right: 0;
}

.inline-edit-fieldset {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  margin: 0;
  padding: 0;
  border: 0;
}

.inline-edit-option {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.25rem 0.35rem;
  border-radius: 0.35rem;
  cursor: pointer;
}

.inline-edit-option:hover {
  background: var(--bg-warm);
}

.inline-edit-option:has(input:checked) {
  font-weight: 600;
}

/* The badge fills the option, so the whole row is a target. */
.inline-edit-option-body {
  flex: 1;
}

.inline-edit-actions {
  display: flex;
  gap: 0.4rem;
  margin-top: 0.6rem;
}

.inline-edit-compact .inline-edit-menu {
  min-width: 13rem;
}

.inline-edit-form .form-label {
  margin-bottom: 0.25rem;
  font-size: 0.85rem;
}

/* ---------- task rows (ADR-019) ---------- */
/* Hover styling applies only when JavaScript is present: the row is clickable
   then, and showing it as clickable without JavaScript would lie. The class is
   added by the controller, so no-JavaScript browsers never get it. */
.task-row.is-row-interactive {
  cursor: pointer;
}

.task-row.is-row-interactive:hover {
  background: var(--bg-warm);
}

/* The row must not look clickable while one of its editors is open. */
.task-row.is-editing-title {
  background: var(--bg-warm);
}

.task-title-cell {
  position: relative;
}

/* The title editor is a popover, exactly like the other inline editors, so
   opening it covers the table instead of making the row taller and shifting
   every row below it. */
.task-title-editor {
  min-width: min(28rem, 80vw);
}

.task-title-editor .form-control {
  width: 100%;
}

/* While the editor is open the link is not the target, so it is dimmed to make
   it clear that the field below it holds the title. */
.task-row.is-editing-title .task-title-link {
  color: var(--ink-mute);
}

/* ---------- flash region ---------- */
/* Flash messages are kept in one replaceable container, so a response that does
   not re-render the page can still report its outcome (ADR-010). */
.flash-region {
  display: contents;
}

.flash-region:empty {
  display: none;
}

/* ---------- page description ---------- */
/* A one-line description under a page heading, for pages inside the shell.
   Deliberately NOT the `lede` class: that is the hero intro of a standalone
   auth card, and under a regular heading it renders close to the heading's own
   size. It sits outside `.tasks-header`, which is the flex row pairing a
   heading with its right-aligned actions. */
.page-description {
  margin: -0.75rem 0 1.5rem;
  max-width: 60ch;
}

/* Multiple controls in one table cell, so two buttons sit side by side rather
   than stacked by the form wrapper each button_to generates. */
.invitation-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  align-items: center;
  /* The buttons keep their natural width instead of being squeezed by the
     table's auto layout, which is what made them wrap while space remained in
     the columns beside them. */
  width: max-content;
  max-width: 100%;
}

.invitation-actions form {
  display: inline-flex;
  margin: 0;
}

.invitation-actions .btn {
  white-space: nowrap;
}

/* The actions column takes the width its buttons need, and the flexible text
   column gives up the space instead. Scoped above the breakpoint: in the list
   form the cell is a block, where width: 1% would collapse it to almost nothing. */
@media (min-width: 721px) {
  .invitations-table td[data-label="Aktionen"],
  .invitations-table thead th:last-child {
    width: 1%;
    white-space: nowrap;
  }
}

/* ---------- responsive tables (ADR-022) ---------- */
/* Below this width a table is displayed as a list rather than as a table that
   scrolls sideways. Horizontal scrolling hides columns and puts the row's
   controls off screen, which is the worst place for them on a phone.

   Every cell carries its column heading in `data-label`, so it can label itself
   once the header row is hidden. This applies to every table in the application,
   not only the ones that exist today. */
@media (max-width: 720px) {
  .table-responsive {
    overflow-x: visible;
  }

  .table-responsive table,
  .table-responsive thead,
  .table-responsive tbody,
  .table-responsive tr,
  .table-responsive th,
  .table-responsive td {
    display: block;
    width: auto;
  }

  /* The header row is replaced by the per-cell labels. */
  .table-responsive thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  /* One card per record. The card uses the same surface as the page rather than
     a second tint, because a tinted card on a tinted lane produced a rippling
     edge that read as a rendering artefact. */
  .table-responsive tbody tr {
    margin-bottom: 0.6rem;
    padding: 0.6rem;
    border: 1px solid var(--rule);
    border-radius: 0.5rem;
    background: var(--bg);
  }

  /* Padding inside the card matches the gap around it, so the cards read as a
     stack rather than as boxes with uneven breathing room. Every card keeps the
     same gap, including the last, so the padding inside matches the gap outside
     for every card. */
  .table-responsive tbody td {
    padding-inline: 0;
  }

  /* The record's own name reads as the card's heading, so it is not labelled. */
  .table-responsive th[scope="row"] {
    margin-bottom: 0.5rem;
    padding: 0 0 0.5rem;
    border-bottom: 1px solid var(--rule-soft);
    font-size: 1.05rem;
  }

  .table-responsive th[scope="row"]::before {
    content: none;
  }

  .table-responsive td {
    display: grid;
    grid-template-columns: 9rem minmax(0, 1fr);
    gap: 0.5rem;
    align-items: baseline;
    padding: 0.3rem 0;
    border: 0;
  }

  /* The label, from the column heading the cell carries. */
  .table-responsive td[data-label]::before {
    content: attr(data-label);
    font-size: 0.72rem;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--ink-mute);
  }

  /* A cell with no label spans the card. */
  .table-responsive td:not([data-label]),
  .table-responsive td[colspan] {
    display: block;
  }

  /* Editors stack under their label instead of sharing a line with it, so the
     popover has the card's width to open into. */
  .table-responsive td > * {
    min-width: 0;
  }

  /* The actions sit on their own line at the bottom of the card, as plain
     buttons rather than as a labelled "Aktionen" field: the label would take a
     column of every card to say the obvious. */
  .table-responsive td[data-label="Aktionen"] {
    display: block;
    margin-top: 0.5rem;
    padding-top: 0.5rem;
    border-top: 1px solid var(--rule-soft);
  }

  .table-responsive td[data-label="Aktionen"]::before {
    content: none;
  }

  .table-responsive .invitation-actions {
    justify-content: flex-start;
    width: auto;
  }
}

/* On the narrowest screens the label sits above its value. */
@media (max-width: 420px) {
  .table-responsive td {
    grid-template-columns: minmax(0, 1fr);
    gap: 0.15rem;
  }
}

/* ---------- flash band (ADR-016 divergence) ---------- */
/* The ported .admin-flash is a rounded, fully bordered box. In this application
   it is a band across the page under the header, so it carries no radius and
   only a bottom border, which separates it from the content without drawing a
   box around a page-wide strip.

   The band itself stays full width, but its text is indented to clear the header
   logo. The logo lives in the header's centred container, so its left edge moves
   with the viewport; a fixed indent cannot track it, which is what let the mark
   sit over the text on wide screens. The text is therefore indented by the
   container's own offset plus the mark's width and gap. */
.admin-flash {
  border: 0;
  border-bottom: 1px solid var(--rule);
  border-radius: 0;
  margin-bottom: 0;
  padding-right: var(--pad-x);
  /* The container offset, then the mark, then its gap. Both the offset and the
     gutter are clamped, so this tracks the logo at every width. */
  padding-left: calc(max(var(--pad-x), (100% - var(--container)) / 2 + var(--pad-x)) + 3.6rem);
}

/* Above 880px the mark is large at rest (ADR-016), so the band's text needs
   clearance for the larger mark, not the mobile one. */
@media (min-width: 880px) {
  .admin-flash {
    padding-left: calc(max(var(--pad-x), (100% - var(--container)) / 2 + var(--pad-x)) + 10.5rem);
  }
}

/* The band is full width, so the success and alert colours keep their tint but
   not their border colour, which only made sense on a box. */
.admin-flash-success {
  border-bottom-color: rgba(152, 149, 88, 0.4);
}

.admin-flash-alert {
  border-bottom-color: rgba(139, 96, 68, 0.4);
}

/* The flash band sits between the header and the content. When a message is
   actually shown, the band supplies its own height as the gap, so the content
   does not need to add its own on top of it. The frame element is always present
   in the markup (ADR-010), so this keys off the message inside it rather than off
   the frame, which would otherwise match on every page and take the content's
   top padding away whether or not anything is shown. */
.flash-region:has(.admin-flash) + .admin-main {
  padding-block-start: 0;
}
