/* Give Me Paw.
   The first section is the intake form, ported from the v2 form
   (givemepaw-frontend/public/customer-intake.html) so the kiosk looks identical
   across the migration. Class names, colours and spacing are kept as-is there
   to make future diffs against v2 obvious, which is why it hardcodes the purple
   rather than using the custom properties below.
   The staff pages start at "staff shell". */

:root {
  --purple: rgba(102, 87, 142, 1);
  --purple-dark: rgba(82, 67, 122, 1);
  --purple-faint: rgba(102, 87, 142, 0.08);
  --ink: #333;
  --ink-soft: #6b6b76;
  --line: #e4e4ec;
  --danger: #d32f2f;
  --ok: #2e7d32;
}

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Helvetica", "Arial", sans-serif;
  background: linear-gradient(135deg, #f0f2f5 0%, #e8eaf0 100%);
  padding: 20px;
  min-height: 100vh;
}

.container {
  max-width: 800px;
  margin: 0 auto;
  background: white;
  border-radius: 16px;
  box-shadow: 0 4px 20px rgba(102, 87, 142, 0.15);
  overflow: hidden;
}

/* ---------------------------------------------------------------- header */

.header {
  background: rgba(102, 87, 142, 1);
  color: white;
  padding: 25px 30px;
  display: flex;
  align-items: center;
  gap: 25px;
}

.header img {
  max-width: 80px;
  height: auto;
  flex-shrink: 0;
  /* Holding the logo reloads the kiosk (static/js/kiosk.js), so iPadOS must
     not answer the hold with its save-image menu or a text selection */
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}

.header-text {
  flex: 1;
}

.header h1 {
  font-size: 28px;
  margin-bottom: 6px;
}

.header p {
  font-size: 16px;
  opacity: 0.95;
  margin: 0;
}

@media (max-width: 640px) {
  .header {
    flex-direction: column;
    text-align: center;
    gap: 15px;
  }

  .header img {
    max-width: 150px;
  }
}

/* ----------------------------------------------------------- form layout */

.form-content {
  padding: 30px;
}

.section {
  margin-bottom: 35px;
}

.section-title {
  font-size: 22px;
  font-weight: 600;
  color: rgba(102, 87, 142, 1);
  margin-bottom: 20px;
  padding-bottom: 10px;
  border-bottom: 2px solid rgba(102, 87, 142, 0.2);
}

.form-group {
  margin-bottom: 20px;
}

label {
  display: block;
  font-size: 15px;
  font-weight: 600;
  color: #333;
  margin-bottom: 8px;
}

label .required {
  color: #d32f2f;
  margin-left: 4px;
}

.row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
}

@media (max-width: 640px) {
  .row {
    grid-template-columns: 1fr;
  }
}

/* --------------------------------------------------------------- inputs */

input[type="text"],
input[type="tel"],
input[type="email"],
input[type="password"],
textarea {
  width: 100%;
  padding: 14px 16px;
  font-size: 16px;
  border: 2px solid #e0e0e0;
  border-radius: 8px;
  transition: all 0.3s;
  font-family: inherit;
}

input[type="text"]:focus,
input[type="tel"]:focus,
input[type="email"]:focus,
input[type="password"]:focus,
textarea:focus {
  outline: none;
  border-color: rgba(102, 87, 142, 1);
  box-shadow: 0 0 0 3px rgba(102, 87, 142, 0.1);
}

textarea {
  resize: vertical;
  min-height: 80px;
}

/* The three rules below are the kiosk's live feedback while somebody fills the
   form in, and they are scoped to the kiosk on purpose. The admin pages have no
   placeholders and open already filled in, so :placeholder-shown never matches
   there: an untouched blank field would count as "filled in wrong" and a
   prefilled edit form would open entirely green. On those pages the server is
   the only thing that says a field is wrong, via .has-error below. */

/* A completed field reads as confirmed. Fields without a placeholder never
   match :placeholder-shown, so :valid is what keeps empty required fields
   from turning green. */
body:not(.admin) input:valid:not(:placeholder-shown):not(:focus),
body:not(.admin) textarea:valid:not(:placeholder-shown):not(:focus) {
  border-color: #4caf50;
}

/* Required-but-empty only turns red once a submit has been attempted. */
body:not(.admin) form.show-validation input:invalid,
body:not(.admin) form.show-validation textarea:invalid {
  border-color: #d32f2f !important;
}

/* Phone and email complain as soon as there is something wrong to complain
   about, matching v2, which validated those two on every keystroke. */
body:not(.admin) input[type="tel"]:not(:placeholder-shown):invalid,
body:not(.admin) input[type="email"]:not(:placeholder-shown):invalid {
  border-color: #d32f2f !important;
}

/* Set by the server when validation rejects a specific field. */
input.has-error,
textarea.has-error {
  border-color: #d32f2f !important;
}

/* ---------------------------------------------------------- sex selector */

.sex-selector {
  display: flex;
  gap: 12px;
}

.sex-option {
  flex: 1;
  padding: 14px;
  border: 2px solid #e0e0e0;
  border-radius: 8px;
  text-align: center;
  cursor: pointer;
  font-size: 16px;
  font-weight: 600;
  transition: all 0.3s;
  background: white;
  font-family: inherit;
  color: #333;
  appearance: none;
}

.sex-option:hover {
  border-color: rgba(102, 87, 142, 0.5);
  background: rgba(102, 87, 142, 0.05);
}

.sex-option.selected {
  border-color: #4caf50;
  background: rgba(76, 175, 80, 0.1);
  color: #2e7d32;
}

/* ------------------------------------------------------------ checkboxes */

.checkbox-group {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  margin-top: 8px;
}

.checkbox-item {
  display: flex;
  align-items: center;
  gap: 10px;
}

.checkbox-item input[type="checkbox"] {
  width: 22px;
  height: 22px;
  cursor: pointer;
  accent-color: rgba(102, 87, 142, 1);
}

.checkbox-item label {
  margin: 0;
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
}

/* ------------------------------------------------------------- pet cards */

.pet-card {
  background: #f9f9fb;
  border: 2px solid #e8e8f0;
  border-radius: 12px;
  padding: 25px;
  margin-bottom: 20px;
  position: relative;
}

.pet-card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
}

.pet-number {
  font-size: 18px;
  font-weight: 600;
  color: rgba(102, 87, 142, 1);
}

.remove-pet-btn {
  background: #f44336;
  color: white;
  border: none;
  padding: 8px 16px;
  border-radius: 6px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.3s;
  font-family: inherit;
}

.remove-pet-btn:hover {
  background: #d32f2f;
}

/* --------------------------------------------------------------- buttons */

