/*
 * Shared theme for Attendify and Grouper: ONE file, byte-identical in both repos
 * (attendify/static/theme.css, grouper-git/src/theme.css). Edit it in one repo, copy it
 * to the other, and check with `cmp`. It holds the rules used by both apps (toolbar, icons,
 * row hover, plain icon button, ...), the Grouper rules and a separate Attendify section;
 * Attendify-only rules must use Attendify-only classes so they cannot change Grouper (and
 * vice versa).
 *
 * Custom classes on top of Bootstrap 5.3. Colours come only from var(--bs-*), so
 * data-bs-theme="dark" on <html> restyles everything.
 */

/* Top toolbar: logo, title, then the page actions */
.app-toolbar {
  position: sticky;
  top: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.75rem 1.5rem;
  background: var(--bs-body-bg);
  border-bottom: var(--bs-border-width) solid var(--bs-border-color);
}
.app-toolbar h1 {
  flex: 1;
  margin: 0;
  font-size: 1.25rem;
  font-weight: 600;
}

/* Toolbar logo that doubles as the trigger of the theme/language menu: looks like the bare icon */
.app-logo-button {
  display: block; /* like the former plain icon span: the icon sits in a block line box, same offset from the title */
  padding: 0;
  border: 0;
  background: none;
  color: var(--bs-primary);
  position: relative;
}
/* invisible enlarged hit area (tap target >= 40px), no layout shift */
.app-logo-button::before {
  content: '';
  position: absolute;
  inset: -10px;
}
.app-logo-button:focus-visible {
  outline: 2px solid var(--bs-primary);
  outline-offset: 2px;
  border-radius: var(--bs-border-radius);
}

/* Material Icons inside buttons and the toolbar */
.app-toolbar .material-icons,
.btn .material-icons {
  font-size: 1.25rem;
  vertical-align: middle;
}

/* Row hover (both apps): the whole row turns grey (Bootstrap paints row states with an inset shadow, so sticky cells follow); hover-capable devices only, so touch does not leave a grey row behind */
@media (hover: hover) {
  .table > tbody > tr:hover > * {
    --bs-table-bg-state: rgba(var(--bs-emphasis-color-rgb), 0.1);
  }
}

/* Plain icon button (both apps, e.g. delete in tables): no border, neutral colour, hover feedback */
.btn-icon-plain {
  border: 0;
  line-height: 1;
  text-decoration: none;
}
.btn-icon-plain:hover,
.btn-icon-plain:focus-visible {
  background: var(--bs-secondary-bg);
}
.btn-icon-plain:focus-visible {
  outline: 2px solid var(--bs-primary);
  outline-offset: 2px;
}

/* Collapsible card: native <details>; the <summary> is the card header */
.card-collapsible {
  display: block;
}
.card-collapsible > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  list-style: none;
  cursor: pointer;
}
.card-collapsible > summary::-webkit-details-marker {
  display: none;
}
.card-collapsible > summary .material-icons {
  transition: transform 0.2s;
}
.card-collapsible:not([open]) > summary {
  border-bottom: 0;
  border-radius: var(--bs-card-inner-border-radius);
}
.card-collapsible:not([open]) > summary .material-icons {
  transform: rotate(-90deg);
}