.add-pet-btn {
  width: 100%;
  padding: 16px;
  background: white;
  color: rgba(102, 87, 142, 1);
  border: 2px dashed rgba(102, 87, 142, 0.5);
  border-radius: 8px;
  font-size: 16px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.3s;
  margin-top: 10px;
  font-family: inherit;
}

.add-pet-btn:hover {
  background: rgba(102, 87, 142, 0.05);
  border-color: rgba(102, 87, 142, 1);
}

.submit-btn {
  width: 100%;
  padding: 18px;
  background: rgba(102, 87, 142, 1);
  color: white;
  border: none;
  border-radius: 8px;
  font-size: 18px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.3s;
  margin-top: 20px;
  font-family: inherit;
}

.submit-btn:hover {
  background: rgba(82, 67, 122, 1);
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(102, 87, 142, 0.3);
}

.submit-btn:disabled {
  background: #ccc;
  cursor: not-allowed;
  transform: none;
}

/* -------------------------------------------------------------- messages */

.message {
  padding: 16px;
  border-radius: 8px;
  margin-bottom: 20px;
  font-weight: 500;
}

.message.success {
  background: #e8f5e9;
  color: #2e7d32;
  border: 1px solid #4caf50;
}

.message.error {
  background: #ffebee;
  color: #c62828;
  border: 1px solid #f44336;
}

/* --------------------------------------------------------------- spinner */

.spinner {
  border: 3px solid #f3f3f3;
  border-top: 3px solid rgba(102, 87, 142, 1);
  border-radius: 50%;
  width: 20px;
  height: 20px;
  animation: spin 1s linear infinite;
  display: inline-block;
  margin-right: 10px;
  vertical-align: middle;
}

@keyframes spin {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

/* ===================================================================
   Staff shell

   v2's screens, drawn as v2 drew them. Staff have used those every day for
   years and want them unchanged, so the numbers here are MUI's, as v2's
   theme.js set them up — measured from v2 running side by side, not
   approximated. Where v3 shows something v2 did not, it is drawn with the
   same pieces so that it looks as if it was always there.
   =================================================================== */

body.admin {
  --font: "Roboto", "Helvetica", "Arial", sans-serif;
  --text: rgba(0, 0, 0, 0.87);
  --text-soft: rgba(0, 0, 0, 0.6);
  --text-faint: rgba(0, 0, 0, 0.38);
  --rule: rgba(224, 224, 224, 1);
  --purple-hover: rgb(81, 69, 113);
  --elevation-1: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14),
    0 1px 3px 0 rgba(0, 0, 0, 0.12);
  --elevation-2: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14),
    0 1px 5px 0 rgba(0, 0, 0, 0.12);
  --elevation-3: 0 3px 3px -2px rgba(0, 0, 0, 0.2), 0 3px 4px 0 rgba(0, 0, 0, 0.14),
    0 1px 8px 0 rgba(0, 0, 0, 0.12);
  --elevation-4: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14),
    0 1px 10px 0 rgba(0, 0, 0, 0.12);
  --elevation-8: 0 5px 5px -3px rgba(0, 0, 0, 0.2), 0 8px 10px 1px rgba(0, 0, 0, 0.14),
    0 3px 14px 2px rgba(0, 0, 0, 0.12);

  background: white;
  padding: 0;
  font-family: var(--font);
  color: var(--text);
}

body.admin.centered {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: white;
}

.icon {
  width: 1em;
  height: 1em;
  flex-shrink: 0;
  fill: currentColor;
}

/* ------------------------------------------------------------ top bar */

/* Fixed, as v2's AppBar is, with the content starting below it as v2's
   spacer Toolbar made it. Sticky would scroll the same, but it is part of the
   page, so the rubber band at the top of a Mac's scroll pulls it down off
   the edge of the window with everything else. */
.appbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 40;
  height: 42px;
  display: flex;
  align-items: center;
  padding: 0 16px;
  background: var(--purple);
  color: white;
  box-shadow: var(--elevation-4);
}

.appbar-left,
.appbar-right {
  display: flex;
  align-items: center;
}

/* Takes the slack, so Add stays in the middle as the names either side of
   it change width. */
.appbar-center {
  flex: 1;
  display: flex;
  justify-content: center;
}

.appbar-logo {
  display: block;
  margin-right: 16px;
}

.appbar-logo img {
  display: block;
  height: 30px;
}

/* MUI's text button in the AppBar's colour. */
.appbar-button {
  display: inline-flex;
  align-items: center;
  padding: 6px 8px;
  border: 0;
  border-radius: 4px;
  background: none;
  color: inherit;
  font-family: var(--font);
  font-size: 14px;
  font-weight: 600;
  line-height: 24.5px;
  letter-spacing: 0.4px;
  white-space: nowrap;
  cursor: pointer;
  list-style: none;
}

.appbar-button::-webkit-details-marker {
  display: none;
}

.appbar-button:hover,
.menu[open] > .appbar-button {
  background: rgba(255, 255, 255, 0.08);
}

.appbar-button .icon {
  font-size: 20px;
}

.appbar-button .icon:first-child {
  margin: 0 8px 0 -4px;
}

.appbar-button .icon:last-child {
  margin: 0 -4px 0 8px;
}

.appbar-icon {
  display: inline-flex;
  padding: 4px;
  margin-right: 32px;
  border: 0;
  border-radius: 50%;
  background: none;
  color: inherit;
  font-size: 24px;
  text-decoration: none;
}

.appbar-icon:hover {
  background: rgba(0, 0, 0, 0.04);
}

/* MUI's Badge, with the overrides v2's Toolbar gives it: a little smaller,
   and lower than MUI puts it. */
.bell {
  position: relative;
  display: inline-flex;
}

.bell-badge {
  position: absolute;
  top: -10px;
  right: 2px;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 10px;
  height: 16px;
  padding: 0 6px;
  border-radius: 10px;
  background: var(--danger);
  color: white;
  font-size: 11.2px;
  font-weight: 500;
  line-height: 1;
  transform: scale(0.9) translate(50%, 50%);
  transform-origin: 100% 0%;
}

.appbar-search {
  margin-right: 48px;
}

.appbar-search .icon:first-child {
  margin: 0 8px 0 -4px;
}

/* ---------------------------------------------------------------- menus */

/* `details` rather than a scripted dropdown: it opens on click and on Enter
   and works before any script has loaded. nav.js closes it on a click
   elsewhere and on Escape, as MUI's Menu closes. */
.menu {
  position: relative;
}

.menu > summary {
  list-style: none;
}

.menu > summary::-webkit-details-marker {
  display: none;
}

.menu-items {
  position: absolute;
  top: calc(100% + 2px);
  left: 0;
  z-index: 45;
  min-width: 100%;
  padding: 12px 0;
  border-radius: 4px;
  background: white;
  box-shadow: var(--elevation-8);
  color: var(--text);
}

.menu-items a,
.menu-items button {
  display: flex;
  align-items: center;
  width: 100%;
  min-height: 32px;
  padding: 4px 12px;
  border: 0;
  background: none;
  font-family: var(--font);
  font-size: 16px;
  line-height: 24px;
  letter-spacing: 0.15px;
  text-align: left;
  text-decoration: none;
  white-space: nowrap;
  color: var(--text);
  cursor: pointer;
}

.menu-items a:hover,
.menu-items button:hover,
.menu-items a:focus-visible,
.menu-items button:focus-visible {
  outline: none;
  background: rgba(0, 0, 0, 0.04);
}

.menu-items form {
  display: block;
}

/* ---------------------------------------------------------------- paper */

#content {
  padding-top: 42px;
  padding-bottom: 16px;
}

/* A list: v2's Paper, the width of the window. */
.list-paper {
  margin: 16px 0;
  padding: 16px;
  border-radius: 4px;
  background: white;
  box-shadow: var(--elevation-1);
}

.list-title {
  margin-bottom: 11.9px;
  font-size: 34px;
  font-weight: 400;
  line-height: 1.235;
  letter-spacing: 0.25px;
}

/* A record: its card, then the tables that belong to it, 16px apart. */
.record-page {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 16px;
}

.record-card {
  padding: 16px;
  border-radius: 4px;
  background: white;
  box-shadow: var(--elevation-1);
}

.record-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 8.4px;
  font-size: 24px;
  font-weight: 400;
  line-height: 32px;
}

.record-title h1 {
  font: inherit;
}

/* The way back up, in the title. Text until the mouse is on it. */
.record-title h1 a {
  color: inherit;
  text-decoration: none;
}

.record-title h1 a:hover {
  text-decoration: underline;
}

/* v2's colours, which are MUI's blue rather than the theme's purple. */
.record-nav {
  display: flex;
  gap: 16px;
  font-size: 14px;
  line-height: 20px;
  letter-spacing: 0.15px;
  color: gray;
  white-space: nowrap;
}

.record-nav a {
  color: #1976d2;
  text-decoration: none;
}

/* v2's Edit Profile: one narrow card, the fields in a single column with
   only their own margins between them. */
.profile-page {
  padding: 22px 16px 16px;
}

.profile-card {
  max-width: 648px;
  margin: 0 auto;
  padding: 24px;
}

.profile-card .cells {
  margin-top: 0;
}

.profile-card .cell {
  padding-top: 0;
}

.profile-card .record-actions {
  justify-content: flex-end;
  margin-top: 24px;
}

/* The tables under a record: v2's Box with p: 2, and an h6 for a title. */
.record-section {
  padding: 16px;
}

.section-heading {
  display: flex;
  align-items: baseline;
  gap: 16px;
  margin-bottom: 7px;
  font-size: 20px;
  font-weight: 500;
  line-height: 32px;
  letter-spacing: 0.15px;
  color: black;
}

/* "All 16" and the like: a v3 addition, so said quietly. */
.section-heading a {
  font-size: 14px;
  font-weight: 400;
  color: var(--purple);
  text-decoration: none;
}

.section-heading a:hover {
  text-decoration: underline;
}

/* v2's IconButton with ExpandMore, ExpandLess once open. */
.folded > summary {
  align-items: center;
  gap: 8px;
  cursor: pointer;
  list-style: none;
}

.folded > summary::-webkit-details-marker {
  display: none;
}

.fold-toggle {
  display: inline-flex;
  padding: 5px;
  border-radius: 50%;
  color: rgba(0, 0, 0, 0.54);
  font-size: 24px;
}

.folded > summary:hover .fold-toggle {
  background: rgba(0, 0, 0, 0.04);
}

.folded[open] .fold-toggle .icon {
  transform: rotate(180deg);
}

.folded[open] > summary {
  margin-bottom: 7px;
}

.empty {
  font-size: 16px;
  line-height: 1.5;
  letter-spacing: 0.15px;
}

/* v2's NotificationsPage: a 600px column, its heading 80px from the top of
   the window, and a Paper per submission. */
.submissions-page {
  max-width: 632px;
  margin: 0 auto;
  padding: 38px 16px 16px;
}

.submissions-title {
  margin-bottom: 8.4px;
  font-size: 24px;
  font-weight: 400;
  line-height: 1.334;
  color: black;
}

.submissions {
  padding: 8px 0;
  list-style: none;
}

.submission {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-bottom: 16px;
  padding: 24px 32px;
  border-radius: 4px;
  background: white;
  box-shadow: var(--elevation-1);
}

.submission-text {
  flex: 1;
  min-width: 0;
  margin: 6px 0;
}

.submission-name,
.submission-meta {
  display: block;
  letter-spacing: 0.15px;
}

.submission-name {
  font-size: 16px;
  line-height: 24px;
}

.submission-meta {
  font-size: 14px;
  line-height: 20.02px;
  color: var(--text-soft);
}

.submission-actions {
  display: flex;
  gap: 8px;
}

/* -------------------------------------------------------- record fields */

/* v2's MUI Grid with spacing 2, inside a box that keeps it off the card's
   edges. A row that does not fill twelve columns is centred, as v2's are. */
.record-form {
  margin: 0 auto;
}

.record-form fieldset {
  min-width: 0;
  border: 0;
}

.cells {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  width: calc(100% + 16px);
  margin: -16px 0 0 -16px;
}

.cell {
  padding: 16px 0 0 16px;
}

.cell-1 { flex: 0 0 8.3333%; }
.cell-2 { flex: 0 0 16.6667%; }
.cell-3 { flex: 0 0 25%; }
.cell-4 { flex: 0 0 33.3333%; }
.cell-5 { flex: 0 0 41.6667%; }
.cell-6 { flex: 0 0 50%; }
.cell-7 { flex: 0 0 58.3333%; }
.cell-9 { flex: 0 0 75%; }
.cell-12 { flex: 0 0 100%; }

.cell-break {
  flex-basis: 100%;
}

@media (max-width: 600px) {
  .cell {
    flex-basis: 100%;
  }
}

/* The image button and the checkboxes sit level with the fields beside
   them rather than at the top of the cell. */
.cell.centered {
  display: flex;
  align-items: center;
  justify-content: center;
  margin-top: 16px;
}