/* Settings card fields */
.settings {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 1.5rem;
}
.settings .form-control {
  width: 8rem;
}
.size-range {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.size-range .form-control {
  width: 6rem;
}

/* Table columns */
.cap-col {
  width: 8rem;
}
.action-col {
  width: 4rem;
}
input.pref {
  min-width: 9rem;
}

/* overflow-x forces overflow-y:auto; reserve room (= .suggestions max-height) so an open popup never scrolls inside */
.table-responsive:has(.suggestions:not([hidden])) {
  padding-bottom: 14rem;
}

/* Combobox suggestion popup (extends the .table-responsive scroll area rather than being clipped) */
.combobox {
  position: relative;
}
.suggestions {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 2;
  min-width: 100%;
  max-height: 14rem;
  margin: 0.125rem 0 0;
  padding: 0.5rem 0;
  overflow-y: auto;
  list-style: none;
  background: var(--bs-body-bg);
  color: var(--bs-body-color);
  border: var(--bs-border-width) solid var(--bs-border-color-translucent);
  border-radius: var(--bs-border-radius);
  box-shadow: var(--bs-box-shadow);
}
.suggestions[hidden] {
  display: none;
}
.suggestion {
  padding: 0.25rem 1rem;
  cursor: pointer;
  white-space: nowrap;
}
.suggestion:hover {
  background: var(--bs-tertiary-bg);
}
.suggestion.active {
  background: var(--bs-primary);
  color: var(--bs-white);
}

/* Results: group cards */
.group-card.is-drop-target {
  background: var(--bs-primary-bg-subtle);
}
.group-warnings {
  margin: 0;
  padding: 0.5rem 1rem;
  list-style: none;
  color: var(--bs-danger-text-emphasis);
  border-bottom: var(--bs-border-width) solid var(--bs-border-color);
}
.member[draggable='true'] {
  cursor: grab;
}

/* Upload dropzone */
.dropzone {
  padding: 2.5rem 1.5rem;
  border: var(--bs-border-width) dashed var(--bs-border-color);
  border-radius: var(--bs-border-radius-lg);
  background: var(--bs-tertiary-bg);
  text-align: center;
  transition:
    background-color 0.15s ease,
    border-color 0.15s ease;
}
.dropzone.dragover {
  background: var(--bs-primary-bg-subtle);
  border-color: var(--bs-primary);
}
.dropzone > .material-icons {
  font-size: 2.5rem;
  color: var(--bs-secondary-color);
}
.dropzone p {
  margin: 0.5rem 0;
}
.dropzone-feedback {
  color: var(--bs-primary-text-emphasis);
  font-weight: 500;
}
.dropzone-feedback:empty {
  display: none;
}

/* Responsive: everything below applies only under the lg breakpoint (desktop >= 992px is unchanged) */
@media (max-width: 991.98px) {
  .app-toolbar {
    flex-wrap: wrap;
    padding: 0.5rem 1rem;
  }
  .btn {
    min-height: 2.5rem;
    min-width: 2.5rem;
  }
  .settings .form-control,
  .size-range .form-control {
    width: 100%;
    min-width: 5rem;
  }
  .cap-col {
    width: 6rem;
  }
  .dropzone {
    padding: 1.5rem 1rem;
  }
  /* Rankings: the Name column stays visible while the priority columns scroll */
  .table-responsive td:first-child,
  .table-responsive th:first-child {
    position: sticky;
    left: 0;
    z-index: 1;
    min-width: 7rem;
    max-width: 9rem;
    overflow-wrap: normal;
    word-break: normal;
    /* opaque base so scrolled cells do not show through; Bootstrap's inset shadow still paints the stripe */
    background-color: var(--bs-body-bg);
  }
  /* priority inputs keep a usable width; the table scrolls instead of squeezing the Name column */
  .table-responsive .form-control {
    min-width: 8rem;
  }
  .suggestions {
    max-width: calc(100vw - 2rem);
  }
  .suggestion {
    padding: 0.625rem 1rem;
    white-space: normal;
  }
}

/* ==========================================================================
 * Attendify (not part of the shared Grouper rules above)
 * ========================================================================== */

/* Toolbar variants: wrapping action rows, long titles (class keeps Grouper's toolbar title unaffected) */
.app-toolbar .toolbar-title {
  min-width: 0;
  word-break: break-word;
}

/* Dashboard search field in the toolbar (Attendify only) */
.dashboard-search {
  max-width: 16rem;
}

/* Dashboard toolbar (Attendify only): the search sits at the true centre, whatever the widths of the left and right parts */
.dash-toolbar {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(max-content, 1fr);
}
.dash-toolbar-left,
.dash-toolbar-right {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.dash-toolbar-left {
  min-width: 0; /* long titles wrap in the left column */
}
.dash-toolbar-right {
  grid-column: 3;
  justify-content: flex-end;
}
.dash-toolbar .dashboard-search {
  width: 16rem;
}

/* Page body below the toolbar */
.app-content {
  padding: 1.5rem;
}

/* Avatar trigger of the theme/language menu (dashboard) and its initials fallback.
 * The initials span is toggled with the hidden attribute, so its display must not be set by a utility class. */
.avatar-trigger {
  padding: 0;
  border: 0;
  border-radius: 50%;
}
.avatar-initials {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.avatar-initials[hidden] {
  display: none;
}

/* Dashboard card buttons */
.card-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  padding: 0;
  border-radius: var(--bs-border-radius);
}
.card-btn .material-icons {
  font-size: 1.25rem;
}

/* Attendance table: sum header, row-sum cells and footer follow the theme */
.table-total,
.table-total > th,
.table-total > td {
  --bs-table-bg: var(--bs-secondary-bg);
  --bs-table-striped-bg: var(--bs-secondary-bg);
  --bs-table-color: var(--bs-body-color);
  background-color: var(--bs-secondary-bg);
  color: var(--bs-body-color);
}
.table-head,
.table-head > tr > th {
  --bs-table-bg: var(--bs-tertiary-bg);
  --bs-table-color: var(--bs-body-color);
  background-color: var(--bs-tertiary-bg);
  color: var(--bs-body-color);
}

/* Random pick highlight (set on the <tr>) */
tr.pick-highlight > td {
  --bs-table-bg: var(--bs-warning-bg-subtle);
  --bs-table-striped-bg: var(--bs-warning-bg-subtle);
  background-color: var(--bs-warning-bg-subtle);
  box-shadow: inset 0 0 0 9999px rgba(var(--bs-warning-rgb), 0.28);
}

/* Colour swatches: "no colour" and selection follow the theme */
.swatch-none {
  background: var(--bs-body-bg);
  outline: 2px solid var(--bs-border-color);
}
.color-swatch.selected {
  outline: 3px solid var(--bs-emphasis-color);
  box-shadow: 0 0 0 2px var(--bs-body-bg);
}

/* Drop zone, code box */
.drop-zone {
  background: var(--bs-tertiary-bg);
  border-style: dashed;
}
.code-box {
  background: var(--bs-tertiary-bg);
}

/* QR image stays on white for scannability */
.qr-img {
  background: #fff;
  padding: 12px;
}

/* Expired QR page: QR faded to grey, code struck through and inert (Attendify only) */
.qr-expired .qr-img {
  filter: grayscale(1);
  opacity: 0.12;
}
[data-bs-theme='dark'] .qr-expired .qr-img {
  filter: grayscale(1) invert(1);
}
.qr-expired .code-box a {
  color: var(--bs-secondary-color);
  text-decoration: line-through;
  cursor: default;
}

/* Inline add-row inputs in table footers */
tfoot input {
  min-width: 0;
}

/* Group notes: journal entries below the attendance table (header row toggles, body holds markdown or the editor) */
.att-note {
  border: 1px solid var(--bs-border-color);
  border-radius: var(--bs-border-radius-lg);
  margin-bottom: 0.625rem;
  overflow: hidden;
}
.att-note:last-child {
  margin-bottom: 0;
}
.att-note-hdr {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.875rem;
  background: var(--bs-tertiary-bg);
  cursor: pointer;
}
.att-note-toggle {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex: 1 1 auto;
  min-width: 0;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font-weight: 700;
  text-align: start;
}
.att-note-chevron {
  transition: transform 0.15s;
}
.att-note-chevron.att-open {
  transform: rotate(180deg);
}
.att-note-actions {
  display: flex;
  gap: 0.375rem;
  flex-shrink: 0;
}
.att-note-actions .btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.att-note-actions .btn .material-icons {
  font-size: 1.125rem;
}
.att-note-body {
  position: relative;
  padding: 0.875rem;
  border-top: 1px solid var(--bs-border-color);
}
.att-note-md {
  line-height: 1.6;
  overflow-wrap: anywhere;
}
.att-note-md > :last-child {
  margin-bottom: 0;
}
.att-note-md h1,
.att-note-md h2,
.att-note-md h3 {
  font-size: 1.15rem;
  font-weight: 700;
  margin: 0.8em 0 0.3em;
}
.att-note-md pre {
  white-space: pre-wrap;
}
.att-note-md img {
  max-width: 100%;
}
.att-note-md code {
  background: var(--bs-tertiary-bg);
  padding: 0.0625rem 0.25rem;
  border-radius: var(--bs-border-radius-sm);
}
.att-note-ta {
  resize: vertical;
}
/* @-mentions: the menu (a .suggestions popup) sits under the caret line; the open note lets it overflow */
.att-note:has(.att-mention-menu:not([hidden])) {
  overflow: visible;
}
.att-note:has(.att-mention-menu:not([hidden])) .att-note-hdr {
  border-radius: var(--bs-border-radius-lg) var(--bs-border-radius-lg) 0 0;
}
.att-mention-menu {
  min-width: 12rem;
  max-width: 100%;
}
.att-mention-menu .suggestion {
  overflow: hidden;
  text-overflow: ellipsis;
}
.att-mention-matnr {
  color: var(--bs-secondary-color);
  font-size: 0.875em;
}
.suggestion.active .att-mention-matnr {
  color: inherit;
  opacity: 0.8;
}
.att-mention {
  padding: 0 0.25rem;
  border-radius: var(--bs-border-radius-sm);
  background: var(--bs-primary-bg-subtle);
  color: var(--bs-primary-text-emphasis);
  cursor: default;
}
.table > tbody > tr.att-row-hl > * {
  --bs-table-bg-state: rgba(var(--bs-emphasis-color-rgb), 0.1);
}
.att-save-state {
  display: inline-flex;
  align-items: center;
  color: var(--bs-secondary-color);
}
.att-save-state .material-icons {
  font-size: 1rem;
  line-height: 1;
}
.att-si-unsaved {
  animation: att-si-pulse 1.4s ease-in-out infinite;
}
.att-si-saving {
  animation: att-si-spin 1s linear infinite;
}
.att-si-saved {
  color: var(--bs-success);
  animation: att-si-pop 0.25s ease-out;
}
.att-si-error {
  color: var(--bs-danger);
  animation: att-si-pop 0.25s ease-out;
}
@keyframes att-si-pop {
  from {
    transform: scale(0.4);
    opacity: 0;
  }
  to {
    transform: scale(1);
    opacity: 1;
  }
}
@keyframes att-si-pulse {
  0%,
  100% {
    opacity: 0.35;
  }
  50% {
    opacity: 1;
  }
}
@keyframes att-si-spin {
  to {
    transform: rotate(360deg);
  }
}

/* Mobile (below lg): desktop >= 992px is unchanged */
@media (max-width: 991.98px) {
  /* long titles wrap onto their own row instead of being squeezed by the action buttons */
  .app-toolbar .toolbar-title {
    flex: 1 1 10rem;
  }
  /* dashboard toolbar: back to the wrapping flex row, the wrappers dissolve */
  .dash-toolbar {
    display: flex;
  }
  .dash-toolbar-left,
  .dash-toolbar-right {
    display: contents;
  }
  .dash-toolbar .dashboard-search {
    width: auto;
  }
  /* dashboard search takes its own full row */
  .dashboard-search {
    flex: 1 1 100%;
    max-width: none;
    order: 1;
  }
  /* colour swatches are tap targets */
  .color-swatch,
  .opt-color-btn,
  .opt-swatch {
    min-width: 2.5rem;
    min-height: 2.5rem;
  }
  /* Attendance table: the last-name column (2nd, after the status icon) stays visible while the dates scroll */
  .table-responsive .table-attendance th:first-child,
  .table-responsive .table-attendance td:first-child {
    position: static;
    min-width: 0;
    max-width: none;
    background-color: var(--bs-table-bg);
  }
  .table-responsive .table-attendance th:nth-child(2),
  .table-responsive .table-attendance td:nth-child(2) {
    position: sticky;
    left: 0;
    z-index: 1;
    min-width: 7rem;
    max-width: 9rem;
    overflow-wrap: normal;
    word-break: normal;
    background-color: var(--bs-table-bg);
  }
  /* Virtual group table has no status column: the last name is the 1st column (Attendify only) */
  .table-responsive .att-vgroup-table th:first-child,
  .table-responsive .att-vgroup-table td:first-child {
    position: sticky;
    left: 0;
    z-index: 1;
    min-width: 7rem;
    max-width: 9rem;
    overflow-wrap: normal;
    word-break: normal;
    background-color: var(--bs-table-bg);
  }
  .table-responsive .att-vgroup-table th:nth-child(2),
  .table-responsive .att-vgroup-table td:nth-child(2) {
    position: static;
    min-width: 0;
    max-width: none;
  }
  .table-attendance input[type='checkbox'] {
    width: 1.5rem;
    height: 1.5rem;
  }
  /* Group notes: less padding; the action buttons wrap below the date when the row is too narrow */
  .att-notes .card-body {
    padding: 0.5rem;
  }
  .att-note-hdr {
    flex-wrap: wrap;
    padding: 0.375rem 0.5rem;
  }
  .att-note-actions {
    margin-left: auto;
  }
  .att-note-body {
    padding: 0.5rem;
  }
}

/* Icon sizes (Attendify only; the material-icons default is 24px) */
.material-icons.icon-sm {
  font-size: 1rem;
}
.material-icons.icon-md {
  font-size: 1.1rem;
}
.material-icons.icon-lg {
  font-size: 2.5rem;
}
.material-icons.icon-xl {
  font-size: 3rem;
}

/* Colour swatch buttons (group colour picker, upload preview, testat option colour) */
.swatch {
  width: 1.5rem;
  height: 1.5rem;
  flex-shrink: 0;
}
.swatch-xs {
  width: 1.25rem;
  height: 1.25rem;
}

/* Scrollable collaborator list */
.collab-list {
  max-height: 320px;
  overflow-y: auto;
}

/* Narrow centred page container */
.page-narrow {
  max-width: 720px;
}

/* One segment of the manual code entry (welcome page) */
.code-seg {
  width: 4.5rem;
  font-size: 1.4rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

/* Avatar sizes (macro `avatar`: image and initials fallback) */
.avatar-sm,
.avatar-md {
  border-radius: 50%;
  object-fit: cover;
  flex-shrink: 0;
}
.avatar-sm {
  width: 1.5rem;
  height: 1.5rem;
  font-size: 0.65rem;
}
.avatar-md {
  width: 2rem;
  height: 2rem;
  font-size: 0.75rem;
}

/* Dashboard card of a group shared with the user */
.card-shared {
  background: rgba(var(--bs-info-rgb), 0.05);
}

/* Attestation editor (group / virtual group settings): a compact column, so option rows stay short */
.testat-editor {
  max-width: 36rem;
}
/* Testat option rows (group / virtual group settings): the label input may shrink; the end slot (code pill or remove
   button) has one width so all labels align */
.testat-opt-row .form-control {
  min-width: 0;
}
.testat-opt-end {
  flex: 0 0 3.25rem;
  display: flex;
  justify-content: center;
}
/* HIS code pill of a fixed testat option; an inline style sets the option colour and its contrast text colour */
.testat-code-pill {
  min-width: 2.75rem;
  background: var(--bs-secondary-bg);
  color: var(--bs-body-color);
}
/* Threshold input of the automatic attestation */
.testat-threshold {
  width: 6.5rem;
}