.images-button {
  display: inline-flex;
  padding: 4px;
  border: 0;
  border-radius: 50%;
  background: none;
  color: rgba(0, 0, 0, 0.54);
  font-size: 30px;
  cursor: pointer;
}

.images-button:hover {
  background: rgba(0, 0, 0, 0.04);
}

/* In the theme's colour when there is something to see, as v2's is. */
.images-button.has-photos,
.photos-cell .has-photos {
  color: var(--purple);
}

/* ---------------------------------------------------------------- photos */

/* v2's Popover: a Paper, 16px in, 300px at most, under the button. A
   popover rather than a menu, so it can sit outside the locked form; nav.js
   places it. */
.photos-panel {
  position: absolute;
  inset: auto;
  width: max-content;
  max-width: min(300px, calc(100vw - 32px));
  margin: 0;
  padding: 16px;
  border: 0;
  border-radius: 8px;
  background: white;
  box-shadow: var(--elevation-3);
  color: var(--text);
}

/* MUI's h6, gutterBottom. */
.photos-title {
  margin: 0 0 0.35em;
  font-size: 20px;
  font-weight: 500;
  line-height: 1.6;
  letter-spacing: 0.15px;
}

/* A Grid of xs=4 items, spacing 1. */
.photos-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  margin-bottom: 8px;
}

.photo img {
  display: block;
  width: 100%;
  border-radius: 4px;
}

/* MUI's caption. */
.photo-caption {
  display: block;
  font-size: 12px;
  line-height: 1.66;
  letter-spacing: 0.4px;
  overflow-wrap: anywhere;
}

.icon-button.photo-delete {
  padding: 5px;
  font-size: 20px;
}

.icon-button:disabled {
  color: rgba(0, 0, 0, 0.26);
  cursor: default;
}

.icon-button:disabled:hover {
  background: none;
}

.photos-empty {
  margin: 0 0 8px;
  font-size: 14px;
  line-height: 1.43;
  letter-spacing: 0.15px;
}

/* v2's Upload: a column, 8px apart. */
.photo-upload {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.photo-choose {
  display: flex;
  align-items: center;
  gap: 16px;
}

.photo-file {
  font-size: 14px;
  line-height: 1.43;
  letter-spacing: 0.15px;
  overflow-wrap: anywhere;
}

.photo-upload .field {
  margin: 0;
}

.photo-upload .field-error {
  margin: 0 14px;
}

/* A list's thumbnails open under their icon, right-aligned, as the
   comments do beside them. */
.photos-menu .photos-popover {
  position: absolute;
  top: calc(100% + 2px);
  right: 0;
  z-index: 45;
  width: max-content;
  max-width: 300px;
  padding: 16px;
  border-radius: 8px;
  background: white;
  box-shadow: var(--elevation-3);
  color: var(--text);
  text-align: left;
  white-space: normal;
}

.record-actions {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  margin: 16px auto 0;
}

/* -------------------------------------------------------------- tables */

table.grid {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
  line-height: 20px;
  letter-spacing: 0.15px;
}

table.grid tr {
  height: 40px;
}

table.grid th,
table.grid td {
  padding: 6px;
  border-bottom: 1px solid var(--rule);
  text-align: left;
  vertical-align: middle;
}

table.grid th {
  background: var(--purple);
  color: white;
  font-weight: 500;
  line-height: 24px;
}

table.grid td {
  color: var(--text);
}

table.grid .amount {
  white-space: nowrap;
}

.sort-label {
  display: inline-flex;
  align-items: center;
  color: inherit;
  text-decoration: none;
}

.sort-label .icon {
  margin: 0 4px;
  font-size: 18px;
  opacity: 0;
  transition: opacity 0.2s, transform 0.2s;
}

.sort-label:hover .icon {
  opacity: 0.5;
}

.sort-label.active .icon {
  opacity: 1;
}

.sort-label.desc .icon {
  transform: rotate(180deg);
}

/* The arrow column and the comments column take what their icon needs. */
table.grid .open-cell,
table.grid .comments-cell {
  width: 1px;
  white-space: nowrap;
}

.open-row {
  display: inline-flex;
  padding: 4px;
  border-radius: 50%;
  color: rgba(0, 0, 0, 0.54);
  font-size: 13px;
}

.open-row:hover {
  background: rgba(0, 0, 0, 0.04);
}

/* A value that is also a way to its record, looking like the value. */
.cell-link {
  color: inherit;
  text-decoration: none;
}

.cell-link:hover {
  text-decoration: underline;
}

.icon-button {
  display: inline-flex;
  padding: 4px;
  border: 0;
  border-radius: 50%;
  background: none;
  color: rgba(0, 0, 0, 0.54);
  font-size: 18px;
  cursor: pointer;
}

.icon-button:hover {
  background: rgba(0, 0, 0, 0.04);
}

.icon-button.disabled {
  color: rgba(0, 0, 0, 0.26);
  cursor: default;
}

.icon-button.disabled:hover {
  background: none;
}

.comments-cell .icon-button.disabled {
  opacity: 0.2;
}

.comments-cell .has-comments {
  color: var(--danger);
  opacity: 0.8;
}

/* Right-aligned to its icon, which sits at the table's right edge. */
.comments-menu .menu-items {
  left: auto;
  right: 0;
  min-width: 200px;
  max-width: 360px;
  padding: 8px 0;
}

.comments-title {
  padding: 4px 12px;
  font-size: 16px;
  line-height: 1.75;
  letter-spacing: 0.15px;
  opacity: 0.38;
}

.comments-text {
  padding: 6px 12px;
  font-size: 14px;
  line-height: 1.43;
  letter-spacing: 0.15px;
  white-space: pre-wrap;
}

.empty-row td {
  color: var(--text-soft);
}

/* ---------------------------------------------------------- pagination */

/* MUI's TablePagination: the size, the range, the chevrons, at the right. */
.pagination {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  min-height: 42px;
  padding: 0 16px;
  font-size: 14px;
  line-height: 20px;
  letter-spacing: 0.15px;
}

.pagination-select {
  position: relative;
  display: inline-flex;
  align-items: center;
  margin: 0 32px 0 8px;
}

.pagination-select select {
  padding: 4px 24px 5px 8px;
  border: 0;
  background: none;
  font-family: var(--font);
  font-size: 14px;
  line-height: 20px;
  color: var(--text);
  appearance: none;
  appearance: base-select;
  cursor: pointer;
}

.pagination-select .icon {
  position: absolute;
  right: 0;
  font-size: 24px;
  color: rgba(0, 0, 0, 0.54);
  pointer-events: none;
}

.pagination-actions {
  display: inline-flex;
  margin-left: 20px;
}

.pagination-actions .icon-button {
  font-size: 18px;
  color: rgba(0, 0, 0, 0.54);
}

.pagination-actions .icon-button.disabled {
  color: rgba(0, 0, 0, 0.26);
}

/* ------------------------------------------------------- badges, tags */

/* A kiosk submission nobody has looked at yet. */
.badge {
  display: inline-block;
  margin-left: 8px;
  padding: 0 6px;
  border-radius: 10px;
  background: var(--purple);
  color: white;
  font-size: 11px;
  font-weight: 500;
  line-height: 18px;
  vertical-align: middle;
}

.tag {
  display: inline-block;
  margin-left: 6px;
  padding: 0 6px;
  border-radius: 10px;
  background: rgba(0, 0, 0, 0.08);
  color: var(--text-soft);
  font-size: 11px;
  line-height: 18px;
  vertical-align: middle;
}

/* ---------------------------------------------------------- navigation */

/* A bar across the top while a page is on its way. A page should arrive
   with nothing drawn first, so it fades in only after a pause, and goes at
   once when the page lands — the delay is on the way in only. The pause is
   longer than a round trip to the VPS, measured at 0.2 to 0.35s; any
   shorter and the bar flashes on every click. */
.nav-progress {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 70;
  height: 3px;
  background: white;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.1s;
}

.nav-progress.active {
  opacity: 0.8;
  transition-delay: 0.5s;
}

/* A request that failed. Fixed and above the dialog, because the dialog is
   where most requests come from, and at the foot of the screen, where it
   covers neither the dialog's heading nor the top bar. Empty, it takes no
   room at all. */
.notice {
  position: fixed;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 60;
  display: flex;
  align-items: center;
  gap: 16px;
  max-width: calc(100% - 32px);
  padding: 6px 16px;
  border-radius: 4px;
  background: var(--danger);
  color: white;
  font-size: 14px;
  line-height: 1.43;
  box-shadow: 0 3px 5px -1px rgba(0, 0, 0, 0.2), 0 6px 10px 0 rgba(0, 0, 0, 0.14),
    0 1px 18px 0 rgba(0, 0, 0, 0.12);
}

/* A form button that reads as a link. */
.link-button {
  padding: 0;
  border: none;
  background: none;
  color: white;
  font: inherit;
  text-decoration: underline;
  cursor: pointer;
}

/* --------------------------------------------------------------- modal */

.modal {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 80px 16px 32px;
  overflow-y: auto;
  background: rgba(0, 0, 0, 0.5);
}

/* v2's dialog is a plain 400px Box, 80px from the top, and the narrowness
   is doing work: one question per row reads as a list of things to fill
   in. */
.modal-card {
  width: 100%;
  max-width: 448px;
  padding: 24px;
  border-radius: 8px;
  background: white;
}

.modal .form-grid {
  grid-template-columns: 1fr;
}

.modal-head h2 {
  font-size: 20px;
  font-weight: 500;
  line-height: 1.6;
  letter-spacing: 0.15px;
}

/* v2 spaces the dialog's fields by a top margin alone, and stars none. */
.modal .field {
  margin: 16px 0 0;
}

.modal .required {
  display: none;
}

/* In the dialog a fixed field is MUI's plain disabled one, greyed out: it
   is settled, not something to read. */
.modal .field :disabled {
  color: rgba(0, 0, 0, 0.38);
  -webkit-text-fill-color: rgba(0, 0, 0, 0.38);
}

.modal .form-actions {
  justify-content: space-between;
  margin-top: 24px;
}

.modal .form-actions.end {
  justify-content: flex-end;
}

/* MUI's DialogContentText. */
.modal-text {
  margin-top: 16px;
  color: var(--text-soft);
  font-size: 16px;
  line-height: 1.5;
  letter-spacing: 0.15px;
}

/* --------------------------------------------------------- search panel */

/* MUI's Drawer from the right, over everything the dialog covers and the top
   bar too. v2's Paper is padded 32px and the Box inside it 24px more, around
   300px of fields.

   It comes in over MUI's 225ms, decelerating, and goes over its 195ms with
   the sharp curve, which MUI's Drawer does too but v2 never showed: it
   unmounted the drawer instead. Closed, it is hidden from the pointer, the
   keyboard and screen readers once the slide out has finished. */
.drawer {
  position: fixed;
  inset: 0;
  z-index: 55;
  background: rgba(0, 0, 0, 0.5);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.195s cubic-bezier(0.4, 0, 0.2, 1), visibility 0s 0.195s;
}

.drawer.open {
  opacity: 1;
  visibility: visible;
  transition: opacity 0.225s cubic-bezier(0.4, 0, 0.2, 1);
}

.drawer-paper {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 412px;
  max-width: 100%;
  padding: 56px;
  overflow-y: auto;
  background: white;
  box-shadow: 0 8px 10px -5px rgba(0, 0, 0, 0.2), 0 16px 24px 2px rgba(0, 0, 0, 0.14),
    0 6px 30px 5px rgba(0, 0, 0, 0.12);
  transform: translateX(100%);
  transition: transform 0.195s cubic-bezier(0.4, 0, 0.6, 1);
}

.drawer.open .drawer-paper {
  transform: none;
  transition: transform 0.225s cubic-bezier(0, 0, 0.2, 1);
}

.drawer-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.drawer-head h2 {
  font-size: 20px;
  font-weight: 500;
  line-height: 32px;
  letter-spacing: 0.15px;
}

.drawer .field {
  margin: 16px 0 0;
}

/* v2's own red, not the theme's. */
.search-helper {
  margin-top: 8px;
  color: red;
  font-size: 12px;
  line-height: 1.66;
  letter-spacing: 0.4px;
}

.drawer .btn {
  width: 100%;
  margin-top: 16px;
}

/* The results: v2's line saying what was searched for, then the list's own
   Paper. v2 has the heading's 7px, then the 42px spacer its list pages keep
   for the top bar, then the Paper's own 16px. */
.search-results {
  margin-top: 14px;
  padding: 16px;
}

.search-heading {
  color: black;
  font-size: 20px;
  font-weight: 500;
  line-height: 32px;
  letter-spacing: 0.15px;
}

.search-results .list-paper {
  margin: 65px 0 0;
}

.search-empty {
  color: black;
  font-size: 24px;
  line-height: 1.334;
}

.search-hint {
  margin-top: 8px;
  color: var(--text-soft);
  font-size: 16px;
  line-height: 1.5;
  letter-spacing: 0.15px;
}

/* ------------------------------------------------------------- reports */

/* v2's Reports Paper is raised more than a list's. It was also 97% wide plus
   its padding, which ran 4px past the window; this one fits. */
.reports-paper {
  box-shadow: var(--elevation-3);
}

.reports-subtitle {
  margin-bottom: 7px;
  font-size: 20px;
  font-weight: 500;
  line-height: 32px;
  letter-spacing: 0.15px;
}

/* MUI's List of ListItemButtons: 48px rows. */
.reports-list {
  padding: 8px 0;
  list-style: none;
}

.reports-list a,
.reports-list span {
  display: block;
  padding: 12px 16px;
  font-size: 16px;
  line-height: 24px;
  letter-spacing: 0.15px;
  color: var(--text);
  text-decoration: none;
}

.reports-list a {
  transition: background-color 0.15s cubic-bezier(0.4, 0, 0.2, 1);
}

.reports-list a:hover {
  background: rgba(0, 0, 0, 0.04);
}

/* MUI's disabled ListItemButton. */
.reports-list [aria-disabled] {
  opacity: 0.38;
  cursor: default;
}

/* v3's Backup, drawn as Reports is: body1 text, then the button. */
.backup-paper {
  box-shadow: var(--elevation-3);
}

/* ---------------------------------------------------------- admin panel */

/* MUI's Tabs: uppercase labels over a hairline, the open one in the primary
   colour and underlined. Each tab is a link to its own page. */
.tabs {
  display: flex;
  margin-top: 16px;
  border-bottom: 1px solid rgba(0, 0, 0, 0.12);
}

.tab {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 90px;
  min-height: 48px;
  margin-bottom: -1px;
  padding: 12px 16px;
  border-bottom: 2px solid transparent;
  color: rgba(0, 0, 0, 0.6);
  font-size: 14px;
  font-weight: 500;
  line-height: 1.25;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  text-decoration: none;
  transition:
    color 0.15s cubic-bezier(0.4, 0, 0.2, 1),
    background-color 0.15s cubic-bezier(0.4, 0, 0.2, 1);
}

.tab:hover {
  background: rgba(102, 87, 142, 0.04);
}

.tab[aria-current="page"] {
  border-bottom-color: var(--purple);
  color: var(--purple);
}

.settings-paper {
  box-shadow: var(--elevation-3);
}

.setting {
  display: flex;
  align-items: flex-start;
  gap: 4px;
  max-width: 640px;
}

.setting-text {
  padding-top: 7px;
}

.setting-text label {
  font-size: 16px;
  font-weight: 400;
  line-height: 1.5;
  letter-spacing: 0.15px;
  cursor: pointer;
}

.setting-help {
  margin: 2px 0 0;
  color: rgba(0, 0, 0, 0.6);
  font-size: 14px;
  line-height: 1.43;
  letter-spacing: 0.17px;
}

.setting-saved {
  min-height: 20px;
  margin: 8px 0 0 62px;
  color: rgba(0, 0, 0, 0.6);
  font-size: 14px;
  line-height: 1.43;
}

/* MUI's Switch: a 34×14 track and a 20px thumb in a 58×38 box. The checkbox
   is the whole box, transparent over them, so it is what is clicked,
   focused and posted. */
.switch {
  position: relative;
  flex-shrink: 0;
  width: 58px;
  height: 38px;
}

.switch input {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.switch-track {
  position: absolute;
  top: 12px;
  left: 12px;
  width: 34px;
  height: 14px;
  border-radius: 7px;
  background: black;
  opacity: 0.38;
  transition:
    opacity 0.15s cubic-bezier(0.4, 0, 0.2, 1),
    background-color 0.15s cubic-bezier(0.4, 0, 0.2, 1);
}

.switch-thumb {
  position: absolute;
  top: 9px;
  left: 9px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: white;
  box-shadow:
    0 2px 1px -1px rgba(0, 0, 0, 0.2),
    0 1px 1px 0 rgba(0, 0, 0, 0.14),
    0 1px 3px 0 rgba(0, 0, 0, 0.12);
  transition:
    transform 0.15s cubic-bezier(0.4, 0, 0.2, 1),
    background-color 0.15s cubic-bezier(0.4, 0, 0.2, 1);
}

.switch input:checked ~ .switch-track {
  background: var(--purple);
  opacity: 0.5;
}

.switch input:checked ~ .switch-thumb {
  transform: translateX(20px);
  background: var(--purple);
}

.switch input:focus-visible ~ .switch-thumb {
  outline: 9px solid rgba(102, 87, 142, 0.12);
}

.backup-text {
  max-width: 640px;
  margin: 0 0 16px;
  font-size: 16px;
  line-height: 1.5;
  letter-spacing: 0.15px;
}

.report-title {
  margin-bottom: 8.4px;
  padding: 16px;
  color: black;
  font-size: 24px;
  font-weight: 400;
  line-height: 1.334;
}

.report-form {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 8px 16px 0;
}

.report-form .field {
  width: 163px;
  margin: 0;
}

/* ------------------------------------------------------ customer picker */

.combo {
  position: relative;
}

/* Over the fields below rather than pushing them down, so the dialog does
   not change height while someone is typing into it. */
.combo-results {
  position: absolute;
  z-index: 5;
  top: calc(100% - 6px);
  left: 0;
  right: 0;
  max-height: 232px;
  overflow-y: auto;
  padding: 8px 0;
  border-radius: 4px;
  background: white;
  box-shadow: var(--elevation-8);
}

.combo-results button {
  display: block;
  width: 100%;
  min-height: 36px;
  padding: 6px 16px;
  border: 0;
  background: none;
  font-family: var(--font);
  font-size: 16px;
  line-height: 24px;
  color: var(--text);
  text-align: left;
  cursor: pointer;
}

.combo-results button:hover {
  background: rgba(0, 0, 0, 0.04);
}

/* Stronger than hover, and deliberately so: with the arrow keys this is the
   only thing telling you which name Enter would choose. */
.combo-results button:focus {
  outline: none;
  background: rgba(102, 87, 142, 0.12);
}

/* Where the next batch of names is asked for: drawn five rows above the end
   of the list, so it has usually arrived before anyone scrolls to the
   bottom. Relative positioning moves it without moving anything else. */
.combo-more {
  position: relative;
  top: -180px;
  height: 1px;
  pointer-events: none;
}

.combo-empty {
  padding: 6px 16px;
  font-size: 16px;
  color: var(--text-soft);
}

/* ---------------------------------------------------------- checkboxes */

/* Wide gaps between items and narrow ones inside them (below), so each label
   reads with its own box. With the items' -11px and the box's 12px margins,
   a label ends about 40px before the next box. */
.admin .checkbox-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0 39px;
  margin: 8px 0;
}

/* No gap: the kiosk's .checkbox-item rule above puts 10px between box and
   label, which on top of the box's margin left the label 22px away. */
.admin .checkbox-item {
  display: inline-flex;
  align-items: center;
  gap: 0;
  margin-left: -11px;
}

/* MUI's checkbox: an 18px box in a 42px target, in the primary colour. The
   right margin is narrower, so the label sits 6px from its box. */
.admin .checkbox-item input[type="checkbox"] {
  width: 18px;
  height: 18px;
  margin: 12px 6px 12px 12px;
  accent-color: var(--purple);
  cursor: pointer;
}

.admin .checkbox-item label {
  margin: 0;
  font-size: 16px;
  font-weight: 400;
  line-height: 1.5;
  letter-spacing: 0.15px;
  color: var(--text);
  cursor: pointer;
}

.admin .checkbox-item input:disabled,
.admin .checkbox-item input:disabled + label {
  cursor: default;
}

.admin .checkbox-item input:disabled + label {
  color: var(--text-faint);
}

/* ------------------------------------------------------------- buttons */

/* MUI's Button with v2's theme: weight 600, no capitals. Outlined is the
   default here; `primary` is contained. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 64px;
  padding: 5px 15px;
  border: 1px solid rgba(102, 87, 142, 0.5);
  border-radius: 4px;
  background: transparent;
  color: var(--purple);
  font-family: var(--font);
  font-size: 14px;
  font-weight: 600;
  line-height: 24.5px;
  letter-spacing: 0.4px;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 0.25s, box-shadow 0.25s, border-color 0.25s;
}

.btn:hover {
  border-color: var(--purple);
  background: rgba(102, 87, 142, 0.04);
}

.btn.primary {
  padding: 6px 16px;
  border: 0;
  background: var(--purple);
  color: white;
  box-shadow: var(--elevation-2);
}

.btn.primary:hover {
  background: var(--purple-hover);
  box-shadow: var(--elevation-4);
}

.btn.danger {
  border-color: rgba(211, 47, 47, 0.5);
  color: var(--danger);
}

.btn.danger:hover {
  border-color: var(--danger);
  background: rgba(211, 47, 47, 0.04);
}

/* MUI's contained button in the error colour: the dialog's Delete. */
.btn.danger.primary {
  background: var(--danger);
  color: white;
}

.btn.danger.primary:hover {
  background: rgb(198, 40, 40);
}

.btn.danger.primary:disabled {
  background: rgba(0, 0, 0, 0.12);
  color: rgba(0, 0, 0, 0.26);
}

/* A text button. The dialog's Cancel. */
.btn.quiet {
  padding: 6px 8px;
  border: 0;
  color: var(--danger);
}

.btn.quiet:hover {
  background: rgba(211, 47, 47, 0.04);
}

/* MUI's text button. */
.btn.text {
  padding: 6px 8px;
  border: 0;
}

.btn.text:hover {
  background: rgba(102, 87, 142, 0.04);
}

/* MUI's size="small". */
.btn.small {
  padding: 3px 9px;
  font-size: 13px;
  line-height: 22.75px;
  letter-spacing: 0.37px;
}

.btn.text.small {
  padding: 4px 5px;
}

.btn:disabled {
  border-color: rgba(0, 0, 0, 0.12);
  color: rgba(0, 0, 0, 0.26);
  background: transparent;
  box-shadow: none;
  cursor: default;
}

.btn.primary:disabled {
  background: rgba(0, 0, 0, 0.12);
}

.form-actions {
  display: flex;
  gap: 16px;
  align-items: center;
  margin-top: 16px;
}

/* ------------------------------------------------------------- fields */

/* MUI's outlined TextField: 56px tall, the label resting inside until the
   field has focus or a value, then riding up into a gap in the outline.
   The gap is the label's white background.

   Empty is detected with :placeholder-shown, so every field carries
   placeholder=" " — a real placeholder would sit under the resting label. */
.field {
  position: relative;
  margin: 16px 0 8px;
}

.field input,
.field textarea,
.field select {
  display: block;
  width: 100%;
  height: 56px;
  padding: 16.5px 14px;
  border: 1px solid rgba(0, 0, 0, 0.23);
  border-radius: 4px;
  background: white;
  font-family: var(--font);
  font-size: 16px;
  line-height: 23px;
  letter-spacing: 0.15px;
  color: var(--text);
  text-overflow: ellipsis;
}

.field textarea {
  height: auto;
  min-height: 79px;
  resize: none;
}

/* MUI's size="small": 40px tall, the label resting 9px down. */
.field.small input {
  height: 40px;
  padding: 8.5px 14px;
}

.field.small input + label {
  transform: translate(8px, 8.5px) scale(1);
}

/* A real placeholder, where there is one, shows only once the label has
   moved out of its way, as MUI's does. */
.field input::placeholder {
  opacity: 0;
}

.field input:focus::placeholder {
  color: currentColor;
  opacity: 0.42;
}

.field select {
  padding-right: 32px;
  appearance: none;
  appearance: base-select;
  background: white url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='rgba(0,0,0,0.54)' d='M7 10l5 5 5-5z'/%3E%3C/svg%3E") no-repeat right 7px center / 24px;
}

/* What a select opens: v2's Select menu, a Paper under the field with its
   options in body text, rather than the operating system's own list.

   `base-select` is what lets a stylesheet draw it, and is the browser's own
   select underneath, so the keyboard, forms, `required` and `data-bind` work
   as before. A browser without it ignores the value, keeps `appearance:
   none` above, and `select.js` opens the same menu below. Every select draws
   its arrow already, and v2 marks the chosen option with a tint rather than
   a tick. The empty option only stands for nothing chosen, so it is not
   offered as a choice, as v2's menus have no blank row. */
@supports (appearance: base-select) {
  .admin select::picker-icon,
  .admin select option::checkmark,
  .admin select option[value=""] {
    display: none;
  }

  .admin select::picker(select) {
    appearance: base-select;
    margin: 0;
    padding: 8px 0;
    border: 0;
    border-radius: 4px;
    background: white;
    box-shadow: var(--elevation-8);
  }

  .admin select option {
    padding: 6px 16px;
    font-family: var(--font);
    font-size: 16px;
    line-height: 24px;
    letter-spacing: 0.15px;
    color: var(--text);
    cursor: pointer;
  }

  .admin select option:hover {
    background: rgba(0, 0, 0, 0.04);
  }

  .admin select option:checked {
    background: rgba(102, 87, 142, 0.08);
  }

  .admin select option:checked:hover {
    background: rgba(102, 87, 142, 0.12);
  }

  .admin select option:focus-visible {
    outline: none;
    background: rgba(0, 0, 0, 0.12);
  }
}

/* The same menu, drawn by `select.js` where the browser has no
   `base-select`. A popover, so `inset` and `margin` undo the browser's
   centring and the script places it under its field. */
.select-menu {
  inset: auto;
  margin: 0;
  padding: 8px 0;
  border: 0;
  border-radius: 4px;
  background: white;
  box-shadow: var(--elevation-8);
  overflow-y: auto;
}

.select-option {
  padding: 6px 16px;
  font-family: var(--font);
  font-size: 16px;
  line-height: 24px;
  letter-spacing: 0.15px;
  white-space: nowrap;
  color: var(--text);
  cursor: pointer;
}

.select-option:hover {
  background: rgba(0, 0, 0, 0.04);
}

.select-option[aria-selected="true"] {
  background: rgba(102, 87, 142, 0.08);
}

.select-option[aria-selected="true"]:hover {
  background: rgba(102, 87, 142, 0.12);
}

.select-option.active {
  background: rgba(0, 0, 0, 0.12);
}

/* v2 draws a locked service's groomer as text, with nothing to open. */
#service-form select:disabled {
  background-image: none;
}

.field input:hover,
.field textarea:hover,
.field select:hover {
  border-color: var(--text);
}

.field label {
  position: absolute;
  top: 0;
  left: 0;
  max-width: calc(100% - 24px);
  margin: 0;
  padding: 0 6px;
  overflow: hidden;
  background: white;
  color: var(--text-soft);
  font-size: 16px;
  font-weight: 400;
  line-height: 23px;
  letter-spacing: 0.15px;
  white-space: nowrap;
  text-overflow: ellipsis;
  pointer-events: none;
  transform-origin: left top;
  transform: translate(8px, 16px) scale(1);
  transition: transform 0.2s cubic-bezier(0, 0, 0.2, 1), color 0.2s;
}

/* Riding up onto the border. A select always shows a value, so its label
   never rests inside the box, and .filled says the same about the date and
   time inputs: a browser draws its own mm/dd/yyyy in them, which a resting
   label would sit on top of. */
.field input:focus + label,
.field input:not(:placeholder-shown) + label,
.field textarea:focus + label,
.field textarea:not(:placeholder-shown) + label,
.field select + label,
.field.filled input + label,
.field.small input:focus + label,
.field.small input:not(:placeholder-shown) + label {
  max-width: calc(133% - 32px);
  transform: translate(9.5px, -9px) scale(0.75);
}

/* Except a select with nothing chosen, which shows nothing: its label
   rests inside, as v2's Select Pet does. */
.field select:has(> option[value=""]:checked):not(:focus) + label {
  max-width: calc(100% - 24px);
  transform: translate(8px, 16px) scale(1);
}

.field input:focus,
.field textarea:focus,
.field select:focus {
  outline: none;
  border-color: var(--purple);
  /* An inset line rather than a wider border, so nothing below moves. */
  box-shadow: inset 0 0 0 1px var(--purple);
}

.field input:focus + label,
.field textarea:focus + label,
.field select:focus + label {
  color: var(--purple);
}

.field input.has-error,
.field textarea.has-error,
.field select.has-error {
  border-color: var(--danger);
}

.field input.has-error + label,
.field textarea.has-error + label,
.field select.has-error + label {
  color: var(--danger);
}

/* Locked, as v2 shows a record: a fainter outline and label, the value
   still in full black, because the value is what someone is reading. */
.field input:disabled,
.field textarea:disabled,
.field select:disabled {
  border-color: rgba(0, 0, 0, 0.26);
  color: black;
  -webkit-text-fill-color: black;
  opacity: 1;
  cursor: default;
}

.field select:disabled {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='rgba(0,0,0,0.26)' d='M7 10l5 5 5-5z'/%3E%3C/svg%3E");
}

.field input:disabled + label,
.field textarea:disabled + label,
.field select:disabled + label {
  color: var(--text-faint);
}

/* A record's fields are not starred: v2's are not, and while the record is
   locked there is nothing to fill in. */
.record-form .required {
  display: none;
}

.form-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 16px;
}

@media (max-width: 640px) {
  .form-grid {
    grid-template-columns: 1fr;
  }
}

/* MUI's helper text, under the field. */
.field-error,
.field-note {
  margin: 3px 14px 0;
  font-size: 12px;
  line-height: 1.66;
  letter-spacing: 0.4px;
}

.field-error {
  color: var(--danger);
}

.field-note {
  color: var(--text-soft);
}

/* A note standing on its own below a record, rather than under a field. */
.field-note.aside {
  margin: 16px 0 0;
  text-align: center;
}

/* Nothing saved: said once, above the buttons. */
.record-form .message.error,
.modal .message.error {
  margin: 16px 0 0;
}

/* --------------------------------------------------------------- login */

/* v2's: a Paper at elevation 3 in the middle of a white page, 250px of
   fields inside 32px of padding. */
.login-card {
  width: 314px;
  max-width: 100%;
  padding: 32px;
  border-radius: 4px;
  background: white;
  box-shadow: var(--elevation-3);
  text-align: center;
}

.login-title {
  margin-bottom: 8.4px;
  font-size: 24px;
  font-weight: 400;
  line-height: 1.334;
}

.login-form {
  display: flex;
  flex-direction: column;
  gap: 24px;
  text-align: left;
}

.login-form .field {
  margin: 0;
}

/* MUI stars a required label in the label's own colour. */
.login-form .required {
  margin-left: 2px;
  color: inherit;
}

.login-form .btn {
  width: 100%;
}

/* MUI's end adornment: an IconButton at the field's right edge, the text
   stopping short of it. The eye offers to show; once shown, the struck-out
   eye offers to hide again. */
.password-field input {
  padding-right: 50px;
}

.password-toggle {
  position: absolute;
  top: 8px;
  right: 2px;
  padding: 8px;
  font-size: 24px;
}

.password-toggle[aria-pressed="true"] .visibility,
.password-toggle[aria-pressed="false"] .visibility-off {
  display: none;
}

/* MUI's standard error Alert. */
.alert {
  display: flex;
  gap: 12px;
  align-items: center;
  margin-bottom: 16px;
  padding: 6px 16px;
  border-radius: 4px;
  background: rgb(253, 237, 237);
  color: rgb(95, 33, 32);
  font-size: 14px;
  line-height: 1.43;
  letter-spacing: 0.15px;
  text-align: left;
}

.alert .icon {
  flex: none;
  padding: 7px 0;
  box-sizing: content-box;
  color: var(--danger);
  font-size: 22px;
}
