/* ========================
   COMPONENTS - Reusable UI pieces, BEM naming, M3 tokens
   ======================== */

/* ---- Theme Toggle (small circle button in header) ---- */
.theme-toggle {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--md-icon-button-size);
  height: var(--md-icon-button-size);
  border: none;
  border-radius: var(--md-shape-full);
  background: none;
  color: var(--md-on-surface-variant);
  cursor: pointer;
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.theme-toggle:hover {
  background-color: var(--md-surface-container-high);
}

.theme-toggle__sun,
.theme-toggle__moon {
  position: absolute;
  font-size: var(--md-icon-size-medium);
  transition: opacity var(--md-motion-duration-medium) var(--md-motion-easing-standard),
              transform var(--md-motion-duration-medium) var(--md-motion-easing-standard);
}

.theme-toggle__sun {
  opacity: 1;
  transform: rotate(0deg);
}

.theme-toggle__moon {
  opacity: 0;
  transform: rotate(90deg);
}

[data-theme="light"] .theme-toggle__sun {
  opacity: 0;
  transform: rotate(-90deg);
}

[data-theme="light"] .theme-toggle__moon {
  opacity: 1;
  transform: rotate(0deg);
}

/* ---- Button (M3 Filled Button) ---- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--md-spacing-2);
  height: var(--md-button-height-medium);
  padding: var(--md-button-padding-y-medium) var(--md-button-padding-x-medium);
  border: none;
  border-radius: var(--md-button-radius);   /* the pill, or the client portal's small corner (variables.css) */
  font-size: var(--md-label-large-size);
  font-weight: var(--md-label-large-weight);
  line-height: var(--md-label-large-line);
  cursor: pointer;
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard),
              box-shadow var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

/* Size icons inside buttons to match button height */
.btn .material-symbols-outlined {
  font-size: var(--md-label-large-line);
}

.btn--primary {
  background-color: var(--md-primary);
  color: var(--md-on-primary);
}

/* Every :hover below restates the variant's text colour: most buttons are anchors, and base.css
   a:hover would otherwise recolour the label to on-primary-container - invisible on the green
   button inside the charcoal bar (pale green on green) */
.btn--primary:hover {
  color: var(--md-on-primary);
  box-shadow: var(--md-elevation-1);
  filter: brightness(1.1);
}

/* M3 Outlined Button */
.btn--outlined {
  background-color: transparent;
  color: var(--md-primary);
  border: var(--md-divider-thickness) solid var(--md-outline);
  padding: calc(var(--md-button-padding-y-medium) - var(--md-divider-thickness)) calc(var(--md-button-padding-x-medium) - var(--md-divider-thickness));
}

.btn--outlined:hover {
  color: var(--md-primary);
  background-color: var(--md-surface-container-high);
}

/* Text button: the public pages, the end-user app (/parkhere/*) and the site-wide consent banner only.
   Never on a client-portal page (the owner's rule, 2026-10-28): there every text button is filled or
   ringed - a table row's word actions are outlined buttons, a dialog's Cancel is the ringed .dialog__btn;
   an icon button is the glyph alone with its hover fill (2026-10-29: no ring on any icon button) */
.btn--text {
  background-color: transparent;
  color: var(--md-primary);
  border: none;
  padding: var(--md-spacing-2) var(--md-spacing-3);
}

.btn--text:hover {
  color: var(--md-primary);
  background-color: var(--md-surface-container-high);
}

.btn--text:disabled {
  color: var(--md-on-surface-variant);
  background-color: transparent;
}

/* M3 Danger Button (destructive actions) */
.btn--danger {
  background-color: var(--md-error);
  color: var(--md-on-error);
}

.btn--danger:hover {
  color: var(--md-on-error);
  box-shadow: var(--md-elevation-1);
  filter: brightness(1.1);
}

/* Outlined danger button: the "Remove …" entry button of a page (the end-user vehicle and residence
   pages); the filled .btn--danger stays the final button of a confirmation page */
.btn--danger-outlined {
  background-color: transparent;
  color: var(--md-error);
  border: var(--md-divider-thickness) solid var(--md-error);
  padding: calc(var(--md-button-padding-y-medium) - var(--md-divider-thickness)) calc(var(--md-button-padding-x-medium) - var(--md-divider-thickness));
}

.btn--danger-outlined:hover {
  color: var(--md-error);
  background-color: var(--md-error-container);
}

.btn--primary:disabled,
.btn--outlined:disabled,
.btn--danger:disabled,
.btn--danger-outlined:disabled {
  background-color: var(--md-surface-container-high);
  color: var(--md-on-surface-variant);
  border-color: var(--md-outline-variant);
  cursor: not-allowed;
  box-shadow: none;
}

.btn--primary:disabled:hover,
.btn--outlined:disabled:hover,
.btn--danger-outlined:disabled:hover {
  box-shadow: none;
  filter: none;
  background-color: var(--md-surface-container-high);
}

/* M3 Large Button (marketing CTAs) */
.btn--large {
  height: var(--md-button-height-large);
  padding: 0 var(--md-button-padding-x-large);
  font-size: var(--md-title-medium-size);
  line-height: var(--md-title-medium-line);
  font-weight: var(--md-title-medium-weight);
}

/* ---- Hero Section ---- */
.hero {
  text-align: center;
  padding: 0 0 var(--md-spacing-10) 0;
}

.hero__title {
  font-size: var(--md-display-medium-size);
  line-height: var(--md-display-medium-line);
  font-weight: var(--md-display-medium-weight);
  color: var(--md-primary);
  margin-bottom: var(--md-spacing-4);
}

.hero__subtitle {
  font-size: var(--md-body-large-size);
  line-height: var(--md-body-large-line);
  color: var(--md-on-surface-variant);
}

/* ---- M3 Card (Filled) ---- */
.card {
  background-color: var(--md-surface-container-high);
  border-radius: var(--md-shape-medium);
  padding: var(--md-spacing-5);
  transition: box-shadow var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.card:hover {
  box-shadow: var(--md-elevation-1);
}

/* A card that is not a target (the Billing page's): no lift on hover */
.card--static:hover {
  box-shadow: none;
}

.card--outlined {
  background-color: var(--md-surface);
  border: var(--md-divider-thickness) solid var(--md-outline-variant);
}

.card--elevated {
  background-color: var(--md-surface-container-low);
  box-shadow: var(--md-elevation-1);
}

.card--elevated:hover {
  box-shadow: var(--md-elevation-2);
}

.card__title {
  font-size: var(--md-title-large-size);
  line-height: var(--md-title-large-line);
  font-weight: var(--md-title-large-weight);
  color: var(--md-on-surface);
  margin-bottom: var(--md-spacing-2);
}

.card__subtitle {
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
  margin-bottom: var(--md-spacing-4);
}

.card__actions {
  display: flex;
  gap: var(--md-spacing-2);
  margin-top: var(--md-spacing-4);
}

/* ---- M3 Chip ---- */
.chip {
  display: inline-flex;
  align-items: center;
  height: var(--md-button-height-small);
  padding: 0 var(--md-spacing-4);
  border-radius: var(--md-shape-small);
  font-size: var(--md-label-large-size);
  font-weight: var(--md-label-large-weight);
  line-height: var(--md-label-large-line);
  border: var(--md-divider-thickness) solid var(--md-outline);
  color: var(--md-on-surface-variant);
  background-color: transparent;
  cursor: pointer;
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.chip:hover {
  background-color: var(--md-surface-container-high);
}

.chip--selected {
  background-color: var(--md-secondary-container);
  color: var(--md-on-secondary-container);
  border-color: transparent;
}

/* A read-only LABEL (2026-10-28, both portals): a word that names what a thing is, not what state it
   is in - Resident, Manager, You, Assistant, Soon / Coming soon, a metered space's tags (EV charger),
   a location's types on the patrol page. The outlined chip at the label-small size, sentence case, no
   tone, nothing to click: the base chip is a control (pointer, hover fill), both off here. A number is
   .badge--count; a state is .status-badge. Inside a rail or drawer row it takes the row's colour. */
.chip--label {
  height: auto;
  padding: var(--md-spacing-1) var(--md-spacing-2);
  gap: var(--md-spacing-1);
  font-size: var(--md-label-small-size);
  line-height: var(--md-label-small-line);
  border-color: var(--md-outline-variant);
  cursor: default;
  white-space: nowrap;
  vertical-align: middle;
}

.chip--label:hover {
  background-color: transparent;
}

/* Inside something clickable (a rail or drawer row, the patrol page's location card, the visitor's space
   slide) the label follows the ancestor's pointer, so the hand never breaks over the chip */
a .chip--label,
button .chip--label {
  cursor: inherit;
}

/* An icon inside a label (the visitor's space tags, enduser-get-pass.js: fmt.tagIcon) */
.chip--label .material-symbols-outlined {
  font-size: var(--md-icon-size-small);
}

/* On the charcoal rail and drawer rows the label takes the row's colour and the dark palette's
   --md-outline for its hairline (--md-outline-variant is the rail's own divider tone there, too faint
   for a ring on the row's fill) */
.nav-rail__item .chip--label,
.drawer__item .chip--label,
.navbar__panel .chip--label {
  color: inherit;
  border-color: var(--md-outline);
}

/* ---- M3 FAB (Floating Action Button) ---- */
.fab {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--md-fab-size-medium);
  height: var(--md-fab-size-medium);
  border-radius: var(--md-shape-large);
  border: none;
  background-color: var(--md-primary-container);
  color: var(--md-on-primary-container);
  font-size: var(--md-icon-size-medium);
  cursor: pointer;
  box-shadow: var(--md-elevation-3);
  transition: box-shadow var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.fab:hover {
  box-shadow: var(--md-elevation-4);
}

.fab--small {
  width: var(--md-fab-size-small);
  height: var(--md-fab-size-small);
  border-radius: var(--md-shape-medium);
  font-size: var(--md-icon-size-small);
}

.fab--large {
  width: var(--md-fab-size-large);
  height: var(--md-fab-size-large);
  border-radius: var(--md-shape-extra-large);
  font-size: var(--md-icon-size-large);
}

/* ---- M3 Text Field ---- */
/* No outer margin below a field: the form column's gap owns the spacing, so a 16px gap plus the
   8px of label room above the next field puts stacked fields 24px apart (the onboarding wizard's
   rhythm) instead of the gap and a margin adding up */
.text-field {
  position: relative;
}

.text-field__input {
  width: 100%;
  padding: var(--md-spacing-6) var(--md-spacing-4) var(--md-spacing-2) var(--md-spacing-4);
  background-color: var(--md-surface-container-highest);
  border: none;
  border-bottom: var(--md-divider-thickness) solid var(--md-on-surface-variant);
  border-radius: var(--md-shape-extra-small) var(--md-shape-extra-small) 0 0;
  color: var(--md-on-surface);
  font-size: var(--md-text-field-font-size);
  line-height: var(--md-text-field-line);
  outline: none;
  transition: border-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.text-field__input:focus {
  border-bottom-width: calc(var(--md-divider-thickness) * 2);
  border-bottom-color: var(--md-primary);
  padding-bottom: calc(var(--md-spacing-2) - var(--md-divider-thickness));
}

.text-field__label {
  position: absolute;
  top: var(--md-spacing-4);
  left: var(--md-spacing-4);
  font-size: var(--md-text-field-font-size);
  line-height: var(--md-text-field-line);
  color: var(--md-on-surface-variant);
  pointer-events: none;
  transition:
    top var(--md-motion-duration-short) var(--md-motion-easing-standard),
    font-size var(--md-motion-duration-short) var(--md-motion-easing-standard),
    line-height var(--md-motion-duration-short) var(--md-motion-easing-standard),
    color var(--md-motion-duration-short) var(--md-motion-easing-standard);
  transform-origin: left top;
}

/* Floating label when focused or has value */
.text-field__input:focus ~ .text-field__label,
.text-field__input:not(:placeholder-shown) ~ .text-field__label {
  top: var(--md-spacing-1);
  font-size: var(--md-body-small-size);
  color: var(--md-primary);
}

/* When not focused but has value, use on-surface-variant color */
.text-field__input:not(:focus):not(:placeholder-shown) ~ .text-field__label {
  color: var(--md-on-surface-variant);
}

/* M3 Outlined Text Field: the button height (--md-text-field-height), so a field, a button, the
   search bar and a segmented group share one line. A single-line input centres its text in its
   box itself, so the 1px -> 2px focus border needs no padding compensation; textareas get the
   derived vertical padding instead (see Textarea) */
.text-field--outlined {
  margin-top: var(--md-spacing-2);
}

.text-field--outlined .text-field__input {
  height: var(--md-text-field-height);
  background-color: transparent;
  border: var(--md-divider-thickness) solid var(--md-outline);
  border-radius: var(--md-shape-extra-small);
  padding: 0 var(--md-spacing-4);
}

/* Hover darkens the outline, like the dropdown trigger's */
.text-field--outlined:not(.text-field--error) .text-field__input:hover:not(:focus):not([readonly]):not(:disabled) {
  border-color: var(--md-on-surface);
}

.text-field--outlined .text-field__input:focus {
  border-color: var(--md-primary);
  border-width: calc(var(--md-divider-thickness) * 2);
  padding: 0 calc(var(--md-spacing-4) - var(--md-divider-thickness));
}

/* Resting label: its line box is the typed text's (same role, centred in the field) and its text
   starts on the typed text's x (border + padding = left + the label's own padding); one line,
   clipped with an ellipsis in a narrow field */
.text-field--outlined .text-field__label {
  top: calc((var(--md-text-field-height) - var(--md-text-field-line)) / 2);
  left: calc(var(--md-spacing-3) + var(--md-divider-thickness));
  max-width: calc(100% - 2 * (var(--md-spacing-3) + var(--md-divider-thickness)));
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  background-color: transparent; /* the notch is painted only once the label floats onto the border */
  padding: 0 var(--md-spacing-1);
}

/* Floating label for outlined variant */
.text-field--outlined .text-field__input:focus ~ .text-field__label,
.text-field--outlined .text-field__input:not(:placeholder-shown) ~ .text-field__label {
  top: var(--md-label-offset);
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
  background-color: var(--md-surface);
  color: var(--md-primary);
}

/* Fields with a trailing control (stepper, eye, calendar, clock): the resting label stops before it */
.number-input .text-field__label,
.password-input .text-field__label,
.date-picker__field .text-field__label,
.time-input__field .text-field__label {
  max-width: calc(100% - var(--md-input-icon-area) - var(--md-spacing-3));
}

/* When not focused but has value, use on-surface-variant color */
.text-field--outlined .text-field__input:not(:focus):not(:placeholder-shown) ~ .text-field__label {
  color: var(--md-on-surface-variant);
}

/* Read-only fields: a manager's auto-filled company profile, a manager's sign-in email.
   Looks like a filled field, never like an editable one - no focus ring, no primary label. */
.text-field__input[readonly] {
  color: var(--md-on-surface-variant);
  cursor: default;
}

.text-field--outlined .text-field__input[readonly] {
  border-style: dashed;
}

.text-field--outlined .text-field__input[readonly]:focus {
  border-color: var(--md-outline);
  border-width: var(--md-divider-thickness);
  padding: 0 var(--md-spacing-4);
}

.text-field__input[readonly]:focus ~ .text-field__label,
.text-field--outlined .text-field__input[readonly]:focus ~ .text-field__label {
  color: var(--md-on-surface-variant);
}

/* Error state + supporting text (emitted by textarea.ejs, toggled by lead-form.js) */
.text-field--error .text-field__input,
.text-field--error .text-field__input:focus {
  border-color: var(--md-error);
}

.text-field--error .text-field__label,
.text-field--error .text-field__input:focus ~ .text-field__label,
.text-field--error .text-field__input:not(:focus):not(:placeholder-shown) ~ .text-field__label {
  color: var(--md-error);
}

.text-field__helper,
.text-field__error-text {
  margin: var(--md-spacing-1) 0 0;
  padding: 0 var(--md-spacing-4);
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
  color: var(--md-on-surface-variant);
}

.text-field__error-text {
  color: var(--md-error);
}

/* A field's trailing status (email-check.js: the green check once the address's domain can receive
   mail): the password toggle's geometry at the small-button size, centred on the single-line box,
   never interactive */
.text-field--with-status .text-field__input {
  padding-right: calc(var(--md-input-icon-area) + var(--md-spacing-2));
}

.text-field__status {
  position: absolute;
  right: var(--md-spacing-1);
  top: calc(var(--md-text-field-height) / 2);
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--md-button-height-small);
  height: var(--md-button-height-small);
  font-size: var(--md-icon-size-medium);
  color: var(--md-primary);
  pointer-events: none;
}

/* The line email-check.js adds under a field that has no error element of its own: the helper
   line's type; "Did you mean name@gmail.com?" as a text button, or a refusal in the error colour */
.text-field__hint {
  margin: var(--md-spacing-1) 0 0;
  padding: 0 var(--md-spacing-4);
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
  color: var(--md-on-surface-variant);
}

.text-field__hint--error {
  color: var(--md-error);
}

.text-field__hint-btn {
  padding: 0;
  border: none;
  background: none;
  font: inherit;
  color: var(--md-primary);
  text-decoration: underline;
  cursor: pointer;
}

/* ---- Cloudflare Turnstile (partials/turnstile, turnstile.js) ----
   The container stays collapsed: nothing shows unless Cloudflare asks for a checkbox, and then the
   component adds --shown (Cloudflare's before-interactive callback). In a flex form stack the
   container shares a .turnstile-row with the submit button, so the collapsed state takes no gap. */
.turnstile {
  height: 0;
  overflow: hidden;
}

.turnstile--shown {
  height: auto;
  overflow: visible;
  margin-bottom: var(--md-spacing-4);
}

.turnstile-row {
  display: flex;
  flex-direction: column;
}

/* ---- M3 Badge ---- */
.badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--md-spacing-4);
  height: var(--md-spacing-4);
  padding: 0 var(--md-spacing-1);
  border-radius: var(--md-shape-full);
  background-color: var(--md-error);
  color: var(--md-on-error);
  font-size: var(--md-label-small-size);
  font-weight: var(--md-label-small-weight);
}

.badge--large {
  min-width: var(--md-icon-size-medium);
  height: var(--md-icon-size-medium);
  padding: 0 var(--md-spacing-2);
}

.badge--count {
  background-color: var(--md-secondary-container);
  color: var(--md-on-secondary-container);
}

/* ---- M3 Divider ---- */
.divider {
  border: none;
  height: var(--md-divider-thickness);
  background-color: var(--md-outline-variant);
  margin: var(--md-spacing-4) 0;
}

/* ---- M3 Switch ---- */
.switch {
  position: relative;
  display: inline-block;
  width: var(--md-switch-width);
  height: var(--md-button-height-small);
}

.switch__input {
  opacity: 0;
  width: 0;
  height: 0;
}

.switch__track {
  position: absolute;
  inset: 0;
  background-color: var(--md-surface-container-highest);
  border: calc(var(--md-divider-thickness) * 2) solid var(--md-outline);
  border-radius: var(--md-shape-full);
  cursor: pointer;
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard),
              border-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.switch__track::before {
  content: '';
  position: absolute;
  width: var(--md-spacing-4);
  height: var(--md-spacing-4);
  left: calc(var(--md-spacing-2) - calc(var(--md-divider-thickness) * 2));
  top: 50%;
  transform: translateY(-50%);
  background-color: var(--md-outline);
  border-radius: var(--md-shape-full);
  transition: transform var(--md-motion-duration-short) var(--md-motion-easing-standard),
              width var(--md-motion-duration-short) var(--md-motion-easing-standard),
              background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.switch__input:checked + .switch__track {
  background-color: var(--md-primary);
  border-color: var(--md-primary);
}

.switch__input:checked + .switch__track::before {
  transform: translateY(-50%) translateX(18px);
  width: var(--md-icon-size-medium);
  height: var(--md-icon-size-medium);
  margin-left: calc(var(--md-spacing-1) * -1);
  background-color: var(--md-on-primary);
}

.switch__input:focus-visible + .switch__track {
  outline: calc(var(--md-divider-thickness) * 2) solid var(--md-primary);
  outline-offset: calc(var(--md-divider-thickness) * 2);
}

.switch__input:disabled + .switch__track {
  opacity: var(--md-opacity-disabled);
  cursor: not-allowed;
}

/* Small switch (partials/switch.ejs small: true): a 40 x 24 track whose thumb grows from 12 to
   16px, so it sits on one line of body text instead of spanning two */
.switch--small {
  width: var(--md-spacing-10);
  height: var(--md-spacing-6);
}

.switch--small .switch__track::before {
  width: var(--md-spacing-3);
  height: var(--md-spacing-3);
}

.switch--small .switch__input:checked + .switch__track::before {
  transform: translateY(-50%) translateX(calc(var(--md-spacing-3) - var(--md-divider-thickness) * 2));
  width: var(--md-spacing-4);
  height: var(--md-spacing-4);
  margin-left: 0;
}

/* Switch row (partials/switch.ejs): the switch beside its label and description */
.switch-row {
  display: flex;
  align-items: flex-start;
  gap: var(--md-spacing-3);
}

.switch-row .switch {
  flex-shrink: 0;
}

.switch-row__text {
  min-width: 0;
  padding-top: var(--md-spacing-1);
}

/* The small switch's 24px track centred on the label's 20px line */
.switch-row--small .switch-row__text {
  padding-top: calc((var(--md-spacing-6) - var(--md-body-medium-line)) / 2);
}

.switch-row__label {
  display: block;
  color: var(--md-on-surface);
  cursor: pointer;
}

.switch-row__description {
  margin: var(--md-spacing-1) 0 0;
  color: var(--md-on-surface-variant);
}

.switch-row--disabled .switch-row__label {
  color: var(--md-on-surface-variant);
  cursor: default;
}

/* Access panel (views/portal/managers.ejs, client-managers.js): the capability groups in
   columns, the location choice, the roster's two-line Access cell */
.access-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--md-spacing-6);
}

@media (min-width: 768px) {
  .access-grid {
    grid-template-columns: 1fr 1fr;
  }
}

.access-group {
  border: 0;
  margin: 0;
  padding: 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-4);
}

/* A legend sits outside its fieldset's flex gap, so the heading carries the panel's block
   rhythm (--md-spacing-4, the gap of .access-where and .tool-panel) as its own bottom margin */
.access-group__title {
  padding: 0;
  margin: 0 0 var(--md-spacing-4);
  color: var(--md-on-surface-variant);
}

.access-where {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-4);
  max-width: var(--md-component-width-xlarge);
}

/* The add form's access block is hidden while editing: the attribute must beat the flex display */
.access-where[hidden] {
  display: none;
}

.access-chosen {
  margin: 0;
  color: var(--md-on-surface-variant);
}

.access-cell__sub {
  display: block;
  color: var(--md-on-surface-variant);
}

/* One row per chosen location under the locations dropdown: the "All units" small switch, the
   name with its unit count, and (when some units are picked) the units dropdown on a line of
   its own below them */
.access-unit-rows {
  display: flex;
  flex-direction: column;
  margin-top: var(--md-spacing-2);
}

.access-unit-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--md-spacing-3) var(--md-spacing-3);
  padding: var(--md-spacing-4) 0;
  border-top: var(--md-divider-thickness) solid var(--md-outline-variant);
}

.access-unit-row__text {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.access-unit-row__picker {
  flex: 1 1 100%;
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-2);
  padding-top: var(--md-spacing-2);
}

.access-unit-row__picker:empty {
  display: none;
}

/* Small button: the 32px small height and tighter padding, the label unchanged (the roster's
   row actions, which must stay on one line) */
.btn--small {
  height: var(--md-button-height-small);
  padding: 0 var(--md-spacing-2);
}

/* A small ringed button (the tables' row actions, the page heads' Go back) keeps a small filled one's
   width: the padding less the border, as the medium outlined variants do */
.btn--outlined.btn--small,
.btn--danger-outlined.btn--small {
  padding: 0 calc(var(--md-spacing-2) - var(--md-divider-thickness));
}

/* ---- Reference Page Grid ---- */
.ref-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(var(--md-card-min-width), 1fr));
  gap: var(--md-spacing-6);
}

/* ---- Property List (end-user wizards: set-residence, get-pass) ---- */
.property-list-wrap {
  position: relative;
}

/* Bottom fade - signals more content below; hidden when scrolled to the end */
.property-list-wrap::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: var(--md-spacing-16);
  background: linear-gradient(to bottom, transparent, var(--md-surface));
  pointer-events: none;
  transition: opacity var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.property-list-wrap--at-end::after {
  opacity: 0;
}

.property-list {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-3);
  max-height: var(--md-list-max-height-large);
  overflow-y: auto;
  padding-right: var(--md-spacing-2);
  scrollbar-width: thin;
  scrollbar-color: var(--md-outline) transparent;
}

.property-list::-webkit-scrollbar {
  width: var(--md-spacing-2);
}

.property-list::-webkit-scrollbar-thumb {
  background-color: var(--md-outline);
  border-radius: var(--md-shape-full);
}

.property-list::-webkit-scrollbar-track {
  background: transparent;
}

.property-list__search {
  margin-bottom: var(--md-spacing-4);
}

/* ---- Status chip (both portals; the owner's pick of 2026-10-28, first on the Billing pages, then
   everywhere the same day) ----
   A thing's STATE is drawn one way: a dot in the status tone before the word, sentence case, no fill,
   no border, one line. Four tones by one rule - --active green = in effect now; --pending amber = ahead
   or waiting on something; --suspended red = refused, failed or shut; --expired grey (also the dot of a
   word no map knows) = over or empty. The word takes the surface's secondary text, so on a charcoal
   surface (the assistant dock, mk-section--dark) it follows the dark tokens by itself. A LABEL that is
   not a state (Resident, Manager, You, Assistant, Soon, a space's tags, a location's type) is
   .chip--label, never a status-badge; a number is .badge--count; the one filled pill left is --exempt
   below. The status word -> tone map: full_documentation.md section 6, "Status chips and labels".
   vertical-align: middle centres the chip on the text's x-height after a name (Commercial's Pending,
   a resident's Not signed in yet); it has no effect inside flex rows. */
.status-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--md-spacing-1);
  padding: 0;
  border: 0;
  background-color: transparent;
  font-size: var(--md-label-medium-size);
  line-height: var(--md-label-medium-line);
  font-weight: var(--md-label-large-weight);
  letter-spacing: var(--md-letter-spacing-default);
  text-transform: none;
  white-space: nowrap;
  vertical-align: middle;
  color: var(--md-on-surface-variant);
}

/* A chip shipped `hidden` until a script fills it (Billing's head and payouts chips) stays hidden: the
   author display would otherwise beat the attribute and the empty chip would show as a lone dot */
.status-badge[hidden],
.chip--label[hidden] {
  display: none;
}

.status-badge::before {
  content: '';
  width: var(--md-spacing-2);
  height: var(--md-spacing-2);
  border-radius: var(--md-shape-full);
  background-color: var(--md-outline);
  flex-shrink: 0;
}

.status-badge--active::before {
  background-color: var(--md-primary);
}

.status-badge--pending::before {
  background-color: var(--md-warning);
}

.status-badge--suspended::before {
  background-color: var(--md-error);
}

.status-badge--expired::before {
  background-color: var(--md-outline);
}

/* Exempt plates (client_exempt_plates): the one filled pill, an instruction to officers ("never tow"),
   not a state - the charcoal pair, uppercase, no dot; on plate rows, search results, the history view
   and the patrol page's Exempt list (plate-history.js exemptBadge) */
.status-badge--exempt {
  gap: 0;
  padding: var(--md-spacing-1) var(--md-spacing-3);
  border-radius: var(--md-shape-full);
  background-color: var(--md-inverse-surface);
  color: var(--md-inverse-on-surface);
  font-size: var(--md-label-small-size);
  line-height: var(--md-label-small-line);
  font-weight: var(--md-weight-bold);
  text-transform: uppercase;
  letter-spacing: calc(var(--md-letter-spacing-wide) / 2);   /* half the eyebrows' tracking: the pill's width of before */
}

.status-badge--exempt::before {
  content: none;
}

#chat-loading .progress--circular {
  width: var(--md-icon-size-medium);
  height: var(--md-icon-size-medium);
}

.ref-section {
  margin-bottom: var(--md-spacing-10);
}

.ref-section__title {
  font-size: var(--md-headline-small-size);
  line-height: var(--md-headline-small-line);
  color: var(--md-primary);
  margin-bottom: var(--md-spacing-4);
  padding-bottom: var(--md-spacing-2);
  border-bottom: var(--md-divider-thickness) solid var(--md-outline-variant);
}

.ref-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--md-spacing-4);
  align-items: center;
  margin-bottom: var(--md-spacing-4);
}

/* ---- Color Swatch ---- */
.swatch {
  width: var(--md-top-app-bar-height-small);
  height: var(--md-top-app-bar-height-small);
  border-radius: var(--md-shape-medium);
  border: var(--md-divider-thickness) solid var(--md-outline-variant);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding-bottom: var(--md-spacing-1);
}

.swatch__label {
  font-size: var(--md-label-small-size);
  text-align: center;
  margin-top: var(--md-spacing-1);
  color: var(--md-on-surface-variant);
}

/* ---- Color Editor ---- */
.color-editor-group {
  flex-wrap: wrap;
}

.color-editor-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--md-spacing-1);
}

.color-editor-item__controls {
  display: flex;
  align-items: center;
  gap: var(--md-spacing-1);
}

.color-editor-item__controls input[type="color"] {
  width: 28px;
  height: 28px;
  border: 1px solid var(--md-outline-variant);
  border-radius: var(--md-shape-small);
  cursor: pointer;
  padding: 0;
  background: none;
  -webkit-appearance: none;
  appearance: none;
}

.color-editor-item__controls input[type="color"]::-webkit-color-swatch-wrapper {
  padding: 2px;
}

.color-editor-item__controls input[type="color"]::-webkit-color-swatch {
  border: none;
  border-radius: calc(var(--md-shape-small) - 2px);
}

.color-editor-item__hex {
  color: var(--md-on-surface-variant);
  font-family: monospace;
  min-width: 64px;
  text-align: center;
}

/* ---- Type Sample ---- */
.type-sample {
  margin-bottom: var(--md-spacing-4);
}

.type-sample__label {
  font-size: var(--md-label-medium-size);
  color: var(--md-on-surface-variant);
  margin-bottom: var(--md-spacing-1);
}

/* ====================================================
   M3 USER FEEDBACK - Snackbar, Banner, Dialog
   ==================================================== */

/* ---- M3 Snackbar ---- */
.snackbar {
  position: fixed;
  bottom: calc(var(--md-spacing-6) + var(--ph-consent-h, 0px));   /* above the consent banner while it is shown (consent-banner.js) */
  left: 50%;
  transform: translateX(-50%) translateY(100px);
  min-width: var(--md-component-width-small);
  max-width: var(--md-component-width-xlarge);
  background-color: var(--md-inverse-surface);
  color: var(--md-inverse-on-surface);
  padding: var(--md-spacing-4) var(--md-spacing-4) var(--md-spacing-4) var(--md-spacing-6);
  border-radius: var(--md-shape-extra-small);
  box-shadow: var(--md-elevation-3);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--md-spacing-4);
  /* Above .dialog-overlay (--md-z-dialog). An error is always the snackbar (2026-10-29), and a dialog that
     stays open after a refusal (Edit location, Rename, Suspend / Ban, the assistant's terms) must show it
     over its scrim with the X and the action clickable. The consent banner keeps 1000: it is never part
     of a dialog's task and sits under the scrim like the rest of the page. */
  z-index: var(--md-z-snackbar);
  opacity: 0;
  transition: transform var(--md-motion-duration-medium) var(--md-motion-easing-decelerate),
              opacity var(--md-motion-duration-medium) var(--md-motion-easing-decelerate);
}

.snackbar--visible {
  transform: translateX(-50%) translateY(0);
  opacity: 1;
}

.snackbar__text {
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  flex: 1;
}

.snackbar__action {
  background: none;
  border: none;
  color: var(--md-inverse-primary);
  font-size: var(--md-label-large-size);
  font-weight: var(--md-label-large-weight);
  cursor: pointer;
  padding: var(--md-spacing-2) var(--md-spacing-3);
  border-radius: var(--md-shape-extra-small);
  white-space: nowrap;
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.snackbar__action:hover {
  background-color: var(--md-primary-hover-overlay);
}

.snackbar__close {
  background: none;
  border: none;
  color: var(--md-inverse-on-surface);
  font-size: var(--md-icon-size-small);
  cursor: pointer;
  padding: var(--md-spacing-1);
  opacity: 0.7;
  line-height: 1;
}

.snackbar__close:hover {
  opacity: 1;
}

/* Snackbar variants */
.snackbar--error {
  background-color: var(--md-error-container);
  color: var(--md-on-error-container);
}

/* The charcoal face's light X would be invisible on the pink one */
.snackbar--error .snackbar__close {
  color: var(--md-on-error-container);
}

/* ═══════════════════════════════════════════════════════════════
   CONSENT BANNER (partials/consent-banner, consent-banner.js)
   A fixed bottom sheet in the snackbar family: inverse surface so it
   reads on every page. One sentence with two actions beside it; the
   three-choice form (pages that also ask for ad measurement) stacks
   the sentence over its actions.
   ═══════════════════════════════════════════════════════════════ */
.consent-banner {
  position: fixed;
  bottom: var(--md-spacing-6);
  left: 50%;
  transform: translateX(-50%);
  width: calc(100% - var(--md-spacing-8));
  max-width: var(--md-component-width-xlarge);
  background-color: var(--md-inverse-surface);
  color: var(--md-inverse-on-surface);
  padding: var(--md-spacing-4) var(--md-spacing-6);
  border-radius: var(--md-shape-medium);
  box-shadow: var(--md-elevation-3);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--md-spacing-6);
  z-index: 1000;
}

.consent-banner[hidden] {
  display: none;
}

.consent-banner__text {
  flex: 1;
  margin: 0;
  color: var(--md-inverse-on-surface);   /* base.css colours <p> for the page surface; this sits on the inverse surface */
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
}

.consent-banner__link {
  color: var(--md-inverse-primary);
  font-weight: var(--md-label-large-weight);
  text-decoration: underline;
}

.consent-banner__actions {
  display: flex;
  align-items: center;
  gap: var(--md-spacing-2);
  flex-shrink: 0;
}

.consent-banner__actions .btn--text {
  color: var(--md-inverse-on-surface);
}

/* Three actions beside the sentence squeeze it into a tall, narrow column. The three-choice form
   puts the sentence on top and the actions on their own row (the snackbar's layout for longer
   actions), as every form already does below 768px. */
.consent-banner--stacked {
  flex-direction: column;
  align-items: stretch;
  gap: var(--md-spacing-4);
}

.consent-banner--stacked .consent-banner__actions {
  justify-content: flex-end;
}

@media (max-width: 767px) {
  .consent-banner {
    flex-direction: column;
    align-items: stretch;
    gap: var(--md-spacing-4);
    bottom: var(--md-spacing-4);
    width: calc(100% - var(--md-spacing-4) * 2);
  }

  .consent-banner__actions {
    justify-content: flex-end;
    flex-wrap: wrap;   /* the three-choice form does not fit one row on a narrow phone */
  }
}

.snackbar--error .snackbar__action {
  color: var(--md-error);
}

/* ---- M3 Banner ---- */
.banner {
  background-color: var(--md-surface-container);
  border-bottom: var(--md-divider-thickness) solid var(--md-outline-variant);
  padding: var(--md-spacing-4) var(--md-spacing-6);
  display: none;
  align-items: flex-start;
  gap: var(--md-spacing-4);
}

.banner--visible {
  display: flex;
}

.banner__icon {
  font-size: var(--md-icon-size-medium);
  color: var(--md-primary);
  flex-shrink: 0;
  line-height: 1;
  padding-top: calc(var(--md-spacing-1) / 2);
}

.banner__content {
  flex: 1;
}

.banner__text {
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface);
  margin-bottom: 0;
}

.banner__actions {
  display: flex;
  gap: var(--md-spacing-2);
  margin-top: var(--md-spacing-3);
}

.banner__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--md-button-height-small);
  background: none;
  border: none;
  color: var(--md-primary);
  font-size: var(--md-label-large-size);
  font-weight: var(--md-label-large-weight);
  line-height: var(--md-label-large-line);
  cursor: pointer;
  padding: var(--md-button-padding-y-small) var(--md-button-padding-x-small);
  border-radius: var(--md-shape-small);
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.banner__btn:hover {
  background-color: var(--md-surface-container-high);
}

/* Banner variants */
.banner--error .banner__icon {
  color: var(--md-error);
}

/* ---- M3 Dialog (Modal) ---- */
.dialog-overlay {
  position: fixed;
  inset: 0;
  background-color: var(--md-scrim-dark);
  z-index: var(--md-z-dialog);
  display: none;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transition: opacity var(--md-motion-duration-medium) var(--md-motion-easing-standard);
}

.dialog-overlay--visible {
  display: flex;
  opacity: 1;
}

/* The dialog surface is the content panel's (--md-surface, layout.css .site--portal > .main), not the
   raised container tint: a dialog over the white panel is the same white (the owner's call,
   2026-10-27); inside the charcoal assistant dock the dark palette's container keeps it readable */
.dialog {
  background-color: var(--md-surface);
  border-radius: var(--md-shape-extra-large);
  padding: var(--md-spacing-6);
  min-width: var(--md-component-width-small);
  max-width: var(--md-component-width-xlarge);
  width: 90%;
  box-shadow: var(--md-elevation-3);
  transform: scale(0.9);
  transition: transform var(--md-motion-duration-medium) var(--md-motion-easing-emphasized);
}

.dialog-overlay--visible .dialog {
  transform: scale(1);
}

.mk-section--dark .dialog {
  background-color: var(--md-surface-container-high);
}

.dialog__icon {
  text-align: center;
  font-size: var(--md-icon-size-medium);
  color: var(--md-primary);
  margin-bottom: var(--md-spacing-4);
}

.dialog__title {
  font-size: var(--md-headline-small-size);
  line-height: var(--md-headline-small-line);
  font-weight: var(--md-headline-small-weight);
  color: var(--md-on-surface);
  margin-bottom: var(--md-spacing-4);
}

.dialog__body {
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
  margin-bottom: var(--md-spacing-6);
}

.dialog__actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--md-spacing-2);
  margin-top: var(--md-spacing-6); /* 24px above the buttons whatever precedes them: the body's own bottom margin collapses into it, a field (no margin of its own) gets it in full */
}

/* Two fields side by side in a dialog (the Edit location dialogs' charge + maximum, price + tax, From +
   To); they stack on a phone (responsive.css) */
.dialog__row {
  display: flex;
  gap: var(--md-spacing-4);
  margin-top: var(--md-spacing-3);
}

.dialog__row > * {
  flex: 1 1 0;
  min-width: 0;
}

/* A row or block a switch hides (the metered Edit location dialog: the hours under Open 24 hours, a
   pricing mode's fields, the cancellation terms): the display rules above would otherwise beat the
   hidden attribute, like .dialog__slot[hidden] below */
.dialog__row[hidden],
.dialog__block[hidden] {
  display: none;
}

/* A switch beside a field in a dialog row (the metered dialog's Booking, tax and refund rows): the
   toggle centred on the field's box - the field's 8px label room, then the box's height minus the
   track's, halved - so the two items of the row share one line, their helper and description lines
   under them */
.dialog__row > .switch-row {
  margin-top: calc(var(--md-spacing-2) + (var(--md-text-field-height) - var(--md-button-height-small)) / 2);
}

/* A block of the dialog after the body (a switch row, a fieldset) */
.dialog__block {
  margin-top: var(--md-spacing-4);
}

/* The settings a location applies to every row (the Edit location dialogs): a fieldset, so a person
   without the capability gets it disabled as one, with the eyebrow naming it */
.dialog__fieldset {
  margin: var(--md-spacing-4) 0 0;
  padding: 0;
  border: 0;
  min-width: 0;
}

.dialog__fieldset:disabled {
  opacity: var(--md-opacity-disabled);
}

.dialog__label {
  margin: 0 0 var(--md-spacing-2);
  font-size: var(--md-title-small-size);
  line-height: var(--md-title-small-line);
  font-weight: var(--md-title-small-weight);
  color: var(--md-on-surface-variant);
}

.dialog__row + .dialog__label {
  margin-top: var(--md-spacing-4);
}

.dialog__hint {
  margin: var(--md-spacing-2) 0 0;
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
  color: var(--md-on-surface-variant);
}

/* The Metered page's Edit location dialog (2026-10-27): a location's hours, prices, slots and
   booking rules in groups - wider than a plain dialog, and it scrolls inside the viewport
   instead of being clipped by the centred overlay */
.dialog--wide {
  max-width: calc(var(--md-component-width-xlarge) + var(--md-component-width-small));
  max-height: calc(100vh - var(--md-spacing-12));
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* The dialog's groups (Hours, Booking, Pricing, Slots, Cancellation): each rule set under a hairline
   with air on both sides, its title (dialog__label) first, then its rows - the ones a switch reveals
   sit inside the group, so the next hairline always follows the group's last row */
.dialog__group {
  margin-top: var(--md-spacing-6);
  padding-top: var(--md-spacing-5);
  border-top: var(--md-divider-thickness) solid var(--md-outline-variant);
}

.dialog__group > .dialog__label {
  color: var(--md-on-surface);
}

/* The slot editor: one outlined card per slot - a head row (the label, Length | Clock, remove) over
   its fields (the hours, or the from and to times, and the price), the fields wrapping on a narrow
   screen; a pre-rendered pool, hidden until added */
.dialog__slots {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-3);
  margin: var(--md-spacing-3) 0;
}

.dialog__slot {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-3);
  padding: var(--md-spacing-3);
  border: var(--md-divider-thickness) solid var(--md-outline-variant);
  border-radius: var(--md-shape-medium);
}

.dialog__slot-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--md-spacing-3);
}

.dialog__slot-head > .dialog__slot-label {
  flex: 1 1 var(--md-component-width-small);
  min-width: 0;
  margin: 0;
}

.dialog__slot-head > .dialog__slot-kind,
.dialog__slot-head > .dialog__slot-remove {
  flex: 0 0 auto;
}

.dialog__slot-head > .dialog__slot-remove {
  margin-left: auto;
}

.dialog__slot-head .segmented-button {
  margin: 0;
}

.dialog__slot-fields {
  display: flex;
  flex-wrap: wrap;
  gap: var(--md-spacing-3);
}

.dialog__slot-fields > * {
  flex: 1 1 var(--md-component-width-xsmall);
  min-width: 0;
}

.dialog__slot-fields > [hidden] {
  display: none;
}

.dialog__slot .time-input {
  display: block;
  width: 100%;
  margin-bottom: 0;
}

.dialog__slot[hidden] {
  display: none;
}

/* The free-parking hint of the pricing group reads in the brand green, with a row's air above it */
.dialog__hint--free {
  margin-top: var(--md-spacing-3);
  color: var(--md-primary);
  font-weight: var(--md-weight-bold);
}

/* A dialog's two buttons (the owner's rule, 2026-10-28): the dismiss button carries the hairline ring
   (the .btn--outlined recipe: the padding less the border, the container-high hover), the confirm
   button is filled - the filled one is always the safe or main choice (Keep my trial beside End trial) */
.dialog__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--md-button-height-medium);
  background: none;
  border: var(--md-divider-thickness) solid var(--md-outline);
  color: var(--md-primary);
  font-size: var(--md-label-large-size);
  font-weight: var(--md-label-large-weight);
  line-height: var(--md-label-large-line);
  cursor: pointer;
  padding: calc(var(--md-button-padding-y-medium) - var(--md-divider-thickness)) calc(var(--md-button-padding-x-medium) - var(--md-divider-thickness));
  border-radius: var(--md-button-radius);
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.dialog__btn:hover {
  background-color: var(--md-surface-container-high);
}

.dialog__btn--confirm {
  background-color: var(--md-primary);
  border-color: var(--md-primary);
  color: var(--md-on-primary);
}

.dialog__btn--confirm:hover {
  background-color: var(--md-primary);
  filter: brightness(1.1);
}

/* A destructive third button at the footer's left (the Edit location dialogs' Delete location,
   2026-10-29): the ringed recipe in the error colour, pushed away from Cancel / Save */
.dialog__btn--danger {
  color: var(--md-error);
  border-color: var(--md-error);
  margin-right: auto;
}

.dialog__btn--danger:hover {
  background-color: var(--md-error-container);
}

/* Dialog icon may hold a Material Symbol instead of a glyph */
.dialog__icon .material-symbols-outlined {
  font-size: var(--md-icon-size-large);
}

/* Error dialog */
.dialog--error .dialog__icon {
  color: var(--md-error);
}

/* ---- Temporary password reveal (managers page dialog; shown once) ---- */
.temp-password {
  display: flex;
  align-items: center;
  gap: var(--md-spacing-3);
  padding: var(--md-spacing-4);
  background-color: var(--md-surface-container-lowest);
  border: var(--md-divider-thickness) dashed var(--md-outline);
  border-radius: var(--md-shape-medium);
  margin-bottom: var(--md-spacing-4);
}

.temp-password__value {
  flex: 1;
  min-width: 0;
  font-family: ui-monospace, 'Courier New', monospace;
  font-size: var(--md-title-large-size);
  line-height: var(--md-title-large-line);
  letter-spacing: 0.08em;
  color: var(--md-primary);
  user-select: all;
  word-break: break-all;
}

.temp-password .btn {
  flex-shrink: 0;
}

/* ---- Inline expand row (the managers, property, services and residents pages' in-place forms) ---- */
.expand-row td {
  padding: 0 !important;
  border: none !important;
}

.expand-row__inner {
  overflow: hidden;
  animation: expandRow var(--md-motion-duration-medium) var(--md-motion-easing-standard);
}

/* Settled (a page adds it on the expand animation's end, 2026-10-23): the row stops clipping, so a
   dropdown menu or a date / time picker near the bottom of the form hangs below it; the closing
   animation removes it first and clips again */
.expand-row__inner--settled {
  overflow: visible;
}

.expand-row__inner--closing {
  animation: collapseRow var(--md-motion-duration-short) var(--md-motion-easing-standard) forwards;
}

/* The cap of the opening and closing sweep: a page may set --expand-max on the wrapper to the panel's
   own height (residents.ejs openFormInRow; the expand-row.js library does), so a panel taller than the
   viewport never pops in at the animation's end; the other pages keep the viewport */
@keyframes expandRow {
  from { opacity: 0; max-height: 0; }
  to { opacity: 1; max-height: var(--expand-max, 100vh); }
}

@keyframes collapseRow {
  from { opacity: 1; max-height: var(--expand-max, 100vh); }
  to { opacity: 0; max-height: 0; }
}

/* ---- Expand-row form (2026-10-23): the in-place form's shell as classes, first on the Residents view
   (residents.ejs), then the Metered page and the Reservations view, and since 2026-10-29 Exempt Plates
   and the Services pages (the Residential and Commercial pages and Managers still draw the same shell
   inline). The column gap owns the rhythm: 16px plus the outlined field's 8px of label room puts
   stacked rows 24px apart (the onboarding wizard's rule, .text-field--outlined / .dropdown--outlined);
   fields sit 16px apart in a row; an actions row 24px under the last row; a section's hairline 24px
   from both sides. No rule here uses a bottom margin or a negative one ---- */
.expand-form {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-4);
  padding: var(--md-spacing-6);
  background-color: var(--md-surface-container-low);
  border-radius: var(--md-shape-medium);
}

/* A capability the person lacks hides a row, a section or a button with the hidden attribute (the
   classes' display would win over the attribute otherwise); an empty message slot or note takes no
   gap slot; a shown alert's own bottom margin yields to the gap (.onb__form .alert) */
.expand-form [hidden],
.expand-form__msg:empty,
.expand-form__note:empty {
  display: none;
}

.expand-form__msg .alert {
  margin-bottom: 0;
}

.expand-form__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--md-spacing-4);
}

/* The read-only pairs over a form (Resident / Property): label over value, the value in the text
   colour (p's default is the variant) */
.expand-form__facts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--md-spacing-2) var(--md-spacing-6);
}

.expand-form__fact {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-1);
}

.expand-form__fact > p {
  margin: 0;
}

.expand-form__fact > p + p {
  color: var(--md-on-surface);
}

/* A row of fields: the cells share the width (.dialog__row's recipe), tops aligned so a dropdown's
   supporting line never stretches its neighbours; --short caps a stepper; --wrap lets cells with
   their own flex bases (the vehicle's five fields, the three picker dropdowns) flow onto more lines */
.expand-form__row {
  display: flex;
  align-items: flex-start;
  gap: var(--md-spacing-4);
}

.expand-form__row > * {
  flex: 1 1 0;
  min-width: 0;
}

.expand-form__row > .expand-form__cell--short {
  max-width: var(--md-text-field-width-short);
}

/* A cell that keeps its own width (the segmented Hours | Days) */
.expand-form__row > .expand-form__cell--auto {
  flex: 0 0 auto;
}

.expand-form__row--wrap {
  flex-wrap: wrap;
}

/* The pickers and the time input fill their cell (the component is an inline-block with no width)
   and drop their stacked-form bottom margin; the segmented group drops its too and takes the fields'
   8px of label room, so its box sits on the field line */
.expand-form__row .date-picker,
.expand-form__row .time-input {
  display: block;
  width: 100%;
  margin-bottom: 0;
}

.expand-form__row .segmented-button {
  margin: var(--md-spacing-2) 0 0;
}

/* The transfer list (the Services panels' locations) drops its stacked-form margin too: the gap owns the rhythm */
.expand-form .transfer-list {
  margin-bottom: 0;
}

/* A dropdown rendered with a blank helper reserves the whole supporting line (whitespace alone makes
   no line box), so a hint that appears later never moves the form; the menu still hugs the field, since
   every dropdown here is outlined (.dropdown--outlined .dropdown__menu measures from the field height) */
.expand-form .dropdown__supporting-text {
  min-height: calc(var(--md-body-small-line) + var(--md-spacing-1) * 2);
}

/* A row and the line that explains it (the end of a pass, a list and its note): 8px apart */
.expand-form__group {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-2);
}

/* The panel's description (what the form does, in the owner's words: the Exempt Plates panel), the
   card subtitle's role; the note under it is one size smaller */
.expand-form__intro {
  margin: 0;
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
}

.expand-form__note {
  margin: 0;
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
  color: var(--md-on-surface-variant);
}

/* A group heading inside the form (.onb__legend's recipe: "When", "Vehicle (optional)") */
.expand-form__legend {
  margin: var(--md-spacing-2) 0 0;
  font-size: var(--md-title-small-size);
  line-height: var(--md-title-small-line);
  font-weight: var(--md-title-small-weight);
  letter-spacing: var(--md-title-small-tracking);
  color: var(--md-on-surface-variant);
}

/* Button row: 24px above (the gap and this margin); wraps on a phone instead of overflowing */
.expand-form__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--md-spacing-2);
  margin-top: var(--md-spacing-2);
}

.expand-form__spacer {
  flex: 1 1 0;
}

/* A section of the form: a hairline with 24px of air on both sides (8px here plus the column's 16px
   above - flex items' margins add to the gap -, the padding below), a column of its own inside, the
   title one role under the panel's (h4.md-title-medium), the count at the right on its baseline (it
   drops under the title on a phone) */
.expand-form__section {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-4);
  margin-top: var(--md-spacing-2);
  padding-top: var(--md-spacing-6);
  border-top: var(--md-divider-thickness) solid var(--md-outline-variant);
}

.expand-form__section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--md-spacing-1) var(--md-spacing-4);
}

.expand-form__section-title {
  margin: 0;
}

/* Secondary text beside a title or a plate: the section count, a vehicle's details */
.expand-form__meta {
  flex-shrink: 0;
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
  color: var(--md-on-surface-variant);
}

/* The list rows (a resident's vehicles): a hairline between rows only, the first and last rows flush
   with the column's gap */
.expand-form__item {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--md-spacing-1) var(--md-spacing-3);
  padding: var(--md-spacing-2) 0;
}

.expand-form__item:first-child { padding-top: 0; }
.expand-form__item:last-child { padding-bottom: 0; }

.expand-form__item + .expand-form__item {
  border-top: var(--md-divider-thickness) solid var(--md-outline-variant);
}

.dialog--error .dialog__btn--confirm,
.dialog--error .dialog__btn--confirm:hover {
  background-color: var(--md-error);
  border-color: var(--md-error);
  color: var(--md-on-error);
}

/* ---- Spacing Utilities ---- */
.mb-2 { margin-bottom: var(--md-spacing-2); }
.mb-4 { margin-bottom: var(--md-spacing-4); }
.mb-8 { margin-bottom: var(--md-spacing-8); }
.mt-2 { margin-top: var(--md-spacing-2); }
.mt-4 { margin-top: var(--md-spacing-4); }

/* ---- Code Example Block ---- */
.code-example {
  margin-top: var(--md-spacing-4);
  padding: var(--md-spacing-4);
}

.code-example__label {
  color: var(--md-primary);
  margin-bottom: var(--md-spacing-2);
}

.code-example__pre {
  color: var(--md-on-surface-variant);
  white-space: pre-wrap;
}

/* ---- Email Preview ---- */

.email-preview {
  margin-bottom: var(--md-spacing-4);
  border-radius: var(--md-shape-medium);
  overflow: hidden;
  border: var(--md-divider-thickness) solid var(--md-outline-variant);
}

.email-preview__iframe {
  width: 100%;
  height: 560px;
  border: none;
  display: block;
  background: #f5f5f5;
}

/* ---- Elevation Demo Box ---- */
.elevation-box {
  min-width: var(--md-min-dropdown-width);
  text-align: center;
}

.elevation-box--0 { box-shadow: var(--md-elevation-0); }
.elevation-box--1 { box-shadow: var(--md-elevation-1); }
.elevation-box--2 { box-shadow: var(--md-elevation-2); }
.elevation-box--3 { box-shadow: var(--md-elevation-3); }
.elevation-box--4 { box-shadow: var(--md-elevation-4); }
.elevation-box--5 { box-shadow: var(--md-elevation-5); }

/* ---- Shape Demo Box ---- */
.shape-box {
  width: var(--md-top-app-bar-height-small);
  height: var(--md-top-app-bar-height-small);
  background-color: var(--md-primary);
}

.shape-box--none        { border-radius: var(--md-shape-none); }
.shape-box--extra-small { border-radius: var(--md-shape-extra-small); }
.shape-box--small       { border-radius: var(--md-shape-small); }
.shape-box--medium      { border-radius: var(--md-shape-medium); }
.shape-box--large       { border-radius: var(--md-shape-large); }
.shape-box--extra-large { border-radius: var(--md-shape-extra-large); }
.shape-box--full        { border-radius: var(--md-shape-full); }

/* ---- Shape Demo Label ---- */
.shape-label {
  width: var(--md-top-app-bar-height-small);
  text-align: center;
}

/* ---- Text Color Utility ---- */
.text-muted {
  color: var(--md-on-surface-variant);
}

/* ---- Banner Demo Override ---- */
.banner--demo {
  margin-top: var(--md-spacing-4);
  border-radius: var(--md-shape-small);
}

/* ---- Portal navigation rail (views/partials/nav-rail.ejs; portal pages only, 768px+) ----
   The column under the top bar of the portal app shell (layout.css .site--portal). The element carries
   mk-section--dark (the dark colour roles, variables.css; background and text colour from marketing.css),
   so every token here resolves against the dark palette: green primary, the dark secondary container for
   the current page. Sticky under the bar for the rest of the viewport (its own scrollbar if the list ever
   outgrows it), never on phones (the drawer under the bar lists the same items). Its grid column is the
   rail width plus the gutter (layout.css), carried as padding on both sides so the rows sit centred in
   the charcoal column and the right padding is the panel's gutter. Mobile first: 768px = the
   80px icon rail (a 56px square target, the icon in a 56x32 pill, the label hidden with the onb__sr recipe
   but still the link's name, shown by title on hover); 1280px = the 256px rail with icon + label rows at
   the large button height. The foot list (support rows, Support, Terms, Privacy) is pinned to the bottom
   with icon-button-sized rows. The :hover rules set color too, so base.css a:hover never recolours a row.
   No data-tooltip in here: the scroller would clip the bubble.
   Groups (Properties, Services; nav-rail.ejs): a hub row over its child rows, open when the page is the
   hub or a child (nav-rail__group--open). On the icon rail the children are 40px pills under the hub pill
   and there is no manual toggle; from 1280px the hub link sits beside a chevron icon button that
   nav-rail.js toggles, the children are indented 40px rows and a child's badge is a chip. */
.nav-rail {
  grid-column: 1;
  grid-row: 2;
  align-self: start;                                /* a grid item stretched to the row has no room to stick */
  position: sticky;
  top: var(--md-portal-bar-height);
  height: calc(100vh - var(--md-portal-bar-height));
  height: calc(100svh - var(--md-portal-bar-height));   /* smallest viewport: the foot stays reachable, no relayout as a toolbar hides */
  display: none;
  flex-direction: column;
  gap: var(--md-spacing-3);
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: var(--md-spacing-2) var(--md-portal-gutter) var(--md-spacing-3);   /* the gutter on both sides */
}

.nav-rail__items {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--md-spacing-1);
}

.nav-rail__items--foot {
  margin-top: auto;
  padding-top: var(--md-spacing-3);
  border-top: var(--md-divider-thickness) solid var(--md-outline-variant);
}

.nav-rail__item {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: var(--md-fab-size-medium);
  height: var(--md-fab-size-medium);
  border-radius: var(--md-shape-full);
  color: var(--md-on-surface-variant);
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard),
              color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

/* The 56x32 pill that takes the hover and current fills on the icon rail */
.nav-rail__icon {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: var(--md-fab-size-medium);
  height: var(--md-button-height-small);
  border-radius: var(--md-shape-full);
  font-size: var(--md-icon-size-medium);
  line-height: 1;
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard),
              color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

/* Foot rows: an icon-button circle with the small glyph */
.nav-rail__items--foot .nav-rail__item,
.nav-rail__items--foot .nav-rail__icon {
  width: var(--md-icon-button-size);
  height: var(--md-icon-button-size);
}

.nav-rail__items--foot .nav-rail__icon {
  font-size: var(--md-icon-size-small);
}

/* Visually hidden on the icon rail (the onb__sr recipe), printed from 1280px */
.nav-rail__label {
  position: absolute;
  width: var(--md-divider-thickness);
  height: var(--md-divider-thickness);
  margin: 0;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  font-size: var(--md-label-large-size);
  line-height: var(--md-label-large-line);
  font-weight: var(--md-label-large-weight);
}

.nav-rail__item:hover {
  color: var(--md-on-surface);
}

.nav-rail__item:hover .nav-rail__icon {
  background-color: var(--md-surface-container-high);
}

.nav-rail__item:focus-visible {
  outline: calc(var(--md-divider-thickness) * 2) solid var(--md-primary);
  outline-offset: calc(var(--md-spacing-1) / 2);
}

.nav-rail__item--active,
.nav-rail__item--active:hover {
  color: var(--md-on-secondary-container);
}

.nav-rail__item--active .nav-rail__icon,
.nav-rail__item--active:hover .nav-rail__icon {
  background-color: var(--md-secondary-container);
  color: var(--md-primary);
}

/* Groups (Properties, Services, Tools, Billing): the hub row over its child rows (nav-rail.ejs). The wrapper is one
   flex child of the list, so .nav-rail__items { align-items: center } shrink-wraps it to its widest row
   (the 56px hub pill) and centres it; the children centre inside it. The group holding the current page
   renders open (nav-rail__group--open, aria-expanded on the chevron); on the icon rail that is the only
   way a group opens (the chevron is hidden: the hub pill navigates to the hub, which opens it), from
   1280px the chevron toggles it (nav-rail.js). The child list animates on grid rows like the drawer's
   group panel and is visibility: hidden while closed, so closed children take no focus or clicks. */
.nav-rail__group {
  display: flex;
  flex-direction: column;
}

.nav-rail__row {
  display: flex;
  align-items: center;
  justify-content: center;
}

/* The chevron belongs to the expanded rail; .nav-rail in the selector outranks .icon-btn's
   display: inline-flex, declared later in this file */
.nav-rail .nav-rail__toggle {
  display: none;
}

.nav-rail__chevron {
  font-size: var(--md-icon-size-medium);
  line-height: 1;
  transition: transform var(--md-motion-duration-medium) var(--md-motion-easing-emphasized);
}

.nav-rail__group--open .nav-rail__chevron {
  transform: rotate(180deg);
}

.nav-rail__children {
  display: grid;
  grid-template-rows: 0fr;
  visibility: hidden;
  transition: grid-template-rows var(--md-motion-duration-medium) var(--md-motion-easing-emphasized),
              visibility 0s linear var(--md-motion-duration-medium);
}

.nav-rail__group--open .nav-rail__children {
  grid-template-rows: 1fr;
  visibility: visible;
  transition: grid-template-rows var(--md-motion-duration-medium) var(--md-motion-easing-emphasized),
              visibility 0s;
  /* A group that renders open (the page is its hub or one of its children) plays the same expansion
     the drawer's group rows play on a tap, so following the hub link reads as the section opening */
  animation: nav-rail-open var(--md-motion-duration-medium) var(--md-motion-easing-emphasized);
}

@keyframes nav-rail-open {
  from { grid-template-rows: 0fr; }
  to { grid-template-rows: 1fr; }
}

/* The group was already open on the page the visitor came from (nav-rail.ejs, from the Referer): no replay */
.nav-rail__group--settled .nav-rail__children {
  animation: none;
}

.nav-rail__children-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--md-spacing-1);
  min-height: 0;
  overflow: hidden;
}

/* The list gap repeated between the hub row and the first child, as a margin so it is clipped with
   the children while the group is closed */
.nav-rail__children-inner > .nav-rail__item:first-child {
  margin-top: var(--md-spacing-1);
}

/* Child rows on the icon rail: the foot rows' size (an icon-button circle, the small glyph) */
.nav-rail__item--child,
.nav-rail__item--child .nav-rail__icon {
  width: var(--md-icon-button-size);
  height: var(--md-icon-button-size);
}

.nav-rail__item--child .nav-rail__icon {
  font-size: var(--md-icon-size-small);
}

/* The inner's overflow: hidden would clip a ring drawn outside the row, so the children's ring is inset */
.nav-rail__item--child:focus-visible {
  outline-offset: calc(-2 * var(--md-divider-thickness));
}

/* A hub whose child is current: no indicator (that is the child's), the glyph tinted and the label at
   full strength */
.nav-rail__item--parent {
  color: var(--md-on-surface);
}

.nav-rail__item--parent .nav-rail__icon {
  color: var(--md-primary);
}

/* A child's chip (pages.js navBadge): title text on the icon rail, a chip after the label from 1280px */
.nav-rail__badge {
  display: none;
}

/* A top-level row's chip (server.js navFor: the Billing row's count of notices needing attention; the
   Billing hub's link since the row became a group, 2026-10-28): on the icon rail a small count on the
   pill's top-right corner, over the pill's fill; from 1280px at the row's end, in the badge's slot
   (before the chevron on a hub) */
.nav-rail__badge--row {
  display: inline-flex;
  position: absolute;
  top: calc((var(--md-fab-size-medium) - var(--md-button-height-small)) / 2 - var(--md-spacing-1));
  right: calc(var(--md-spacing-1) * -1);
  background-color: var(--md-primary);
  color: var(--md-on-primary);
  box-shadow: 0 0 0 calc(var(--md-divider-thickness) * 2) var(--md-surface);
}

/* A locked row (server.js navFor: the AI Assistant while the account has no card on file): a small
   lock on the pill's bottom-right corner on the icon rail, on a disc of the rail's own surface so it
   reads over the pill's fill; from 1280px it sits at the row's end, in the badge's slot */
.nav-rail__lock {
  position: absolute;
  right: calc(var(--md-spacing-1) * -1);
  bottom: calc((var(--md-fab-size-medium) - var(--md-button-height-small)) / 2 - var(--md-spacing-1));
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: calc(var(--md-icon-size-small) + var(--md-spacing-1));
  height: calc(var(--md-icon-size-small) + var(--md-spacing-1));
  border-radius: var(--md-shape-full);
  background-color: var(--md-surface);
  color: var(--md-on-surface-variant);
  font-size: var(--md-icon-size-small);
  line-height: 1;
}

@media (min-width: 768px) {
  .nav-rail {
    display: flex;
  }
}

/* Expanded rail: icon + label rows, the fill moves from the icon pill to the row */
@media (min-width: 1280px) {
  .nav-rail__items {
    align-items: stretch;
  }

  .nav-rail__item,
  .nav-rail__items--foot .nav-rail__item {
    flex-direction: row;
    justify-content: flex-start;
    gap: var(--md-spacing-3);
    width: auto;
    padding: 0 var(--md-spacing-4);
  }

  .nav-rail__item {
    height: var(--md-button-height-large);
  }

  .nav-rail__items--foot .nav-rail__item {
    height: var(--md-icon-button-size);
  }

  .nav-rail__icon,
  .nav-rail__items--foot .nav-rail__icon {
    width: var(--md-icon-size-medium);              /* one icon column, so the labels align in both lists */
    height: var(--md-icon-size-medium);
    border-radius: 0;
  }

  .nav-rail__label {
    position: static;
    width: auto;
    height: auto;
    overflow: visible;
    clip-path: none;
  }

  .nav-rail__item:hover {
    background-color: var(--md-surface-container-high);
  }

  .nav-rail__item:hover .nav-rail__icon {
    background-color: transparent;
  }

  .nav-rail__item--active,
  .nav-rail__item--active:hover {
    background-color: var(--md-secondary-container);
  }

  .nav-rail__item--active .nav-rail__icon,
  .nav-rail__item--active:hover .nav-rail__icon {
    background-color: transparent;
  }

  /* Groups: the hub row paints the hover / current fill under the link and the chevron together, so
     the two targets read as one 48px row; the link inside paints nothing of its own */
  .nav-rail__children-inner {
    align-items: stretch;
  }

  .nav-rail__row {
    justify-content: flex-start;
    border-radius: var(--md-shape-full);
    transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
  }

  .nav-rail__row > .nav-rail__item {
    flex: 1 1 auto;
    min-width: 0;
    padding-right: var(--md-spacing-2);
  }

  .nav-rail__row > .nav-rail__item,
  .nav-rail__row > .nav-rail__item:hover,
  .nav-rail__row > .nav-rail__item--active,
  .nav-rail__row > .nav-rail__item--active:hover {
    background-color: transparent;
  }

  .nav-rail__row:hover {
    background-color: var(--md-surface-container-high);
  }

  .nav-rail__row--active,
  .nav-rail__row--active:hover {
    background-color: var(--md-secondary-container);
  }

  /* The chevron: an icon-button circle inside the 48px row, its own hover a step brighter than the row's */
  .nav-rail .nav-rail__toggle {
    display: inline-flex;
    flex-shrink: 0;
    margin-right: var(--md-spacing-1);
  }

  .nav-rail__toggle:hover {
    background-color: var(--md-surface-container-highest);
    color: var(--md-on-surface);
  }

  .nav-rail__toggle:focus-visible {
    outline: calc(var(--md-divider-thickness) * 2) solid var(--md-primary);
    outline-offset: calc(-2 * var(--md-divider-thickness));
  }

  .nav-rail__row--active .nav-rail__toggle {
    color: var(--md-on-secondary-container);
  }

  /* Child rows: one step lower than the hub rows, indented to the hub label column (row padding +
     icon + gap, the drawer's recipe), the glyph back in the 24px icon column (restated: the icon-rail
     rule above carries two classes and would outrank this block's .nav-rail__icon) */
  .nav-rail__item--child {
    height: var(--md-button-height-medium);
    padding-left: calc(var(--md-spacing-4) + var(--md-icon-size-medium) + var(--md-spacing-3));
  }

  .nav-rail__item--child .nav-rail__icon {
    width: var(--md-icon-size-medium);
    height: var(--md-icon-size-medium);
    font-size: var(--md-icon-size-medium);
  }

  .nav-rail__badge {
    display: inline-flex;
    margin-left: auto;
  }

  .nav-rail__badge--row {
    position: static;
    box-shadow: none;
    background-color: var(--md-secondary-container);
    color: var(--md-on-secondary-container);
  }

  .nav-rail__lock {
    position: static;
    width: auto;
    height: auto;
    margin-left: auto;
    background-color: transparent;
  }

  /* On the current row the count bubble would vanish into the same secondary-container fill (a label
     chip - Surveillance "Soon" - keeps its hairline and the row's text colour) */
  .nav-rail__item--active .nav-rail__badge.badge {
    background-color: var(--md-primary);
    color: var(--md-on-primary);
  }
}

@media (prefers-reduced-motion: reduce) {
  .nav-rail__row,
  .nav-rail__chevron,
  .nav-rail__children,
  .nav-rail__group--open .nav-rail__children {
    transition: none;
    animation: none;
  }
}

/* ---- M3 Data Table ---- */
.data-table__wrapper {
  overflow-x: auto;
  border-radius: var(--md-shape-medium);
  border: var(--md-divider-thickness) solid var(--md-outline-variant);
  margin-bottom: var(--md-spacing-6);
}

.data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
}

.data-table__caption {
  font-size: var(--md-title-medium-size);
  font-weight: var(--md-title-medium-weight);
  text-align: left;
  padding: var(--md-spacing-4) var(--md-spacing-4) var(--md-spacing-2);
  color: var(--md-on-surface);
}

.data-table__head {
  background-color: var(--md-surface-container);
}

.data-table__header {
  padding: var(--md-spacing-3) var(--md-spacing-4);
  text-align: left;
  font-size: var(--md-label-large-size);
  font-weight: var(--md-label-large-weight);
  color: var(--md-on-surface);
  border-bottom: var(--md-divider-thickness) solid var(--md-outline-variant);
  white-space: nowrap;
}

.data-table__header--sortable {
  cursor: pointer;
  user-select: none;
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.data-table__header--sortable:hover {
  background-color: var(--md-surface-container-high);
}

.data-table__sort-icon {
  font-size: var(--md-icon-size-small);
  vertical-align: middle;
  margin-left: var(--md-spacing-1);
  color: var(--md-on-surface-variant);
}

.data-table__cell {
  padding: var(--md-spacing-3) var(--md-spacing-4);
  color: var(--md-on-surface-variant);
  border-bottom: var(--md-divider-thickness) solid var(--md-outline-variant);
}

.data-table__row:last-child .data-table__cell {
  border-bottom: none;
}

/* The stripes count the data rows only: a form row (.expand-row) opened under a row is not one, so the
   rhythm holds below it where the browser knows `of` (every current one); the plain rule is the fallback */
@supports not selector(:nth-child(even of .data-table__row)) {
  .data-table--striped .data-table__body .data-table__row:nth-child(even) {
    background-color: var(--md-surface-container-low);
  }
}

@supports selector(:nth-child(even of .data-table__row)) {
  .data-table--striped .data-table__body .data-table__row:nth-child(even of .data-table__row) {
    background-color: var(--md-surface-container-low);
  }
}

.data-table__body .data-table__row:hover {
  background-color: var(--md-surface-container-high);
}

/* ---- The client portal's one table grid (2026-10-29, the owner's rules) ----
   location-groups.js, client-managers.js and client-tools-codes.js add the modifier to every table of the
   portal (the public compare-table and the assistant's fixes table keep the automatic layout). Fixed
   layout, so a column of one KIND is the same width on every table: the width sits on the <col> of the
   kind (variables.css --md-table-col-*; a width on the <th> would gain its padding), a text column has
   none and the text columns share what is left equally; a section whose text columns all folded into its
   header omits the actions width, so that column alone absorbs the slack and Unit / Status keep their
   place. One row height on every row (the 40px button plus the cell's paddings): a value that does not
   fit is cut with an ellipsis and read whole in the cell's title (data-table.js fitTitles); an inline chip
   that does not fit is clipped. Below the table's floor the wrapper scrolls instead of crushing the text
   columns. The actions column is the last, its header word and its content at the right edge. */
.data-table--fixed {
  table-layout: fixed;
  min-width: var(--md-table-min-width);
}

.data-table--fixed.data-table--wide {
  min-width: var(--md-table-min-width-wide);
}

.data-table__col--select { width: var(--md-table-col-select); }
.data-table__col--code { width: var(--md-table-col-code); }
.data-table__col--number { width: var(--md-table-col-number); }
.data-table__col--status { width: var(--md-table-col-status); }
.data-table__col--date { width: var(--md-table-col-date); }
.data-table__col--phone { width: var(--md-table-col-phone); }
.data-table__col--label { width: var(--md-table-col-label); }
.data-table__col--actions-1 { width: var(--md-table-col-actions-1); }
.data-table__col--actions-2 { width: var(--md-table-col-actions-2); }
.data-table__col--actions-3 { width: var(--md-table-col-actions-3); }

.data-table--fixed .data-table__header {
  overflow: hidden;
  text-overflow: ellipsis;
}

.data-table--fixed .data-table__cell {
  height: var(--md-table-cell-content-height);
  vertical-align: middle;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.data-table__header--actions,
.data-table__cell--actions {
  text-align: right;
}

/* A row's actions: one row of buttons at the right edge that never wraps (an under-measured width clips,
   never grows the row), the destructive one first and the row's main action last, at the edge (the
   owner's placement, 2026-10-29: Edit at the edge, the trash to its left) */
.data-table__actions {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  flex-wrap: nowrap;
  gap: var(--md-spacing-2);
}

.data-table__actions > .btn,
.data-table__actions > .icon-btn {
  flex-shrink: 0;
}

/* ---- M3 Video Player ---- */
.video-player {
  margin: 0 0 var(--md-spacing-6);
}

.video-player__frame {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  background-color: var(--md-surface-container);
  border-radius: var(--md-shape-large);
  overflow: hidden;
  box-shadow: var(--md-elevation-1);
}

.video-player__video,
.video-player__iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border: none;
}

.video-player__video {
  object-fit: contain;
  background-color: var(--md-media-background);
}

.video-player__caption {
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
  color: var(--md-on-surface-variant);
  text-align: center;
  margin-top: var(--md-spacing-2);
  padding: 0 var(--md-spacing-4);
}

/* ---- M3 Tabs ---- */
.tabs {
  margin-bottom: var(--md-spacing-6);
}

.tabs__bar {
  display: flex;
  position: relative;
  border-bottom: var(--md-divider-thickness) solid var(--md-outline-variant);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.tabs__tab {
  flex: 0 0 auto;
  padding: var(--md-spacing-4) var(--md-spacing-6);
  background: none;
  border: none;
  font-size: var(--md-title-small-size);
  font-weight: var(--md-title-small-weight);
  line-height: var(--md-title-small-line);
  color: var(--md-on-surface-variant);
  cursor: pointer;
  position: relative;
  white-space: nowrap;
  transition: color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.tabs__tab:hover {
  color: var(--md-on-surface);
  background-color: var(--md-surface-container-high);
}

.tabs__tab--active {
  color: var(--md-primary);
}

.tabs__tab--active::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: var(--md-shape-small-half);
  background-color: var(--md-primary);
  border-radius: var(--md-shape-small-half) var(--md-shape-small-half) 0 0;
}

.tabs__panel {
  display: none;
  padding: var(--md-spacing-6) 0;
}

.tabs__panel--active {
  display: block;
}

/* ---- M3 Chip Group ---- */
.chip-group {
  display: flex;
  flex-wrap: wrap;
  gap: var(--md-spacing-2);
  margin-bottom: var(--md-spacing-6);
}

/* Inside a form panel or a dialog the column gap owns the rhythm (the tag chips of a metered space) */
.expand-form .chip-group,
.dialog .chip-group {
  margin-bottom: 0;
}

.chip__icon {
  font-size: var(--md-icon-size-small);
  margin-right: var(--md-spacing-1);
}

.chip__check {
  font-size: var(--md-icon-size-small);
  margin-right: var(--md-spacing-1);
}

.chip__label {
  font-size: var(--md-label-large-size);
  font-weight: var(--md-label-large-weight);
  line-height: var(--md-label-large-line);
}

.chip__remove {
  font-size: var(--md-icon-size-small);
  margin-left: var(--md-spacing-1);
  cursor: pointer;
  border-radius: var(--md-shape-full);
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.chip__remove:hover {
  background-color: var(--md-surface-container-highest);
}

.chip--input {
  background-color: var(--md-surface-container);
  border-color: transparent;
}

.chip--suggestion {
  border-style: dashed;
}

/* ---- M3 Accordion / Expansion Panel ---- */
.accordion {
  border: var(--md-divider-thickness) solid var(--md-outline-variant);
  border-radius: var(--md-shape-medium);
  overflow: hidden;
  margin-bottom: var(--md-spacing-6);
}

.accordion__item {
  border-bottom: var(--md-divider-thickness) solid var(--md-outline-variant);
}

.accordion__item:last-child {
  border-bottom: none;
}

.accordion__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: var(--md-spacing-4) var(--md-spacing-6);
  background: none;
  border: none;
  font-size: var(--md-title-small-size);
  font-weight: var(--md-title-small-weight);
  line-height: var(--md-title-small-line);
  color: var(--md-on-surface);
  cursor: pointer;
  text-align: left;
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.accordion__header:hover {
  background-color: var(--md-surface-container-high);
}

.accordion__title {
  flex: 1;
}

.accordion__icon {
  font-size: var(--md-icon-size-medium);
  color: var(--md-on-surface-variant);
  transition: transform var(--md-motion-duration-medium) var(--md-motion-easing-emphasized);
  flex-shrink: 0;
}

.accordion__item--expanded .accordion__icon {
  transform: rotate(180deg);
}

.accordion__panel {
  max-height: 0;
  overflow: hidden;
  transition: max-height var(--md-motion-duration-medium) var(--md-motion-easing-emphasized);
}

.accordion__item--expanded .accordion__panel {
  max-height: var(--md-max-content-height);
}

.accordion__content {
  padding: 0 var(--md-spacing-6) var(--md-spacing-6);
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
}

/* ---- Visually hidden, still announced (the onb__sr / demo-scheduler__sr recipe as one shared utility) ---- */
.sr-only {
  position: absolute;
  width: var(--md-divider-thickness);
  height: var(--md-divider-thickness);
  margin: 0;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---- M3 Tooltip (CSS-only, attribute-based) ---- */
[data-tooltip] {
  position: relative;
}

/* Hidden, the bubble is also visibility: hidden: an invisible but laid-out bubble under a button at
   the page edge (the bar's Sign out) once widened the page a few px, and with html's overflow-x
   clipped a script could scroll the page sideways with no scrollbar to undo it (the unit carousel) */
[data-tooltip]::before,
[data-tooltip]::after {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--md-motion-duration-short) var(--md-motion-easing-standard), visibility 0s linear var(--md-motion-duration-short);
  z-index: 500;
}

[data-tooltip]::after {
  content: attr(data-tooltip);
  bottom: calc(100% + var(--md-dropdown-offset));
  background-color: var(--md-inverse-surface);
  color: var(--md-inverse-on-surface);
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
  padding: var(--md-spacing-1) var(--md-spacing-2);
  border-radius: var(--md-shape-extra-small);
  white-space: nowrap;
  max-width: var(--md-max-tooltip-width);
  overflow: hidden;
  text-overflow: ellipsis;
}

[data-tooltip]::before {
  content: '';
  bottom: calc(100% + var(--md-spacing-1));
  border: var(--md-spacing-1) solid transparent;
  border-top-color: var(--md-inverse-surface);
}

[data-tooltip]:hover::before,
[data-tooltip]:hover::after,
[data-tooltip]:focus::before,
[data-tooltip]:focus::after {
  opacity: 1;
  visibility: visible;
  transition-delay: 0s;
}

[data-tooltip-position="bottom"]::after {
  bottom: auto;
  top: calc(100% + var(--md-dropdown-offset));
}

[data-tooltip-position="bottom"]::before {
  bottom: auto;
  top: calc(100% + var(--md-spacing-1));
  border-top-color: transparent;
  border-bottom-color: var(--md-inverse-surface);
}

/* ---- M3 Progress Indicator ---- */
.progress {
  margin-bottom: var(--md-spacing-4);
}

/* Linear */
.progress--linear {
  display: block;
  width: 100%;
}

.progress__track {
  width: 100%;
  height: var(--md-spacing-1);
  background-color: var(--md-surface-container-highest);
  border-radius: var(--md-shape-extra-small-half);
  overflow: hidden;
}

.progress__fill {
  height: 100%;
  background-color: var(--md-primary);
  border-radius: var(--md-shape-extra-small-half);
  transition: width var(--md-motion-duration-medium) var(--md-motion-easing-standard);
}

.progress--indeterminate .progress__fill {
  width: 40%;
  animation: progress-linear-indeterminate 1.8s var(--md-motion-easing-standard) infinite;
}

@keyframes progress-linear-indeterminate {
  0% { transform: translateX(-100%); }
  60% { transform: translateX(250%); }
  100% { transform: translateX(250%); }
}

/* Circular */
.progress--circular {
  display: inline-block;
  width: var(--md-menu-item-height);
  height: var(--md-menu-item-height);
}

.progress__circle {
  width: 100%;
  height: 100%;
}

.progress__circle-track {
  fill: none;
  stroke: var(--md-surface-container-highest);
  stroke-width: 4;
}

.progress__circle-fill {
  fill: none;
  stroke: var(--md-primary);
  stroke-width: 4;
  stroke-linecap: round;
  stroke-dasharray: 125.6;
  stroke-dashoffset: 125.6;
  transform: rotate(-90deg);
  transform-origin: center;
  transition: stroke-dashoffset var(--md-motion-duration-medium) var(--md-motion-easing-standard);
}

.progress--indeterminate .progress__circle-fill {
  stroke-dashoffset: 80;
  animation: progress-circular-indeterminate 1.4s linear infinite;
}

@keyframes progress-circular-indeterminate {
  0% { transform: rotate(-90deg); }
  100% { transform: rotate(270deg); }
}

/* ---- M3 List ---- */
.list {
  list-style: none;
  margin: 0 0 var(--md-spacing-6);
  padding: 0;
  border-radius: var(--md-shape-medium);
  overflow: hidden;
}

.list__item {
  display: flex;
  align-items: center;
  gap: var(--md-spacing-4);
  padding: var(--md-spacing-3) var(--md-spacing-4);
  min-height: var(--md-input-field-height);
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.list__item:hover {
  background-color: var(--md-surface-container-high);
}

.list__leading {
  font-size: var(--md-icon-size-medium);
  color: var(--md-on-surface-variant);
  flex-shrink: 0;
}

.list__avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--md-icon-button-size);
  height: var(--md-icon-button-size);
  border-radius: var(--md-shape-full);
  background-color: var(--md-primary-container);
  color: var(--md-on-primary-container);
  font-size: var(--md-title-medium-size);
  font-weight: var(--md-title-medium-weight);
  flex-shrink: 0;
}

.list__content {
  flex: 1;
  min-width: 0;
}

.list__headline {
  display: block;
  font-size: var(--md-body-large-size);
  line-height: var(--md-body-large-line);
  color: var(--md-on-surface);
}

.list__supporting {
  display: block;
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.list--two-line .list__item {
  min-height: var(--md-list-item-height-large);
  padding: var(--md-spacing-2) var(--md-spacing-4);
}

.list__trailing {
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
  flex-shrink: 0;
}

.list__divider {
  height: var(--md-divider-thickness);
  background-color: var(--md-outline-variant);
  margin: 0;
  list-style: none;
}

/* ---- M3 Bottom Sheet ---- */
.bottom-sheet__scrim {
  position: fixed;
  inset: 0;
  background-color: var(--md-scrim-light);
  z-index: 300;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--md-motion-duration-medium) var(--md-motion-easing-standard);
}

.bottom-sheet__scrim--visible {
  opacity: 1;
  pointer-events: auto;
}

.bottom-sheet {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  max-height: 80vh;
  background-color: var(--md-surface-container-low);
  border-radius: var(--md-shape-extra-large) var(--md-shape-extra-large) 0 0;
  box-shadow: var(--md-elevation-3);
  z-index: 301;
  transform: translateY(100%);
  transition: transform var(--md-motion-duration-medium) var(--md-motion-easing-emphasized);
  overflow-y: auto;
}

.bottom-sheet--visible {
  transform: translateY(0);
}

.bottom-sheet__drag-handle {
  display: flex;
  justify-content: center;
  padding: var(--md-spacing-4) 0 0;
}

.bottom-sheet__drag-handle::after {
  content: '';
  width: var(--md-button-height-small);
  height: var(--md-spacing-1);
  border-radius: var(--md-shape-extra-small-half);
  background-color: var(--md-on-surface-variant);
  opacity: 0.4;
}

.bottom-sheet__content {
  padding: var(--md-spacing-4) var(--md-spacing-6) var(--md-spacing-8);
}

/* ---- M3 Dropdown Menu ---- */
.menu__anchor {
  position: relative;
  display: inline-block;
}

.menu {
  position: absolute;
  top: calc(100% + var(--md-spacing-1));
  left: 0;
  min-width: var(--md-min-button-width);
  max-width: var(--md-component-width-small);
  max-height: var(--md-component-width-small);
  overflow-y: auto;
  background-color: var(--md-surface-container);
  border-radius: var(--md-shape-extra-small);
  box-shadow: var(--md-elevation-2);
  z-index: 200;
  padding: var(--md-spacing-2) 0;
  opacity: 0;
  transform: scaleY(0.8);
  transform-origin: top left;
  pointer-events: none;
  outline: none;
  transition: opacity var(--md-motion-duration-short) var(--md-motion-easing-standard),
              transform var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.menu--open {
  opacity: 1;
  transform: scaleY(1);
  pointer-events: auto;
}

.menu__item {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--md-spacing-3);
  width: 100%;
  min-height: var(--md-menu-item-height);
  padding: var(--md-spacing-3) var(--md-spacing-4);
  background: none;
  border: none;
  font-size: var(--md-label-large-size);
  font-weight: var(--md-label-large-weight);
  line-height: var(--md-label-large-line);
  color: var(--md-on-surface);
  cursor: pointer;
  text-align: left;
  white-space: nowrap;
  outline: none;
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.menu__item:hover {
  background-color: var(--md-surface-container-high);
}

.menu__item:focus-visible {
  background-color: var(--md-surface-container-highest);
}

.menu__item:focus-visible::before {
  content: '';
  position: absolute;
  inset: calc(var(--md-spacing-1) / 2);
  border: calc(var(--md-divider-thickness) * 2) solid var(--md-primary);
  border-radius: var(--md-shape-extra-small);
  pointer-events: none;
}

.menu__item--selected {
  background-color: var(--md-secondary-container);
  color: var(--md-on-secondary-container);
}

.menu__item--selected:hover {
  background-color: var(--md-secondary-container);
  opacity: 0.92;
}

.menu__item--disabled {
  color: var(--md-on-surface);
  opacity: 0.38;
  cursor: default;
  pointer-events: none;
}

.menu__icon {
  font-size: var(--md-label-large-line);
  flex-shrink: 0;
}

.menu__icon--start {
  color: var(--md-on-surface-variant);
}

.menu__item--selected .menu__icon--start {
  color: var(--md-on-secondary-container);
}

.menu__icon--end {
  color: var(--md-on-surface-variant);
  margin-left: auto;
}

.menu__icon-spacer {
  width: var(--md-label-large-line);
  flex-shrink: 0;
}

.menu__label {
  flex: 1;
  font-size: var(--md-label-large-size);
  font-weight: var(--md-label-large-weight);
  line-height: var(--md-label-large-line);
}

.menu__shortcut {
  font-size: var(--md-label-large-size);
  font-weight: var(--md-label-large-weight);
  line-height: var(--md-label-large-line);
  color: var(--md-on-surface-variant);
  margin-left: var(--md-spacing-6);
}

.menu__item--selected .menu__shortcut {
  color: var(--md-on-secondary-container);
}

.menu__divider {
  height: var(--md-divider-thickness);
  background-color: var(--md-outline-variant);
  margin: var(--md-spacing-2) 0;
}

/* ---- M3 Dropdown (Text Field + Menu Combo) ---- */
.dropdown {
  position: relative; /* no outer margin below, like .text-field: the form column's gap spaces it */
}

.dropdown__field {
  position: relative;
  width: 100%;
  min-height: var(--md-input-field-height);
  padding: var(--md-spacing-4);
  padding-top: var(--md-spacing-6);
  padding-right: var(--md-input-icon-area);
  background-color: var(--md-surface-container-highest);
  border: none;
  border-bottom: var(--md-divider-thickness) solid var(--md-on-surface-variant);
  border-radius: var(--md-shape-extra-small) var(--md-shape-extra-small) 0 0;
  font-size: var(--md-text-field-font-size);
  font-weight: var(--md-body-medium-weight);
  line-height: var(--md-text-field-line);
  color: var(--md-on-surface);
  cursor: pointer;
  text-align: left;
  outline: none;
  transition: border-color var(--md-motion-duration-short) var(--md-motion-easing-standard),
              background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.dropdown__field:hover {
  background-color: var(--md-surface-container-high);
  border-bottom-color: var(--md-on-surface);
}

.dropdown__field:focus {
  border-bottom-width: calc(var(--md-divider-thickness) * 2);
  border-bottom-color: var(--md-primary);
  padding-bottom: calc(var(--md-spacing-4) - var(--md-divider-thickness));
}

.dropdown__label {
  position: absolute;
  top: var(--md-spacing-2);
  left: var(--md-spacing-4);
  font-size: var(--md-body-small-size);
  font-weight: var(--md-body-small-weight);
  line-height: var(--md-body-small-line);
  color: var(--md-on-surface-variant);
  pointer-events: none;
  transition: color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.dropdown__field:focus ~ .dropdown__label,
.dropdown__field:focus .dropdown__label {
  color: var(--md-primary);
}

.dropdown__value {
  display: block;
  padding-top: calc(var(--md-spacing-1) / 2);
  font-size: var(--md-text-field-font-size);
  font-weight: var(--md-body-medium-weight);
  line-height: var(--md-text-field-line);
  color: var(--md-on-surface);
}

.dropdown__value:empty::before {
  content: '\00a0';
}

.dropdown__icon {
  position: absolute;
  right: var(--md-spacing-3);
  top: 50%;
  transform: translateY(-50%);
  font-size: var(--md-icon-size-medium);
  color: var(--md-on-surface-variant);
  pointer-events: none;
  transition: transform var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.dropdown--open .dropdown__icon {
  transform: translateY(-50%) rotate(180deg);
}

/* The menu: one sheet for every dropdown (the selects, the location comboboxes of group-search.js), the
   owner's pick of 2026-10-29: white, a hairline, the field corner, the soft tinted shadow, 4px under the
   field (it sat 8px over the field's bottom edge before). 100% is the container's bottom: the field's,
   unless a helper or error line follows the menu; an outlined dropdown's menu is measured from the field
   height instead (the rule in the outlined variant below), and a filled dropdown with such a line - none
   on a live page, the reference page's demo - opens under the line */
.dropdown__menu {
  position: absolute;
  top: calc(100% + var(--md-spacing-1));
  left: 0;
  right: 0;
  max-height: var(--md-component-width-small);
  overflow-y: auto;
  background-color: var(--md-surface-container-lowest);
  border: var(--md-divider-thickness) solid var(--md-outline-variant);
  border-radius: var(--md-shape-extra-small);
  box-shadow: var(--md-elevation-tinted);
  z-index: 200;
  padding: var(--md-spacing-2) 0;
  opacity: 0;
  transform: scaleY(0);
  transform-origin: top;
  pointer-events: none;
  outline: none;
  transition: opacity var(--md-motion-duration-short) var(--md-motion-easing-standard),
              transform var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.dropdown--open .dropdown__menu {
  opacity: 1;
  transform: scaleY(1);
  pointer-events: auto;
}

.dropdown__item {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--md-spacing-3);
  width: 100%;
  min-height: var(--md-menu-item-height);
  padding: var(--md-spacing-3) var(--md-spacing-4);
  background: none;
  border: none;
  font-size: var(--md-label-large-size);
  font-weight: var(--md-label-large-weight);
  line-height: var(--md-label-large-line);
  color: var(--md-on-surface);
  cursor: pointer;
  text-align: left;
  outline: none;
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.dropdown__item:hover {
  background-color: var(--md-surface-container-high);
}

/* Keyboard highlight for menus driven from a text input (focus stays in the input) */
.dropdown__item--active {
  background-color: var(--md-surface-container-high);
}

.dropdown__item:focus-visible {
  background-color: var(--md-surface-container-highest);
}

.dropdown__item:focus-visible::before {
  content: '';
  position: absolute;
  inset: calc(var(--md-spacing-1) / 2);
  border: calc(var(--md-divider-thickness) * 2) solid var(--md-primary);
  border-radius: var(--md-shape-extra-small);
  pointer-events: none;
}

.dropdown__item--selected {
  background-color: var(--md-secondary-container);
  color: var(--md-on-secondary-container);
}

.dropdown__item--selected:hover {
  background-color: var(--md-secondary-container);
  opacity: 0.92;
}

.dropdown__check {
  font-size: var(--md-icon-size-medium);
  color: var(--md-on-secondary-container);
  flex-shrink: 0;
}

.dropdown__check-spacer {
  width: var(--md-icon-size-medium);
  flex-shrink: 0;
}

.dropdown__item-label {
  flex: 1;
  font-size: var(--md-label-large-size);
  font-weight: var(--md-label-large-weight);
  line-height: var(--md-label-large-line);
}

/* Optional secondary text on a menu item (populate() `hint`); never shown in the field value */
.dropdown__item-hint {
  flex-shrink: 0;
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
  color: var(--md-on-surface-variant);
}

.dropdown__item--selected .dropdown__item-hint {
  color: var(--md-on-secondary-container);
}

.dropdown__supporting-text {
  padding: var(--md-spacing-1) var(--md-spacing-4);
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
  color: var(--md-on-surface-variant);
}

/* Outlined variant */
.dropdown--outlined {
  margin-top: var(--md-spacing-2);
}

.dropdown--outlined .dropdown__field {
  min-height: var(--md-text-field-height);
  background-color: transparent;
  border: var(--md-divider-thickness) solid var(--md-outline);
  border-radius: var(--md-shape-extra-small);
  padding: 0 var(--md-input-icon-area) 0 var(--md-spacing-4);
}

.dropdown--outlined .dropdown__value {
  padding-top: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.dropdown--outlined .dropdown__field:hover {
  background-color: transparent;
  border-color: var(--md-on-surface);
}

.dropdown--outlined .dropdown__field:focus {
  border-width: calc(var(--md-divider-thickness) * 2);
  border-color: var(--md-primary);
  padding: 0 calc(var(--md-input-icon-area) - var(--md-divider-thickness)) 0 calc(var(--md-spacing-4) - var(--md-divider-thickness));
}

.dropdown--outlined .dropdown__label {
  top: calc(var(--md-spacing-2) * -1);
  background-color: var(--md-surface);
  padding: 0 var(--md-spacing-1);
  left: calc(var(--md-spacing-3) + var(--md-divider-thickness));
}

.dropdown--outlined .dropdown__icon {
  right: var(--md-spacing-3);
}

/* An outlined field keeps the field height (the value never wraps, the label floats), so its menu is
   measured from that height and hugs the field whatever the container holds under it: a helper or error
   line sits after the menu in the markup, and 100% would measure from the line's bottom (the Managers
   page's preset helper, the expand forms' reserved line, the public forms' error lines). Every live
   dropdown is outlined; the comboboxes of group-search.js carry no variant and no line, so 100% is their
   field's bottom */
.dropdown--outlined .dropdown__menu {
  top: calc(var(--md-text-field-height) + var(--md-spacing-1));
}

/* Error state */
.dropdown--error .dropdown__field {
  border-bottom-color: var(--md-error);
}

.dropdown--error .dropdown__field:hover {
  border-bottom-color: var(--md-error);
}

.dropdown--error .dropdown__field:focus {
  border-bottom-color: var(--md-error);
}

.dropdown--error .dropdown__label {
  color: var(--md-error);
}

.dropdown--error .dropdown__supporting-text {
  color: var(--md-error);
}

.dropdown--error.dropdown--outlined .dropdown__field {
  border-color: var(--md-error);
}

.dropdown--error.dropdown--outlined .dropdown__field:hover {
  border-color: var(--md-error);
}

.dropdown--error.dropdown--outlined .dropdown__field:focus {
  border-color: var(--md-error);
}

/* Disabled state */
.dropdown--disabled .dropdown__field {
  opacity: var(--md-opacity-disabled);
  cursor: default;
  background-color: var(--md-surface-container-highest);
}

.dropdown--disabled .dropdown__field:hover {
  background-color: var(--md-surface-container-highest);
  border-bottom-color: var(--md-on-surface-variant);
}

/* ---- M3 Slider ---- */
.slider {
  margin-bottom: var(--md-spacing-6);
}

.slider__label {
  display: block;
  font-size: var(--md-label-large-size);
  font-weight: var(--md-label-large-weight);
  color: var(--md-on-surface);
  margin-bottom: var(--md-spacing-2);
}

.slider__row {
  display: flex;
  align-items: center;
  gap: var(--md-spacing-4);
}

.slider__input {
  flex: 1;
  -webkit-appearance: none;
  appearance: none;
  height: var(--md-spacing-1);
  background: var(--md-surface-container-highest);
  border-radius: var(--md-shape-extra-small-half);
  outline: none;
}

.slider__input::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: var(--md-slider-thumb-size);
  height: var(--md-slider-thumb-size);
  border-radius: var(--md-shape-full);
  background-color: var(--md-primary);
  cursor: pointer;
  border: none;
  box-shadow: var(--md-elevation-1);
  transition: box-shadow var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.slider__input::-webkit-slider-thumb:hover {
  box-shadow: var(--md-elevation-2);
}

.slider__input::-moz-range-thumb {
  width: var(--md-slider-thumb-size);
  height: var(--md-slider-thumb-size);
  border-radius: var(--md-shape-full);
  background-color: var(--md-primary);
  cursor: pointer;
  border: none;
  box-shadow: var(--md-elevation-1);
}

.slider__input::-moz-range-track {
  height: var(--md-spacing-1);
  background: var(--md-surface-container-highest);
  border-radius: var(--md-shape-extra-small-half);
}

.slider__value {
  min-width: var(--md-button-height-small);
  text-align: center;
  font-size: var(--md-label-large-size);
  font-weight: var(--md-label-large-weight);
  color: var(--md-on-surface);
}

/* Ticks and the drawn thumb (2026-11-01; the partial's `ticks` / `animated`, slider.js sync): both are
   overlays inside .slider__track-wrap, which wraps the input alone, so they span exactly its width and
   the value readout stays outside. A point's place is the native thumb's centre: half a thumb in from
   either end, the rest of the width in proportion (--slider-at on a tick, --slider-pct on the slider) */
.slider__track-wrap {
  position: relative;
  display: flex;
  flex: 1;
  min-width: 0;
}

.slider__ticks {
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: var(--md-spacing-2);
  transform: translateY(-50%);
  pointer-events: none;
}

.slider__tick {
  position: absolute;
  top: 0;
  bottom: 0;
  width: var(--md-divider-thickness);
  left: calc(var(--md-slider-thumb-size) / 2 + var(--slider-at, 0) * (100% - var(--md-slider-thumb-size)));
  transform: translateX(-50%);
  background-color: var(--md-outline-variant);
}

/* The drawn thumb slides between the points like the segmented button's thumb (the same duration and
   easing); the native thumb stays, invisible, for hit-testing and the keyboard */
.slider--animated .slider__input::-webkit-slider-thumb {
  opacity: 0;
}

.slider--animated .slider__input::-moz-range-thumb {
  opacity: 0;
}

.slider__thumb {
  position: absolute;
  top: 50%;
  left: calc(var(--md-slider-thumb-size) / 2 + var(--slider-pct, 0) * (100% - var(--md-slider-thumb-size)));
  width: var(--md-slider-thumb-size);
  height: var(--md-slider-thumb-size);
  border-radius: var(--md-shape-full);
  background-color: var(--md-primary);
  box-shadow: var(--md-elevation-1);
  transform: translate(-50%, -50%);
  pointer-events: none;
  transition: left var(--md-motion-duration-medium) var(--md-motion-easing-emphasized),
              box-shadow var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

/* A drag follows the pointer (slider.js adds slider--dragging from the first move after the press);
   a click on the track or an arrow key slides */
.slider--dragging .slider__thumb {
  transition: none;
}

.slider__input:not(:disabled):hover ~ .slider__thumb {
  box-shadow: var(--md-elevation-2);
}

.slider__input:focus-visible ~ .slider__thumb {
  outline: calc(2 * var(--md-divider-thickness)) solid var(--md-primary);
  outline-offset: var(--md-shape-extra-small-half);
}

@media (prefers-reduced-motion: reduce) {
  .slider__thumb {
    transition: none;
  }
}

/* ---- M3 Date Picker ---- */
.date-picker {
  position: relative;
  display: inline-block;
  margin-bottom: var(--md-spacing-6);
}

.date-picker__field {
  cursor: pointer;
}

.date-picker__input {
  cursor: pointer;
  padding-right: var(--md-menu-item-height) !important;
}

.date-picker__icon {
  position: absolute;
  right: var(--md-spacing-3);
  top: 50%;
  transform: translateY(-50%);
  font-size: var(--md-icon-size-medium);
  color: var(--md-on-surface-variant);
  pointer-events: none;
}

.date-picker__dropdown {
  position: absolute;
  top: calc(100% + var(--md-spacing-1));
  left: 0;
  width: var(--md-component-width-medium);
  background-color: var(--md-surface-container);
  border-radius: var(--md-shape-large);
  box-shadow: var(--md-elevation-3);
  z-index: 200;
  padding: var(--md-spacing-4);
  opacity: 0;
  transform: scaleY(0.9);
  transform-origin: top left;
  pointer-events: none;
  transition: opacity var(--md-motion-duration-short) var(--md-motion-easing-standard),
              transform var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.date-picker--open .date-picker__dropdown {
  opacity: 1;
  transform: scaleY(1);
  pointer-events: auto;
}

.date-picker__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--md-spacing-3);
}

.date-picker__month-year {
  font-size: var(--md-title-small-size);
  font-weight: var(--md-title-small-weight);
  color: var(--md-on-surface);
}

.date-picker__nav {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--md-carousel-button-size);
  height: var(--md-carousel-button-size);
  border-radius: var(--md-shape-full);
  background: none;
  border: none;
  color: var(--md-on-surface-variant);
  cursor: pointer;
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.date-picker__nav:hover {
  background-color: var(--md-surface-container-high);
}

.date-picker__weekdays {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  text-align: center;
  margin-bottom: var(--md-spacing-1);
}

.date-picker__weekdays span {
  font-size: var(--md-label-small-size);
  font-weight: var(--md-label-small-weight);
  color: var(--md-on-surface-variant);
  padding: var(--md-spacing-2) 0;
}

.date-picker__days {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: calc(var(--md-spacing-1) / 2);
}

.date-picker__day {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--md-carousel-button-size);
  height: var(--md-carousel-button-size);
  margin: 0 auto;
  border-radius: var(--md-shape-full);
  background: none;
  border: none;
  font-size: var(--md-body-medium-size);
  color: var(--md-on-surface);
  cursor: pointer;
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.date-picker__day:hover {
  background-color: var(--md-surface-container-high);
}

.date-picker__day--today {
  border: var(--md-divider-thickness) solid var(--md-primary);
  color: var(--md-primary);
}

.date-picker__day--selected {
  background-color: var(--md-primary);
  color: var(--md-on-primary);
}

.date-picker__day--selected:hover {
  background-color: var(--md-primary);
}

.date-picker__day--outside {
  color: var(--md-on-surface-variant);
  opacity: 0.38;
}

/* ---- Demo Scheduler (Book a Demo: partials/demo-scheduler.ejs + demo-scheduler.js) ---- */
/* A tinted panel inside the form card. The month grid and the chosen day's times sit side by side
   when the card is wide and stack when it is not (flex-wrap on the two columns' bases, no
   breakpoint). Days and times are visually hidden native radios; the face after each one carries
   every state: open = tonal, chosen = primary, today = primary ring, closed = faded. */
.demo-scheduler {
  min-width: 0;   /* a fieldset defaults to min-content and would push the card wider */
  margin: 0;
  padding: var(--md-spacing-4);
  border: var(--md-divider-thickness) solid var(--md-outline-variant);
  border-radius: var(--md-shape-large);
  background-color: var(--md-surface-container-low);
  transition: border-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

/* Shipped hidden (revealed by the component); no display rule below may override [hidden] */
.demo-scheduler[hidden],
.demo-scheduler [hidden] {
  display: none !important;
}

.demo-scheduler--error {
  border-color: var(--md-error);
}

.demo-scheduler__legend {
  float: left;    /* a floated legend lays out like any block inside the fieldset */
  width: 100%;
  padding: 0;
  font-size: var(--md-title-medium-size);
  line-height: var(--md-title-medium-line);
  font-weight: var(--md-title-medium-weight);
  color: var(--md-on-surface);
}

.demo-scheduler__legend + * {
  clear: both;
}

.demo-scheduler__meta {
  margin: 0 0 var(--md-spacing-4);
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
}

.demo-scheduler__status {
  margin: 0;
  padding: var(--md-spacing-6) 0;
  text-align: center;
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
}

.demo-scheduler__panel {
  display: flex;
  flex-wrap: wrap;
  gap: var(--md-spacing-6);
}

.demo-scheduler__calendar {
  flex: 1 1 var(--md-component-width-small);
  min-width: 0;
}

.demo-scheduler__times {
  flex: 1 1 var(--md-component-width-xsmall);
  min-width: 0;
}

.demo-scheduler__month {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--md-spacing-2);
}

.demo-scheduler__month-label,
.demo-scheduler__times-label {
  margin: 0;
  font-size: var(--md-title-small-size);
  line-height: var(--md-title-small-line);
  font-weight: var(--md-title-small-weight);
  color: var(--md-on-surface);
}

.demo-scheduler__times-label {
  min-height: var(--md-title-small-line);
  margin-bottom: var(--md-spacing-3);
}

.demo-scheduler__nav {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--md-carousel-button-size);
  height: var(--md-carousel-button-size);
  border-radius: var(--md-shape-full);
  background: none;
  border: none;
  color: var(--md-on-surface-variant);
  cursor: pointer;
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.demo-scheduler__nav:hover:not(:disabled) {
  background-color: var(--md-surface-container-high);
}

.demo-scheduler__nav:disabled {
  opacity: var(--md-opacity-disabled);
  cursor: default;
}

.demo-scheduler__nav:focus-visible {
  outline: calc(var(--md-divider-thickness) * 2) solid var(--md-primary);
  outline-offset: calc(var(--md-spacing-1) / 2);
}

.demo-scheduler__weekdays,
.demo-scheduler__grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
}

.demo-scheduler__grid {
  row-gap: var(--md-spacing-1);
}

.demo-scheduler__weekdays span {
  padding: var(--md-spacing-1) 0;
  text-align: center;
  font-size: var(--md-label-small-size);
  line-height: var(--md-label-small-line);
  font-weight: var(--md-label-small-weight);
  color: var(--md-on-surface-variant);
}

.demo-scheduler__day {
  position: relative;
  display: flex;
  justify-content: center;
}

.demo-scheduler__day-face {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  max-width: var(--md-icon-button-size);
  aspect-ratio: 1;
  border-radius: var(--md-shape-full);
  font-size: var(--md-body-medium-size);
  font-variant-numeric: tabular-nums;
  color: var(--md-on-surface-variant);
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard),
              color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.demo-scheduler__day--off .demo-scheduler__day-face {
  opacity: var(--md-opacity-disabled);
}

.demo-scheduler__day--open {
  cursor: pointer;
}

.demo-scheduler__day--open .demo-scheduler__day-face {
  background-color: var(--md-secondary-container);
  color: var(--md-on-secondary-container);
  font-weight: var(--md-weight-bold);
}

/* Hover = the primary state layer over the face's own colour */
.demo-scheduler__day--open:hover .demo-scheduler__day-face,
.demo-scheduler__slot:hover .demo-scheduler__slot-face {
  background-image: linear-gradient(var(--md-primary-hover-overlay), var(--md-primary-hover-overlay));
}

.demo-scheduler__day--today .demo-scheduler__day-face {
  box-shadow: inset 0 0 0 var(--md-divider-thickness) var(--md-primary);
}

.demo-scheduler__day--today.demo-scheduler__day--off .demo-scheduler__day-face {
  opacity: 1;
  color: var(--md-primary);
}

.demo-scheduler__input:checked + .demo-scheduler__day-face {
  background-color: var(--md-primary);
  color: var(--md-on-primary);
}

.demo-scheduler__slots {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(var(--md-spacing-24), 1fr));
  gap: var(--md-spacing-2);
}

.demo-scheduler__slot {
  position: relative;
  display: block;
  cursor: pointer;
}

.demo-scheduler__slot-face {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: var(--md-button-height-medium);
  padding: 0 var(--md-spacing-3);
  border: var(--md-divider-thickness) solid var(--md-outline-variant);
  border-radius: var(--md-shape-full);
  background-color: var(--md-surface-container-lowest);
  font-size: var(--md-label-large-size);
  line-height: var(--md-label-large-line);
  font-weight: var(--md-label-large-weight);
  font-variant-numeric: tabular-nums;
  color: var(--md-primary);
  white-space: nowrap;
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard),
              border-color var(--md-motion-duration-short) var(--md-motion-easing-standard),
              color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.demo-scheduler__input:checked + .demo-scheduler__slot-face {
  background-color: var(--md-primary);
  border-color: var(--md-primary);
  color: var(--md-on-primary);
}

.demo-scheduler__input:focus-visible + .demo-scheduler__day-face,
.demo-scheduler__input:focus-visible + .demo-scheduler__slot-face {
  outline: calc(var(--md-divider-thickness) * 2) solid var(--md-primary);
  outline-offset: calc(var(--md-spacing-1) / 2);
}

/* Visually hidden, still focusable and announced */
.demo-scheduler__input,
.demo-scheduler__sr {
  position: absolute;
  width: var(--md-divider-thickness);
  height: var(--md-divider-thickness);
  margin: 0;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.demo-scheduler__fallback .alert {
  margin: 0;
}

.demo-scheduler__error {
  margin: var(--md-spacing-2) 0 0;
}

/* ---- M3 Time Input ---- */
.time-input {
  position: relative;
  display: inline-block;
  margin-bottom: var(--md-spacing-6);
}

.time-input__field {
  cursor: pointer;
}

.time-input__input {
  cursor: pointer;
  padding-right: var(--md-menu-item-height) !important;
}

.time-input__icon {
  position: absolute;
  right: var(--md-spacing-3);
  top: 50%;
  transform: translateY(-50%);
  font-size: var(--md-icon-size-medium);
  color: var(--md-on-surface-variant);
  pointer-events: none;
}

.time-input__dropdown {
  position: absolute;
  top: calc(100% + var(--md-spacing-1));
  left: 0;
  z-index: 10;
  background-color: var(--md-surface-container-high);
  border-radius: var(--md-shape-medium);
  box-shadow: var(--md-elevation-2);
  padding: var(--md-spacing-4);
  min-width: var(--md-list-max-height);
  opacity: 0;
  transform: scaleY(0.8);
  transform-origin: top;
  pointer-events: none;
  transition: opacity var(--md-motion-duration-short) var(--md-motion-easing-standard),
              transform var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.time-input--open .time-input__dropdown {
  opacity: 1;
  transform: scaleY(1);
  pointer-events: auto;
}

.time-input__header {
  text-align: center;
  margin-bottom: var(--md-spacing-4);
}

.time-input__display {
  font-size: var(--md-headline-medium-size);
  font-weight: var(--md-headline-medium-weight);
  color: var(--md-on-surface);
}

.time-input__body {
  display: flex;
  gap: var(--md-spacing-2);
  margin-bottom: var(--md-spacing-4);
}

.time-input__column {
  flex: 1;
  display: flex;
  flex-direction: column;
}

.time-input__column--period {
  flex: 0 0 auto;
  width: var(--md-narrow-component-width);
}

.time-input__label {
  font-size: var(--md-label-small-size);
  color: var(--md-on-surface-variant);
  text-align: center;
  margin-bottom: var(--md-spacing-2);
}

.time-input__scroller {
  height: var(--md-scrollable-list-height);
  overflow-y: auto;
  background-color: var(--md-surface-container-high);
  border-radius: var(--md-shape-small);
  scroll-snap-type: y mandatory;
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.time-input__scroller::-webkit-scrollbar {
  display: none;
}

.time-input__option {
  height: var(--md-button-height-medium);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--md-body-large-size);
  color: var(--md-on-surface);
  cursor: pointer;
  scroll-snap-align: start;
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.time-input__option:hover {
  background-color: var(--md-surface-container-highest);
}

.time-input__option--selected {
  background-color: var(--md-primary-container);
  color: var(--md-on-primary-container);
}

.time-input__period-btn {
  width: 100%;
  height: var(--md-button-height-medium);
  border: var(--md-divider-thickness) solid var(--md-outline);
  background: none;
  color: var(--md-on-surface);
  cursor: pointer;
  font-size: var(--md-label-large-size);
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.time-input__period-btn:first-child {
  border-radius: var(--md-shape-small) var(--md-shape-small) 0 0;
  margin-bottom: var(--md-spacing-2);
}

.time-input__period-btn:last-child {
  border-radius: 0 0 var(--md-shape-small) var(--md-shape-small);
}

.time-input__period-btn--active {
  background-color: var(--md-primary-container);
  color: var(--md-on-primary-container);
  border-color: transparent;
}

.time-input__actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--md-spacing-2);
}

/* ====================================================
   NEW COMPONENTS
   ==================================================== */

/* ---- M3 Checkbox ---- */
.checkbox {
  display: inline-flex;
  align-items: center;
  gap: var(--md-spacing-3);
  cursor: pointer;
}

/* Box styled like the outlined text field (same outline colour, weight and radius) so
   checkboxes sit naturally next to inputs; fills with primary when checked. */
.checkbox__input {
  -webkit-appearance: none;
  appearance: none;
  width: var(--md-spacing-5);
  height: var(--md-spacing-5);
  background-color: transparent;
  border: var(--md-divider-thickness) solid var(--md-outline);
  border-radius: var(--md-shape-extra-small);
  cursor: pointer;
  position: relative;
  flex-shrink: 0;
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard),
              border-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.checkbox:hover .checkbox__input:not(:checked):not(:disabled) {
  border-color: var(--md-on-surface);
}

.checkbox__input:checked {
  background-color: var(--md-primary);
  border-color: var(--md-primary);
}

.checkbox__input:checked::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  width: var(--md-dropdown-arrow-width);
  height: var(--md-dropdown-arrow-height);
  border: solid var(--md-on-primary);
  border-width: 0 calc(var(--md-divider-thickness) * 2) calc(var(--md-divider-thickness) * 2) 0;
  transform: translate(-50%, -60%) rotate(45deg);
}

.checkbox__input:focus-visible {
  outline: calc(var(--md-divider-thickness) * 2) solid var(--md-primary);
  outline-offset: calc(var(--md-spacing-1) / 2);
}

/* Some of the rows it stands for are ticked (a section's "select all" box): primary fill, a dash */
.checkbox__input:indeterminate {
  background-color: var(--md-primary);
  border-color: var(--md-primary);
}

.checkbox__input:indeterminate::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  width: calc(var(--md-spacing-5) / 2);
  height: calc(var(--md-divider-thickness) * 2);
  background-color: var(--md-on-primary);
  transform: translate(-50%, -50%);
}

.checkbox__label {
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface);
  user-select: none;
}

.checkbox__input:disabled {
  opacity: 0.38;
  cursor: default;
}

.checkbox__input:disabled ~ .checkbox__label {
  opacity: 0.38;
  cursor: default;
}

/* ---- M3 Radio Button ---- */
.radio {
  display: inline-flex;
  align-items: center;
  gap: var(--md-spacing-3);
  cursor: pointer;
}

.radio__input {
  -webkit-appearance: none;
  appearance: none;
  width: var(--md-spacing-5);
  height: var(--md-spacing-5);
  border: calc(var(--md-divider-thickness) * 2) solid var(--md-on-surface-variant);
  border-radius: var(--md-shape-full);
  cursor: pointer;
  position: relative;
  flex-shrink: 0;
  transition: border-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.radio__input:checked {
  border-color: var(--md-primary);
}

.radio__input:checked::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: var(--md-indicator-size-medium);
  height: var(--md-indicator-size-medium);
  border-radius: var(--md-shape-full);
  background-color: var(--md-primary);
}

.radio__input:focus-visible {
  outline: calc(var(--md-divider-thickness) * 2) solid var(--md-primary);
  outline-offset: calc(var(--md-spacing-1) / 2);
}

.radio__label {
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface);
  user-select: none;
}

.radio-group {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-3);
  margin-bottom: var(--md-spacing-6);
}

.radio-group--horizontal {
  flex-direction: row;
  gap: var(--md-spacing-6);
}

/* ---- M3 Segmented Button: the white thumb (2026-10-29, the owner's pick after the sub-nav review) ----
   An in-place switch between views of the same data (the dashboard's type, a toolbar's period presets,
   Upcoming | Active, the app's My passes switches, a form's Hours | Days): a tinted track and one thumb
   under the chosen segment, which slides when the choice changes. segmented-button.js appends the thumb
   and places it from the selected item's box, again on every class change, size change and font load,
   so a page script that toggles --selected itself (patrol.js, enduser-get-pass.js) moves it too. The
   chosen label is bold and its icon green, so the choice reads before the thumb is placed and without
   it; no check mark (the partial renders none; one a script still inserts draws nothing) and no fill
   on hover. The track takes the portal's button corner: the pill on the public pages and the end-user
   app, the small corner on the client portal. A multi-select group has no thumb: its pressed segments
   keep the tonal fill. The view switch (partials/view-switch) has its own block below. */
.segmented-button {
  position: relative;
  display: inline-flex;
  align-items: center;
  padding: var(--md-segmented-pad);
  background-color: var(--md-surface-container-high);
  border: none;
  border-radius: var(--md-button-radius);
  margin-bottom: var(--md-spacing-6);
}

.segmented-button__item {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--md-spacing-2);
  min-height: calc(var(--md-button-height-medium) - 2 * var(--md-segmented-pad)); /* the track's padding makes the button height */
  padding: calc(var(--md-button-padding-y-medium) - var(--md-segmented-pad)) var(--md-spacing-4);
  background: none;
  border: none;
  border-radius: calc(var(--md-button-radius) - var(--md-segmented-pad));
  font-size: var(--md-label-large-size);
  font-weight: var(--md-label-large-weight);
  line-height: var(--md-label-large-line);
  color: var(--md-on-surface-variant);
  cursor: pointer;
  transition: color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.segmented-button__item:hover {
  color: var(--md-on-surface);
}

.segmented-button__item:focus-visible {
  outline: calc(var(--md-divider-thickness) * 2) solid var(--md-primary);
  outline-offset: calc(-2 * var(--md-divider-thickness));
}

.segmented-button__item--selected {
  color: var(--md-on-surface);
  font-weight: var(--md-weight-bold);
}

.segmented-button__item--selected .segmented-button__icon {
  color: var(--md-primary);
}

/* The thumb: appended by segmented-button.js, placed through the group's --segmented-x / --segmented-w
   (the first placement with the transition off, so it appears under the selected item) and shown once
   placed (segmented-button--placed), so a group shown again never paints it at a stale position */
.segmented-button__thumb {
  position: absolute;
  z-index: 0;
  top: var(--md-segmented-pad);
  bottom: var(--md-segmented-pad);
  left: var(--segmented-x, var(--md-segmented-pad));
  width: var(--segmented-w, 0);
  background-color: var(--md-segmented-thumb);
  border-radius: calc(var(--md-button-radius) - var(--md-segmented-pad));
  box-shadow: var(--md-elevation-1);
  opacity: 0;
  pointer-events: none;
  transition: left var(--md-motion-duration-medium) var(--md-motion-easing-emphasized),
              width var(--md-motion-duration-medium) var(--md-motion-easing-emphasized),
              opacity var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.segmented-button--placed .segmented-button__thumb {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .segmented-button__thumb {
    transition: none;
  }
}

/* Greyed-out option (aria-disabled, so the title tooltip still shows) */
.segmented-button__item--disabled {
  opacity: var(--md-opacity-disabled);
  cursor: not-allowed;
}

.segmented-button__item--disabled:hover {
  color: var(--md-on-surface-variant);
}

.segmented-button__icon {
  font-size: var(--md-icon-size-small);
}

/* Retired with the thumb: a check mark a page script still inserts draws nothing */
.segmented-button__check {
  display: none;
}

/* A multi-select group (reference.ejs): no thumb, the pressed segments filled */
.segmented-button[data-segmented-multi="true"] .segmented-button__thumb {
  display: none;
}

.segmented-button[data-segmented-multi="true"] .segmented-button__item--selected {
  background-color: var(--md-secondary-container);
  color: var(--md-on-secondary-container);
}

/* ---- View switch: the sliding folder (2026-10-29, the owner's pick after the sub-nav review) ----
   partials/view-switch: the sibling views of one page as links (Units | Residents | Exempt Plates). A
   tinted tray above the content sheet, in which the current view is the sheet's own tab: the sheet's
   colour, the tray's hairline around it, a green top edge, its bottom open into the sheet (a negative
   margin of one hairline on every side, so it covers the tray's outline and the sheet's top border).
   The sheet is the section that follows the nav (.view-sheet on the six pages): a card whose top-left
   corner is square, so the tab is its corner. Links, no JS: a click leaves the page, so nothing slides. */
.view-switch {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: stretch;
  background-color: var(--md-surface-container-low);
  border: var(--md-divider-thickness) solid var(--md-outline-variant);
  border-bottom: none;
  border-radius: var(--md-shape-small) var(--md-shape-small) 0 0;
}

.view-switch__link {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--md-spacing-2);
  padding: var(--md-button-padding-y-medium) var(--md-spacing-5) calc(var(--md-button-padding-y-medium) - var(--md-divider-thickness));
  font-size: var(--md-label-large-size);
  font-weight: var(--md-label-large-weight);
  line-height: var(--md-label-large-line);
  color: var(--md-on-surface-variant);
  text-decoration: none;
  transition: color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

/* The colours restated under :hover because base.css a:hover (a type + pseudo-class) outranks the
   single-class rules */
.view-switch__link:hover {
  color: var(--md-on-surface);
}

.view-switch__link--current,
.view-switch__link--current:hover {
  z-index: 1;
  margin: calc(-1 * var(--md-divider-thickness));
  padding-top: calc(var(--md-button-padding-y-medium) + var(--md-divider-thickness));
  padding-bottom: var(--md-button-padding-y-medium);
  background-color: var(--md-surface);
  border: var(--md-divider-thickness) solid var(--md-outline-variant);
  border-bottom: none;
  border-radius: var(--md-shape-small) var(--md-shape-small) 0 0;
  box-shadow: inset 0 var(--md-shape-small-half) 0 var(--md-primary);
  color: var(--md-on-surface);
  font-weight: var(--md-weight-bold);
}

.view-switch__icon {
  font-size: var(--md-icon-size-small);
}

.view-switch__link--current .view-switch__icon {
  color: var(--md-primary);
}

.view-switch__link:focus-visible {
  outline: calc(var(--md-divider-thickness) * 2) solid var(--md-primary);
  outline-offset: calc(-2 * var(--md-divider-thickness));
}

/* The sheet the current tab opens into: the page's content section under the view switch */
.view-sheet {
  background-color: var(--md-surface);
  border: var(--md-divider-thickness) solid var(--md-outline-variant);
  border-radius: 0 var(--md-shape-medium) var(--md-shape-medium) var(--md-shape-medium);
  padding: var(--md-spacing-4) var(--md-spacing-5) var(--md-spacing-5);
  margin-bottom: var(--md-spacing-10);
}

/* ---- M3 Icon Button ---- */
.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--md-icon-button-size);
  height: var(--md-icon-button-size);
  border: none;
  border-radius: var(--md-button-radius);   /* the disc, or the client portal's small corner (variables.css) */
  background: none;
  color: var(--md-on-surface-variant);
  font-size: var(--md-icon-size-medium);
  cursor: pointer;
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.icon-btn:hover {
  background-color: var(--md-surface-container-high);
}

.icon-btn--filled {
  background-color: var(--md-primary);
  color: var(--md-on-primary);
}

.icon-btn--filled:hover {
  background-color: var(--md-primary);   /* restated: .icon-btn:hover would grey the fill */
  box-shadow: var(--md-elevation-1);
  filter: brightness(1.1);
}

.icon-btn--tonal {
  background-color: var(--md-secondary-container);
  color: var(--md-on-secondary-container);
}

.icon-btn--tonal:hover {
  background-color: var(--md-secondary-container);
  box-shadow: var(--md-elevation-1);
}

/* No ringed icon button any more (the owner's call of 2026-10-29, after the tables review: the glyph
   alone, the hover fill says it is a button): the outlined modifier is gone from the stylesheet and the
   markup, and a grep for it must stay empty */

/* A destructive action (a row's or a section's trash, the Location Codes page's Remove): the glyph in the
   error colour, the error container on hover */
.icon-btn--error {
  color: var(--md-error);
}

.icon-btn--error:hover {
  background-color: var(--md-error-container);
}

/* The hidden attribute wins over the button's own display (a section's trash, shown only while rows are
   ticked; a dialog's Delete location without the capability) */
.icon-btn[hidden],
.dialog__btn[hidden] {
  display: none;
}

/* ---- M3 Search Bar: the outlined text field with a leading search icon, on every page of both portals (the owner's pick, 2026-10-29) ----
   The recipe of .text-field--outlined and .dropdown--outlined: transparent, the hairline, the field
   corner, the field height; hover darkens the outline, focus is the 2px primary border with 1px of
   padding given back so the text never moves. The text starts one icon area in (the dropdown's caret
   room: 12px after the 24px icon) and ends one icon area before the edge, where the clear X sits; the X
   keeps its disc as part of the bigger control. The bar keeps a 24px margin below: the section pages'
   #searchSection collapses its own 16px into it, so the sections sit 24px under the bar */
.search-bar {
  position: relative;
  margin-bottom: var(--md-spacing-6);
}

.search-bar__input {
  width: 100%;
  height: var(--md-text-field-height);
  padding: 0 var(--md-input-icon-area);
  background-color: transparent;
  border: var(--md-divider-thickness) solid var(--md-outline);
  border-radius: var(--md-shape-extra-small);
  color: var(--md-on-surface);
  font-size: var(--md-text-field-font-size);
  line-height: var(--md-text-field-line);
  outline: none;
  -webkit-appearance: none; /* the box from these rules, never Safari's own search field */
  appearance: none;
  transition: border-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.search-bar__input:hover:not(:focus):not(:disabled) {
  border-color: var(--md-on-surface);
}

.search-bar__input:focus {
  border-color: var(--md-primary);
  border-width: calc(var(--md-divider-thickness) * 2);
  padding: 0 calc(var(--md-input-icon-area) - var(--md-divider-thickness));
}

.search-bar__input:disabled {
  opacity: var(--md-opacity-disabled);
  cursor: not-allowed;
}

.search-bar__input::placeholder {
  color: var(--md-on-surface-variant);
}

/* Hide native search input clear button (to avoid duplicate with custom button) */
.search-bar__input::-webkit-search-cancel-button {
  display: none;
}

.search-bar__input::-webkit-search-decoration {
  display: none;
}

.search-bar__leading {
  position: absolute;
  left: var(--md-spacing-3);
  top: 50%;
  transform: translateY(-50%);
  font-size: var(--md-icon-size-medium);
  color: var(--md-on-surface-variant);
  pointer-events: none;
}

.search-bar__trailing {
  position: absolute;
  right: var(--md-spacing-1);
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--md-button-height-small);
  height: var(--md-button-height-small);
  border: none;
  border-radius: var(--md-shape-full);
  background: none;
  color: var(--md-on-surface-variant);
  font-size: var(--md-icon-size-medium);
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--md-motion-duration-short) var(--md-motion-easing-standard),
              background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.search-bar__trailing--visible {
  opacity: 1;
  pointer-events: auto;
}

.search-bar__trailing:hover {
  background-color: var(--md-surface-container-highest);
}

/* ---- M3 Pagination ---- */
.pagination {
  display: flex;
  align-items: center;
  gap: var(--md-spacing-1);
  margin-bottom: var(--md-spacing-6);
}

.pagination__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--md-icon-button-size);
  height: var(--md-icon-button-size);
  padding: 0 var(--md-spacing-1);
  border: none;
  border-radius: var(--md-shape-full);
  background: none;
  color: var(--md-on-surface);
  font-size: var(--md-body-medium-size);
  font-weight: var(--md-label-large-weight);
  cursor: pointer;
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.pagination__btn:hover {
  background-color: var(--md-surface-container-high);
}

.pagination__btn--active {
  background-color: var(--md-primary);
  color: var(--md-on-primary);
}

.pagination__btn--active:hover {
  background-color: var(--md-primary);
  filter: brightness(1.1);
}

.pagination__btn:disabled {
  opacity: 0.38;
  cursor: default;
  pointer-events: none;
}

.pagination__ellipsis {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--md-icon-button-size);
  height: var(--md-icon-button-size);
  color: var(--md-on-surface-variant);
  font-size: var(--md-body-medium-size);
}

/* ---- M3 Breadcrumbs ---- */
.breadcrumbs {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--md-spacing-1);
  margin-bottom: var(--md-spacing-6);
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
}

.breadcrumbs__item {
  display: inline-flex;
  align-items: center;
}

.breadcrumbs__link {
  color: var(--md-primary);
  text-decoration: none;
  padding: var(--md-spacing-1) var(--md-spacing-2);
  border-radius: var(--md-shape-extra-small);
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.breadcrumbs__link:hover {
  background-color: var(--md-surface-container-high);
}

.breadcrumbs__separator {
  color: var(--md-on-surface-variant);
  font-size: var(--md-icon-size-small);
  margin: 0 var(--md-spacing-1);
}

.breadcrumbs__current {
  color: var(--md-on-surface);
  padding: var(--md-spacing-1) var(--md-spacing-2);
}

/* ---- M3 Stepper ---- */
.stepper {
  display: flex;
  align-items: flex-start;
  margin-bottom: var(--md-spacing-6);
}

.stepper--vertical {
  flex-direction: column;
}

.stepper__step {
  display: flex;
  align-items: center;
}

.stepper--vertical .stepper__step {
  align-items: flex-start;
}

.stepper__indicator {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--md-button-height-small);
  height: var(--md-button-height-small);
  border-radius: var(--md-shape-full);
  background-color: var(--md-surface-container-highest);
  color: var(--md-on-surface-variant);
  font-size: var(--md-label-large-size);
  font-weight: var(--md-label-large-weight);
  flex-shrink: 0;
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.stepper__step--active .stepper__indicator {
  background-color: var(--md-primary);
  color: var(--md-on-primary);
}

.stepper__step--completed .stepper__indicator {
  background-color: var(--md-primary);
  color: var(--md-on-primary);
}

.stepper__content {
  margin-left: var(--md-spacing-3);
}

.stepper__title {
  font-size: var(--md-label-large-size);
  font-weight: var(--md-label-large-weight);
  line-height: var(--md-label-large-line);
  color: var(--md-on-surface-variant);
}

.stepper__step--active .stepper__title,
.stepper__step--completed .stepper__title {
  color: var(--md-on-surface);
}

.stepper__subtitle {
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
  color: var(--md-on-surface-variant);
}

.stepper__connector {
  flex: 1;
  height: var(--md-divider-thickness);
  background-color: var(--md-outline-variant);
  margin: 0 var(--md-spacing-3);
  align-self: center;
  min-width: var(--md-icon-size-medium);
}

.stepper__step--completed + .stepper__connector {
  background-color: var(--md-primary);
}

.stepper--vertical .stepper__connector {
  width: var(--md-divider-thickness);
  height: var(--md-button-height-small);
  flex: none;
  min-width: auto;
  margin: var(--md-spacing-1) 0 var(--md-spacing-1) var(--md-spacing-4);
  align-self: flex-start;
}

/* ---- M3 Skeleton Loader ---- */
.skeleton {
  background: linear-gradient(
    90deg,
    var(--md-surface-container-high) 25%,
    var(--md-surface-container-highest) 50%,
    var(--md-surface-container-high) 75%
  );
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.5s ease-in-out infinite;
  border-radius: var(--md-shape-extra-small);
}

@keyframes skeleton-shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

.skeleton--text {
  height: var(--md-skeleton-text-height);
  margin-bottom: var(--md-spacing-2);
  width: 100%;
}

.skeleton--text-short {
  height: var(--md-skeleton-text-height);
  margin-bottom: var(--md-spacing-2);
  width: 60%;
}

.skeleton--heading {
  height: var(--md-icon-size-medium);
  margin-bottom: var(--md-spacing-3);
  width: 40%;
}

.skeleton--avatar {
  width: var(--md-icon-button-size);
  height: var(--md-icon-button-size);
  border-radius: var(--md-shape-full);
}

.skeleton--image {
  width: 100%;
  height: var(--md-image-placeholder-height);
  border-radius: var(--md-shape-medium);
}

.skeleton--button {
  width: var(--md-skeleton-button-width);
  height: var(--md-icon-button-size);
  border-radius: var(--md-shape-full);
}

/* ---- M3 Avatar (Standalone) ---- */
.avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--md-icon-button-size);
  height: var(--md-icon-button-size);
  border-radius: var(--md-shape-full);
  background-color: var(--md-primary-container);
  color: var(--md-on-primary-container);
  font-size: var(--md-title-medium-size);
  font-weight: var(--md-title-medium-weight);
  flex-shrink: 0;
  overflow: hidden;
}

.avatar--small {
  width: var(--md-avatar-size-small);
  height: var(--md-avatar-size-small);
  font-size: var(--md-label-medium-size);
}

.avatar--large {
  width: var(--md-fab-size-medium);
  height: var(--md-fab-size-medium);
  font-size: var(--md-headline-small-size);
}

.avatar--extra-large {
  width: var(--md-avatar-size-large);
  height: var(--md-avatar-size-large);
  font-size: var(--md-display-small-size);
}

.avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.avatar-group {
  display: flex;
  margin-bottom: var(--md-spacing-6);
}

.avatar-group .avatar {
  border: calc(var(--md-divider-thickness) * 2) solid var(--md-surface);
  margin-left: calc(var(--md-spacing-2) * -1);
}

.avatar-group .avatar:first-child {
  margin-left: 0;
}

/* ---- M3 Alert / Callout ---- */
.alert {
  display: flex;
  align-items: flex-start;
  gap: var(--md-spacing-3);
  padding: var(--md-spacing-4) var(--md-spacing-6);
  border-radius: var(--md-shape-medium);
  margin-bottom: var(--md-spacing-4);
}

.alert--info {
  background-color: var(--md-surface-container);
  border-left: var(--md-spacing-1) solid var(--md-primary);
}

.alert--success {
  background-color: var(--md-surface-container);
  border-left: var(--md-spacing-1) solid var(--md-primary);
}

.alert--warning {
  background-color: var(--md-surface-container);
  border-left: var(--md-spacing-1) solid var(--md-warning);
}

.alert--error {
  background-color: var(--md-error-container);
  border-left: var(--md-spacing-1) solid var(--md-error);
}

.alert__icon {
  font-size: var(--md-icon-size-medium);
  flex-shrink: 0;
  line-height: 1;
  padding-top: calc(var(--md-spacing-1) / 2);
}

.alert--info .alert__icon { color: var(--md-primary); }
.alert--success .alert__icon { color: var(--md-primary); }
.alert--warning .alert__icon { color: var(--md-on-warning-container); }
.alert--error .alert__icon { color: var(--md-error); }

.alert__content {
  flex: 1;
}

.alert__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--md-spacing-2);
  margin-top: var(--md-spacing-3);
}

.alert__title {
  font-size: var(--md-title-small-size);
  font-weight: var(--md-title-small-weight);
  line-height: var(--md-title-small-line);
  color: var(--md-on-surface);
  margin-bottom: var(--md-spacing-1);
}

.alert__text {
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
  margin-bottom: 0;
}

.alert__close {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--md-button-height-small);
  height: var(--md-button-height-small);
  border: none;
  border-radius: var(--md-shape-full);
  background: none;
  color: var(--md-on-surface-variant);
  cursor: pointer;
  flex-shrink: 0;
  font-size: var(--md-icon-size-small);
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.alert__close:hover {
  background-color: var(--md-surface-container-high);
}

/* ---- M3 Bottom Navigation Bar ---- */
.bottom-nav {
  display: flex;
  align-items: center;
  justify-content: space-around;
  background-color: var(--md-surface-container);
  height: var(--md-nav-rail-width);
  padding: 0 var(--md-spacing-2);
  box-shadow: var(--md-elevation-2);
  border-radius: var(--md-shape-large);
}

.bottom-nav__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  flex: 1;
  padding: var(--md-spacing-3) 0;
  text-decoration: none;
  color: var(--md-on-surface-variant);
  transition: color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.bottom-nav__indicator {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--md-top-app-bar-height-small);
  height: var(--md-button-height-small);
  border-radius: var(--md-shape-full);
  margin-bottom: var(--md-spacing-1);
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.bottom-nav__item:hover .bottom-nav__indicator {
  background-color: var(--md-surface-container-high);
}

.bottom-nav__item--active .bottom-nav__indicator {
  background-color: var(--md-secondary-container);
}

.bottom-nav__item--active {
  color: var(--md-on-surface);
}

.bottom-nav__icon {
  font-size: var(--md-icon-size-medium);
}

.bottom-nav__label {
  font-size: var(--md-label-medium-size);
  font-weight: var(--md-label-medium-weight);
  line-height: var(--md-label-medium-line);
}

/* ---- M3 Carousel ---- */
.carousel {
  position: relative;
  overflow: hidden;
  border-radius: var(--md-shape-large);
  margin-bottom: var(--md-spacing-6);
}

.carousel__track {
  display: flex;
  transition: transform var(--md-motion-duration-long) var(--md-motion-easing-emphasized);
}

.carousel__slide {
  min-width: 100%;
  aspect-ratio: 16 / 9;
  background-color: var(--md-surface-container);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.carousel__slide img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.carousel__btn {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--md-menu-item-height);
  height: var(--md-menu-item-height);
  border: none;
  border-radius: var(--md-shape-full);
  background-color: var(--md-surface-container);
  color: var(--md-on-surface);
  font-size: var(--md-icon-size-medium);
  cursor: pointer;
  box-shadow: var(--md-elevation-2);
  z-index: 1;
  opacity: 0.9;
  transition: opacity var(--md-motion-duration-short) var(--md-motion-easing-standard),
              box-shadow var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.carousel__btn:hover {
  opacity: 1;
  box-shadow: var(--md-elevation-3);
}

.carousel__btn--prev {
  left: var(--md-spacing-3);
}

.carousel__btn--next {
  right: var(--md-spacing-3);
}

.carousel__dots {
  display: flex;
  justify-content: center;
  gap: var(--md-spacing-2);
  padding: var(--md-spacing-3) 0;
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
}

.carousel__dot {
  width: var(--md-indicator-size-small);
  height: var(--md-indicator-size-small);
  border-radius: var(--md-shape-full);
  border: none;
  background-color: var(--md-on-surface-variant);
  opacity: 0.5;
  cursor: pointer;
  padding: 0;
  transition: opacity var(--md-motion-duration-short) var(--md-motion-easing-standard),
              width var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.carousel__dot--active {
  opacity: 1;
  background-color: var(--md-primary);
  width: var(--md-icon-size-medium);
}

/* ---- M3 Timeline ---- */
.timeline {
  position: relative;
  margin-bottom: var(--md-spacing-6);
  padding-left: var(--md-spacing-8);
}

.timeline::before {
  content: '';
  position: absolute;
  left: var(--md-icon-position-offset);
  top: 0;
  bottom: 0;
  width: calc(var(--md-divider-thickness) * 2);
  background-color: var(--md-outline-variant);
}

.timeline__item {
  position: relative;
  padding-bottom: var(--md-spacing-6);
}

.timeline__item:last-child {
  padding-bottom: 0;
}

.timeline__dot {
  position: absolute;
  left: calc(-1 * var(--md-spacing-8) + var(--md-spacing-2));
  top: var(--md-spacing-1);
  width: var(--md-spacing-4);
  height: var(--md-spacing-4);
  border-radius: var(--md-shape-full);
  background-color: var(--md-surface-container-highest);
  border: calc(var(--md-divider-thickness) * 2) solid var(--md-outline-variant);
}

.timeline__item--active .timeline__dot {
  background-color: var(--md-primary);
  border-color: var(--md-primary);
}

/* A refused or undone event (timeline.js tone 'negative'): the dot in the error pair, the word stays
   in the title (never colour alone) */
.timeline__item--negative .timeline__dot {
  background-color: var(--md-error-container);
  border-color: var(--md-error);
}

/* The divider before each day or month of items (timeline.js): the label sits on the line, its own
   background covering it, pulled left by the items' indent */
.timeline__group {
  position: relative;
  margin: 0 0 var(--md-spacing-3) calc(-1 * var(--md-spacing-8));
  padding: var(--md-spacing-1) 0;
  font-size: var(--md-label-large-size);
  line-height: var(--md-label-large-line);
  font-weight: var(--md-label-large-weight);
  color: var(--md-on-surface-variant);
  background-color: var(--md-surface);
}

.timeline__title {
  font-size: var(--md-title-small-size);
  font-weight: var(--md-title-small-weight);
  line-height: var(--md-title-small-line);
  color: var(--md-on-surface);
  margin-bottom: var(--md-spacing-1);
}

.timeline__time {
  font-size: var(--md-label-small-size);
  line-height: var(--md-label-small-line);
  font-weight: var(--md-label-small-weight);
  color: var(--md-on-surface-variant);
  margin-bottom: var(--md-spacing-2);
  display: block;
}

.timeline__text {
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
  margin-bottom: 0;
}

/* ---- M3 Rating ---- */
.rating {
  display: inline-flex;
  align-items: center;
  gap: var(--md-spacing-1);
  margin-bottom: var(--md-spacing-6);
}

.rating__star {
  font-size: var(--md-headline-small-size);
  cursor: pointer;
  color: var(--md-outline);
  transition: color var(--md-motion-duration-short) var(--md-motion-easing-standard),
              transform var(--md-motion-duration-short) var(--md-motion-easing-standard);
  user-select: none;
  -webkit-user-select: none;
}

.rating__star:hover {
  transform: scale(1.2);
}

.rating__star--filled {
  color: var(--md-rating-active);
}

.rating__value {
  font-size: var(--md-label-large-size);
  font-weight: var(--md-label-large-weight);
  color: var(--md-on-surface);
  margin-left: var(--md-spacing-2);
}

.rating--readonly .rating__star {
  cursor: default;
}

.rating--readonly .rating__star:hover {
  transform: none;
}

/* ---- M3 File Upload ---- */
.file-upload {
  margin-bottom: var(--md-spacing-6);
}

.file-upload__dropzone {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--md-spacing-3);
  padding: var(--md-spacing-8);
  border: calc(var(--md-divider-thickness) * 2) dashed var(--md-outline);
  border-radius: var(--md-shape-medium);
  background-color: var(--md-surface-container-low);
  cursor: pointer;
  transition: border-color var(--md-motion-duration-short) var(--md-motion-easing-standard),
              background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.file-upload__dropzone:hover,
.file-upload__dropzone--dragover {
  border-color: var(--md-primary);
  background-color: var(--md-surface-container);
}

.file-upload__icon {
  font-size: var(--md-menu-item-height);
  color: var(--md-on-surface-variant);
}

.file-upload__text {
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
  text-align: center;
  margin-bottom: 0;
}

.file-upload__text strong {
  color: var(--md-primary);
}

.file-upload__hint {
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
  color: var(--md-on-surface-variant);
  margin-bottom: 0;
}

.file-upload__input {
  display: none;
}

.file-upload__list {
  margin-top: var(--md-spacing-4);
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-2);
}

.file-upload__file {
  display: flex;
  align-items: center;
  gap: var(--md-spacing-3);
  padding: var(--md-spacing-3) var(--md-spacing-4);
  background-color: var(--md-surface-container);
  border-radius: var(--md-shape-small);
}

.file-upload__file-icon {
  font-size: var(--md-icon-size-medium);
  color: var(--md-primary);
}

.file-upload__file-name {
  flex: 1;
  font-size: var(--md-body-medium-size);
  color: var(--md-on-surface);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.file-upload__file-size {
  font-size: var(--md-body-small-size);
  color: var(--md-on-surface-variant);
}

.file-upload__file-remove {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--md-icon-size-medium-large);
  height: var(--md-icon-size-medium-large);
  border: none;
  border-radius: var(--md-shape-full);
  background: none;
  color: var(--md-on-surface-variant);
  cursor: pointer;
  font-size: var(--md-icon-size-small);
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.file-upload__file-remove:hover {
  background-color: var(--md-surface-container-high);
}

/* ---- M3 Empty State ---- */
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: var(--md-spacing-16) var(--md-spacing-6);
  margin-bottom: var(--md-spacing-6);
}

.empty-state__icon {
  font-size: var(--md-top-app-bar-height-small);
  color: var(--md-on-surface-variant);
  opacity: 0.5;
  margin-bottom: var(--md-spacing-4);
}

.empty-state__title {
  font-size: var(--md-title-large-size);
  font-weight: var(--md-title-large-weight);
  line-height: var(--md-title-large-line);
  color: var(--md-on-surface);
  margin-bottom: var(--md-spacing-2);
}

.empty-state__text {
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
  max-width: var(--md-component-width-medium);
  margin-bottom: var(--md-spacing-6);
}

.empty-state__actions {
  display: flex;
  gap: var(--md-spacing-3);
}

/* ---- M3 Side Sheet ---- */
.side-sheet__scrim {
  position: fixed;
  inset: 0;
  background-color: var(--md-scrim-light);
  z-index: 300;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--md-motion-duration-medium) var(--md-motion-easing-standard);
}

.side-sheet__scrim--visible {
  opacity: 1;
  pointer-events: auto;
}

.side-sheet {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: var(--md-component-width-medium);
  max-width: 90vw;
  background-color: var(--md-surface-container-low);
  box-shadow: var(--md-elevation-3);
  z-index: 301;
  transform: translateX(100%);
  transition: transform var(--md-motion-duration-medium) var(--md-motion-easing-emphasized);
  overflow-y: auto;
}

.side-sheet--visible {
  transform: translateX(0);
}

.side-sheet__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--md-spacing-4) var(--md-spacing-6);
  border-bottom: var(--md-divider-thickness) solid var(--md-outline-variant);
}

.side-sheet__title {
  font-size: var(--md-title-large-size);
  font-weight: var(--md-title-large-weight);
  line-height: var(--md-title-large-line);
  color: var(--md-on-surface);
}

.side-sheet__close {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--md-icon-button-size);
  height: var(--md-icon-button-size);
  border: none;
  border-radius: var(--md-shape-full);
  background: none;
  color: var(--md-on-surface-variant);
  font-size: var(--md-icon-size-medium);
  cursor: pointer;
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.side-sheet__close:hover {
  background-color: var(--md-surface-container-high);
}

.side-sheet__content {
  padding: var(--md-spacing-6);
}

/* ---- M3 Top App Bar Variants (demo only) ---- */
.top-app-bar-demo {
  background-color: var(--md-surface);
  border: var(--md-divider-thickness) solid var(--md-outline-variant);
  border-radius: var(--md-shape-medium);
  margin-bottom: var(--md-spacing-6);
  overflow: hidden;
}

/* Small / Default variant */
.top-app-bar-demo__bar {
  display: flex;
  align-items: center;
  padding: 0 var(--md-spacing-2);
  height: var(--md-top-app-bar-height-small);
  gap: var(--md-spacing-2);
}

/* Center-aligned variant */
.top-app-bar-demo__bar--center .top-app-bar-demo__title {
  flex: 1;
  text-align: center;
}

/* Medium variant */
.top-app-bar-demo__bar--medium {
  flex-wrap: wrap;
  height: auto;
  min-height: var(--md-top-app-bar-height-medium);
  align-content: flex-start;
  padding-top: var(--md-spacing-2);
  padding-bottom: var(--md-spacing-5);
}

.top-app-bar-demo__bar--medium .top-app-bar-demo__title {
  width: 100%;
  order: 10;
  font-size: var(--md-title-large-size);
  font-weight: var(--md-title-large-weight);
  line-height: var(--md-title-large-line);
  margin-top: var(--md-spacing-4);
  padding: 0 var(--md-spacing-4);
}

/* Large variant */
.top-app-bar-demo__bar--large {
  flex-wrap: wrap;
  height: auto;
  min-height: var(--md-top-app-bar-height-large);
  align-content: flex-start;
  padding-top: var(--md-spacing-2);
  padding-bottom: var(--md-spacing-6);
}

.top-app-bar-demo__bar--large .top-app-bar-demo__title {
  width: 100%;
  order: 10;
  font-size: var(--md-headline-small-size);
  font-weight: var(--md-headline-small-weight);
  line-height: var(--md-headline-small-line);
  margin-top: var(--md-spacing-6);
  padding: 0 var(--md-spacing-4);
}

/* Default title (small and center-aligned) */
.top-app-bar-demo__title {
  font-size: var(--md-title-medium-size);
  font-weight: var(--md-title-medium-weight);
  line-height: var(--md-title-medium-line);
  color: var(--md-on-surface);
}

/* Spacer for medium/large variants (pushes title to new line) */
.top-app-bar-demo__spacer {
  flex: 1;
}
/* ====================================================
   EXTENDED COMPONENTS - Additional M3 Components
   ==================================================== */

/* ---- Number Input ---- */
.number-input {
  position: relative;
  display: flex;
  align-items: center;
}

.number-input__input {
  padding-right: calc(var(--md-spacing-12) + var(--md-spacing-2));
  -moz-appearance: textfield;
}

.number-input__input::-webkit-outer-spin-button,
.number-input__input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

.number-input__controls {
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  flex-direction: column;
  gap: 0;
}

.number-input__btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--md-button-height-small);
  height: calc((var(--md-text-field-height) - 2 * var(--md-divider-thickness)) / 2);
  border: none;
  background: transparent;
  color: var(--md-on-surface-variant);
  cursor: pointer;
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
  font-size: var(--md-icon-size-small);
}

.number-input__btn:hover {
  background-color: var(--md-surface-container-high);
}

.number-input__btn .material-symbols-outlined {
  font-size: var(--md-icon-size-small);
}

.number-input__btn--increment {
  border-radius: 0 var(--md-shape-extra-small) 0 0;
}

.number-input__btn--decrement {
  border-radius: 0 0 var(--md-shape-extra-small) 0;
}

.text-field--outlined .number-input__btn--increment {
  border-radius: 0 var(--md-shape-extra-small) 0 0;
}

.text-field--outlined .number-input__btn--decrement {
  border-radius: 0 0 var(--md-shape-extra-small) 0;
}

/* ---- Password Input ---- */
.password-input {
  position: relative;
  display: flex;
  align-items: center;
}

.password-input__input {
  padding-right: calc(var(--md-input-icon-area) + var(--md-spacing-2));
}

.password-input__toggle {
  position: absolute;
  right: var(--md-spacing-1);
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--md-button-height-small);
  height: var(--md-button-height-small);
  border: none;
  border-radius: var(--md-shape-full);
  background: transparent;
  color: var(--md-on-surface-variant);
  cursor: pointer;
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.password-input__toggle:hover {
  background-color: var(--md-surface-container-high);
}

.password-input__icon {
  position: absolute;
  font-size: var(--md-icon-size-medium);
  transition: opacity var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.password-input__icon--hide {
  opacity: 0;
}

.password-input__toggle.password-input__toggle--visible .password-input__icon--show {
  opacity: 0;
}

.password-input__toggle.password-input__toggle--visible .password-input__icon--hide {
  opacity: 1;
}

/* Password Strength Indicator */
.password-strength {
  margin-top: var(--md-spacing-1);
}

.password-strength__bar {
  height: var(--md-progress-bar-height);
  background-color: var(--md-surface-container-high);
  border-radius: var(--md-shape-full);
  overflow: hidden;
}

.password-strength__fill {
  height: 100%;
  width: 0%;
  background-color: var(--md-error);
  transition: width var(--md-motion-duration-medium) var(--md-motion-easing-standard),
              background-color var(--md-motion-duration-medium) var(--md-motion-easing-standard);
}

.password-strength--weak .password-strength__fill {
  width: 33%;
  background-color: var(--md-error);
}

.password-strength--medium .password-strength__fill {
  width: 66%;
  background-color: var(--md-warning);
}

.password-strength--strong .password-strength__fill {
  width: 100%;
  background-color: var(--md-primary);
}

.password-strength__text {
  font-size: var(--md-body-small-size);
  color: var(--md-on-surface-variant);
  margin-top: 0;
}

/* ---- Textarea ---- */
.text-field--textarea .text-field__textarea {
  min-height: var(--md-textarea-min-height);
  resize: vertical;
  font-family: var(--md-font-main);
}

/* Outlined textarea: no fixed height; the vertical padding puts its first line where a field's
   text sits (half the room a field leaves around one line, less the border) */
.text-field--outlined .text-field__textarea {
  height: auto;
  padding-top: calc((var(--md-text-field-height) - var(--md-text-field-line)) / 2 - var(--md-divider-thickness));
  padding-bottom: calc((var(--md-text-field-height) - var(--md-text-field-line)) / 2 - var(--md-divider-thickness));
}

.text-field--outlined .text-field__textarea:focus {
  padding-top: calc((var(--md-text-field-height) - var(--md-text-field-line)) / 2 - var(--md-divider-thickness) * 2);
  padding-bottom: calc((var(--md-text-field-height) - var(--md-text-field-line)) / 2 - var(--md-divider-thickness) * 2);
}

/* Room for the counter (12px from the bottom, one body-small line) under the last text line */
.text-field--outlined:has(.textarea__counter) .text-field__textarea {
  padding-bottom: calc(var(--md-spacing-3) + var(--md-body-small-line));
}

.text-field--textarea .text-field__textarea[data-auto-resize="true"] {
  resize: none;
  overflow: hidden;
}

.textarea__counter {
  position: absolute;
  bottom: var(--md-spacing-2);
  right: var(--md-spacing-4);
  font-size: var(--md-body-small-size);
  color: var(--md-on-surface-variant);
  pointer-events: none;
}

.text-field--outlined .textarea__counter {
  bottom: var(--md-spacing-3);
}

/* ---- Time Picker ---- */
.time-picker {
  position: relative;
}

.time-picker__input {
  cursor: pointer;
  padding-right: var(--md-input-icon-area);
}

.time-picker .text-field__icon {
  position: absolute;
  right: var(--md-spacing-4);
  top: 50%;
  transform: translateY(-50%);
  font-size: var(--md-icon-size-medium);
  color: var(--md-on-surface-variant);
  pointer-events: none;
}

.time-picker__dropdown {
  position: absolute;
  top: calc(100% + var(--md-spacing-1));
  left: 0;
  z-index: 100;
  background-color: var(--md-surface-container);
  border-radius: var(--md-shape-large);
  box-shadow: var(--md-elevation-3);
  padding: var(--md-spacing-4);
  display: none;
  min-width: var(--md-list-max-height);
}

.time-picker__dropdown--visible {
  display: block;
}

.time-picker__header {
  text-align: center;
  margin-bottom: var(--md-spacing-4);
}

.time-picker__display {
  font-size: var(--md-headline-medium-size);
  font-weight: var(--md-headline-medium-weight);
  color: var(--md-on-surface);
}

.time-picker__body {
  display: flex;
  gap: var(--md-spacing-2);
  margin-bottom: var(--md-spacing-4);
}

.time-picker__column {
  flex: 1;
  display: flex;
  flex-direction: column;
}

.time-picker__column--period {
  flex: 0 0 auto;
  width: var(--md-narrow-component-width);
}

.time-picker__label {
  font-size: var(--md-label-small-size);
  color: var(--md-on-surface-variant);
  text-align: center;
  margin-bottom: var(--md-spacing-2);
}

.time-picker__scroller {
  height: var(--md-scrollable-list-height);
  overflow-y: auto;
  background-color: var(--md-surface-container-high);
  border-radius: var(--md-shape-small);
  scroll-snap-type: y mandatory;
}

.time-picker__option {
  height: var(--md-button-height-medium);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  scroll-snap-align: center;
  font-size: var(--md-body-large-size);
  color: var(--md-on-surface-variant);
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.time-picker__option:hover {
  background-color: var(--md-surface-container-highest);
}

.time-picker__option--selected {
  background-color: var(--md-primary-container);
  color: var(--md-on-primary-container);
}

.time-picker__period-btn {
  width: 100%;
  height: var(--md-button-height-medium);
  border: var(--md-divider-thickness) solid var(--md-outline);
  background-color: transparent;
  color: var(--md-on-surface-variant);
  font-size: var(--md-body-large-size);
  cursor: pointer;
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.time-picker__period-btn:first-child {
  border-radius: var(--md-shape-small) var(--md-shape-small) 0 0;
  margin-bottom: var(--md-spacing-2);
}

.time-picker__period-btn:last-child {
  border-radius: 0 0 var(--md-shape-small) var(--md-shape-small);
}

.time-picker__period-btn--active {
  background-color: var(--md-primary-container);
  color: var(--md-on-primary-container);
  border-color: transparent;
}

.time-picker__actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--md-spacing-2);
}

/* ---- Color Picker ---- */
.color-picker {
  position: relative;
}

.color-picker__input {
  cursor: pointer;
  padding-right: calc(var(--md-spacing-12) + var(--md-spacing-2));
}

.color-picker__swatch {
  position: absolute;
  right: var(--md-spacing-4);
  top: 50%;
  transform: translateY(-50%);
  width: var(--md-button-height-small);
  height: var(--md-button-height-small);
  border-radius: var(--md-shape-small);
  border: var(--md-divider-thickness) solid var(--md-outline-variant);
  cursor: pointer;
}

.color-picker__dropdown {
  position: absolute;
  top: calc(100% + var(--md-spacing-1));
  left: 0;
  z-index: 100;
  background-color: var(--md-surface-container);
  border-radius: var(--md-shape-large);
  box-shadow: var(--md-elevation-3);
  padding: var(--md-spacing-4);
  display: none;
  min-width: var(--md-component-width-small);
}

.color-picker__dropdown--visible {
  display: block;
}

.color-picker__preview {
  display: flex;
  gap: var(--md-spacing-3);
  margin-bottom: var(--md-spacing-4);
  align-items: center;
}

.color-picker__preview-box {
  width: var(--md-fab-size-small);
  height: var(--md-fab-size-small);
  border-radius: var(--md-shape-small);
  border: var(--md-divider-thickness) solid var(--md-outline-variant);
}

.color-picker__hex-input {
  flex: 1;
  padding: var(--md-spacing-2) var(--md-spacing-3);
  background-color: var(--md-surface-container-highest);
  border: var(--md-divider-thickness) solid var(--md-outline);
  border-radius: var(--md-shape-extra-small);
  color: var(--md-on-surface);
  font-size: var(--md-body-medium-size);
  font-family: monospace;
  text-transform: uppercase;
}

.color-picker__canvas {
  position: relative;
  margin-bottom: var(--md-spacing-3);
  border-radius: var(--md-shape-small);
  overflow: hidden;
}

.color-picker__saturation,
.color-picker__hue {
  display: block;
  cursor: crosshair;
}

.color-picker__hue-wrap {
  position: relative;
  margin-bottom: var(--md-spacing-4);
  border-radius: var(--md-shape-small);
  overflow: hidden;
}

.color-picker__saturation-cursor,
.color-picker__hue-cursor {
  position: absolute;
  width: var(--md-indicator-size-large);
  height: var(--md-indicator-size-large);
  border: calc(var(--md-divider-thickness) * 2) solid var(--md-on-surface);
  border-radius: var(--md-shape-full);
  box-shadow: 0 0 0 var(--md-divider-thickness) var(--md-scrim-light);
  pointer-events: none;
}

.color-picker__saturation-cursor {
  transform: translate(-50%, -50%);
}

.color-picker__hue-cursor {
  top: 50%;
  transform: translate(-50%, -50%);
}

.color-picker__presets {
  display: flex;
  gap: var(--md-spacing-2);
  flex-wrap: wrap;
}

.color-picker__preset {
  width: var(--md-color-preset-size);
  height: var(--md-color-preset-size);
  border-radius: var(--md-shape-small);
  border: var(--md-divider-thickness) solid var(--md-outline-variant);
  cursor: pointer;
  transition: transform var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.color-picker__preset:hover {
  transform: scale(1.1);
}

/* ---- OTP Input ---- */
.otp-input {
  margin-bottom: var(--md-spacing-4);
}

.otp-input__label {
  display: block;
  font-size: var(--md-body-medium-size);
  color: var(--md-on-surface-variant);
  margin-bottom: var(--md-spacing-3);
}

.otp-input__fields {
  display: flex;
  gap: var(--md-spacing-2);
  justify-content: center;
}

.otp-input__field {
  width: var(--md-input-icon-area);
  height: var(--md-input-field-height);
  text-align: center;
  font-size: var(--md-title-large-size);
  font-weight: var(--md-title-large-weight);
  background-color: var(--md-surface-container-highest);
  border: none;
  border-bottom: calc(var(--md-divider-thickness) * 2) solid var(--md-outline);
  border-radius: var(--md-shape-extra-small) var(--md-shape-extra-small) 0 0;
  color: var(--md-on-surface);
  outline: none;
  transition: border-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.otp-input__field:focus {
  border-bottom-color: var(--md-primary);
}

.otp-input__helper {
  font-size: var(--md-body-small-size);
  color: var(--md-on-surface-variant);
  margin-top: var(--md-spacing-2);
  text-align: center;
}

/* ---- OTP Login (two-step flow) ---- */
.otp-login__step {
  display: none;
  opacity: 0;
  transform: translateX(20px);
  transition: opacity var(--md-motion-duration-medium) var(--md-motion-easing-standard),
              transform var(--md-motion-duration-medium) var(--md-motion-easing-standard);
}

.otp-login__step--active {
  display: block;
  opacity: 1;
  transform: translateX(0);
  animation: otpStepIn var(--md-motion-duration-medium) var(--md-motion-easing-standard);
}

@keyframes otpStepIn {
  from {
    opacity: 0;
    transform: translateX(20px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

.otp-login__error {
  font-size: var(--md-body-small-size);
  color: var(--md-error);
  text-align: center;
  margin-top: var(--md-spacing-2);
  min-height: 0;
  opacity: 0;
  transition: opacity var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.otp-login__error--visible {
  opacity: 1;
}

/* Consent checkbox on the phone step (one box: SMS opt-in + Terms + Privacy) */
.otp-login__consent {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-3);
  margin-top: var(--md-spacing-4);
  text-align: left;
}

.otp-login__consent .checkbox {
  align-items: flex-start;
}

.otp-login__consent .checkbox__input {
  flex-shrink: 0;
  margin-top: calc(var(--md-spacing-1) * -0.5);   /* centre the 20px box on the 16px first line */
}

/* Legal boilerplate reads at the small body size, like the "Need help?" line below */
.otp-login__consent .checkbox__label {
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
  color: var(--md-on-surface-variant);
}

.otp-login__consent .checkbox__label strong {
  color: var(--md-on-surface);
}

.otp-login__consent a {
  color: var(--md-primary);
  font-weight: var(--md-weight-bold);
}

/* ---- Sign-in page (views/sign-in.ejs, sign-in.js; 2026-11-03) ----
   One outlined card at the auth width: the Login | Client Portal segments across the card's width
   (the drawer's full-width recipe: the segments share the room), then one panel per segment. The
   card is a one-column grid whose second row both panels share, so it keeps the taller panel's height
   on either segment and the toggle never jumps (the owner's call): the unchosen panel stays in the
   layout but invisible and inert (visibility, never display, so its height still counts). Each panel
   is the same wireframe, a column: the form (__body: its title, the segment's audience in one line at
   the public pages' reading size (__who), the lead and the fields) and the foot row - "Need help?" / "Don't have an account?" - pinned to the card's bottom (__foot,
   margin-top auto; the foot carries no inline margin, which would win over the pin) with at least the
   body's bottom margin above it. The phone panel clips its steps' slide (.otp-login__step translates
   in from the right). Below 768px the card is flat, like the app pages' sections (responsive.css). */
.sign-in {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  max-width: var(--md-auth-card-width);
  margin: 0 auto;
}

.sign-in__segments {
  grid-row: 1;
}

.sign-in__panel {
  grid-row: 2;
  grid-column: 1;
  display: flex;
  flex-direction: column;
}

.sign-in__panel[hidden] {
  display: flex;
  visibility: hidden;
}

.sign-in__who {
  margin-bottom: var(--md-spacing-2);
  font-size: var(--md-marketing-small-size);
  line-height: var(--md-marketing-small-line);
  color: var(--md-on-surface-variant);
  text-align: center;
}

.sign-in__body {
  margin-bottom: var(--md-spacing-4);
}

.sign-in__foot {
  margin-top: auto;
  padding-top: var(--md-spacing-4);
  border-top: var(--md-divider-thickness) solid var(--md-outline-variant);
  text-align: center;
}

.sign-in__segments .segmented-button {
  display: flex;
  width: 100%;
  margin-bottom: var(--md-spacing-8);   /* clear air between the toggle and the title under it */
}

.sign-in__segments .segmented-button__item {
  flex: 1;
}

.sign-in__panel--otp {
  overflow: hidden;
}

.otp-input--error .otp-input__field {
  border-color: var(--md-error);
  color: var(--md-error);
}

/* ---- Autocomplete ---- */
.autocomplete {
  position: relative;
}

.autocomplete__input {
  padding-left: var(--md-input-icon-area);
  padding-right: var(--md-input-icon-area);
}

.autocomplete--no-icon .autocomplete__input {
  padding-left: var(--md-spacing-4);
}

.autocomplete__icon {
  position: absolute;
  font-size: var(--md-icon-size-medium);
  color: var(--md-on-surface-variant);
  pointer-events: none;
}

.autocomplete__icon--search {
  left: var(--md-spacing-4);
  top: 50%;
  transform: translateY(-50%);
}

.autocomplete__clear {
  position: absolute;
  right: var(--md-spacing-1);
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--md-button-height-small);
  height: var(--md-button-height-small);
  border: none;
  border-radius: var(--md-shape-full);
  background: transparent;
  color: var(--md-on-surface-variant);
  cursor: pointer;
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.autocomplete__clear:hover {
  background-color: var(--md-surface-container-high);
}

.autocomplete__dropdown {
  position: absolute;
  top: calc(100% + var(--md-spacing-1));
  left: 0;
  right: 0;
  z-index: 100;
  background-color: var(--md-surface-container);
  border-radius: var(--md-shape-small);
  box-shadow: var(--md-elevation-2);
  max-height: var(--md-list-max-height);
  overflow-y: auto;
  display: none;
}

.autocomplete__dropdown--visible {
  display: block;
}

.autocomplete__list {
  padding: var(--md-spacing-2) 0;
}

.autocomplete__item {
  display: flex;
  align-items: center;
  gap: var(--md-spacing-3);
  padding: var(--md-spacing-3) var(--md-spacing-4);
  cursor: pointer;
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.autocomplete__item:hover,
.autocomplete__item--highlighted,
.autocomplete__item--focused {
  background-color: var(--md-surface-container-high);
}

.autocomplete__item--selected {
  background-color: var(--md-primary-container);
  color: var(--md-on-primary-container);
}

.autocomplete__item-icon {
  font-size: var(--md-icon-size-medium);
  color: var(--md-on-surface-variant);
}

.autocomplete__item-text {
  flex: 1;
  font-size: var(--md-label-large-size);
}

.autocomplete__empty {
  padding: var(--md-spacing-6) var(--md-spacing-4);
  text-align: center;
  color: var(--md-on-surface-variant);
  font-size: var(--md-body-medium-size);
}

/* ---- Range Slider ---- */
.range-slider {
  margin-bottom: var(--md-spacing-6);
}

.range-slider__label {
  display: block;
  font-size: var(--md-body-medium-size);
  color: var(--md-on-surface-variant);
  margin-bottom: var(--md-spacing-4);
}

.range-slider__container {
  position: relative;
  height: var(--md-icon-button-size);
  padding: 0 var(--md-spacing-2);
}

.range-slider__track {
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  height: var(--md-progress-bar-height);
  background-color: var(--md-surface-container-highest);
  border-radius: var(--md-shape-full);
  transform: translateY(-50%);
}

.range-slider__fill {
  position: absolute;
  top: 50%;
  height: var(--md-progress-bar-height);
  background-color: var(--md-primary);
  border-radius: var(--md-shape-full);
  transform: translateY(-50%);
  pointer-events: none;
}

.range-slider__thumb {
  position: absolute;
  top: 50%;
  width: var(--md-slider-thumb-size);
  height: var(--md-slider-thumb-size);
  background-color: var(--md-primary);
  border-radius: var(--md-shape-full);
  transform: translate(-50%, -50%);
  cursor: grab;
  transition: box-shadow var(--md-motion-duration-short) var(--md-motion-easing-standard);
  outline: none;
}

.range-slider__thumb:hover,
.range-slider__thumb:focus-visible {
  box-shadow: 0 0 0 8px rgba(var(--md-primary-rgb), 0.16);
}

.range-slider__thumb:active,
.range-slider__thumb--active {
  cursor: grabbing;
  box-shadow: 0 0 0 12px rgba(var(--md-primary-rgb), 0.24);
}

.range-slider__value {
  position: absolute;
  bottom: calc(100% + var(--md-spacing-1));
  left: 50%;
  transform: translateX(-50%);
  background-color: var(--md-inverse-surface);
  color: var(--md-inverse-on-surface);
  padding: var(--md-spacing-1) var(--md-spacing-2);
  border-radius: var(--md-shape-extra-small);
  font-size: var(--md-label-small-size);
  white-space: nowrap;
  opacity: 0;
  transition: opacity var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.range-slider__thumb:hover .range-slider__value,
.range-slider__thumb:focus .range-slider__value,
.range-slider__thumb:active .range-slider__value,
.range-slider__thumb--active .range-slider__value {
  opacity: 1;
}

/* ---- Speed Dial ---- */
.speed-dial {
  position: fixed;
  bottom: var(--md-spacing-6);
  right: var(--md-spacing-6);
  z-index: 1000;
}

.speed-dial__trigger {
  position: relative;
  z-index: 3;
}

.speed-dial__icon {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: opacity var(--md-motion-duration-short) var(--md-motion-easing-standard),
              transform var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.speed-dial__icon--close {
  opacity: 0;
  transform: rotate(-90deg);
}

.speed-dial--open .speed-dial__icon--main {
  opacity: 0;
  transform: rotate(90deg);
}

.speed-dial--open .speed-dial__icon--close {
  opacity: 1;
  transform: rotate(0deg);
}

.speed-dial__actions {
  position: absolute;
  bottom: 100%;
  right: 0;
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-3);
  padding-bottom: var(--md-spacing-3);
  pointer-events: none;
}

.speed-dial--open .speed-dial__actions {
  pointer-events: auto;
}

.speed-dial__action-wrapper {
  display: flex;
  align-items: center;
  gap: var(--md-spacing-4);
  opacity: 0;
  transform: translateY(var(--md-spacing-4));
  transition: opacity var(--md-motion-duration-medium) var(--md-motion-easing-emphasized),
              transform var(--md-motion-duration-medium) var(--md-motion-easing-emphasized);
}

.speed-dial__action {
  margin-left: auto;
}

.speed-dial--open .speed-dial__action-wrapper {
  opacity: 1;
  transform: translateY(0);
}

.speed-dial__action-wrapper:nth-child(1) { transition-delay: var(--md-motion-stagger-delay); }
.speed-dial__action-wrapper:nth-child(2) { transition-delay: calc(var(--md-motion-stagger-delay) * 2); }
.speed-dial__action-wrapper:nth-child(3) { transition-delay: calc(var(--md-motion-stagger-delay) * 3); }
.speed-dial__action-wrapper:nth-child(4) { transition-delay: calc(var(--md-motion-stagger-delay) * 4); }
.speed-dial__action-wrapper:nth-child(5) { transition-delay: calc(var(--md-motion-stagger-delay) * 5); }

.speed-dial__label {
  background-color: var(--md-inverse-surface);
  color: var(--md-inverse-on-surface);
  padding: var(--md-spacing-2) var(--md-spacing-3);
  border-radius: var(--md-shape-extra-small);
  font-size: var(--md-label-medium-size);
  white-space: nowrap;
}

.speed-dial__backdrop {
  position: fixed;
  inset: 0;
  background-color: var(--md-scrim-light);
  z-index: -1;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--md-motion-duration-medium) var(--md-motion-easing-standard);
}

.speed-dial--open .speed-dial__backdrop {
  opacity: 1;
  pointer-events: auto;
}

/* ---- Navigation Drawer ---- */
/* ---- Navigation drawer: the collapsed-tier menu, docked under the header bar ----
   Rendered by header.ejs inside nav.navbar after the bar row and positioned against .header
   (layout.css keeps .navbar and .navbar__inner static; the /reference demo positions against
   its own .navbar). Like the desktop .navbar__panel it paints at z-index -1 inside the header's
   stacking context - over the header background, under the bar row - so opening reads as the
   bar itself growing downward. Only the bar's left 360px grows: the panel is the drawer's column
   (--md-component-width-medium) at the bar's left edge, and the rest of the bar keeps its rounded
   bottom-right corner. The grid row goes 0fr -> 1fr (height from the content, capped at the
   room under the bar with the body scrolling inside), the ::before strip squares the bar's
   bottom-left corner while open, and the closed state is visibility: hidden (delayed on close so
   the exit plays) rather than display: none, which would cut the transitions short. A
   descendant that manages its own visibility (.drawer__group-panel) inherits rather than
   forcing visible, so a closed drawer hides all of it. Collapsed tier only: from 1280px the
   link cluster and its panels take over. Below 768px the public drawer lifts the 360px cap too
   and spans the whole bar (the phones block below). Portal pages (layout.css .site--portal) lift
   the cap at every width, show the rows as a short dropdown and hand over to the rail from 768px
   (the rules after the reduced-motion block below). */
.drawer {
  position: absolute;
  top: 100%;
  left: 0;
  width: 100%;
  max-width: var(--md-component-width-medium);
  z-index: -1;
  display: grid;
  grid-template-rows: 0fr;
  background-color: var(--md-surface);
  box-shadow: var(--md-elevation-2);
  border-bottom-left-radius: var(--md-shape-large);
  border-bottom-right-radius: var(--md-shape-large);
  visibility: hidden;
  transition: grid-template-rows var(--md-motion-duration-medium) var(--md-motion-easing-accelerate),
              visibility 0s linear var(--md-motion-duration-medium);
}

/* Squares the header's rounded bottom-left corner while open (the strip spans the panel's width
   only) and covers the shadow's upward bleed */
.drawer::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 100%;
  height: var(--md-shape-large);
  background-color: var(--md-surface);
}

.drawer--open {
  grid-template-rows: 1fr;
  visibility: visible;
  transition: grid-template-rows var(--md-motion-duration-long) var(--md-motion-easing-emphasized),
              visibility 0s;
}

/* The grid row: clips while the bar grows and collapses, so the column inside keeps its full
   height throughout and its body never gets squeezed into showing a scrollbar mid-transition */
.drawer__row {
  overflow: hidden;
  min-height: 0;
}

/* Body + footer in one column no taller than the room under the bar (the panel sets the width) */
.drawer__content {
  display: flex;
  flex-direction: column;
  max-height: calc(100vh - var(--md-header-height));
  max-height: calc(100dvh - var(--md-header-height));
}

/* Phones: the drawer spans the whole bar (the 360px column is for tablets, where the bar has room
   beside it; here it would leave a dimmed sliver at the right, as the portal drawer never does)
   and the column fills the room under the bar, like a sheet (the body stretches, the contact
   footer sits at the bottom edge) */
@media (max-width: 767px) {
  .drawer {
    max-width: none;
  }

  .drawer__content {
    min-height: calc(100vh - var(--md-header-height));
    min-height: calc(100dvh - var(--md-header-height));
  }
}

/* Dims the page while a drawer is open. Rendered by header.ejs right after the header, not inside
   it: one step under the header (bar, shadow and docked drawer are all inside its z-index 100)
   and over the page, so the bar's rounded corners show the dimmed page and the bar's shadow
   falls on the scrim. core.js toggles --open together with the drawer; the /reference demo
   renders no scrim */
.drawer__scrim {
  position: fixed;
  inset: 0;
  z-index: 99;
  background-color: var(--md-scrim-medium);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--md-motion-duration-medium) var(--md-motion-easing-accelerate),
              visibility 0s linear var(--md-motion-duration-medium);
}

.drawer__scrim--open {
  opacity: 1;
  visibility: visible;
  transition: opacity var(--md-motion-duration-long) var(--md-motion-easing-standard),
              visibility 0s;
}

/* The drawer belongs to the collapsed tier; the desktop link cluster has its own panels */
@media (min-width: 1280px) {
  .drawer,
  .drawer__scrim {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .drawer,
  .drawer--open,
  .drawer__scrim,
  .drawer__scrim--open {
    transition: none;
  }
}

/* Portal app shell (layout.css .site--portal): the drawer spans the whole charcoal bar (no 360px column),
   lists the rail's items, is charcoal through the dark roles the bar carries (mk-section--dark: rows, the
   row icons in the tone-80 green and the end-user contact footer recolour through their own tokens), keeps its rounded
   bottom corners over the dimmed panel as a short dropdown (no phone sheet: min-height 0), and hands over
   to the rail from 768px, the tier navigation-drawer.js reads from data-desktop-query on the element. The
   ::before corner strip above it is charcoal on charcoal and still hides the shadow's upward bleed. */
.site--portal .drawer {
  max-width: none;
}

.site--portal .drawer__content {
  min-height: 0;
  max-height: calc(100vh - var(--md-portal-bar-height));    /* the portal bar's own height, not the app-bar's */
  max-height: calc(100dvh - var(--md-portal-bar-height));
}

@media (min-width: 768px) {
  .site--portal .drawer,
  .site--portal .drawer__scrim {
    display: none;
  }
}

/* The bottom breathing room sits on the list (.drawer__nav), not the body, so a segment's
   sticky CTA block ends flush with the scrollable content and never jogs at the end of a scroll */
.drawer__body {
  flex: 1 1 auto;
  min-height: 0;   /* lets the body shrink and scroll inside the capped column */
  overflow-y: auto;
  padding: var(--md-spacing-2) 0 0;
}

.drawer__nav {
  padding-bottom: var(--md-spacing-2);
}

/* Audience switch ("Park | Manage"): a segmented switch across the drawer at the row height (48px
   outer, like the rows and the CTA buttons: items at the large button height less the group's two
   hairlines, no vertical padding - the large button's 14px padding assumes a 20px text line, and
   the 24px row icons would push it to 52px) with the rows' 24px icons, without the M3 check mark -
   two segments need no selection icon. Panels (.drawer__panel) carry no display rule so the
   `hidden` attribute keeps working. */
.drawer__segments {
  padding: var(--md-spacing-2) var(--md-spacing-6) var(--md-spacing-3);
}

.drawer__segments .segmented-button {
  display: flex;
  width: 100%;
  margin-bottom: 0;
}

.drawer__segments .segmented-button__item {
  flex: 1;
  min-height: calc(var(--md-button-height-large) - 2 * var(--md-segmented-pad));
  padding: 0 var(--md-button-padding-x-small);
  font-size: var(--md-marketing-small-size);
  line-height: var(--md-marketing-small-line);
}

/* The segments' icons are the row icons' size; unpressed ones take their primary tint, the pressed one
   the label's own colour over the thumb (the charcoal palette's lightest grey, --md-segmented-thumb) */
.drawer__segments .segmented-button__icon {
  font-size: var(--md-icon-size-medium);
  color: var(--md-primary);
}

.drawer__segments .segmented-button__item--selected .segmented-button__icon {
  color: var(--md-on-surface);
}

/* CTA block: one full-width large filled button (btn--large: 48px meets the 48dp / 44pt touch
   minimums; the segment's only filled button - every other action is a destination row) and,
   when the segment declares a secondary button (Manage: Client Portal), an outlined one stacked
   under it. It closes the segment's list behind a divider line and sticks to the bottom of the
   scrolling body: a long list (Manage) scrolls under it, a short one (Park) simply ends with it;
   the surface background hides the rows passing beneath */
.drawer__cta {
  position: sticky;
  bottom: 0;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--md-spacing-2);
  padding: var(--md-spacing-3) var(--md-spacing-6);
  border-top: var(--md-divider-thickness) solid var(--md-outline-variant);
  background-color: var(--md-surface);
}

/* The buttons keep btn--large's height and padding, but their labels read at the nav voice of the
   rows and the switch (marketing-small on its 20px line), not the hero CTA's title-medium */
.drawer__cta .btn {
  width: 100%;
  font-size: var(--md-marketing-small-size);
  line-height: var(--md-marketing-small-line);
}

.drawer__heading {
  padding: var(--md-spacing-4) var(--md-spacing-6) var(--md-spacing-2);
  font-size: var(--md-label-small-size);
  font-weight: var(--md-label-small-weight);
  color: var(--md-on-surface-variant);
  text-transform: uppercase;
  letter-spacing: var(--md-letter-spacing-tight-small);
}

.drawer__item {
  display: flex;
  align-items: center;
  gap: var(--md-spacing-3);
  margin: 0 var(--md-spacing-3);
  padding: var(--md-spacing-3);
  border-radius: var(--md-shape-full);
  color: var(--md-on-surface);
  text-decoration: none;
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard),
              color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

/* Rows read at the panel row's colour (.navbar__panel-item: on-surface), not the supporting
   colour, so a label outranks the sentence under it; hover adds a header pill's background
   (.navbar__link:hover). The :hover selectors also outrank base.css a:hover, which would
   otherwise recolour the row */
.drawer__item:hover {
  background-color: var(--md-surface-container-high);
  color: var(--md-on-surface);
}

.drawer__item--active,
.drawer__item--active:hover {
  background-color: var(--md-secondary-container);
  color: var(--md-on-secondary-container);
}

.drawer__item-icon {
  font-size: var(--md-icon-size-medium);
  color: var(--md-primary);
}

/* Row labels at the nav-label voice: the header pill's size and weight (.navbar__link, the
   panel row label .navbar__panel-label), so a row ranks with the Park | Manage switch above
   and one step over a group's member labels (.drawer__item-label below) */
.drawer__item-text {
  flex: 1;
  font-size: var(--md-marketing-small-size);
  font-weight: var(--md-label-large-weight);
  line-height: var(--md-marketing-small-line);
}

/* A locked portal row (the AI Assistant while the account has no card on file): a lock at the row's end */
.drawer__item-lock {
  margin-left: auto;
  font-size: var(--md-icon-size-small);
  color: var(--md-on-surface-variant);
}

.drawer__item--bold {
  font-weight: var(--md-weight-bold);
}

/* Expandable group row (a header menu such as Solutions, folded into the drawer): the toggle is
   a <button> dressed as a row with a trailing chevron that turns while open, and its members
   follow as two-line rows (label, the route's menuDescription) indented to the label column.
   One group is open per list (navigation-drawer.js). The panel animates on grid rows like the
   header panel and is visibility: hidden while closed, so its links take no focus or clicks */
.drawer__group-toggle {
  width: calc(100% - 2 * var(--md-spacing-3));
  background: none;
  border: none;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
}

.drawer__group-chevron {
  font-size: var(--md-icon-size-medium);
  color: var(--md-on-surface-variant);
  transition: transform var(--md-motion-duration-medium) var(--md-motion-easing-emphasized);
}

.drawer__group--expanded .drawer__group-chevron {
  transform: rotate(180deg);
}

.drawer__group-panel {
  display: grid;
  grid-template-rows: 0fr;
  visibility: hidden;
  transition: grid-template-rows var(--md-motion-duration-medium) var(--md-motion-easing-emphasized),
              visibility 0s linear var(--md-motion-duration-medium);
}

.drawer__group--expanded .drawer__group-panel {
  grid-template-rows: 1fr;
  visibility: inherit;   /* not `visible`: a closed drawer (visibility hidden) must hide it too */
  transition: grid-template-rows var(--md-motion-duration-medium) var(--md-motion-easing-emphasized),
              visibility 0s;
}

.drawer__group-inner {
  overflow: hidden;
  min-height: 0;
}

/* Member rows carry no icon; the label starts under the group label (row padding + icon + gap) */
.drawer__item--child {
  padding-left: calc(var(--md-spacing-3) + var(--md-icon-size-medium) + var(--md-spacing-3));
}

/* A member is a two-line list row: the label at the list headline voice (the body weight on the
   row's on-surface, .list__headline), one step under its group row, over the route's
   menuDescription at the supporting-text role (body-medium on on-surface-variant,
   .list__supporting, the header panel's sentence) and, on Careers while a role is open, the
   Hiring chip at the row's end */
.drawer__item-label {
  font-weight: var(--md-body-large-weight);
}

.drawer__item-desc {
  display: block;
  font-size: var(--md-body-medium-size);
  font-weight: var(--md-body-medium-weight);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
}

.drawer__item--active .drawer__item-desc {
  color: inherit;
}

/* Portal hub rows (layout.ejs gives the group an href): the head is a link to the hub beside a 40px
   chevron icon button (.icon-btn) carrying the toggle class; the row paints the hover / current fill
   under both so they read as one row, and the link inside paints nothing of its own. The public menus
   keep the button-only head. Declared after .drawer__group-toggle so the icon width wins its
   full-width rule */
.drawer__group-row {
  display: flex;
  align-items: center;
  margin: 0 var(--md-spacing-3);
  border-radius: var(--md-shape-full);
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.drawer__group-row > .drawer__item {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
}

.drawer__group-row > .drawer__item,
.drawer__group-row > .drawer__item:hover,
.drawer__group-row > .drawer__item--active,
.drawer__group-row > .drawer__item--active:hover {
  background-color: transparent;
}

.drawer__group-row:hover {
  background-color: var(--md-surface-container-high);
}

.drawer__group-row--active,
.drawer__group-row--active:hover {
  background-color: var(--md-secondary-container);
}

.drawer__group-toggle--icon {
  width: var(--md-icon-button-size);
  height: var(--md-icon-button-size);
  flex-shrink: 0;
  margin-right: var(--md-spacing-1);
  padding: 0;
  text-align: center;
}

.drawer__group-toggle--icon:hover {
  background-color: var(--md-surface-container-highest);
}

.drawer__group-row--active .drawer__group-chevron {
  color: var(--md-on-secondary-container);
}

/* A member with an icon (the portal's children): the small glyph at the start of the indented row */
.drawer__item-icon--child {
  font-size: var(--md-icon-size-small);
}

@media (prefers-reduced-motion: reduce) {
  .drawer__group-row,
  .drawer__group-chevron,
  .drawer__group-panel,
  .drawer__group--expanded .drawer__group-panel {
    transition: none;
  }
}

.drawer__footer {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--md-spacing-2);
  padding: var(--md-spacing-4) var(--md-spacing-6);
  border-top: var(--md-divider-thickness) solid var(--md-outline-variant);
}

.drawer__footer-contact {
  display: flex;
  align-items: center;
  gap: var(--md-spacing-2);
  font-size: var(--md-marketing-small-size);
  line-height: var(--md-marketing-small-line);
  color: var(--md-on-surface-variant);
  text-decoration: none;
  transition: color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.drawer__footer-contact:hover {
  color: var(--md-primary);
}

.drawer__footer-contact .material-symbols-outlined {
  font-size: var(--md-icon-size-extra-small);
  color: var(--md-primary);
}


/* ---- Modern Navbar / Top App Bar ---- */
.navbar-demo {
  background-color: var(--md-surface);
  border-radius: var(--md-shape-medium);
  padding: var(--md-spacing-4);
  margin-bottom: var(--md-spacing-6);
}

/* The demo navbar is its own stacking context, so the drawer docked under it (z-index -1) paints
   above the card instead of behind the page */
.navbar-demo .navbar {
  isolation: isolate;
}

.navbar {
  background-color: var(--md-surface-container);
  border-radius: var(--md-shape-medium);
  box-shadow: var(--md-elevation-1);
  position: relative;
}

.navbar__inner {
  display: flex;
  align-items: center;
  position: relative;
  gap: var(--md-spacing-4);
  padding: var(--md-spacing-3) var(--md-spacing-4);
  min-height: var(--md-top-app-bar-height-small);
}

.navbar__menu-btn {
  display: none;
}

.navbar__logo {
  display: flex;
  align-items: center;
  text-decoration: none;
  flex-shrink: 0;
}

/* The light-text wordmark (the bar is charcoal on every page, header.ejs); the portal bar's P mark
   variant and its tier swap live in the "Portal top bar" block below */
.navbar__logo-img {
  height: var(--md-navbar-logo-height);
  width: auto;
}

/* No hover state on the brand mark: an opacity fade blended the logo toward the page surface,
   which dulled the green disc (removed 2026-09-28) */

/* The link cluster stays in the flex flow and centres itself in the room between the logo and
   the two buttons (Book a Demo, Sign in), so the two can never overlap however wide the buttons
   get; below 1280px the cluster hides and the drawer takes over */
.navbar__links {
  display: flex;
  flex: 1 1 auto;
  justify-content: center;
  min-width: 0;
  gap: var(--md-spacing-1);
}

/* Nav labels read at the public-page reading size (marketing-small, 14px on a 20px line, same
   as the footer links and the drawer contact lines); the 20px line keeps the pill at 36px */
.navbar__link {
  padding: var(--md-spacing-2) var(--md-spacing-3);
  border-radius: var(--md-shape-full);
  font-size: var(--md-marketing-small-size);
  font-weight: var(--md-label-large-weight);
  line-height: var(--md-marketing-small-line);
  color: var(--md-on-surface-variant);
  text-decoration: none;
  white-space: nowrap;   /* a label never stacks: one spacing from 1280px up, the 1200px row is sized for it */
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard),
              color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.navbar__link:hover {
  background-color: var(--md-surface-container-high);
  color: var(--md-on-surface);
}

.navbar__link--active {
  background-color: var(--md-secondary-container);
  color: var(--md-on-secondary-container);
}

/* An open dropdown trigger shows the same tinted pill as an active link (after --active and
   :hover so the open state wins) */
.navbar__link--menu[aria-expanded="true"] {
  background-color: var(--md-secondary-container);
  color: var(--md-on-secondary-container);
}

.navbar__actions {
  display: flex;
  gap: var(--md-spacing-2);
}

.navbar__cta {
  white-space: nowrap;
}

/* Navbar dropdown trigger (Solutions, Resources, Company): a <button> styled as a nav link; the mega
   panel it opens follows below. Markup: views/partials/nav-menu.ejs; behaviour: src/js/components/nav-menu.js */
.navbar__link--menu {
  display: inline-flex;
  align-items: center;
  gap: var(--md-spacing-1);
  background: none;
  border: none;
  font-family: inherit;
  line-height: inherit;
  cursor: pointer;
}

.navbar__link-chevron {
  font-size: var(--md-icon-size-small);
  transition: transform var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.navbar__link--menu[aria-expanded="true"] .navbar__link-chevron {
  transform: rotate(180deg);
}

/* Navbar panel: a header group's mega panel (Solutions, Resources, Company), the surface that
   expands the header bar downward (markup in nav-menu.ejs next to its trigger; behaviour in
   nav-menu.js). Overlay, not in flow: the header is sticky inside the .site grid, so an in-flow
   panel would push the page down on every hover. It positions against .header (layout.css makes
   .navbar and .navbar__inner static) at z-index -1 - over the header background, under the bar
   row - so it slides out from behind the bar. Height is the content's (grid rows 0fr -> 1fr, the
   footer's pattern), never fixed. visibility is delayed on close so the collapsed panel paints no
   shadow line and takes no hover or focus (its links leave the Tab order with it). */
.navbar__panel {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: -1;
  display: grid;
  grid-template-rows: 0fr;
  background-color: var(--md-surface);
  box-shadow: var(--md-elevation-2);
  border-bottom-left-radius: var(--md-shape-large);
  border-bottom-right-radius: var(--md-shape-large);
  visibility: hidden;
  transition: grid-template-rows var(--md-motion-duration-short) var(--md-motion-easing-accelerate),
              visibility 0s linear var(--md-motion-duration-short);
}

/* Squares the header's rounded bottom corners while open and covers the shadow's upward bleed */
.navbar__panel::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 100%;
  height: var(--md-shape-large);
  background-color: var(--md-surface);
}

.navbar__panel--open {
  grid-template-rows: 1fr;
  visibility: visible;
  transition: grid-template-rows var(--md-motion-duration-medium) var(--md-motion-easing-emphasized),
              visibility 0s;
}

/* A sibling group is taking over: this panel drops with no collapse animation, and the panel
   taking over opens with no grow (--swap), so the surface changes height in one frame
   (nav-menu.js holds each class for one style pass) */
.navbar__panel--instant,
.navbar__panel--instant .navbar__panel-item,
.navbar__panel--instant .navbar__panel-card,
.navbar__panel--swap {
  transition: none;
}

.navbar__panel-row {
  overflow: hidden;
  min-height: 0;   /* grid rows default to min-content; 0fr needs this to collapse */
}

/* The panel's content sits on the bar's 1200px row (the same max-width and auto margins as
   .navbar__inner; the header's symmetric side padding centres both on one axis from 1248px, so
   the left edge is the wordmark's), divided into sections: the columns share the room left of the
   featured card evenly, the card is the medium component width at the right edge under the
   buttons. The left padding is the row's padding minus a row's own padding, so the row icons sit
   flush with the wordmark; the right padding is the row's, so the card ends under Sign in. The
   max-height keeps the content reachable on a short snapped window (the row above keeps clipping
   for the animation) */
.navbar__panel-inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--md-component-width-medium);
  column-gap: var(--md-spacing-8);
  max-width: var(--md-layout-max-width);
  margin: 0 auto;
  padding: var(--md-spacing-4) var(--md-spacing-4) var(--md-spacing-6) var(--md-spacing-1);
  max-height: calc(100dvh - var(--md-header-height));
  overflow-y: auto;
  text-align: left;
}

.navbar__panel-inner--cols-2 {
  grid-template-columns: repeat(2, minmax(0, 1fr)) var(--md-component-width-medium);
}

/* Sections: every column after the first, and the card, starts with a hairline - the column gap
   on one side of the line, the same air on the other; the grid items stretch, so the lines run
   the panel's full height */
.navbar__panel-col + .navbar__panel-col,
.navbar__panel-card {
  border-left: var(--md-divider-thickness) solid var(--md-outline-variant);
  padding-left: var(--md-spacing-8);
}

/* A column: its eyebrow (the section eyebrow without its block margin; marketing.css loads later,
   the two-class selector outranks it) over the list of rows */
.navbar__panel .mk-eyebrow {
  margin: 0;
}

.navbar__panel-eyebrow {
  padding: 0 var(--md-spacing-3) var(--md-spacing-1);
}

.navbar__panel-list {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-1);
  list-style: none;
  margin: 0;
  padding: 0;
}

/* One row: the route's icon, label (+ badge chip) and menuDescription; hidden until the panel
   opens, then fades in and rises. The delay list keeps the hover tint instant (delays apply to
   opacity and transform only). */
.navbar__panel-item {
  display: flex;
  align-items: flex-start;
  gap: var(--md-spacing-3);
  padding: var(--md-spacing-2) var(--md-spacing-3);
  border-radius: var(--md-shape-medium);
  color: var(--md-on-surface);
  text-decoration: none;
  opacity: 0;
  transform: translateY(var(--md-spacing-1));
  transition: opacity var(--md-motion-duration-short) var(--md-motion-easing-standard),
              transform var(--md-motion-duration-short) var(--md-motion-easing-standard),
              background-color var(--md-motion-duration-short) var(--md-motion-easing-standard),
              color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

/* base.css a:hover would otherwise recolour the anchor */
.navbar__panel-item:hover {
  background-color: var(--md-surface-container-high);
  color: var(--md-on-surface);
}

.navbar__panel-item:focus-visible {
  outline: calc(var(--md-divider-thickness) * 2) solid var(--md-primary);
  outline-offset: calc(var(--md-divider-thickness) * 2);
}

.navbar__panel-item--current,
.navbar__panel-item--current:hover {
  background-color: var(--md-secondary-container);
  color: var(--md-on-secondary-container);
}

.navbar__panel-item--current .navbar__panel-desc {
  color: inherit;
}

/* The glyph is centred on the label's line (the icon is taller than the line) */
.navbar__panel-icon {
  flex-shrink: 0;
  font-size: var(--md-icon-size-medium);
  color: var(--md-primary);
  margin-top: calc((var(--md-marketing-small-line) - var(--md-icon-size-medium)) / 2);
}

.navbar__panel-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

/* The label at the nav-label voice (the pill's size and weight, never wrapping), the sentence
   under it at the supporting-text role (body-medium on on-surface-variant, the list's pattern) */
.navbar__panel-label {
  display: flex;
  align-items: center;
  gap: var(--md-spacing-2);
  font-size: var(--md-marketing-small-size);
  font-weight: var(--md-label-large-weight);
  line-height: var(--md-marketing-small-line);
  white-space: nowrap;
}

.navbar__panel-desc {
  font-size: var(--md-body-medium-size);
  font-weight: var(--md-body-medium-weight);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
}

/* Featured card (partials/nav-menu-card): the panel's last section behind its hairline (above),
   no box of its own, holding the vignette or the article banner, then eyebrow, title, text, the
   contact rows and the button; the article card is one anchor. Its content is indented by a row's
   side padding so it lines up with the columns' eyebrows and labels. It fades in with the rows
   (opacity and transform only) */
.navbar__panel-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--md-spacing-2);
  padding-left: calc(var(--md-spacing-8) + var(--md-spacing-3));
  color: var(--md-on-surface);
  text-decoration: none;
  opacity: 0;
  transform: translateY(var(--md-spacing-1));
  transition: opacity var(--md-motion-duration-short) var(--md-motion-easing-standard),
              transform var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.navbar__panel-card .mk-vig {
  width: 100%;
  max-width: none;
  box-shadow: none;
  margin-bottom: var(--md-spacing-2);
}

/* The article banner in a 16:9 window (the article card's crop), rounded inside the padding; the
   image is fetched by nav-menu.js on the first open (data-src), the window shows the surface until then */
.navbar__panel-card-media {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: var(--md-shape-medium);
  background-color: var(--md-surface-container-high);
  margin-bottom: var(--md-spacing-2);
}

.navbar__panel-card-media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.navbar__panel-card-title {
  margin: 0;
  font-size: var(--md-title-medium-size);
  line-height: var(--md-title-medium-line);
  font-weight: var(--md-weight-bold);
  color: var(--md-on-surface);   /* base.css p is on-surface-variant */
  transition: color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.navbar__panel-card--article:hover .navbar__panel-card-title {
  color: var(--md-primary);
}

.navbar__panel-card-text {
  margin: 0;
  font-size: var(--md-body-medium-size);
  font-weight: var(--md-body-medium-weight);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
}

/* Contact rows (phone, email): icon + text links at the drawer footer's size */
.navbar__panel-card-row {
  display: inline-flex;
  align-items: center;
  gap: var(--md-spacing-2);
  font-size: var(--md-marketing-small-size);
  line-height: var(--md-marketing-small-line);
  color: var(--md-on-surface);
  text-decoration: none;
}

.navbar__panel-card-row .material-symbols-outlined {
  font-size: var(--md-icon-size-small);
  color: var(--md-primary);
}

/* base.css a:hover would recolour it otherwise */
.navbar__panel-card-row:hover {
  color: var(--md-primary);
}

/* The vignette and contact cards end with a filled Book a demo button (the bar's button style) */
.navbar__panel-card .btn {
  margin-top: var(--md-spacing-2);
}

/* The article card's "Read the article" line (a span inside the card anchor): label + arrow in primary */
.navbar__panel-card-link {
  display: inline-flex;
  align-items: center;
  gap: var(--md-spacing-1);
  margin-top: var(--md-spacing-1);
  font-size: var(--md-label-large-size);
  font-weight: var(--md-label-large-weight);
  line-height: var(--md-label-large-line);
  color: var(--md-primary);
  text-decoration: none;
}

.navbar__panel-card-link .material-symbols-outlined {
  font-size: var(--md-icon-size-small);
}

.navbar__panel-card-link:hover,
.navbar__panel-card--article:hover .navbar__panel-card-link {
  color: var(--md-primary);
  text-decoration: underline;
}

.navbar__panel-card:focus-visible,
.navbar__panel-card-link:focus-visible,
.navbar__panel-card-row:focus-visible {
  outline: calc(var(--md-divider-thickness) * 2) solid var(--md-primary);
  outline-offset: calc(var(--md-divider-thickness) * 2);
}

/* Cascade (the speed dial's pattern): row n of each column starts n stagger steps after the bar
   begins to open, the columns in parallel; the card arrives with the second row */
.navbar__panel-list > li:nth-child(1) .navbar__panel-item { --navbar-panel-i: 1; }
.navbar__panel-list > li:nth-child(2) .navbar__panel-item { --navbar-panel-i: 2; }
.navbar__panel-list > li:nth-child(3) .navbar__panel-item { --navbar-panel-i: 3; }
.navbar__panel-list > li:nth-child(4) .navbar__panel-item { --navbar-panel-i: 4; }
.navbar__panel-list > li:nth-child(5) .navbar__panel-item { --navbar-panel-i: 5; }
.navbar__panel-list > li:nth-child(6) .navbar__panel-item { --navbar-panel-i: 6; }
.navbar__panel-card { --navbar-panel-i: 2; }

.navbar__panel--open .navbar__panel-item {
  opacity: 1;
  transform: translateY(0);
  transition-delay: calc(var(--md-motion-stagger-delay) * var(--navbar-panel-i, 1)),
                    calc(var(--md-motion-stagger-delay) * var(--navbar-panel-i, 1)),
                    0s,
                    0s;
}

.navbar__panel--open .navbar__panel-card {
  opacity: 1;
  transform: translateY(0);
  transition-delay: calc(var(--md-motion-stagger-delay) * var(--navbar-panel-i, 1)),
                    calc(var(--md-motion-stagger-delay) * var(--navbar-panel-i, 1));
}

@media (prefers-reduced-motion: reduce) {
  .navbar__panel,
  .navbar__panel--open,
  .navbar__panel-item,
  .navbar__panel--open .navbar__panel-item,
  .navbar__panel-card,
  .navbar__panel--open .navbar__panel-card {
    transition: none;
  }

  .navbar__panel-item,
  .navbar__panel-card {
    transform: none;
  }
}

/* Responsive - Mobile First.
   Hamburger below the 1280px desktop tier: the five links and the two buttons do not fit on one
   line under ~1280px, so the link cluster hides and the drawer takes over.
   responsive.css sets the header's side padding per tier (none on the left while collapsed) */
@media (max-width: 1279px) {
  .navbar__inner {
    gap: var(--md-spacing-2);
    padding: var(--md-spacing-2) var(--md-spacing-3);
  }

  /* The collapsed row spans the header's content box: layout.css caps the row at 1200px and
     centres it, which between ~1241px and 1279px would float the hamburger up to ~20px in from
     the left edge (width is auto, so the auto margins resolve to 0 on their own) */
  .header .navbar__inner {
    max-width: none;
  }

  .navbar__menu-btn {
    display: flex;
    margin-right: var(--md-spacing-1);
  }

  .navbar__links {
    display: none;
  }

  .navbar__logo {
    font-size: var(--md-title-medium-size);
    margin-left: 0;
  }

  .navbar__actions {
    margin-left: auto;
    gap: var(--md-spacing-1);
  }

  .navbar__actions .icon-btn:not(:last-child) {
    display: none;
  }
}

/* ---- Portal top bar (layout.css .site--portal; header.ejs isPortal, mk-section--dark on .header) ----
   The bar carries the dark colour roles, so it, its icon buttons, their tooltips (inverse roles: light
   bubble, dark text) and the drawer docked under it recolour through the tokens they already use. No link
   cluster on portal pages (the rail carries the destinations), the hamburger on phones only, and the brand
   mark follows the rail: the white-text wordmark on phones and from 1280px, the P mark alone over the 80px
   icon rail. Three-class selectors outrank the collapsed-tier rules above (which hide every icon button
   but the last, and show the hamburger up to 1279px); the row's geometry is in layout.css. */
.site--portal .header .navbar__menu-btn {
  display: flex;
  margin-right: 0;
}

.site--portal .header .navbar__actions {
  margin-left: auto;
  gap: var(--md-spacing-1);
}

.site--portal .header .navbar__actions .icon-btn {
  display: inline-flex;                             /* (0,4,0): beats .navbar__actions .icon-btn:not(:last-child) */
}

.site--portal .header .navbar__actions .icon-btn:hover {
  color: var(--md-on-surface);                      /* base.css a:hover would tint the glyph */
}

.site--portal .header .navbar__actions .icon-btn:focus-visible {
  outline: calc(var(--md-divider-thickness) * 2) solid var(--md-primary);
  outline-offset: calc(var(--md-spacing-1) / 2);
}

/* The profile button is the Account page's shortcut: tonal on Account and its subpages (the same pair
   the active drawer row and rail row use) */
.site--portal .header .navbar__action--active,
.site--portal .header .navbar__action--active:hover {
  background-color: var(--md-secondary-container);
  color: var(--md-on-secondary-container);
}

.navbar__logo-mark {
  display: none;                                    /* rendered on portal pages only; shown on the icon rail tier */
}

@media (min-width: 768px) {
  .site--portal .header .navbar__menu-btn {
    display: none;
  }

  .site--portal .header .navbar__logo-word {
    display: none;
  }

  .site--portal .header .navbar__logo-mark {
    display: block;
  }
}

@media (min-width: 1280px) {
  .site--portal .header .navbar__logo-word {
    display: block;
  }

  .site--portal .header .navbar__logo-mark {
    display: none;
  }
}

/* ---- Tree View ---- */
.tree-view {
  padding: var(--md-spacing-2);
}

.tree-view__node {
  margin-bottom: var(--md-spacing-1);
}

.tree-view__node-content {
  display: flex;
  align-items: center;
  gap: var(--md-spacing-2);
  padding: var(--md-spacing-2) var(--md-spacing-3);
  border-radius: var(--md-shape-small);
  cursor: pointer;
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.tree-view__node-content:hover {
  background-color: var(--md-surface-container-high);
}

.tree-view__toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--md-icon-size-medium);
  height: var(--md-icon-size-medium);
  border: none;
  background: transparent;
  color: var(--md-on-surface-variant);
  cursor: pointer;
  padding: 0;
  transition: transform var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.tree-view__toggle--expanded {
  transform: rotate(90deg);
}

.tree-view__spacer {
  width: var(--md-icon-size-medium);
  height: var(--md-icon-size-medium);
}

.tree-view__icon {
  font-size: var(--md-icon-size-medium);
  color: var(--md-on-surface-variant);
}

.tree-view__label {
  flex: 1;
  font-size: var(--md-label-large-size);
  color: var(--md-on-surface);
}

.tree-view__children {
  margin-left: var(--md-spacing-6);
  max-height: 0;
  overflow: hidden;
  transition: max-height var(--md-motion-duration-medium) var(--md-motion-easing-emphasized);
}

.tree-view__children--expanded {
  max-height: 2000px;
}

/* ---- Transfer List ---- */
.transfer-list {
  margin-bottom: var(--md-spacing-6);
}

.transfer-list__title {
  font-size: var(--md-title-medium-size);
  color: var(--md-on-surface);
  margin-bottom: var(--md-spacing-4);
}

.transfer-list__container {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: var(--md-spacing-4);
  align-items: start;
}

.transfer-list__panel {
  background-color: var(--md-surface-container);
  border-radius: var(--md-shape-medium);
  overflow: hidden;
}

.transfer-list__header {
  padding: var(--md-spacing-4);
  border-bottom: var(--md-divider-thickness) solid var(--md-outline-variant);
}

.transfer-list__panel-title {
  font-size: var(--md-title-small-size);
  color: var(--md-on-surface);
  margin-bottom: var(--md-spacing-3);
}

.transfer-list__check-all {
  margin: 0;
}

.transfer-list__search {
  padding: var(--md-spacing-3) var(--md-spacing-4);
  border-bottom: var(--md-divider-thickness) solid var(--md-outline-variant);
}

/* The panel's search field: the search bar's outlined recipe (2026-10-29), no icon */
.transfer-list__search-input {
  width: 100%;
  height: var(--md-text-field-height);
  padding: 0 var(--md-spacing-4);
  background-color: transparent;
  border: var(--md-divider-thickness) solid var(--md-outline);
  border-radius: var(--md-shape-extra-small);
  color: var(--md-on-surface);
  font-size: var(--md-text-field-font-size);
  line-height: var(--md-text-field-line);
  outline: none;
  -webkit-appearance: none;
  appearance: none;
  transition: border-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.transfer-list__search-input:hover:not(:focus):not(:disabled) {
  border-color: var(--md-on-surface);
}

.transfer-list__search-input:focus {
  border-color: var(--md-primary);
  border-width: calc(var(--md-divider-thickness) * 2);
  padding: 0 calc(var(--md-spacing-4) - var(--md-divider-thickness));
}

.transfer-list__search-input::placeholder {
  color: var(--md-on-surface-variant);
}

.transfer-list__list {
  max-height: var(--md-list-max-height);
  overflow-y: auto;
  padding: var(--md-spacing-2);
  scrollbar-width: thin;
  scrollbar-color: var(--md-outline-variant) transparent;
}

.transfer-list__list::-webkit-scrollbar {
  width: 6px;
}

.transfer-list__list::-webkit-scrollbar-track {
  background: transparent;
}

.transfer-list__list::-webkit-scrollbar-thumb {
  background-color: var(--md-outline-variant);
  border-radius: var(--md-shape-full);
}

.transfer-list__list::-webkit-scrollbar-thumb:hover {
  background-color: var(--md-outline);
}

.transfer-list__item {
  display: flex;
  align-items: center;
  padding: var(--md-spacing-2);
  border-radius: var(--md-shape-small);
  cursor: pointer;
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.transfer-list__item:hover {
  background-color: var(--md-surface-container-high);
}

.transfer-list__checkbox {
  -webkit-appearance: none;
  appearance: none;
  width: var(--md-icon-size-small);
  height: var(--md-icon-size-small);
  border: calc(var(--md-divider-thickness) * 2) solid var(--md-on-surface-variant);
  border-radius: var(--md-shape-extra-small-half);
  cursor: pointer;
  position: relative;
  flex-shrink: 0;
  margin-right: var(--md-spacing-3);
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard),
              border-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.transfer-list__checkbox:checked {
  background-color: var(--md-primary);
  border-color: var(--md-primary);
}

.transfer-list__checkbox:checked::after {
  content: '';
  position: absolute;
  left: var(--md-spacing-1);
  top: var(--md-divider-thickness);
  width: var(--md-dropdown-arrow-width);
  height: var(--md-dropdown-arrow-height);
  border: solid var(--md-on-primary);
  border-width: 0 calc(var(--md-divider-thickness) * 2) calc(var(--md-divider-thickness) * 2) 0;
  transform: rotate(45deg);
}

.transfer-list__checkbox:focus-visible {
  outline: calc(var(--md-divider-thickness) * 2) solid var(--md-primary);
  outline-offset: calc(var(--md-spacing-1) / 2);
}

.transfer-list__checkbox:disabled {
  opacity: 0.38;
  cursor: default;
}

.transfer-list__item-text {
  font-size: var(--md-label-large-size);
  color: var(--md-on-surface);
}

.transfer-list__count {
  padding: var(--md-spacing-3) var(--md-spacing-4);
  border-top: var(--md-divider-thickness) solid var(--md-outline-variant);
}

.transfer-list__count-text {
  font-size: var(--md-label-medium-size);
  color: var(--md-on-surface-variant);
}

.transfer-list__controls {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-2);
  padding-top: var(--md-spacing-16);
}

.transfer-list__btn:disabled {
  opacity: 0.38;
  cursor: not-allowed;
}

/* ---- Progress Button ---- */
.progress-button {
  position: relative;
}

.progress-button--loading {
  pointer-events: none;
}

.progress-button__content {
  display: flex;
  align-items: center;
  gap: var(--md-spacing-2);
  transition: opacity var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.progress-button--loading .progress-button__content {
  opacity: 0;
}

.progress-button__spinner {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transition: opacity var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.progress-button--loading .progress-button__spinner {
  opacity: 1;
}

.progress-button__svg {
  width: var(--md-icon-size-medium);
  height: var(--md-icon-size-medium);
  animation: progress-button-spin var(--md-motion-duration-long) linear infinite;
}

.progress-button__circle {
  stroke: currentColor;
  stroke-dasharray: 63;
  stroke-dashoffset: 50;
  stroke-linecap: round;
  transform-origin: center;
}

@keyframes progress-button-spin {
  to { transform: rotate(360deg); }
}

/* ---- Split Button ---- */
.split-button {
  position: relative;
  display: inline-flex;
  align-items: stretch;
}

.split-button__main {
  border-radius: var(--md-shape-full) 0 0 var(--md-shape-full);
  padding-right: var(--md-spacing-5);
}

.split-button__divider {
  width: var(--md-divider-thickness);
  background-color: currentColor;
  opacity: 0.2;
}

.split-button__toggle {
  border-radius: 0 var(--md-shape-full) var(--md-shape-full) 0;
  padding: var(--md-button-padding-y-medium) var(--md-spacing-3);
  min-width: auto;
}

.split-button .menu {
  top: calc(100% + var(--md-spacing-1));
  left: 0;
  right: auto;
}

/* ---- Tag Input ---- */
.tag-input {
  margin-bottom: var(--md-spacing-4);
}

.tag-input__container {
  position: relative;
  background-color: var(--md-surface-container-highest);
  border-radius: var(--md-shape-extra-small) var(--md-shape-extra-small) 0 0;
  border-bottom: var(--md-divider-thickness) solid var(--md-on-surface-variant);
  transition: border-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.tag-input--outlined .tag-input__container {
  background-color: transparent;
  border: var(--md-divider-thickness) solid var(--md-outline);
  border-radius: var(--md-shape-extra-small);
}

.tag-input__container:focus-within {
  border-bottom-width: calc(var(--md-divider-thickness) * 2);
  border-bottom-color: var(--md-primary);
}

.tag-input--outlined .tag-input__container:focus-within {
  border-color: var(--md-primary);
  border-width: calc(var(--md-divider-thickness) * 2);
}

.tag-input__label {
  position: absolute;
  top: var(--md-spacing-4);
  left: var(--md-spacing-4);
  font-size: var(--md-body-large-size);
  color: var(--md-on-surface-variant);
  pointer-events: none;
  transition: top var(--md-motion-duration-short) var(--md-motion-easing-standard),
              font-size var(--md-motion-duration-short) var(--md-motion-easing-standard),
              color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.tag-input__label--floating,
.tag-input__container:focus-within .tag-input__label {
  top: var(--md-spacing-1);
  font-size: var(--md-body-small-size);
  color: var(--md-primary);
}

.tag-input--outlined .tag-input__label {
  background-color: var(--md-surface);
  padding: 0 var(--md-spacing-1);
  left: calc(var(--md-spacing-4) - var(--md-spacing-1));
}

.tag-input--outlined .tag-input__label--floating,
.tag-input--outlined .tag-input__container:focus-within .tag-input__label {
  top: calc(var(--md-spacing-2) * -1);
}

.tag-input__content {
  display: flex;
  flex-wrap: wrap;
  gap: var(--md-spacing-2);
  padding: var(--md-spacing-5) var(--md-spacing-4) var(--md-spacing-2);
  min-height: var(--md-input-field-height);
}

.tag-input__tags {
  display: contents;
}

.tag-input__input {
  flex: 1;
  min-width: 120px;
  border: none;
  background: transparent;
  color: var(--md-on-surface);
  font-size: var(--md-body-large-size);
  outline: none;
  padding: var(--md-spacing-1) 0;
}

.chip--input {
  display: inline-flex;
  align-items: center;
  gap: var(--md-spacing-1);
}

.chip__remove {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--md-icon-size-small);
  height: var(--md-icon-size-small);
  border: none;
  background: transparent;
  color: currentColor;
  cursor: pointer;
  border-radius: var(--md-shape-full);
  padding: 0;
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.chip__remove:hover {
  background-color: var(--md-state-overlay-light);
}

.chip__remove .material-symbols-outlined {
  font-size: 16px;
}

.tag-input__helper {
  font-size: var(--md-body-small-size);
  color: var(--md-on-surface-variant);
  margin-top: var(--md-spacing-2);
  padding: 0 var(--md-spacing-4);
}

.tag-input__suggestions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--md-spacing-2);
  margin-top: var(--md-spacing-3);
}

.chip--suggestion {
  border-style: dashed;
}

/* ---- Billing ---- */
/* The owner's Billing page (views/portal/billing.ejs + src/js/components/billing/*, the rebuild of
   2026-10-28) and the Payment history page (billing-history.ejs). One column of static cards; every
   value a token. The vocabulary: pagehead (title, status badge, lead), notices (the alert recipe with
   one action), cardhead (icon, title, subtitle, an end slot), plan rows (icon, name, detail, the
   stepper or a figure, the row's total), the three-step flow beside its summary (two columns from
   1024px, the same height), change lines, summary lines, method rows and method cards, Stripe's form,
   the pay-with choice, the agreement's open invoice, the history ledger. */

/* The page's column */
.billing-stack {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-6);
  padding: 0 0 var(--md-spacing-10);
}

/* The scripts show and hide with the hidden attribute: it wins over every display rule here (a
   button's inline-flex, a badge's inline-block, the express block's flex) */
.billing-stack [hidden] {
  display: none !important;
}

/* The status chips: the shared .status-badge recipe (the "Status chip" block of this file: these pages'
   pick of 2026-10-28, extended to both portals the same day) */

/* On the card tile the word takes the face's own light text */
.billing-stack .billing-pm .status-badge {
  color: inherit;
}

/* The head card: the title row with the status badge, the lead under it */
.billing-pagehead {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-1);
}

.billing-pagehead__title {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--md-spacing-3);
}

.billing-pagehead__title h1 {
  margin: 0;
}

.billing-pagehead__icon {
  font-size: var(--md-icon-size-large);
  color: var(--md-primary);
}

.billing-pagehead__badge {
  margin-left: var(--md-spacing-1);
}

.billing-pagehead__lead {
  margin: 0;
  color: var(--md-on-surface-variant);
}

/* The sub-page's way back: the outlined button (btn btn--outlined, the one string of every page head's
   "Go back", at the portal's one button height), a divider, the title */
.billing-pagehead__sep {
  color: var(--md-outline);
  font-size: var(--md-title-large-size);
}

/* Notices: the alert recipe, one action per notice, nothing dismissible */
.billing-notices {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-3);
}

.billing-notices:empty {
  display: none;
}

.billing-notices .alert {
  margin-bottom: 0;
}

/* Card heads: the card's title and subtitle beside an icon, an end slot for a chip or a button */
.billing-cardhead {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--md-spacing-3);
  margin-bottom: var(--md-spacing-4);
}

.billing-cardhead .card__title,
.billing-cardhead .card__subtitle {
  margin-bottom: 0;
}

/* The lead fills the row (a basis of one small component, then every spare pixel), so a long subtitle
   wraps inside its column and the end slot keeps its place at the right; without the basis the lead
   asked for its whole sentence and the row wrapped the actions under it (the Stripe payouts card once
   connected, 2026-10-28). The end wraps under only when the row is narrower than both together */
.billing-cardhead__lead {
  display: flex;
  align-items: center;
  flex: 1 1 var(--md-component-width-small);
  gap: var(--md-spacing-3);
  min-width: 0;
}

.billing-cardhead__text {
  min-width: 0;
}

.billing-cardhead__text a {
  color: var(--md-primary);
}

/* A title beside its status chip on one line (the Stripe payouts card) */
.billing-cardhead__titlerow {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--md-spacing-2);
}

.billing-cardhead__icon {
  font-size: var(--md-icon-size-large);
  color: var(--md-primary);
  flex-shrink: 0;
}

.billing-cardhead__end {
  display: flex;
  align-items: center;
  flex: 0 0 auto;
  flex-wrap: wrap;
  gap: var(--md-spacing-2);
  margin-left: auto;
}

/* A one-row card (the Stripe payouts card, the history page's head): nothing under it */
.billing-cardhead--row {
  margin-bottom: 0;
  align-items: center;
}

.billing-cardhead--row .btn .material-symbols-outlined {
  font-size: var(--md-icon-size-small);
}

/* Eyebrow + figure: the KPI rule (title-large, bold, brand green, tabular numerals) */
.billing-eyebrow {
  margin: 0;
  font-size: var(--md-label-large-size);
  line-height: var(--md-label-large-line);
  font-weight: var(--md-weight-bold);
  letter-spacing: var(--md-letter-spacing-wide);
  text-transform: uppercase;
  color: var(--md-on-surface-variant);
}

.billing-figure {
  margin: 0;
  font-size: var(--md-title-large-size);
  line-height: var(--md-title-large-line);
  font-weight: var(--md-weight-bold);
  color: var(--md-primary);
  font-variant-numeric: tabular-nums;
}

.billing-figure--headline {
  font-size: var(--md-headline-small-size);
  line-height: var(--md-headline-small-line);
}

.billing-figure__code {
  font-size: var(--md-body-small-size);
  font-weight: var(--md-body-small-weight);
  color: var(--md-on-surface-variant);
  margin-left: var(--md-spacing-1);
}

/* Sentences: body-medium muted, the facts bold on the surface colour */
.billing-line {
  margin: 0;
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
}

.billing-line strong {
  color: var(--md-on-surface);
  font-weight: var(--md-weight-bold);
}

.billing-line + .billing-line {
  margin-top: var(--md-spacing-1);
}

.billing-note {
  margin: var(--md-spacing-3) 0 0;
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
  color: var(--md-on-surface-variant);
}

.billing-inline {
  display: inline-flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--md-spacing-2);
}

.billing-divider {
  height: var(--md-divider-thickness);
  background-color: var(--md-outline-variant);
  margin: var(--md-spacing-4) 0;
}

/* Summary lines: label left, amount right; the total on a hairline, the struck "was" line */
.billing-lines {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-2);
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  font-variant-numeric: tabular-nums;
}

.billing-lines li {
  display: flex;
  justify-content: space-between;
  gap: var(--md-spacing-4);
  color: var(--md-on-surface-variant);
}

.billing-lines li span:last-child {
  color: var(--md-on-surface);
  white-space: nowrap;
}

.billing-lines li.billing-lines__total {
  padding-top: var(--md-spacing-2);
  border-top: var(--md-divider-thickness) solid var(--md-outline-variant);
  color: var(--md-on-surface);
  font-weight: var(--md-weight-bold);
}

.billing-lines li.billing-lines__total span:last-child {
  color: var(--md-primary);
}

.billing-lines li.billing-lines__from span:last-child {
  color: var(--md-on-surface-variant);
  text-decoration: line-through;
}

/* The plan's quantity rows: icon, name and detail, the stepper (or a plain figure), the row's total */
.billing-plan {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-3);
}

.billing-plan__row {
  display: flex;
  align-items: center;
  gap: var(--md-spacing-3);
  padding: var(--md-spacing-3) var(--md-spacing-4);
  border-radius: var(--md-shape-medium);
  background-color: var(--md-surface-container-low);
}

.billing-plan__icon {
  font-size: var(--md-icon-size-large);
  color: var(--md-primary);
  flex-shrink: 0;
}

.billing-plan__info {
  flex: 1 1 0;
  min-width: 0;
}

.billing-plan__name {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--md-spacing-2);
  font-size: var(--md-title-small-size);
  line-height: var(--md-title-small-line);
  font-weight: var(--md-title-small-weight);
  color: var(--md-on-surface);
}

.billing-plan__detail {
  margin: 0;
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
  color: var(--md-on-surface-variant);
}

.billing-plan__qty {
  display: flex;
  align-items: center;
  gap: var(--md-spacing-2);
}

.billing-plan__qty .btn--outlined {
  min-width: var(--md-button-height-medium);
  padding: 0;
}

.billing-plan__value {
  width: var(--md-spacing-20);
  height: var(--md-text-field-height);
  text-align: center;
  font-family: inherit;
  font-size: var(--md-title-large-size);
  font-weight: var(--md-weight-bold);
  color: var(--md-on-surface);
  border: var(--md-divider-thickness) solid var(--md-outline-variant);
  border-radius: var(--md-shape-small);
  background-color: var(--md-surface);
  font-variant-numeric: tabular-nums;
  -moz-appearance: textfield;
}

.billing-plan__value::-webkit-outer-spin-button,
.billing-plan__value::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

.billing-plan__value:focus-visible {
  outline: calc(var(--md-divider-thickness) * 2) solid var(--md-primary);
  outline-offset: calc(var(--md-divider-thickness) * 2);
}

.billing-plan__figure {
  min-width: var(--md-spacing-20);
  text-align: center;
  font-size: var(--md-title-large-size);
  line-height: var(--md-title-large-line);
  font-weight: var(--md-weight-bold);
  color: var(--md-on-surface);
  font-variant-numeric: tabular-nums;
}

.billing-plan__total {
  min-width: var(--md-spacing-24);
  text-align: right;
  font-size: var(--md-body-medium-size);
  font-weight: var(--md-weight-bold);
  color: var(--md-on-surface);
  font-variant-numeric: tabular-nums;
}

/* The foot, in three ruled regions under the rows: the total line (the currency and the sentence at
   the left, the monthly total as a figure at the right, on the rows' own horizontal padding so the
   figure sits under the rows' totals), then the action bar (the buttons together at the right end,
   the destructive one first, the one main action last) */
.billing-plan__foot {
  margin-top: var(--md-spacing-4);
}

.billing-plan__summary {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--md-spacing-3) var(--md-spacing-6);
  padding: var(--md-spacing-4) var(--md-spacing-4) 0;
  border-top: var(--md-divider-thickness) solid var(--md-outline-variant);
}

.billing-plan__text {
  min-width: 0;
  flex: 1 1 var(--md-component-width-small);
}

.billing-plan__sum {
  flex: 0 0 auto;
  margin-left: auto;
  text-align: right;
}

.billing-figure__suffix {
  font-size: var(--md-body-small-size);
  font-weight: var(--md-body-small-weight);
  color: var(--md-on-surface-variant);
}

.billing-plan__was {
  margin: 0;
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
  font-weight: var(--md-body-small-weight);
  color: var(--md-on-surface-variant);
  text-decoration: line-through;
}

.billing-plan__bar {
  display: flex;
  justify-content: flex-end;
  margin-top: var(--md-spacing-4);
  padding-top: var(--md-spacing-4);
  border-top: var(--md-divider-thickness) solid var(--md-outline-variant);
}

.billing-plan__bar-end {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: var(--md-spacing-2);
  margin-left: auto;
}

@media (max-width: 767px) {
  .billing-plan__row {
    flex-wrap: wrap;
  }

  .billing-plan__info {
    flex-basis: calc(100% - var(--md-icon-size-large) - var(--md-spacing-3));
  }

  .billing-plan__total {
    flex: 1 1 auto;
  }
}

/* Two columns from 1024px: the flow's steps beside the summary, the same height (the owner's rule:
   both columns stretch, the flow's action row sits at the card's bottom with its usual air above);
   one column again while the assistant's docked panel takes the third grid column */
.billing-grid {
  display: grid;
  gap: var(--md-spacing-6);
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
}

@media (min-width: 1024px) {
  .billing-grid--2 {
    grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
    align-items: stretch;
  }

  .billing-grid--2 > div {
    display: flex;
    flex-direction: column;
    min-width: 0;
  }

  .billing-grid--2 > div > .card {
    flex: 1 1 auto;
  }

  .billing-grid--2 > div > .billing-flow {
    display: flex;
    flex-direction: column;
  }

  /* Two classes on purpose: the base .billing-flow__actions rule further down declares a margin-top
     too and, later in the file at the same specificity, would win over a one-class rule here - the
     Payment step's bar then floated right under its short content with the stretched card empty
     below it (2026-10-28) */
  .billing-grid--2 .billing-flow__actions {
    margin-top: auto;
  }

  .billing-flow > :nth-last-child(2) {
    margin-bottom: var(--md-spacing-6);
  }
}

/* The assistant's docked panel is the shell's third column from 1600px (layout.css): the flow goes
   back to one column beside it */
@media (min-width: 1600px) {
  .body--assistant-open .billing-grid--2 {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* The plan card in flow mode carries the two cards itself: no chrome of its own (card--static keeps
   the hover flat) */
.card--flow {
  padding: 0;
  border: 0;
  background-color: transparent;
}

/* The stepper flow; the stepper stands vertical below 768px */
.billing-flow .stepper {
  margin-bottom: var(--md-spacing-6);
}

@media (max-width: 767px) {
  .billing-flow .stepper {
    flex-direction: column;
  }

  .billing-flow .stepper__step {
    align-items: flex-start;
  }

  .billing-flow .stepper__connector {
    width: var(--md-divider-thickness);
    height: var(--md-button-height-small);
    flex: none;
    min-width: auto;
    margin: var(--md-spacing-1) 0 var(--md-spacing-1) var(--md-spacing-4);
    align-self: flex-start;
  }
}

.billing-changes {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
}

.billing-change {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--md-spacing-2) var(--md-spacing-3);
  padding: var(--md-spacing-3) 0;
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
}

.billing-change + .billing-change {
  border-top: var(--md-divider-thickness) solid var(--md-outline-variant);
}

.billing-change__icon {
  font-size: var(--md-icon-size-medium);
  color: var(--md-primary);
}

.billing-change__name {
  flex: 1 1 var(--md-component-width-xsmall);
  color: var(--md-on-surface);
  font-weight: var(--md-weight-bold);
}

.billing-change__from {
  color: var(--md-on-surface-variant);
}

.billing-change__arrow {
  font-size: var(--md-icon-size-small);
  color: var(--md-on-surface-variant);
}

.billing-change__to {
  color: var(--md-on-surface);
  font-weight: var(--md-weight-bold);
}

.billing-change__sub {
  flex-basis: 100%;
  margin: 0;
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
  color: var(--md-on-surface-variant);
}

.billing-flow__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--md-spacing-2);
  margin-top: var(--md-spacing-6);
  padding-top: var(--md-spacing-4);
  border-top: var(--md-divider-thickness) solid var(--md-outline-variant);
}

/* Rows with an icon, a label, a sub-line and actions on hairlines (the agreement card) */
.billing-method {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--md-spacing-2) var(--md-spacing-3);
  padding: var(--md-spacing-3) 0;
}

.billing-method + .billing-method {
  border-top: var(--md-divider-thickness) solid var(--md-outline-variant);
}

.billing-method__icon {
  font-size: var(--md-icon-size-medium);
  color: var(--md-primary);
  flex-shrink: 0;
}

.billing-method__text {
  flex: 1 1 var(--md-component-width-xsmall);
  min-width: 0;
}

.billing-method__label {
  margin: 0;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--md-spacing-2);
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface);
}

.billing-method__sub {
  margin: 0;
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
  color: var(--md-on-surface-variant);
}

.billing-method__sub a {
  color: var(--md-primary);
}

.billing-method__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--md-spacing-1);
  margin-left: auto;
}

/* Payment methods as cards side by side: the methods on file, the dashed card to add the other kind */
.billing-method-cards {
  display: grid;
  gap: var(--md-spacing-4);
  grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 768px) {
  .billing-method-cards {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .billing-method-cards--one {
    grid-template-columns: minmax(0, 1fr);
  }
}

.billing-method-card {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-2);
  min-width: 0;
}

/* The empty slot of the Payment step: its "Add a payment method" keeps a button's own width (the
   column box would stretch it across the card) */
.billing-method-card--add > .btn {
  align-self: flex-start;
}

/* The tile: a card drawn as a card (the charcoal face, the chip, the brand, the masked number, the
   status chip), a bank account as a light slip with the institution's glyph, an empty slot as a card
   with no values. Its actions live on a veil over the blurred face - shown on hover, on keyboard
   focus and on a tap (billing-pm--open): the × at the corner removes, the centred buttons update,
   set as default, verify; an empty slot's veil offers one +. Every tile keeps a card's proportions
   and the width of a small component */
.billing-pm {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--md-spacing-3);
  width: 100%;
  max-width: var(--md-component-width-small);
  aspect-ratio: 1.586;
  padding: var(--md-spacing-4);
  border-radius: var(--md-shape-medium);
  background-color: var(--md-inverse-surface);
  color: var(--md-inverse-on-surface);
  box-shadow: var(--md-elevation-1);
  overflow: hidden;
  transition: box-shadow var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.billing-pm:hover,
.billing-pm:focus-within,
.billing-pm--open {
  box-shadow: var(--md-elevation-3);
}

.billing-pm--bank {
  background-color: var(--md-surface-container-high);
  color: var(--md-on-surface);
  box-shadow: none;
  border: var(--md-divider-thickness) solid var(--md-outline-variant);
}

.billing-pm--empty {
  background-color: var(--md-surface-container-high);
  color: var(--md-on-surface-variant);
  box-shadow: none;
  border: var(--md-divider-thickness) dashed var(--md-outline);
}

.billing-pm__top,
.billing-pm__bottom {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--md-spacing-2);
}

.billing-pm__bottom {
  flex-wrap: wrap;
  align-items: flex-end;
}

.billing-pm__bottom .status-badge {
  margin-left: auto;
}

/* The chip: the card's own mark, in the brand green */
.billing-pm__chip {
  display: block;
  width: var(--md-spacing-8);
  height: var(--md-spacing-6);
  border-radius: var(--md-shape-extra-small);
  background-color: var(--md-primary-container);
  border: var(--md-divider-thickness) solid var(--md-primary);
}

.billing-pm--empty .billing-pm__chip {
  background-color: var(--md-surface-container-highest);
  border-color: var(--md-outline-variant);
}

.billing-pm__glyph {
  font-size: var(--md-icon-size-large);
  color: var(--md-primary);
}

.billing-pm--empty .billing-pm__glyph {
  color: var(--md-outline);
}

.billing-pm__brand {
  font-size: var(--md-label-large-size);
  line-height: var(--md-label-large-line);
  font-weight: var(--md-weight-bold);
  letter-spacing: var(--md-letter-spacing-wide);
  text-transform: uppercase;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.billing-pm__number {
  font-size: var(--md-title-large-size);
  line-height: var(--md-title-large-line);
  font-weight: var(--md-weight-bold);
  letter-spacing: var(--md-letter-spacing-wide);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.billing-pm--empty .billing-pm__number {
  color: var(--md-outline);
}

.billing-pm__kind {
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
}

/* The veil: the face greyed and blurred under it, the actions on top */
.billing-pm__veil {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  visibility: hidden;
  backdrop-filter: blur(var(--md-spacing-1));
  -webkit-backdrop-filter: blur(var(--md-spacing-1));
  transition: opacity var(--md-motion-duration-short) var(--md-motion-easing-standard),
              visibility 0s linear var(--md-motion-duration-short);
}

.billing-pm__veil::before {
  content: '';
  position: absolute;
  inset: 0;
  background-color: var(--md-surface);
  opacity: var(--md-veil-opacity);
}

.billing-pm:hover .billing-pm__veil,
.billing-pm:focus-within .billing-pm__veil,
.billing-pm--open .billing-pm__veil {
  opacity: 1;
  visibility: visible;
  transition-delay: 0s;
}

.billing-pm__veil > * {
  position: relative;
}

/* The centre: one button, or two split evenly */
.billing-pm__veil-actions {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--md-spacing-3);
  width: 100%;
  padding: 0 var(--md-spacing-6);
}

.billing-pm__veil-actions > .btn {
  flex: 1 1 0;
  justify-content: center;
  max-width: calc(50% - var(--md-spacing-2));
}

.billing-pm__veil-actions > .btn:only-child {
  max-width: none;
  flex: 0 1 auto;
}

/* The × at the corner */
.billing-pm__remove {
  position: absolute;
  top: var(--md-spacing-2);
  right: var(--md-spacing-2);
  color: var(--md-on-surface);
}

.billing-pm__remove:hover {
  background-color: var(--md-error-container);
  color: var(--md-error);
}

/* The + of an empty slot: an icon button at the portal's one button height (40px, 2026-10-29) */
.billing-pm__add {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--md-icon-button-size);
  height: var(--md-icon-button-size);
  border: none;
  border-radius: var(--md-button-radius);
  background-color: var(--md-primary);
  color: var(--md-on-primary);
  font-size: var(--md-icon-size-medium);
  cursor: pointer;
  box-shadow: var(--md-elevation-1);
}

.billing-pm__add .material-symbols-outlined {
  font-size: var(--md-icon-size-large);
}

.billing-pm__add:hover {
  box-shadow: var(--md-elevation-2);
}

.billing-pm__add:focus-visible,
.billing-pm__remove:focus-visible {
  outline: calc(var(--md-divider-thickness) * 2) solid var(--md-primary);
  outline-offset: calc(var(--md-divider-thickness) * 2);
}

@media (prefers-reduced-motion: reduce) {
  .billing-pm,
  .billing-pm__veil {
    transition: none;
  }
}

.billing-method-card__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--md-spacing-1);
  margin-top: auto;
}

/* Stripe's form (the Payment Element in the site's type roles, stripe-elements.js) under the cards */
.billing-stripe {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-4);
  margin-top: var(--md-spacing-4);
}

.billing-stripe .billing-cardhead {
  margin-bottom: 0;
}

.billing-stripe__element {
  min-height: var(--md-input-field-height);
}

.billing-stripe__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: var(--md-spacing-2);
}

/* The card-or-bank choice before a payment (both modes): a label beside the segmented control */
.billing-paywith {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--md-spacing-2) var(--md-spacing-3);
}

.billing-paywith__label {
  font-size: var(--md-label-large-size);
  line-height: var(--md-label-large-line);
  font-weight: var(--md-weight-bold);
  color: var(--md-on-surface-variant);
}

.billing-flow .billing-paywith {
  margin-bottom: var(--md-spacing-4);
}

.billing-method__actions .billing-paywith {
  margin-left: auto;
}

/* The commercial agreement's open invoice: the figure and its lines beside the actions, stacked under 768px */
.billing-invoice {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--md-spacing-4) var(--md-spacing-6);
  padding: var(--md-spacing-4);
  border: var(--md-divider-thickness) solid var(--md-outline-variant);
  border-radius: var(--md-shape-medium);
}

.billing-invoice__main {
  flex: 1 1 var(--md-component-width-small);
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-2);
}

.billing-invoice__head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--md-spacing-2);
}

.billing-invoice__actions {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-2);
  flex: 0 1 auto;
  max-width: 100%;
}

.billing-invoice__actions .btn {
  justify-content: center;
}

.billing-invoice__actions .billing-note {
  margin-top: 0;
}

.billing-invoice__actions .billing-paywith {
  flex-direction: column;
  align-items: stretch;
}

.billing-invoice__actions .segmented-button {
  width: 100%;
}

@media (max-width: 767px) {
  .billing-invoice__actions {
    width: 100%;
  }
}

/* The history ledger: hairline rows, regular weight, the amount tabular, the chip last */
.billing-ledger {
  display: flex;
  flex-direction: column;
}

.billing-ledger:empty {
  display: none;
}

.billing-ledger__row {
  display: grid;
  grid-template-columns: var(--md-spacing-20) minmax(0, 1fr) auto auto;
  gap: var(--md-spacing-2) var(--md-spacing-4);
  align-items: center;
  padding: var(--md-spacing-3) 0;
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
}

.billing-ledger__row + .billing-ledger__row {
  border-top: var(--md-divider-thickness) solid var(--md-outline-variant);
}

.billing-ledger__date {
  color: var(--md-on-surface);
  white-space: nowrap;
}

.billing-ledger__desc {
  min-width: 0;
}

.billing-ledger__sub {
  display: block;
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
}

.billing-ledger__amount {
  color: var(--md-on-surface);
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.billing-ledger__amount--failed {
  color: var(--md-error);
}

@media (max-width: 479px) {
  .billing-ledger__row {
    grid-template-columns: minmax(0, 1fr) auto;
  }

  .billing-ledger__date {
    grid-column: 1 / -1;
  }
}

/* ---- Visitor Activity card (portal dashboard) ---- */
/* Header: title block, then the controls on their own row beneath it.
   Stage: the chart area, kept at one height in every state. */
.activity__header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--md-spacing-4) var(--md-spacing-6);
  margin-bottom: var(--md-spacing-6);
}

/* Type filter + group search always share one row (phones wrap, see responsive.css) */
.activity__toolbar {
  display: flex;
  flex: 1 1 100%;
  flex-wrap: nowrap;
  align-items: center;
  gap: var(--md-spacing-3);
}

/* Compact segmented button: theme control height, tighter side padding, no stacked-form margin */
.activity__toolbar .segmented-button {
  margin-bottom: 0;
  flex-shrink: 0;
}

.activity__toolbar .segmented-button__item {
  padding-left: var(--md-spacing-3);
  padding-right: var(--md-spacing-3);
}

/* Property-group search: the search-bar partial with an M3 menu of the top matches beneath it
   (the wrapper reuses .dropdown / .dropdown__menu, opted out of dropdown.js via data-dropdown-manual) */
.activity__toolbar .activity__search {
  margin: 0;
  flex: 1 1 var(--md-component-width-medium); /* fills the row to the card's content edge */
  min-width: 0;
}

.activity__search .search-bar {
  margin-bottom: 0;
}

/* The stage is a one-track grid, so its lone visible item (#activityBody, #activityMapWrap or
   #activityState: mutually exclusive through [hidden]) is stretched to a DEFINITE height in every
   engine (a flex column with height: auto gives its items an indefinite height, so Firefox would
   neither stretch the heatmap's rows nor centre the map). One height in every state (2026-11-01): the
   token, the same on every card since the header's second control row - Activity | Availability and the
   day slider - is always shown (greyed where it cannot apply, never hidden); from 1024px the height is
   fixed (responsive.css) */
.activity__stage {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: minmax(var(--md-activity-stage-height), auto);
}

/* The body (#activityBody): the chart column and, for a person who may create passes, the residential
   view's Create Pass panel in a second track - the same grid and slide as the map wrap, declared once
   with it below ("The detail panel", 2026-11-01) */

/* A load dims the chart column only, so the panel beside it stays live */
.activity__main {
  min-width: 0;
  transition: opacity var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.activity--busy .activity__main {
  opacity: var(--md-opacity-disabled);
  pointer-events: none;
}

/* The chart: the heatmap with the placeholder note over it (the note's inset: 0 covers the grid and its
   legend, never the facts under them); from 768px it takes the room the facts leave and the heatmap's
   rows stretch to fill it (responsive.css) */
.activity__chart {
  position: relative;
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

/* Placeholder: the neutral grid stays as the backdrop, dimmed, with a note card on top */
.activity--placeholder .heatmap {
  opacity: var(--md-opacity-disabled);
}

.activity__note {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--md-spacing-4);
}

.activity__note-panel {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--md-spacing-3);
  width: 100%;
  max-width: var(--md-component-width-medium);
  padding: var(--md-spacing-5) var(--md-spacing-6);
  background-color: var(--md-surface);
  border: var(--md-divider-thickness) solid var(--md-outline-variant);
  border-radius: var(--md-shape-medium);
  box-shadow: var(--md-elevation-1);
  text-align: center;
}

.activity__note-title {
  color: var(--md-on-surface);
  margin: 0;
}

.activity__note-text {
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
  margin: 0;
}

/* The facts under the chart (2026-11-01): the three stat tiles as equal columns, the same three on a
   residential and a metered group (the Pass source bars went the same day, the owner's call), one per
   tile, so the row reflows when the Create Pass panel opens; two columns on a phone (responsive.css) */
.activity__facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
  gap: var(--md-spacing-6) var(--md-spacing-8);
  margin-top: var(--md-spacing-6);
}

/* Shared with the marketing vignette (partials/vignette, type activity): two columns, the first stat
   (passes started) spanning the row as the hero number; the dashboard flattens it below */
.activity__stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--md-spacing-4);
}

.activity__stats .activity__stat:first-child {
  grid-column: 1 / -1;
}

.activity__facts .activity__stats {
  display: contents;   /* the tiles are the grid's own items; the shared rule stays for the marketing vignette */
}

/* Flattened, the first tile is an item of the facts grid: never the vignette's full-row span */
.activity__facts .activity__stats .activity__stat:first-child {
  grid-column: auto;
}

.activity__stat {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-1);
  min-width: 0;
}

.activity__stat-label {
  font-size: var(--md-label-medium-size);
  line-height: var(--md-label-medium-line);
  font-weight: var(--md-label-medium-weight);
  color: var(--md-on-surface-variant);
}

/* The figure itself: the shared rule in the Client Tools block */
.activity__stat-value {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.activity__stat-hint {
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
  color: var(--md-on-surface-variant);
}

/* Whole-stage empty state (no properties / no groups of this type), centred at the stage height */
.activity__state {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--md-spacing-4);
}

.activity__state .empty-state {
  padding: 0;
  margin-bottom: 0;
}

.activity__state .empty-state__icon {
  font-size: var(--md-icon-size-large);
}

.activity__state .empty-state__text {
  margin-bottom: 0;
}

/* The flex/grid rules above would otherwise override the hidden attribute */
.activity [hidden] {
  display: none !important;
}

/* ---- Activity | Availability (2026-10-31): a second control row under the toolbar, always shown since
   2026-11-01 - the Availability segment greyed with a title where the group has no parking map, the day
   slider greyed (activity__day--off) outside Availability and where the location takes no reservations
   ahead -; Availability swaps the body for the lot map in the renderer's view mode, each space's
   reservations of one day as bars (client-dashboard-map.js) ---- */
.activity__viewbar {
  display: flex;
  flex: 1 1 100%;
  align-items: center;
  gap: var(--md-spacing-3);
}

.activity__viewbar .segmented-button {
  margin-bottom: 0;
  flex-shrink: 0;
}

.activity__viewbar .segmented-button__item {
  padding-left: var(--md-spacing-3);
  padding-right: var(--md-spacing-3);
}

/* The day: its word (Today / Tomorrow / "Mon, Nov 3"), then the slider over the location's days ahead */
.activity__day {
  display: flex;
  align-items: center;
  gap: var(--md-spacing-3);
  flex: 1 1 var(--md-component-width-medium);
  min-width: 0;
}

.activity__day .slider {
  margin-bottom: 0;
  flex: 1 1 auto;
  min-width: 0;
}

/* The word bold and against the slider: right-aligned in a box wide enough for the longest day text, so
   the slider's start never moves as the word changes (2026-11-01) */
.activity__day-label {
  flex: 0 0 auto;
  min-width: calc(2.5 * var(--md-button-height-medium));
  text-align: right;
  font-size: var(--md-label-large-size);
  line-height: var(--md-label-large-line);
  font-weight: var(--md-weight-bold);
  color: var(--md-on-surface);
  white-space: nowrap;
}

/* Outside Availability, and where the location takes no reservations ahead, the day row is greyed - the
   input disabled, never hidden (client-dashboard-map.js setDayEnabled, 2026-11-01) */
.activity__day--off {
  opacity: var(--md-opacity-disabled);
}

.activity__day--off .slider__input,
.activity__day--off .slider__input::-webkit-slider-thumb {
  cursor: default;
}

.activity__day--off .slider__input::-moz-range-thumb {
  cursor: default;
}

/* The Availability body and an open panel beside the chart (activity--panel, 2026-11-01) need more than
   the fixed stage height of 1024px and up and must never clip their menus; responsive.css restates the
   lift after its fixed-height rule, so it always wins */
.activity--map .activity__stage,
.activity--panel .activity__stage {
  height: auto;
  overflow: visible;
}

/* A day loading dims the map column only; the detail panel stays crisp (its own submit disables its
   button), and so stays out of an opacity stacking context that would trap its menus (2026-10-31) */
.activity--busy .activity__map-main {
  opacity: var(--md-opacity-disabled);
  pointer-events: none;
}

/* A shorter lot fills the Availability stage (2026-11-01; Get Pass's map is untouched): the map column is
   a flex column down to the viewport, which keeps the base rule's height - the plane at the fit plus the
   controls' room - as its flex basis, grows into the room the foot leaves and never shrinks under the
   fit, centring the plane at the fit through the box's auto margins; zoomed, the box outgrows the
   viewport, the auto margins drop to 0 and the viewport scrolls from the top-left like Get Pass's, the
   card keeping its height (2026-11-03: `height: auto` here had sized the viewport to the zoomed box, so
   the + button grew the card instead of the map scrolling inside it; viewport.js fits on the stage's
   width and scrolls only: a taller viewport changes nothing but the zoom centre). The level picker, the
   hint and the zoom buttons are anchored to .pmap__stage, which fills the column */
.activity--map .activity__map-main {
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.activity--map .pmap {
  flex: 1 1 auto;
  min-height: 0;
}

.activity--map .pmap__stage {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
}

.activity--map .pmap__viewport {
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
}

.activity--map .pmap__plane-box {
  flex: 0 0 auto;
  margin: auto;
}

.activity__map-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--md-spacing-3);
  margin-top: var(--md-spacing-3);
}

.activity__map-line {
  margin: 0;
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
}

/* The map's legend, the heatmap legend's shape; the Closed swatch takes the map's one hatch rule */
.activity__legend {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: var(--md-spacing-3);
  font-size: var(--md-label-small-size);
  line-height: var(--md-label-small-line);
  color: var(--md-on-surface-variant);
}

.activity__key {
  display: inline-flex;
  align-items: center;
  gap: var(--md-spacing-1);
}

.activity__swatch {
  display: inline-block;
  width: var(--md-spacing-4);
  height: var(--md-spacing-2);
  border-radius: var(--md-shape-extra-small-half);
}

.activity__swatch--reserved {
  background-color: var(--md-map-bar-bg);
}

.activity__swatch--over {
  background-color: var(--md-map-bar-over-bg);
}

.activity__swatch--closed {
  border: var(--md-map-stroke-line) solid var(--md-map-stall-outline);
}

.activity__swatch--now {
  width: var(--md-map-stroke-wall);
  height: var(--md-spacing-3);
  background-color: var(--md-map-now);
}

/* ---- The detail panel (2026-10-31, the owner's point 4): a click on a stall opens the selected space's
   facts - or the compact Create Reservation form - in the wrap's second grid track; since 2026-11-01 the
   Activity body (#activityBody) is the same grid, its second track the residential view's Create Pass
   panel (client-dashboard-pass.js), so every rule here names both wraps. Mobile first the panel sits
   under the chart, the rows idiom of .loc-group__panel (0fr → 1fr); from 1024px beside it, the dock's
   columns idiom (layout.css: a 0px track that grows to --md-activity-detail-width; responsive.css). The
   panel keeps its own width, so nothing reflows while the track animates; the item clips it meanwhile and
   activity-dock.js adds --settled on transitionend, when the clip goes so the menus and the pickers hang
   below the panel as on the Reservations view. Visibility is delayed on the way back (the dock's rule).
   Never `hidden` on the panel: the card's [hidden] rule would skip the slide. The transitions are
   declared once here, so the reduced-motion rule below covers both tiers. */
.activity__map,
.activity__body {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto 0fr;
  gap: 0;
  transition: grid-template-rows var(--md-motion-duration-medium) var(--md-motion-easing-emphasized),
              grid-template-columns var(--md-motion-duration-medium) var(--md-motion-easing-emphasized),
              gap var(--md-motion-duration-medium) var(--md-motion-easing-emphasized);
}

.activity__map--detail,
.activity__body--detail {
  grid-template-rows: auto 1fr;
  row-gap: var(--md-spacing-6);
}

.activity__map-main {
  min-width: 0;
}

.activity__detail {
  display: flex;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
  visibility: hidden;
  transition: visibility 0s linear var(--md-motion-duration-medium);
}

.activity__map--detail .activity__detail,
.activity__body--detail .activity__detail {
  visibility: visible;
  transition: visibility 0s;
}

.activity__map--detail.activity__map--settled .activity__detail,
.activity__body--detail.activity__body--settled .activity__detail {
  overflow: visible;
}

/* The instant open or close (activity-dock.js open / close({ immediate }): the Create Pass panel's first
   open on load, after the body rendered): the transitions off while the classes land, declared after
   them, so the track and the clip change in one frame */
.activity__map--instant,
.activity__map--instant .activity__detail,
.activity__body--instant,
.activity__body--instant .activity__detail {
  transition: none;
}

/* The panel: the note panel's surface (surface, the outline-variant hairline, the medium corner; no
   shadow, it is in flow). Its own column: head / body / footer. Under the map its height is its content
   (the item clips it while the row grows); beside the map it stretches to the row, so the footer sits at
   the panel's bottom opposite the head (responsive.css) */
.activity__detail-panel {
  flex: 1 1 auto;
  align-self: flex-start;
  display: flex;
  flex-direction: column;
  min-width: 0;
  background-color: var(--md-surface);
  border: var(--md-divider-thickness) solid var(--md-outline-variant);
  border-radius: var(--md-shape-medium);
}

.activity__detail-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--md-spacing-3);
  padding: var(--md-spacing-3) var(--md-spacing-3) var(--md-spacing-3) var(--md-spacing-4);
}

.activity__detail-title {
  margin: 0;
  color: var(--md-on-surface);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* The body never scrolls: the row grows instead (the stage is height:auto under .activity--map), because
   a scrolling body would clip the option menu and the time picker */
.activity__detail-body {
  flex: 1 1 auto;
  min-height: 0;
  padding: 0 var(--md-spacing-4) var(--md-spacing-4);
}

.activity__detail-facts {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--md-spacing-3);
}

/* The form column: the expand-form rhythm (16px plus the outlined field's 8px of label room) */
.activity__detail-form {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-4);
}

/* The dropdowns' hint line keeps its height while blank (the expand-form rule), so "Choose an address
   first." coming and going never moves the Create Pass form (2026-11-01) */
.activity__detail-form .dropdown__supporting-text {
  min-height: calc(var(--md-body-small-line) + var(--md-spacing-1) * 2);
}

/* A block of the form that belongs to one type - the residential Address → Resident rows, the metered
   Space row, the two tails - keeps the form's rhythm; the other type's block is [hidden] (the card's rule) */
.activity__detail-block {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-4);
}

.activity__detail-meta,
.activity__detail-day,
.activity__detail-now {
  margin: 0;
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
}

/* The one line the chip cannot say: "Until 3:00 PM · ABC 123" / "Next 2:00 – 4:00 PM · ABC 123" */
.activity__detail-now {
  color: var(--md-on-surface);
}

/* The day's reservations as lines, one each (off by default: the bars already show them) */
.activity__detail-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-1);
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
  color: var(--md-on-surface);
}

.activity__detail-list li {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.activity__detail-res--over {
  color: var(--md-on-surface-variant);
}

/* The time picker's sheet (--md-list-max-height wide) can be wider than the field: anchored at the
   field's right edge it opens leftward over the map instead of past the card's edge */
.activity__detail .time-input__dropdown {
  left: auto;
  right: 0;
}

/* The footer locked to the panel's bottom: a hairline above, the buttons together at the right end -
   Cancel first, the one main action last (the action bar rule) */
.activity__detail-foot {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--md-spacing-2);
  margin-top: auto;
  padding: var(--md-spacing-3) var(--md-spacing-4);
  border-top: var(--md-divider-thickness) solid var(--md-outline-variant);
}

@media (prefers-reduced-motion: reduce) {
  .activity__map,
  .activity__map--detail,
  .activity__body,
  .activity__body--detail,
  .activity__detail,
  .activity__map--detail .activity__detail,
  .activity__body--detail .activity__detail {
    transition: none;
  }
}

/* ---- Heatmap: 7 weekday columns × 24 hour rows; JS sets data-level 0–4 per cell ---- */
.heatmap {
  --heatmap-axis: var(--md-spacing-10);
}

.heatmap__grid {
  display: grid;
  grid-template-columns: var(--heatmap-axis) repeat(7, minmax(0, 1fr));
  column-gap: var(--md-spacing-2);
  row-gap: var(--md-spacing-1);
  align-items: center;
}

.heatmap__day {
  font-size: var(--md-label-small-size);
  line-height: var(--md-label-small-line);
  font-weight: var(--md-label-small-weight);
  color: var(--md-on-surface-variant);
  text-align: center;
  padding-bottom: var(--md-spacing-1);
}

.heatmap__hour {
  font-size: var(--md-label-small-size);
  line-height: var(--md-spacing-2); /* keeps every grid row at the bar height; labels appear only every 6 rows */
  color: var(--md-on-surface-variant);
  text-align: right;
  padding-right: var(--md-spacing-2);
  white-space: nowrap;
}

.heatmap__cell {
  --heat: 0;
  display: block;
  height: var(--md-spacing-2);
  border-radius: var(--md-shape-full);
  background-color: var(--md-surface-container-high);
  transition: background-color var(--md-motion-duration-medium) var(--md-motion-easing-standard);
  /* a button cell (partials/heatmap selectable: the dashboard's time windows, 2026-11-01) draws like the
     span: the UA's border and padding reset, the width the grid's; an empty button has no line box, so its
     font never sizes it (measured: 0px in Chrome and Firefox) - the floor the dashboard's stretched grid
     keeps is the hour labels' line-height, which every 1fr row shares, and the grid's min-height: 0
     (responsive.css) lets the chart drop under it inside its box */
  -webkit-appearance: none;
  appearance: none;
  border: 0;
  padding: 0;
  margin: 0;
  width: 100%;
  font: inherit;
}

/* Intensity ramp: primary at 25 / 50 / 75 / 100 % over the card surface (works in both themes) */
.heatmap__cell[data-level="1"] { --heat: 0.25; }
.heatmap__cell[data-level="2"] { --heat: 0.5; }
.heatmap__cell[data-level="3"] { --heat: 0.75; }
.heatmap__cell[data-level="4"] { --heat: 1; }

.heatmap__cell:not([data-level="0"]) {
  background-color: rgba(var(--md-primary-rgb), var(--heat));
}

.heatmap__cell--peak {
  outline: var(--md-divider-thickness) solid var(--md-primary);
  outline-offset: var(--md-shape-extra-small-half);
}

/* The dashboard's chart draws no ring on the busiest hour: the only ring is the selected time window's
   (the owner's call, 2026-11-01); the patrol page keeps the peak ring, and the Busiest time tile says it */
.activity .heatmap__cell--peak {
  outline: none;
}

/* Time windows (the dashboard's residential view for a person who may create passes, 2026-11-01;
   client-dashboard-pass.js marks the grid heatmap--select): a selectable cell takes the pointer and a
   dashed ring on hover; a past hour of today (--past) neither, its colour kept; the selected one the
   highlighted border (two hairlines, under hover too; both selectors under the grid's heatmap--select:
   the no-ring rule's specificity and after it, so a selected busiest hour keeps its ring); the focus
   ring wider than both, declared last because every ring is the outline */
.heatmap--select .heatmap__cell {
  cursor: pointer;
}

.heatmap--select .heatmap__cell:hover {
  outline: var(--md-divider-thickness) dashed var(--md-primary);
  outline-offset: var(--md-shape-extra-small-half);
}

.heatmap--select .heatmap__cell--past {
  cursor: default;
}

.heatmap--select .heatmap__cell--past:hover {
  outline: none;
}

.heatmap--select .heatmap__cell--selected,
.heatmap--select .heatmap__cell--selected:hover {
  outline: calc(2 * var(--md-divider-thickness)) solid var(--md-primary);
  outline-offset: var(--md-shape-extra-small-half);
}

.heatmap--select .heatmap__cell:focus-visible {
  outline: calc(2 * var(--md-divider-thickness)) solid var(--md-primary);
  outline-offset: var(--md-spacing-1);
}

.heatmap__cell--swatch {
  width: var(--md-spacing-4);
}

/* Legend: one swatch per level, labelled with the real count range (JS fills it from the group's max) */
.heatmap__legend {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--md-spacing-3);
  margin-top: var(--md-spacing-3);
  font-size: var(--md-label-small-size);
  line-height: var(--md-label-small-line);
  color: var(--md-on-surface-variant);
}

.heatmap__key {
  display: inline-flex;
  align-items: center;
  gap: var(--md-spacing-1);
}

/* ---- Share bars: label / proportional bar / percentage rows; JS sets --share (0–1) ---- */
.share-bars {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-3);
}

.share-bars__title {
  font-size: var(--md-label-medium-size);
  line-height: var(--md-label-medium-line);
  font-weight: var(--md-label-medium-weight);
  color: var(--md-on-surface-variant);
  margin: 0;
}

.share-bars__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  column-gap: var(--md-spacing-3);
  row-gap: var(--md-spacing-1);
  align-items: center;
}

.share-bars__label {
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface);
}

.share-bars__pct {
  font-size: var(--md-label-large-size);
  line-height: var(--md-label-large-line);
  font-weight: var(--md-label-large-weight);
  color: var(--md-on-surface);
  font-variant-numeric: tabular-nums;
}

.share-bars__track {
  grid-column: 1 / -1;
  display: block;
  height: var(--md-spacing-2);
  border-radius: var(--md-shape-full);
  background-color: var(--md-surface-container-high);
  overflow: hidden;
}

.share-bars__fill {
  --share: 0;
  display: block;
  height: 100%;
  width: calc(var(--share) * 100%);
  border-radius: var(--md-shape-full);
  background-color: var(--md-primary);
  transition: width var(--md-motion-duration-medium) var(--md-motion-easing-standard);
}

.share-bars__count {
  grid-column: 1 / -1;
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
  color: var(--md-on-surface-variant);
}

/* ---- Billing band (portal dashboard): full-width status strip, same shape as the page header ---- */
.billing-band {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--md-spacing-4) var(--md-spacing-8);
}

.billing-band__intro {
  display: flex;
  align-items: center;
  gap: var(--md-spacing-3);
  flex: 1 1 var(--md-component-width-small);
  min-width: 0;
}

.billing-band__icon {
  font-size: var(--md-icon-size-large);
  color: var(--md-primary);
  flex-shrink: 0;
}

.billing-band__status {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-1);
  flex: 0 1 auto;
  min-width: var(--md-component-width-xsmall);
}

/* The figure itself: the shared rule in the Client Tools block */
.billing-band__value {
  margin: 0;
}

.billing-band__hint {
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
  color: var(--md-on-surface-variant);
  margin: 0;
}

.billing-band__value--error {
  color: var(--md-error);
}

.billing-band__hint:empty {
  display: none;
}

.billing-band .btn {
  flex-shrink: 0;
}

/* The flex rules above would otherwise override the hidden attribute (the manager's
   "Manage billing" button, the Getting-started band once setup is done) */
.billing-band[hidden],
.billing-band [hidden] {
  display: none !important;
}

/* ---- Getting-started band (portal dashboard): the billing band's shape plus the setup checklist ---- */
.setup-band .progress {
  margin: var(--md-spacing-1) 0 0;
}

.setup-band__steps {
  flex: 1 1 100%;
  min-width: 0;
}

.setup-band__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--md-spacing-2);
  flex-shrink: 0;
}

/* The step list, in the band and in the open strip: steps share the width, short connectors */
.setup-band .stepper,
.setup-strip .stepper {
  margin-bottom: 0;
}

.setup-band .stepper__step,
.setup-strip .stepper__step {
  flex: 1 1 0;
  align-items: flex-start;
  min-width: 0;
}

.setup-band .stepper__connector,
.setup-strip .stepper__connector {
  flex: 0 0 var(--md-spacing-6);
  min-width: var(--md-spacing-6);
  align-self: flex-start;
  margin: calc(var(--md-button-height-small) / 2) var(--md-spacing-2) 0;
}

.stepper__check {
  font-size: var(--md-icon-size-small);
}

/* The optional step's link (Connect Stripe): a small outlined button under the subtitle, its left edge
   on the title's (2026-10-28: the negative margin went with the text button) */
.stepper__action {
  margin-top: var(--md-spacing-2);
}

/* The one "Next step" button (strip and band): same label, same place, on every page */
.setup-strip__next-step {
  flex-shrink: 0;
}

/* ---- Setup strip (client portal, every page but the dashboard): progress, next step, trial clock,
        and the step list that "Steps" opens in place ---- */
.setup-strip {
  margin-bottom: var(--md-spacing-6);
  padding: var(--md-spacing-3) var(--md-spacing-5);
  background-color: var(--md-surface);
  border: var(--md-divider-thickness) solid var(--md-outline-variant);
  border-left: var(--md-spacing-1) solid var(--md-primary);
  border-radius: var(--md-shape-medium);
}

.setup-strip[hidden] {
  display: none !important;
}

/* The one billing notice needing attention (lib/billing/ topNotice) above the guide's bar; a strip
   that carries only the notice (the guide is done) has no bar of its own */
.setup-strip__notice .alert {
  margin-bottom: 0;
}

.setup-strip__notice + .setup-strip__bar {
  margin-top: var(--md-spacing-3);
  padding-top: var(--md-spacing-3);
  border-top: var(--md-divider-thickness) solid var(--md-outline-variant);
}

.setup-strip--notice-only {
  border-left-color: var(--md-outline-variant);
}

.setup-strip__bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--md-spacing-2) var(--md-spacing-6);
}

.setup-strip__progress {
  display: flex;
  align-items: center;
  gap: var(--md-spacing-2);
  flex: 0 0 auto;
}

.setup-strip__progress .progress {
  width: var(--md-spacing-16);
  margin: 0;
}

.setup-strip__icon {
  font-size: var(--md-icon-size-medium);
  color: var(--md-primary);
}

.setup-strip__count {
  font-size: var(--md-label-large-size);
  font-weight: var(--md-label-large-weight);
  line-height: var(--md-label-large-line);
  color: var(--md-on-surface);
  white-space: nowrap;
}

.setup-strip__next {
  flex: 1 1 var(--md-component-width-small);
  min-width: 0;
  margin: 0;
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
}

.setup-strip__next-label,
.setup-strip__next-title {
  font-weight: var(--md-label-large-weight);
  color: var(--md-on-surface);
}

.setup-strip__next-text::before {
  content: '· ';
}

.setup-strip__trial {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 var(--md-spacing-2);
  margin: 0;
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface);
}

.setup-strip__trial strong {
  color: var(--md-primary);
  font-variant-numeric: tabular-nums;
}

.setup-strip__trial-hint {
  font-size: var(--md-body-small-size);
  color: var(--md-on-surface-variant);
}

/* Buttons always sit together at the right end of the bar, so they never move with the text */
.setup-strip__actions {
  display: flex;
  flex-wrap: wrap;   /* three 40px buttons (a trial with no card) do not fit a 360px phone on one row */
  align-items: center;
  gap: var(--md-spacing-2) var(--md-spacing-4);
  margin-left: auto;
  flex-shrink: 0;
}

/* "Steps" is the outlined button like its neighbours (btn btn--outlined in the markup, 2026-10-28):
   only the chevron's tighter gap lives here; its turn while the list is open is below */
.setup-strip__toggle {
  gap: var(--md-spacing-1);
  white-space: nowrap;
}

.setup-strip__toggle .material-symbols-outlined {
  font-size: var(--md-icon-size-small);
  transition: transform var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.setup-strip--open .setup-strip__toggle .material-symbols-outlined {
  transform: rotate(180deg);
}

.setup-strip__steps {
  display: none;
}

.setup-strip--open .setup-strip__steps {
  display: block;
  margin-top: var(--md-spacing-3);
  padding-top: var(--md-spacing-4);
  border-top: var(--md-divider-thickness) solid var(--md-outline-variant);
}

/* ---- Patrol page (/parkhere/patrol, patrol.js): picker, location header, plate lists ---- */
.patrol {
  padding: 0 0 var(--md-spacing-10);
}

.patrol__screen {
  margin: 0 auto;
}

.patrol__screen--card {
  max-width: var(--md-page-width-card);
}

.patrol__screen--wide {
  max-width: var(--md-page-width-narrow);
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-4);
}

.patrol__tab,
.patrol__lists,
.patrol-overlay {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-4);
}

/* The flex rules above would otherwise override the hidden attribute */
.patrol [hidden] {
  display: none !important;
}

/* Card header row: 36px icon + title / subtitle (the end-user card convention) */
.patrol-card__head {
  display: flex;
  align-items: center;
  gap: var(--md-spacing-3);
  margin-bottom: var(--md-spacing-4);
}

.patrol-card__head .card__title,
.patrol-card__head .card__subtitle {
  margin-bottom: 0;
}

.patrol-card__icon,
.patrol-header__icon {
  font-size: var(--md-icon-size-large);
  color: var(--md-primary);
  flex-shrink: 0;
}

.patrol-loading {
  margin: 0;
  padding: var(--md-spacing-6) 0;
  text-align: center;
  color: var(--md-on-surface-variant);
}

/* Location header: back / refresh icon buttons around the name, then the tab strip */
.patrol-header__row {
  display: flex;
  align-items: center;
  gap: var(--md-spacing-2);
}

.patrol-header__text {
  flex: 1;
  min-width: 0;
}

.patrol-header__title,
.patrol-header__meta {
  margin-bottom: 0;
  overflow-wrap: anywhere;
}

.patrol-header__tabs {
  margin-top: var(--md-spacing-4);
}

.patrol-header__tabs .segmented-button {
  display: flex;
  width: 100%;
  margin-bottom: 0;
}

.patrol-header__tabs .segmented-button__item {
  flex: 1 1 0;
  min-width: 0;
  padding-left: var(--md-spacing-2);
  padding-right: var(--md-spacing-2);
  white-space: nowrap;
}

.icon-btn:disabled {
  opacity: var(--md-opacity-disabled);
  cursor: default;
  box-shadow: none;
  filter: none;
}

/* A plain or ringed icon button drops its hover fill while disabled; a filled or tonal one keeps its
   fill at the disabled opacity (the assistant's Send while an answer runs, 2026-10-28) */
.icon-btn:disabled:not(.icon-btn--filled):not(.icon-btn--tonal) {
  background: none;
}

.icon-btn--busy .material-symbols-outlined {
  animation: progress-button-spin var(--md-motion-duration-long) linear infinite;
}

/* Picker: one tappable card per assigned location inside the bounded property list */
.patrol-picker__search .search-bar {
  margin-bottom: var(--md-spacing-4);
}

.patrol-location {
  display: block;
  width: 100%;
  text-align: left;
  font: inherit;
  color: inherit;
  cursor: pointer;
}

.patrol-location__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--md-spacing-2);
}

.patrol-location__code {
  font-size: var(--md-label-large-size);
  font-weight: var(--md-weight-bold);
  letter-spacing: var(--md-plate-tracking);
  color: var(--md-primary);
}

.patrol-location__name {
  display: block;
  margin-bottom: var(--md-spacing-1);
}

.patrol-location__client {
  display: block;
  margin-bottom: var(--md-spacing-2);
}

.patrol-location__meta {
  display: block;
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
  color: var(--md-on-surface-variant);
  margin-bottom: var(--md-spacing-2);
}

.patrol-location__badges {
  display: flex;
  flex-wrap: wrap;
  gap: var(--md-spacing-2);
}

/* Check-a-plate card and the lists under it */
.patrol-search__title {
  margin-bottom: var(--md-spacing-1);
}

.patrol-search .search-bar {
  margin-bottom: var(--md-spacing-3);
}

.patrol-search__btn {
  width: 100%;
}

.patrol-list {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-3);
}

.patrol-list__heading {
  margin: 0;
  color: var(--md-on-surface-variant);
}

.patrol-subhead {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--md-spacing-2);
}

.patrol-subhead__title {
  flex: 1;
  margin: 0;
  color: var(--md-on-surface-variant);
}

.patrol-cta {
  width: 100%;
}

/* Plate rows and the plate history are styled in the "End-user app pages" block (.app-plate,
   .app-history); here only the containers and the pieces shared with the Investigate a Plate tool */
.plate-history {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-4);
}

.plate-history__pii {
  color: var(--md-on-surface-variant);
}

.plate-signals {
  display: flex;
  flex-wrap: wrap;
  gap: var(--md-spacing-2);
  margin: 0;
}

.plate-signal {
  cursor: default;
}

.plate-signal .chip__icon {
  font-size: var(--md-icon-size-small);
}

/* Activity: the heatmap for one location plus three stat tiles */
.patrol-activity__head .card__title {
  margin-bottom: 0;
}

.patrol-activity__type .segmented-button {
  margin-bottom: var(--md-spacing-4);
}

.patrol-activity__stage {
  position: relative;
  margin-bottom: var(--md-spacing-6);
}

.patrol-activity--busy .heatmap,
.patrol-activity--placeholder .heatmap {
  opacity: var(--md-opacity-disabled);
}

.patrol-stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--md-spacing-4);
}

.patrol-stat {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-1);
  min-width: 0;
}

.patrol-stat__label {
  font-size: var(--md-label-medium-size);
  line-height: var(--md-label-medium-line);
  font-weight: var(--md-label-medium-weight);
  color: var(--md-on-surface-variant);
}

/* The figure itself: the shared rule in the Client Tools block */
.patrol-stat__value {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.patrol-stat__hint {
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
  color: var(--md-on-surface-variant);
}

.patrol-stat__delta {
  display: inline-flex;
  align-items: center;
  gap: var(--md-spacing-1);
}

.patrol-stat__delta .material-symbols-outlined {
  font-size: var(--md-icon-size-extra-small);
}

/* ---- Investigate a plate (/portal/tools/plate, client-plate-lookup.js) ---- */
.plate-lookup__header {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--md-spacing-4);
  margin-bottom: var(--md-spacing-4);
}

.plate-lookup__header .card__title,
.plate-lookup__header .card__subtitle {
  margin-bottom: 0;
}

.plate-lookup__toolbar {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--md-spacing-3);
  margin-bottom: var(--md-spacing-6);
}

.plate-lookup__group,
.plate-lookup__query {
  margin: 0;
  min-width: 0;
}

.plate-lookup__group .search-bar,
.plate-lookup__query .search-bar {
  margin-bottom: 0;
}

.plate-lookup__results,
.plate-lookup__history {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-4);
}

.plate-lookup__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(var(--md-component-width-small), 1fr));
  gap: var(--md-spacing-4);
}

.plate-lookup__state .empty-state {
  margin-bottom: 0;
}

.plate-lookup [hidden] {
  display: none !important;
}

/* ---- Client onboarding wizard (views/onboarding/*, partials/onboarding-panel + onboarding-header,
        src/js/components/client-onboarding.js) ----
   A full-screen two-column page rendered without the site chrome (layout.ejs bare): the charcoal
   brand panel on the left carries the dark palette itself (mk-section--dark, variables.css), the
   white form column on the right. The panel is pinned while the form scrolls; below 1024px it
   becomes a compact band above the form. */
.onb {
  position: relative;
  display: grid;
  grid-template-columns: minmax(var(--md-component-width-large), 5fr) minmax(0, 7fr);
  width: 100%;
  min-height: 100vh;
  min-height: 100svh;
}

/* The flex and grid rules below would otherwise override the hidden attribute (field groups,
   the error alert) */
.onb [hidden] {
  display: none !important;
}

/* Visually hidden, still announced (the demo-scheduler__sr recipe) */
.onb__sr {
  position: absolute;
  width: var(--md-divider-thickness);
  height: var(--md-divider-thickness);
  margin: 0;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---- Brand panel ---- */
.onb__brand {
  position: sticky;
  top: 0;
  align-self: start;
  height: 100vh;
  height: 100svh;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-10);
  padding: var(--md-spacing-10) var(--md-spacing-12);
}

.onb__brand-logo {
  height: var(--md-navbar-logo-height);
  width: auto;
  align-self: flex-start;
}

.onb__brand-body {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-8);
  max-width: var(--md-component-width-large);
}

/* Headline-large at the heavy weight every page title on the site carries (.mk-hero__title,
   .mk-section__title); the lead under it is supporting text, body-medium like .card__subtitle */
.onb__brand-title {
  font-size: var(--md-headline-large-size);
  line-height: var(--md-headline-large-line);
  font-weight: var(--md-weight-heavy);
  letter-spacing: var(--md-headline-large-tracking);
  color: var(--md-on-surface);
  overflow-wrap: anywhere;
  margin: 0;
}

/* The business name in the brand green */
.onb__brand-title strong {
  color: var(--md-primary);
  font-weight: inherit;
}

.onb__brand-lead {
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
  margin: 0;
}

/* Step list: every row is a link; the circles are the stepper's (.stepper__indicator) */
.onb__steps {
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: 0;
}

.onb__step {
  position: relative;
  padding-bottom: var(--md-spacing-6);
}

.onb__step:last-child {
  padding-bottom: 0;
}

/* Connector: a hairline from the bottom of one circle to the top of the next */
.onb__step:not(:last-child)::before {
  content: '';
  position: absolute;
  left: calc(var(--md-button-height-small) / 2 - var(--md-divider-thickness) / 2);
  top: var(--md-button-height-small);
  bottom: 0;
  width: var(--md-divider-thickness);
  background-color: var(--md-outline-variant);
}

.onb__step--done:not(:last-child)::before {
  background-color: var(--md-primary);
}

.onb__step-link {
  display: flex;
  align-items: center;
  gap: var(--md-spacing-3);
  color: var(--md-on-surface-variant);
  border-radius: var(--md-shape-full);
  transition: color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.onb__step-link:hover,
.onb__step--current .onb__step-link,
.onb__step--done .onb__step-link {
  color: var(--md-on-surface);
}

.onb__step--locked .onb__step-link {
  color: var(--md-outline);
}

.onb__step-link:focus-visible {
  outline: calc(var(--md-divider-thickness) * 2) solid var(--md-primary);
  outline-offset: var(--md-spacing-1);
}

.onb__step--current .stepper__indicator,
.onb__step--done .stepper__indicator {
  background-color: var(--md-primary);
  color: var(--md-on-primary);
}

.onb__step-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.onb__step-title {
  font-size: var(--md-label-large-size);
  line-height: var(--md-label-large-line);
  font-weight: var(--md-label-large-weight);
}

.onb__step-meta {
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
  color: var(--md-on-surface-variant);
}

.onb__return {
  display: inline-flex;
  align-items: center;
  gap: var(--md-spacing-1);
  align-self: flex-start;
  font-size: var(--md-label-large-size);
  line-height: var(--md-label-large-line);
  font-weight: var(--md-label-large-weight);
  color: var(--md-on-surface-variant);
}

.onb__return:hover {
  color: var(--md-on-surface);
}

.onb__return .material-symbols-outlined {
  font-size: var(--md-icon-size-small);
}

/* Support line and legal links, pinned to the bottom of the panel */
.onb__brand-foot {
  margin-top: auto;
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-2);
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
}

.onb__brand-foot p {
  margin: 0;
  color: inherit;
}

.onb__brand-foot a {
  color: var(--md-on-surface-variant);
  text-decoration: underline;
  text-underline-offset: var(--md-spacing-1);
}

.onb__brand-foot a:hover {
  color: var(--md-on-surface);
}

.onb__brand-legal {
  display: flex;
  gap: var(--md-spacing-2);
}

/* ---- Form column ---- */
/* White, like Stripe: --md-surface is restated so the outlined label notch (.text-field--outlined
   .text-field__label paints --md-surface) matches the column */
.onb__panel {
  --md-surface: var(--md-surface-container-lowest);
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100svh;
  background-color: var(--md-surface);
  padding: var(--md-spacing-20) var(--md-spacing-12) var(--md-spacing-24);
}

.onb__main {
  width: 100%;
  max-width: var(--md-component-width-xlarge);
  margin-inline: auto;
  animation: otpStepIn var(--md-motion-duration-medium) var(--md-motion-easing-decelerate);
}

/* "Finish later": pinned to the viewport's top-right corner, over the form column. It sits
   outside .onb__main on purpose - the entrance transform there would pin it to the column. */
.onb__close {
  position: fixed;
  top: var(--md-spacing-6);
  right: var(--md-spacing-6);
  z-index: 10;
}

.onb__eyebrow {
  margin-bottom: var(--md-spacing-3);
}

/* The step title: headline-large at the heavy weight of every page title on the site */
.onb__title {
  font-size: var(--md-headline-large-size);
  line-height: var(--md-headline-large-line);
  font-weight: var(--md-weight-heavy);
  letter-spacing: var(--md-headline-large-tracking);
  margin: 0 0 var(--md-spacing-3);
}

.onb__title:focus {
  outline: none;
}

.onb__lead {
  font-size: var(--md-body-large-size);
  line-height: var(--md-body-large-line);
  color: var(--md-on-surface-variant);
  max-width: var(--md-content-measure);
  margin: 0 0 var(--md-spacing-8);
}

.onb__error {
  margin: 0 0 var(--md-spacing-6);
}

/* The field stack: the gap is the rhythm; the outlined field keeps its top room for the floating
   label and drops its own bottom margin */
.onb__form,
.onb__stack,
.onb__group {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-4);
}

.onb__form .alert,
.onb__stack .alert {
  margin-bottom: 0;
}

/* The first property through the assistant (property.ejs): the thread in a bordered box with an
   explicit height, which is what makes the thread scroll inside it (.assistant fills the box,
   .assistant__thread flexes and scrolls); the box is capped at the page thread's height and at the
   viewport, so the composer stays in view on a phone */
.onb__assistant {
  display: flex;
  flex-direction: column;
  height: min(calc(var(--md-component-width-xlarge) * 1.25), calc(100vh - var(--md-spacing-24)));
  height: min(calc(var(--md-component-width-xlarge) * 1.25), calc(100svh - var(--md-spacing-24)));
  border: var(--md-divider-thickness) solid var(--md-outline-variant);
  border-radius: var(--md-shape-medium);
  background-color: var(--md-surface);
  overflow: hidden;
}

/* A shown error replaces the helper (lead-form.js pattern: .text-field--error + #<id>-error) */
.onb .text-field--error .text-field__helper {
  display: none;
}

.onb__row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--md-spacing-4);
}

.onb__row--address {
  grid-template-columns: 1fr 2fr;
}

.onb__row--city {
  grid-template-columns: 2fr 1fr 1fr;
}

.onb__row > * {
  min-width: 0;
}

/* Section heading inside a form (Property / Residential / Metered / Card) */
.onb__legend {
  font-size: var(--md-title-small-size);
  line-height: var(--md-title-small-line);
  font-weight: var(--md-title-small-weight);
  color: var(--md-on-surface-variant);
  margin: var(--md-spacing-2) 0 0;
  padding: 0;
}

.onb__help,
.onb__fine {
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
  margin: 0;
}

.onb__fine a,
.onb__help a {
  color: var(--md-primary);
  font-weight: var(--md-weight-bold);
}

/* "Review the assistant terms" (property.ejs #onbTermsAgain) ships hidden and is shown after Not now on
   the terms dialog; .btn's display would win over [hidden] */
.onb__help .btn[hidden] {
  display: none;
}

/* Button row: Back on the left, the primary on the right, every button large */
/* The plan step's "Verifying your bank account" variant hides its wait while the card form is open
   (client-onboarding.js initBankPending); the flex rule below would otherwise beat [hidden] */
.onb__actions[hidden],
.onb__fine[hidden] {
  display: none;
}

.onb__actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--md-spacing-3);
  margin-top: var(--md-spacing-10);
  padding-top: var(--md-spacing-6);
  border-top: var(--md-divider-thickness) solid var(--md-outline-variant);
}

.onb__actions-end {
  display: flex;
  align-items: center;
  gap: var(--md-spacing-3);
  margin-left: auto;
}

/* The wizard's buttons are the portal's standard 40px button (the one height rule of 2026-10-29; they were
   the large 48px with a title-medium label until then) */

/* The arrow follows the label (progress-button.ejs renders the icon first) */
.onb__actions .progress-button__icon {
  order: 1;
}

/* ---- Free trial (step 2) ---- */
/* What the trial includes is the site's check list (partials/check-list, marketing.css
   .mk-check-list: body-large lines, primary check icons) under a form legend */
.onb__included .mk-check-list__item {
  color: var(--md-on-surface-variant);
}

/* The card form's shared pieces (stripe-elements.js mountExpressCheckout): the wizard's trial
   step, the client Billing page's card form and the resident card page carry the same three.
   Stripe's Express Checkout Element (Google Pay / Apple Pay, rendered by Stripe when the browser
   offers one) above the card fields; the script hides the block when Stripe reports nothing to show */
.pay-express {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-4);
}

/* "Or enter your card" between the express buttons and the card fields */
.pay-or {
  display: flex;
  align-items: center;
  gap: var(--md-spacing-3);
  margin: 0;
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
}

.pay-or::before,
.pay-or::after {
  content: '';
  flex: 1;
  height: var(--md-divider-thickness);
  background-color: var(--md-outline-variant);
}

/* Stripe's Payment Element mounts here; the floor stops the page jumping while it loads */
.onb__payment {
  min-height: calc(var(--md-input-field-height) * 3);
}

/* Trust line under the card fields: Stripe's own "Powered by Stripe" badge beside the sentence */
.pay-trust {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--md-spacing-2) var(--md-spacing-3);
  margin: 0;
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
}

.pay-trust-badge {
  height: var(--md-icon-size-medium);
  width: auto;
  flex-shrink: 0;
}

/* ---- Property type: two radio cards (step 3) ---- */
.onb__type {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-3);
  border: 0;
  margin: 0;
  padding: 0;
  min-width: 0;
}

.onb__type-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--md-spacing-3);
}

.onb__type-card {
  display: flex;
  align-items: flex-start;
  gap: var(--md-spacing-3);
  padding: var(--md-spacing-4);
  border: var(--md-divider-thickness) solid var(--md-outline-variant);
  border-radius: var(--md-shape-medium);
  background-color: var(--md-surface-container-lowest);
  cursor: pointer;
  transition: border-color var(--md-motion-duration-short) var(--md-motion-easing-standard),
              background-color var(--md-motion-duration-short) var(--md-motion-easing-standard),
              box-shadow var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.onb__type-card:hover {
  border-color: var(--md-outline);
}

.onb__type-card:has(.radio__input:checked) {
  border-color: var(--md-primary);
  background-color: var(--md-surface-container-low);
  box-shadow: inset 0 0 0 var(--md-divider-thickness) var(--md-primary);
}

.onb__type-card:has(.radio__input:focus-visible) {
  outline: calc(var(--md-divider-thickness) * 2) solid var(--md-primary);
  outline-offset: calc(var(--md-spacing-1) / 2);
}

.onb__type-card .radio__input {
  flex-shrink: 0;
}

.onb__type-icon {
  font-size: var(--md-icon-size-medium);
  color: var(--md-primary);
  flex-shrink: 0;
}

.onb__type-text {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-1);
  min-width: 0;
}

.onb__type-title {
  font-size: var(--md-label-large-size);
  line-height: var(--md-label-large-line);
  font-weight: var(--md-label-large-weight);
  color: var(--md-on-surface);
}

.onb__type-desc {
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
  color: var(--md-on-surface-variant);
}

/* ---- All-set page ---- */
.onb__done-icon {
  display: block;
  font-size: var(--md-step-badge-size);
  color: var(--md-primary);
  margin-bottom: var(--md-spacing-4);
}

.onb__summary {
  display: flex;
  flex-direction: column;
  margin: 0 0 var(--md-spacing-6);
  padding: 0;
  border: var(--md-divider-thickness) solid var(--md-outline-variant);
  border-radius: var(--md-shape-medium);
  background-color: var(--md-surface-container-lowest);
}

.onb__summary-item {
  display: flex;
  align-items: flex-start;
  gap: var(--md-spacing-3);
  padding: var(--md-spacing-4) var(--md-spacing-5);
}

.onb__summary-item + .onb__summary-item {
  border-top: var(--md-divider-thickness) solid var(--md-outline-variant);
}

.onb__summary-icon {
  font-size: var(--md-icon-size-medium);
  color: var(--md-primary);
  flex-shrink: 0;
}

.onb__summary-text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-1);
}

.onb__summary-title {
  font-size: var(--md-title-medium-size);
  line-height: var(--md-title-medium-line);
  font-weight: var(--md-title-medium-weight);
  color: var(--md-on-surface);
}

.onb__summary-meta {
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
  margin: 0;
  overflow-wrap: anywhere;
}

.onb__summary-meta a {
  color: var(--md-primary);
  font-weight: var(--md-weight-bold);
}

/* The 6-digit location code: big, spaced like the plate lettering (.patrol-location__code) */
.onb__code {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  margin-block: var(--md-spacing-2);
  padding: var(--md-spacing-2) var(--md-spacing-5);
  border-radius: var(--md-shape-small);
  background-color: var(--md-primary-container);
  color: var(--md-on-primary-container);
  font-size: var(--md-headline-medium-size);
  line-height: var(--md-headline-medium-line);
  font-weight: var(--md-weight-heavy);
  letter-spacing: var(--md-plate-tracking);
  font-variant-numeric: tabular-nums;
}

@media (prefers-reduced-motion: reduce) {
  .onb__main {
    animation: none;
  }
}

/* Narrow desktops: tighter gutters */
@media (max-width: 1279px) {
  .onb__brand {
    padding: var(--md-spacing-8);
  }

  .onb__panel {
    padding: var(--md-spacing-16) var(--md-spacing-8) var(--md-spacing-20);
  }
}

/* Tablet and phone: the brand panel becomes a compact band above the form (logo, headline, one
   row of steps); the X moves into the band's top-right corner and takes the dark palette's text
   colour (the inverse tokens: charcoal things on the light page) */
@media (max-width: 1023px) {
  .onb {
    grid-template-columns: 1fr;
  }

  .onb__brand {
    position: static;
    height: auto;
    overflow: visible;
    gap: var(--md-spacing-5);
    padding: var(--md-spacing-6);
    padding-right: calc(var(--md-spacing-6) + var(--md-icon-button-size) + var(--md-spacing-2));
  }

  .onb__brand-logo {
    height: var(--md-icon-size-medium);
  }

  .onb__brand-body {
    max-width: none;
    gap: var(--md-spacing-4);
  }

  .onb__brand-title {
    font-size: var(--md-headline-small-size);
    line-height: var(--md-headline-small-line);
  }

  .onb__brand-lead,
  .onb__return,
  .onb__step-meta {
    display: none;
  }

  .onb__steps {
    flex-direction: row;
    flex-wrap: wrap;
    gap: var(--md-spacing-3) var(--md-spacing-6);
  }

  .onb__step {
    padding-bottom: 0;
  }

  .onb__step:not(:last-child)::before {
    display: none;
  }

  .onb__brand-foot {
    margin-top: 0;
    flex-direction: row;
    flex-wrap: wrap;
    gap: var(--md-spacing-2) var(--md-spacing-4);
  }

  .onb__panel {
    min-height: 0;
    padding: var(--md-spacing-10) var(--md-spacing-6) var(--md-spacing-20);
  }

  .onb__close {
    position: absolute;
    top: var(--md-spacing-4);
    right: var(--md-spacing-4);
    color: var(--md-inverse-on-surface);
  }

  .onb__close:hover {
    background-color: var(--md-scrim-light);
  }
}

@media (max-width: 767px) {
  .onb__type-grid {
    grid-template-columns: 1fr;
  }
}

/* Phones: one field per row (province and postal share one), inactive step titles hidden, the
   button row stacks with the primary on top */
@media (max-width: 480px) {
  .onb__brand {
    padding-inline: var(--md-spacing-4);
    padding-right: calc(var(--md-spacing-4) + var(--md-icon-button-size) + var(--md-spacing-2));
  }

  .onb__panel {
    padding: var(--md-spacing-8) var(--md-spacing-4) var(--md-spacing-16);
  }

  .onb__row,
  .onb__row--address {
    grid-template-columns: 1fr;
  }

  .onb__row--city {
    grid-template-columns: 1fr 1fr;
  }

  .onb__row--city > :first-child {
    grid-column: 1 / -1;
  }

  .onb__step:not(.onb__step--current) .onb__step-title {
    position: absolute;
    width: var(--md-divider-thickness);
    height: var(--md-divider-thickness);
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .onb__actions,
  .onb__actions-end {
    flex-direction: column-reverse;
    align-items: stretch;
    margin-left: 0;
  }

  .onb__actions .btn {
    width: 100%;
  }
}

/* ---- Location groups (the grouped client-portal pages; src/js/components/location-groups.js) ----
   One collapsible section per location code: a header row (a chevron button wrapping the location's
   name and its code · counts line, an Add button at the end) over the section's own data table. Every
   section renders closed on load and the page remembers the ones opened across its reloads (2026-10-29).
   The panel collapses on grid rows like the drawer's group rows (0fr -> 1fr) and is visibility: hidden
   while closed, so its buttons take no focus or clicks; the table inside keeps the data-table styles and
   its own horizontal scroll. Not .card: its hover shadow and padding are a tile's, not a section's. */
.loc-groups {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-4);
  margin-bottom: var(--md-spacing-6);
}

.loc-group {
  background-color: var(--md-surface);
  border: var(--md-divider-thickness) solid var(--md-outline-variant);
  border-radius: var(--md-shape-medium);
}

.loc-group__header {
  display: flex;
  align-items: center;
  gap: var(--md-spacing-3);
  padding: var(--md-spacing-2) var(--md-spacing-4) var(--md-spacing-2) var(--md-spacing-2);
}

.loc-group__title {
  flex: 1;
  min-width: 0;
  margin: 0;
  font: inherit;
}

.loc-group__toggle {
  display: flex;
  align-items: center;
  gap: var(--md-spacing-3);
  width: 100%;
  min-height: var(--md-button-height-large);
  padding: var(--md-spacing-2);
  background: none;
  border: none;
  border-radius: var(--md-shape-small);
  font-family: inherit;
  text-align: left;
  color: var(--md-on-surface);
  cursor: pointer;
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.loc-group__toggle:hover {
  background-color: var(--md-surface-container-high);
}

.loc-group__toggle:focus-visible {
  outline: calc(var(--md-divider-thickness) * 2) solid var(--md-primary);
  outline-offset: calc(var(--md-spacing-1) / 2);
}

.loc-group__chevron {
  flex-shrink: 0;
  font-size: var(--md-icon-size-medium);
  color: var(--md-on-surface-variant);
  transition: transform var(--md-motion-duration-medium) var(--md-motion-easing-emphasized);
}

.loc-group--expanded .loc-group__chevron {
  transform: rotate(180deg);
}

.loc-group__heading {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.loc-group__name {
  font-size: var(--md-title-medium-size);
  font-weight: var(--md-title-medium-weight);
  line-height: var(--md-title-medium-line);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.loc-group__meta {
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
}

.loc-group__code {
  font-weight: var(--md-weight-bold);
  color: var(--md-on-surface);
  font-variant-numeric: tabular-nums;
}

/* The header's tools after the title (2026-10-29): the pencil that opens the location's dialog (its name,
   never the code; on the Residential page also its Neighbour passes switch and the unit settings), the
   trash that deletes the rows ticked in this section - shown only while some are: the page keeps its
   [hidden] in step with the ticks - and the Add button */
.loc-group__tools {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  gap: var(--md-spacing-3);
}

.loc-group__add,
.loc-group__rename,
.loc-group__delete {
  flex-shrink: 0;
}

.loc-group__panel {
  display: grid;
  grid-template-rows: 0fr;
  visibility: hidden;
  transition: grid-template-rows var(--md-motion-duration-medium) var(--md-motion-easing-emphasized),
              visibility 0s linear var(--md-motion-duration-medium);
}

.loc-group--expanded .loc-group__panel {
  grid-template-rows: 1fr;
  visibility: visible;
  transition: grid-template-rows var(--md-motion-duration-medium) var(--md-motion-easing-emphasized),
              visibility 0s;
}

.loc-group__inner {
  overflow: hidden;
  min-height: 0;
}

/* The section is the surface: the table keeps a top hairline and the bottom corners only */
.loc-group__inner .data-table__wrapper {
  margin-bottom: 0;
  border: none;
  border-top: var(--md-divider-thickness) solid var(--md-outline-variant);
  border-radius: 0 0 var(--md-shape-medium) var(--md-shape-medium);
}

/* The selection column of the Residential and Metered pages (a checkbox per row; the section's trash
   deletes the ticked ones): its width is the select kind's <col> (variables.css --md-table-col-select) */
.loc-group__cell--select {
  padding-right: 0;
}

/* Secondary text in a cell (addresses, notes); the page names the column (columns[].cellClass) */
.loc-group__cell--muted {
  color: var(--md-on-surface-variant);
}

/* The tags of a metered space in its cell (2026-10-27): label chips (.chip--label) on one line - the first
   two and a "+N" chip, every tag in the cell's title, since a row never grows (the one grid, 2026-10-29) */
.loc-group__tags {
  display: inline-flex;
  flex-wrap: nowrap;
  gap: var(--md-spacing-1);
}

/* A search with no match (location-groups.js render, filtered) */
.loc-groups__empty {
  text-align: center;
  padding: var(--md-spacing-6);
}

.loc-groups__empty p {
  margin: 0;
  color: var(--md-on-surface-variant);
}

@media (max-width: 767px) {
  .loc-group__header {
    flex-wrap: wrap;
  }

  .loc-group__title {
    flex-basis: 100%;
  }

  .loc-group__tools {
    margin-left: auto;
  }
}

@media (prefers-reduced-motion: reduce) {
  .loc-group__chevron,
  .loc-group__panel,
  .loc-group--expanded .loc-group__panel {
    transition: none;
  }
}

/* ---- Client Tools (views/portal/tools-*.ejs; src/js/components/client-tools-*.js) ----
   The toolbar of a tool page without location sections (the Activity Log, the Audit Log, Investigate a
   Plate: the location picker - the plate tool's search bar + menu -, the period presets, an end-aligned
   action; the three grouped Tools pages use .page-toolbar below), the period's totals as stat tiles,
   and the small text roles the tables share. The location picker reuses .plate-lookup__group's recipe. */
.tool-panel {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-4);
}

.tool-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--md-spacing-3);
}

/* A segmented group in a toolbar row drops its stacked-form margin, so it centres on the buttons' line
   (the Tools pages' period presets, the Reservations view's Upcoming | Active) */
.tool-toolbar .segmented-button,
.page-toolbar .segmented-button {
  margin-bottom: 0;
}

.tool-toolbar__group {
  flex: 1 1 var(--md-component-width-medium);
  min-width: 0;
}

.tool-toolbar__group .search-bar {
  width: 100%;
  margin-bottom: 0;
}

.tool-toolbar__end {
  margin-left: auto;
}

/* Fields in a toolbar row (the location comboboxes): no stacked-form margins (the floated label's 8px
   overflow lands in the card padding), so the row centres the visible boxes */
.tool-toolbar .text-field,
.tool-toolbar .dropdown {
  margin: 0;
}

.tool-summary {
  display: flex;
  flex-wrap: wrap;
  gap: var(--md-spacing-3);
}

.tool-stat {
  display: flex;
  flex-direction: column;
  min-width: var(--md-component-width-xsmall);
  padding: var(--md-spacing-3) var(--md-spacing-4);
  border-radius: var(--md-shape-medium);
  background-color: var(--md-surface-container-low);
}

/* One figure for every stat tile of the portals (plate-history.js statTile builds the markup): the tool
   pages' tiles, the plate history's and the residence page's figures, the patrol summary, the
   dashboard's activity stats and billing band. Bold in the brand green at the title-large size; a
   regular-weight charcoal figure on a tinted tile read as washed out. Each variant keeps only its
   layout below. */
.tool-stat__value,
.app-stat__value,
.patrol-stat__value,
.activity__stat-value,
.billing-band__value {
  font-size: var(--md-title-large-size);
  line-height: var(--md-title-large-line);
  font-weight: var(--md-weight-bold);
  color: var(--md-primary);
  font-variant-numeric: tabular-nums;
}

/* The summary tiles are display: flex, which the hidden attribute alone does not beat */
.tool-summary[hidden] {
  display: none;
}

.tool-stat__label {
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
  color: var(--md-on-surface-variant);
}

/* Inline totals beside the period switch (Service requests) */
.tool-summary--inline .tool-stat {
  flex-direction: row;
  align-items: baseline;
  gap: var(--md-spacing-2);
  min-width: 0;
  padding: var(--md-spacing-1) var(--md-spacing-3);
}

.tool-summary--inline .tool-stat__value {
  font-size: var(--md-title-medium-size);
  line-height: var(--md-title-medium-line);
}

.tool-strong {
  font-weight: var(--md-weight-bold);
}

.tool-muted {
  color: var(--md-on-surface-variant);
}

.tool-code {
  font-weight: var(--md-weight-bold);
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--md-letter-spacing-tight-small);
}

.tool-nowrap {
  white-space: nowrap;
}

/* The line above a timeline (the row count, the 500-row note) */
.tool-note {
  margin: 0 0 var(--md-spacing-3);
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
}

.tool-person {
  display: block;
}

/* A phone number anywhere in the client tables and the plate history (plate-history.js phoneHtml):
   bold in the brand green, plain text (never a link: a desktop has no dialer, and the green would
   read as one) */
.phone-number {
  font-weight: var(--md-weight-bold);
  color: var(--md-primary);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* The Expand all / Collapse all pair over the location sections (location-groups.js shows the wrapper
   with two or more sections and no search); scoped to :not([hidden]) because display would otherwise
   beat the attribute */
[data-loc-controls]:not([hidden]) {
  display: flex;
  gap: var(--md-spacing-2);
}

/* ---- The client portal's toolbar (2026-10-29): the three property pages, Residents, Exempt Plates,
   Patrol, Service Providers, the Reservations view, the three grouped Tools pages and Managers ----
   Expand all / Collapse all first at the left, then the page's quiet line (the capacity line, a count,
   the period presets and totals); the outlined tools and the one filled Add at the right edge
   (margin-left: auto keeps them there when the section controls hide: one location, or a search on);
   the search bar under the row. Wraps on narrow widths, the line under the controls */
.page-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--md-spacing-3);
  margin-bottom: var(--md-spacing-4);
}

.page-toolbar__lead {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--md-spacing-3);
  min-width: 0;
}

.page-toolbar__actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--md-spacing-2);
  margin-left: auto;
}

/* The page's quiet line of facts (the owner's rule of 2026-10-29), never a box: the property pages'
   capacity - what the trial, the plan or the agreement covers and how many are in use, the pending
   count, one link -, Exempt Plates' "N exempt plates across M locations", Managers' "N of M managers
   used"; the billing state itself is the setup strip's notice above the page. The figures bold, the
   link in the alert link's recipe */
.capacity-line {
  margin: 0;
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
}

.capacity-line__fact {
  font-weight: var(--md-weight-bold);
  color: var(--md-on-surface);
}

.capacity-line__link {
  color: inherit;
  font-weight: var(--md-label-large-weight);
  text-decoration: underline;
}

/* ---- Location sign and message to residents (views/portal/tools-sign.ejs, tools-message.ejs: bare
   pages; client-tools-sign.js, client-tools-message.js) ----
   On screen: a toolbar over a letter-shaped sheet on the container colour. On paper: the sheet alone,
   edge to edge inside the printer margins (the toolbar, the message line and the consent banner are
   hidden). The sign carries the code as one row of six squares; the message sheet reads as a letter. */
.sign-page {
  min-height: 100vh;
  padding: var(--md-spacing-6);
  background-color: var(--md-surface-container);
  color: var(--md-on-surface);
}

.sign-page__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--md-spacing-4);
}

.sign-toolbar {
  width: 100%;
  max-width: var(--md-component-width-xlarge);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--md-spacing-3);
}

.sign-sheet {
  width: 100%;
  max-width: var(--md-component-width-xlarge);
  padding: var(--md-spacing-12) var(--md-spacing-10);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--md-spacing-4);
  background-color: var(--md-surface);
  border: var(--md-divider-thickness) solid var(--md-outline-variant);
  border-radius: var(--md-shape-medium);
}

.sign-sheet__logo {
  height: calc(var(--md-navbar-logo-height) * 1.5);
}

.sign-sheet__eyebrow {
  margin: var(--md-spacing-4) 0 0;
  font-size: var(--md-label-large-size);
  font-weight: var(--md-weight-bold);
  letter-spacing: 0.1em;   /* the eyebrow tracking (.mk-eyebrow) */
  text-transform: uppercase;
  color: var(--md-primary);
}

.sign-sheet__title {
  margin: 0;
  font-size: var(--md-headline-large-size);
  font-weight: var(--md-headline-large-weight);
  line-height: var(--md-headline-large-line);
}

.sign-sheet__label {
  margin: var(--md-spacing-6) 0 0;
  font-size: var(--md-label-large-size);
  font-weight: var(--md-weight-bold);
  letter-spacing: 0.1em;   /* the eyebrow tracking (.mk-eyebrow) */
  text-transform: uppercase;
  color: var(--md-on-surface-variant);
}

/* The code: one square per character in one row; the squares share the sheet's width, each at most
   --md-sign-cell-size (a letter-spaced display size wrapped to two lines on the screen sheet) */
.sign-sheet__code {
  width: 100%;
  margin: 0;
  display: flex;
  justify-content: center;
  gap: var(--md-spacing-2);
}

.sign-sheet__cell {
  flex: 1 1 0;
  max-width: var(--md-sign-cell-size);
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  border: calc(var(--md-divider-thickness) * 2) solid var(--md-primary);
  border-radius: var(--md-shape-small);
  font-size: var(--md-display-medium-size);
  line-height: 1;
  font-weight: var(--md-weight-bold);
  color: var(--md-primary);
  font-variant-numeric: tabular-nums;
}

.sign-sheet__steps {
  width: 100%;
  margin: var(--md-spacing-6) 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: var(--md-spacing-3);
  text-align: left;
}

.sign-sheet__step {
  display: flex;
  align-items: flex-start;
  gap: var(--md-spacing-3);
  font-size: var(--md-title-medium-size);
  line-height: var(--md-title-medium-line);
}

.sign-sheet__step-num {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--md-icon-size-large);
  height: var(--md-icon-size-large);
  border-radius: var(--md-shape-full);
  background-color: var(--md-primary);
  color: var(--md-on-primary);
  font-size: var(--md-label-large-size);
  font-weight: var(--md-weight-bold);
}

.sign-sheet__foot {
  margin: var(--md-spacing-6) 0 0;
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
}

/* The message to residents reads as a letter: left-aligned text under the centred brand */
.sign-sheet--message {
  align-items: stretch;
  text-align: left;
}

.sign-sheet__brand {
  display: flex;
  justify-content: center;
}

.sign-sheet--message .sign-sheet__eyebrow {
  text-align: center;
}

.sign-sheet__lead {
  margin: 0;
  font-size: var(--md-title-medium-size);
  line-height: var(--md-title-medium-line);
  color: var(--md-on-surface-variant);
}

.sign-sheet__inline-code {
  color: var(--md-primary);
  font-weight: var(--md-weight-bold);
  letter-spacing: var(--md-plate-tracking);
}

.sign-sheet__heading {
  margin: var(--md-spacing-6) 0 0;
  font-size: var(--md-title-large-size);
  font-weight: var(--md-title-large-weight);
  line-height: var(--md-title-large-line);
}

.sign-sheet--message .sign-sheet__steps {
  margin-top: var(--md-spacing-3);
}

.sign-toolbar__end {
  display: flex;
  gap: var(--md-spacing-2);
}

/* ---- End-user app pages (/parkhere/*): title row, flat sections, rows, vehicle cards, action bar ----
   The page pattern of the end-user portal (Account and the vehicle pages first, 2026-10-17): one title
   row per page (the h1), then sections. On phones a section is flat (no border, no padding: the panel's
   own padding is the only frame); from 768px it is an outlined card (responsive.css). The items inside a
   section (a vehicle, a pass, a tile) stay .card.card--outlined at every width. Tokens only. */
.app-page {
  max-width: var(--md-page-width-narrow);
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-6);
  padding-bottom: var(--md-spacing-10);
}

.app-page--form {
  max-width: var(--md-page-width-card);
}

/* The flex rules would otherwise override the hidden attribute (as .patrol [hidden]) */
.app-page [hidden] {
  display: none !important;
}

/* Title row: an optional back link to the parent page, the h1, a one-line lead */
.app-page__head {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-1);
}

.app-page__back {
  align-self: flex-start;
  gap: var(--md-spacing-1);
  margin: 0 0 var(--md-spacing-2) calc(-1 * var(--md-spacing-3));   /* the arrow sits on the text edge */
}

.app-page__title {
  font-size: var(--md-headline-small-size);
  line-height: var(--md-headline-small-line);
  font-weight: var(--md-headline-small-weight);
  letter-spacing: var(--md-headline-small-tracking);
  color: var(--md-on-surface);
  margin: 0;
}

.app-page__lead {
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
  margin: 0;
}

/* Section: flat on phones; responsive.css frames it from 768px */
.app-section {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-4);
  min-width: 0;
}

.app-section__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--md-spacing-3);
}

/* Eyebrow: label-large in capitals; the count after it keeps the body weight and case */
.app-section__eyebrow {
  font-size: var(--md-label-large-size);
  line-height: var(--md-label-large-line);
  font-weight: var(--md-label-large-weight);
  letter-spacing: var(--md-label-large-tracking);
  text-transform: uppercase;
  color: var(--md-on-surface-variant);
  margin: 0;
}

.app-section__count {
  font-weight: var(--md-body-medium-weight);
  text-transform: none;
}

.app-section__text {
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
  margin: 0;
}

/* The message slot takes no room until an alert is written into it */
.app-section__msg:empty {
  display: none;
}

.app-section .empty-state {
  padding: var(--md-spacing-6) var(--md-spacing-4);
  margin-bottom: 0;
}

/* Lists of item cards */
.app-list {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-3);
}

/* A tappable row (an <a>): leading icon, headline and supporting lines, trailing chevron.
   The hover restates the text colour: base.css a:hover would recolour it (see .btn--primary:hover) */
.app-row {
  display: flex;
  align-items: center;
  gap: var(--md-spacing-3);
  padding: var(--md-spacing-4);
  color: var(--md-on-surface);
}

.app-row:hover {
  color: var(--md-on-surface);
  background-color: var(--md-surface-container-low);
}

.app-row__icon {
  font-size: var(--md-icon-size-medium);
  color: var(--md-primary);
  flex-shrink: 0;
}

.app-row__text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-1);
}

.app-row__headline {
  font-size: var(--md-title-medium-size);
  line-height: var(--md-title-medium-line);
  font-weight: var(--md-title-medium-weight);
  color: var(--md-on-surface);
}

.app-row__supporting {
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
}

.app-row__chevron {
  font-size: var(--md-icon-size-medium);
  color: var(--md-on-surface-variant);
  flex-shrink: 0;
}
/* Get Pass's Recent rows (2026-10-30, the owner's rule: every card the same height): three lines, each
   kept to one with an ellipsis - the kicker (what a location's name says before its " - ", a blank line
   when it says nothing), the name, the address with the last visit -, so the cards line up whatever a
   name's length; the whole text sits in the row's title */
.app-row--recent {
  text-align: left;
  min-height: calc(var(--md-label-large-line) + var(--md-title-medium-line) + var(--md-body-medium-line) + 2 * var(--md-spacing-1) + 2 * var(--md-spacing-4));
}
.app-row--recent .app-row__kicker,
.app-row--recent .app-row__headline,
.app-row--recent .app-row__supporting {
  display: block;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.app-row__kicker {
  font-size: var(--md-label-large-size);
  line-height: var(--md-label-large-line);
  font-weight: var(--md-label-large-weight);
  letter-spacing: var(--md-label-large-tracking);
  color: var(--md-on-surface-variant);
}

/* A row that acts inside its page (a property to pick) is a <button>: the same look as the link rows */
button.app-row {
  width: 100%;
  text-align: left;
  font: inherit;
  cursor: pointer;
}

.app-row__supporting strong {
  color: var(--md-primary);
  font-weight: var(--md-title-small-weight);
}

/* Vehicle card: the plate in capitals with the plate tracking. The ghost card is the add button,
   drawn like a vehicle card (two placeholder bars where the plate and the model lines would be) */
.app-vehicle__plate {
  text-transform: uppercase;
  letter-spacing: var(--md-plate-tracking);
}

.app-vehicle--ghost {
  border-style: dashed;
  background-color: transparent;
}

.app-vehicle--ghost .app-row__icon {
  color: var(--md-outline);
}

.app-vehicle--ghost .app-row__chevron {
  color: var(--md-primary);
}

.app-vehicle__bar {
  display: block;
  height: var(--md-spacing-3);
  border-radius: var(--md-shape-full);
  background-color: var(--md-surface-container-high);
}

.app-vehicle__bar--plate {
  width: 40%;
}

.app-vehicle__bar--model {
  width: 60%;
}

.app-vehicle__add {
  margin-top: var(--md-spacing-1);
  font-size: var(--md-label-large-size);
  line-height: var(--md-label-large-line);
  font-weight: var(--md-label-large-weight);
  color: var(--md-primary);
}

/* Forms: fields 16px apart (24px with the floated label's room); a row holds two fields side by side
   (minmax(0) lets an input shrink below its intrinsic width, so two fit on a 360px phone) */
.app-form {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-4);
}

.app-form__row {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--md-spacing-4);
}

.app-form__plate .text-field__input {
  text-transform: uppercase;
  letter-spacing: var(--md-plate-tracking);
}

/* Action bar: on phones a column of full-width buttons with the primary first; from 768px one row,
   right-aligned, the primary last (responsive.css) */
.app-actions {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-3);
  margin-top: var(--md-spacing-2);
}

.app-actions .btn {
  width: 100%;
  justify-content: center;
}

/* Two actions side by side at every width (Approve / Deny on a visitor request card) */
.app-actions--inline {
  flex-direction: row;
}

.app-actions--inline .btn {
  flex: 1 1 0;
  min-width: 0;
}

/* The home's residence summary as the title block: one link to /parkhere/residence */
.app-page__head-link {
  display: flex;
  align-items: center;
  gap: var(--md-spacing-3);
  color: var(--md-on-surface);
}

.app-page__head-link:hover {
  color: var(--md-on-surface);
}

.app-page__head-text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-1);
}

.app-page__code {
  font-weight: var(--md-weight-bold);
  letter-spacing: var(--md-plate-tracking);
  color: var(--md-primary);
}

.app-row__icon--muted {
  color: var(--md-on-surface-variant);
}

/* Item cards that are not links (a pass, a visitor request, a charge): top row, title, lines */
.app-card {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-2);
  padding: var(--md-spacing-4);
}

.app-card__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--md-spacing-2);
}

.app-card__title {
  font-size: var(--md-title-medium-size);
  line-height: var(--md-title-medium-line);
  font-weight: var(--md-title-medium-weight);
  color: var(--md-on-surface);
  margin: 0;
  overflow-wrap: anywhere;
}

.app-card__subtitle {
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
  margin: 0;
}

.app-card__amount {
  font-size: var(--md-title-medium-size);
  line-height: var(--md-title-medium-line);
  font-weight: var(--md-title-medium-weight);
  color: var(--md-on-surface);
  white-space: nowrap;
}

.app-lines {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-1);
}

.app-line {
  display: flex;
  align-items: center;
  gap: var(--md-spacing-2);
  margin: 0;
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
  overflow-wrap: anywhere;
}

.app-line .material-symbols-outlined {
  font-size: var(--md-icon-size-small);
  flex-shrink: 0;
}

.app-line strong {
  color: var(--md-on-surface);
  font-weight: var(--md-title-small-weight);
}

/* A choice row: a card around a radio and its text (the vehicle to park, the unit to claim) */
.app-choice {
  display: flex;
  align-items: center;
  gap: var(--md-spacing-3);
  padding: var(--md-spacing-3) var(--md-spacing-4);
  width: 100%;
  text-align: left;
  font: inherit;
  color: var(--md-on-surface);
  cursor: pointer;
}

.app-choice--selected,
.app-choice:has(.radio__input:checked) {
  border-color: var(--md-primary);
  background-color: var(--md-surface-container-low);
}

/* A short bill: rows of label and amount, the total on its own line */
.app-summary {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-2);
  padding: var(--md-spacing-4);
  border-radius: var(--md-shape-medium);
  background-color: var(--md-surface-container-low);
}

.app-summary__row {
  display: flex;
  justify-content: space-between;
  gap: var(--md-spacing-3);
  margin: 0;
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
}

.app-summary__row strong {
  color: var(--md-on-surface);
  font-weight: var(--md-title-small-weight);
}

.app-summary__total {
  padding-top: var(--md-spacing-2);
  border-top: var(--md-divider-thickness) solid var(--md-outline-variant);
  color: var(--md-on-surface);
  font-weight: var(--md-title-small-weight);
}

.app-summary__total strong {
  color: var(--md-primary);
}

/* Figures with their label (passes used and left this month) */
.app-stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--md-spacing-4);
}

.app-stat {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-1);
  min-width: 0;
}

/* .app-stat__value: the shared figure rule in the Client Tools block */

.app-stat__label {
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
}

/* A result screen (Get Pass step 4): icon, title, text, then the pass code and its details */
.app-result {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--md-spacing-2);
}

.app-result__icon {
  font-size: var(--md-icon-size-large);
  color: var(--md-primary);
}

.app-result__icon--error {
  color: var(--md-error);
}

.app-result__icon--muted {
  color: var(--md-on-surface-variant);
}

.app-result__icon--pulse {
  animation: app-pulse calc(var(--md-motion-duration-long) * 3) var(--md-motion-easing-standard) infinite;
}

@keyframes app-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: var(--md-opacity-disabled); }
}

.app-result__title {
  font-size: var(--md-headline-small-size);
  line-height: var(--md-headline-small-line);
  font-weight: var(--md-headline-small-weight);
  color: var(--md-on-surface);
  margin: 0;
}

.app-result__text {
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
  margin: 0;
}

.app-result .app-lines {
  width: 100%;
  align-items: center;
  margin-top: var(--md-spacing-2);
}

/* The pass code, large, on a tinted panel */
.app-code-panel {
  width: 100%;
  margin-top: var(--md-spacing-3);
  padding: var(--md-spacing-4);
  border-radius: var(--md-shape-medium);
  background-color: var(--md-surface-container-low);
  text-align: center;
}

.app-code-panel__label {
  display: block;
  font-size: var(--md-label-large-size);
  line-height: var(--md-label-large-line);
  font-weight: var(--md-label-large-weight);
  color: var(--md-on-surface-variant);
}

.app-code-panel__code {
  display: block;
  font-size: var(--md-headline-small-size);
  line-height: var(--md-headline-small-line);
  font-weight: var(--md-weight-bold);
  letter-spacing: var(--md-code-tracking);
  color: var(--md-primary);
}

/* The location code field: capitals, spaced like the sign, centred */
.app-form__code .text-field__input {
  text-align: center;
  text-transform: uppercase;
  letter-spacing: var(--md-code-tracking);
  font-size: var(--md-title-medium-size);
}

/* Controls over a list (My Passes): a full-width segmented switch, then a chip row */
.app-controls {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-3);
}

.app-controls .segmented-button {
  display: flex;
  width: 100%;
  margin-bottom: 0;
}

.app-controls .segmented-button__item {
  flex: 1 1 0;
  min-width: 0;
}

/* The selected segment shows its check (two wide segments have the room); the range chips show
   their selection by the fill alone */
.app-controls .chip__check {
  display: none;
}

.app-controls .chip-group {
  margin-bottom: 0;
}

/* Stripe's Payment Element keeps the form's height while it loads */
.app-stripe {
  min-height: var(--md-spacing-24);
}

/* In-page steps (Get Pass and Set Residence, until each step has a URL of its own) */
.app-step {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-6);
}

/* The patrol page on the pattern: its header, search and activity blocks are sections, whose own
   spacing comes from the section's gap */
.app-section > .patrol-card__head,
.app-section > .patrol-header__tabs,
.app-section > .patrol-activity__stage {
  margin: 0;
}

.app-section.patrol-search .search-bar,
.app-section > .patrol-activity__type .segmented-button {
  margin-bottom: 0;
}

/* The location picker rows: the leading icon */
.patrol-location__icon {
  font-size: var(--md-icon-size-medium);
  color: var(--md-primary);
}

/* The Plates tab filter: a full-width segmented control carrying the counts (patrol.js) */
.patrol-filter .segmented-button {
  display: flex;
  width: 100%;
  margin-bottom: 0;
}

.patrol-filter .segmented-button__item {
  flex: 1 1 0;
  min-width: 0;
  padding-left: var(--md-spacing-2);
  padding-right: var(--md-spacing-2);
  white-space: nowrap;
}

/* Plate rows (plate-history.js: the officer's lists, search results, exempt plates, service requests,
   related plates, and the Investigate a Plate tool): the main button opens the history (or the
   request's page), a trailing truck button requests service, a chevron marks a row that opens a page */
.app-plate {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: var(--md-spacing-1);
  padding: 0;
}

.app-plate__main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-1);
  padding: var(--md-spacing-3) var(--md-spacing-4);
  background: none;
  border: none;
  border-radius: inherit;
  text-align: left;
  font: inherit;
  color: var(--md-on-surface);
  cursor: pointer;
}

.app-plate__top {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--md-spacing-2);
}

.app-plate__plate {
  flex: 1;
  min-width: 0;
  font-size: var(--md-title-medium-size);
  line-height: var(--md-title-medium-line);
  font-weight: var(--md-title-medium-weight);
  letter-spacing: var(--md-plate-tracking);
  text-transform: uppercase;
  overflow-wrap: anywhere;
}

.app-plate__meta {
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
  overflow-wrap: anywhere;
}

.app-plate--expired .app-plate__when {
  color: var(--md-error);
}

.app-plate__tow,
.app-plate__chevron {
  flex-shrink: 0;
  margin-right: var(--md-spacing-2);
}

.app-plate__tow {
  color: var(--md-primary);
}

.app-plate__chevron {
  font-size: var(--md-icon-size-medium);
  color: var(--md-on-surface-variant);
}

/* The plate history (plate-history.js renderHistory): the summary card with three figures, the source
   cards, the two-line lists */
/* The plate is the subject of the view: the headline role (a size step over the 20px figures under
   it, the heading weight), the plate tracking */
.app-history__plate {
  font-size: var(--md-headline-medium-size);
  line-height: var(--md-headline-medium-line);
  font-weight: var(--md-headline-medium-weight);
  letter-spacing: var(--md-plate-tracking);
  text-transform: uppercase;
  overflow-wrap: anywhere;
}

.app-history__badges {
  display: flex;
  gap: var(--md-spacing-2);
  flex-shrink: 0;
}

/* The summary and history cards are read, not clicked: no lift on hover (the related plate rows keep
   theirs) */
.app-history__summary:hover,
.app-history__source:hover {
  box-shadow: none;
}

/* The source chips over the merged timeline (plate-history.js bindHistoryFilters) */
.app-history__filters {
  display: flex;
  flex-wrap: wrap;
  gap: var(--md-spacing-2);
  margin-bottom: var(--md-spacing-4);
}

/* The label of a people line ("Resident:", "Account created:") in bold on-surface */
.app-history__role {
  font-weight: var(--md-weight-bold);
  color: var(--md-on-surface);
}

/* "None" for a missing name: the reason on hover / focus through the CSS tooltip (focusable so a
   keyboard reaches it; the hidden text tells screen readers) */
.app-history__none {
  display: inline-block;
  color: var(--md-on-surface-variant);
  font-style: italic;
  border-bottom: var(--md-divider-thickness) dotted var(--md-outline);
  cursor: help;
}

.app-history__none:focus-visible {
  outline: var(--md-divider-thickness) solid var(--md-primary);
  outline-offset: var(--md-spacing-1);
  border-radius: var(--md-shape-extra-small);
}

.app-stats--3 {
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--md-spacing-3);
}

.app-stats--3 .app-stat__label {
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
}

.app-history__heading {
  margin: var(--md-spacing-2) 0 0;
  font-size: var(--md-label-large-size);
  line-height: var(--md-label-large-line);
  font-weight: var(--md-label-large-weight);
  color: var(--md-on-surface-variant);
}

.app-history__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-2);
}

.app-history__list li {
  display: flex;
  flex-direction: column;
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface);
}

.app-history__hint {
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
  color: var(--md-on-surface-variant);
}

.app-history__count {
  color: var(--md-on-surface-variant);
  font-weight: var(--md-body-medium-weight);
}

.app-history__source .timeline {
  margin-bottom: 0;
}

/* A quiet ledger (the charges on Billing): rows on hairlines, nothing bold */
.app-ledger {
  list-style: none;
  margin: 0;
  padding: 0;
}

.app-ledger__row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--md-spacing-4);
  padding: var(--md-spacing-3) 0;
  border-bottom: var(--md-divider-thickness) solid var(--md-outline-variant);
}

.app-ledger__row:last-child {
  border-bottom: none;
}

.app-ledger__main {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-1);
  min-width: 0;
}

.app-ledger__label,
.app-ledger__amount {
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface);
}

.app-ledger__amount {
  white-space: nowrap;
}

.app-ledger__sub {
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
  color: var(--md-on-surface-variant);
}

.app-ledger__sub--error {
  color: var(--md-error);
}

/* The unit carousel (partials/app-carousel + app-carousel.js): a scroll-snap track of unit cards that
   swipes on a phone, the neighbours peeking at the sides, prev / next buttons with the position
   between them, dots up to eight slides */
.app-carousel {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-3);
}

.app-carousel__track {
  display: flex;
  gap: var(--md-spacing-3);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: var(--md-spacing-4);
  padding: var(--md-spacing-1) var(--md-spacing-4);
  margin: 0 calc(-1 * var(--md-spacing-4));   /* the track bleeds into the panel's padding so the neighbours peek */
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}

.app-carousel__track::-webkit-scrollbar {
  display: none;
}

.app-carousel__slide {
  flex: 0 0 min(78%, var(--md-component-width-small));
  scroll-snap-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--md-spacing-1);
  min-height: var(--md-spacing-32);
  padding: var(--md-spacing-4);
  text-align: center;
  font: inherit;
  color: var(--md-on-surface);
  cursor: pointer;
}

.app-carousel__slide--selected {
  border-color: var(--md-primary);
  box-shadow: inset 0 0 0 var(--md-divider-thickness) var(--md-primary);   /* a second hairline: a 2px outline with no layout shift */
  background-color: var(--md-surface-container-low);
}

.app-unit__kicker {
  font-size: var(--md-label-large-size);
  line-height: var(--md-label-large-line);
  font-weight: var(--md-label-large-weight);
  letter-spacing: var(--md-label-large-tracking);
  text-transform: uppercase;
  color: var(--md-on-surface-variant);
}

.app-unit__number {
  font-size: var(--md-headline-medium-size);
  line-height: var(--md-headline-medium-line);
  font-weight: var(--md-headline-medium-weight);
  letter-spacing: var(--md-headline-medium-tracking);
  color: var(--md-primary);
  overflow-wrap: anywhere;
}

.app-unit__number--name {
  font-size: var(--md-title-large-size);
  line-height: var(--md-title-large-line);
  font-weight: var(--md-title-large-weight);
  letter-spacing: var(--md-title-large-tracking);
}

.app-unit__detail {
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
}

/* A metered space's slide (2026-10-27): the label big like a unit number, its tags under it; the
   "Any space" slide dashed */
.app-space__tags {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--md-spacing-1);
  margin-top: var(--md-spacing-2);
}

.app-carousel__slide--any {
  border-style: dashed;
}

/* The day chips of a reservation's start: one scrolling row with the carousel's bleed */
.app-days {
  display: flex;
  gap: var(--md-spacing-2);
  overflow-x: auto;
  scrollbar-width: none;
  padding: var(--md-spacing-1) var(--md-spacing-4);
  margin: 0 calc(-1 * var(--md-spacing-4));
}

.app-days::-webkit-scrollbar {
  display: none;
}

.app-days .chip {
  flex: 0 0 auto;
  white-space: nowrap;
}

.app-days .chip__check {
  display: none;
}

/* A free reservation's bill */
.app-summary--free .app-summary__total strong {
  color: var(--md-tertiary);
}

.app-summary__note {
  margin: 0;
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
  color: var(--md-on-surface-variant);
}
/* A result's ticket (2026-10-30, the owner's pick): the receipt box and the info box read left to right
   inside the centred result; a row's plain value is readable but quiet, `strong` marks the values that
   matter (the space, the time, the price); a long value wraps under itself, right-aligned */
.app-result .app-summary,
.app-result .alert {
  align-self: stretch;
  text-align: left;
}
.app-summary__row > :last-child {
  min-width: 0;
  text-align: right;
  overflow-wrap: anywhere;
}
.app-summary__value {
  color: var(--md-on-surface);
}

/* A link inside an alert's sentence (the property pages' capacity lines, alert.js alertLink): the text's
   own colour, bold, underlined, so it reads inside the prose */
.alert__link {
  color: inherit;
  font-weight: var(--md-label-large-weight);
  text-decoration: underline;
}

/* A link standing alone under the text (enduser-get-pass.js "Change card") keeps its air and its look of
   before: the primary colour, no underline */
.alert__text + .alert__link {
  display: inline-block;
  margin-top: var(--md-spacing-1);
  color: var(--md-primary);
  text-decoration: none;
}

/* The Bulk Upload preview under the file picker (the three property pages): the alert takes its air
   from the slot, never from a style attribute */
.bulk-preview .alert {
  margin-top: var(--md-spacing-4);
}

.app-carousel__nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--md-spacing-2);
}

.app-carousel--single .app-carousel__nav {
  display: none;
}

.app-carousel__count {
  min-width: var(--md-spacing-16);
  text-align: center;
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
}

.app-carousel__dots {
  display: flex;
  justify-content: center;
  gap: var(--md-spacing-2);
}

.app-carousel__dots:empty {
  display: none;
}

.app-carousel__dot {
  width: var(--md-spacing-2);
  height: var(--md-spacing-2);
  padding: 0;
  border: none;
  border-radius: var(--md-shape-full);
  background-color: var(--md-outline-variant);
  cursor: pointer;
}

.app-carousel__dot--active {
  background-color: var(--md-primary);
}

@media print {
  @page {
    size: letter;
    margin: 1.25cm;   /* the printer's own margin; the sheet fills the rest */
  }

  .sign-toolbar,
  .sign-page #signMsg,
  .consent-banner {
    display: none;
  }

  .sign-page {
    min-height: 0;
    padding: 0;
    background: none;
  }

  .sign-sheet {
    max-width: none;
    min-height: 100vh;
    justify-content: center;
    padding: 0;
    border: none;
    border-radius: 0;
  }

  /* The message is a letter: it starts at the top of the page and may run onto a second one */
  .sign-sheet--message {
    min-height: 0;
    justify-content: flex-start;
  }
}

/* ---- Parking map (/parkhere/get-pass space step; 2026-10-30; the client dashboard's Availability
   view in the view mode since 2026-10-31) ----
   The hand-drawn map of a metered location's spaces (partials/parking-map, drawn by
   src/js/components/parking-map/: the document comes from the lookup, the stall states from
   availability). All HTML, no SVG: every drawn element is a positioned .pmap__el carrying --x / --y / --w /
   --h in document units and the stage carries --pmap-scale (the renderer's fit-to-width scale times the
   zoom step), so the GEOMETRY scales through calc() while words, icons and strokes keep their size (the
   --md-map-min-scale floor keeps a stall's number and icon on one line). Colours by role through the
   --md-map-* aliases of variables.css; two looks for a stall's availability - the free green, or ONE
   hatch, shared with a hatched building band, for a taken or closed stall (the rule sits after
   .pmap__stall so its background wins; 2026-10-31) - and a free stall outside the tag filter faded;
   nothing animates (a pick is set at once, the owner's rule). The drawing sits flat on the page at the
   section's width. An opening (an entrance, an exit, a ramp) is a gap in the wall, an icon and a small
   word just inside it, never anything outside the outline (2026-10-31). */
.pmap {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-3);
  min-width: 0;
}

.pmap__stage {
  position: relative;
}

/* The viewport is as tall as the plane at the fit scale plus the room the overlaid controls take, so the
   fit never scrolls; zooming grows the plane box inside it and the visitor pans by scrolling - a touch, the
   wheel - or, with a mouse or pen, by dragging (viewport.js, 2026-10-31); nothing on the map is text to
   select, and a drag starts on a number as often as on an aisle. At the fit the viewport scrolls sideways
   only (the --md-map-min-scale floor, where the plane is wider than the box): nothing is ever taller than
   it there, so the one vertical scrollbar it could show is the one a horizontal scrollbar's height breeds
   - which then narrowed the box, and the fit with it (2026-11-02); the horizontal scrollbar takes its
   height from the plane box's bottom padding instead. Zoomed (pmap--zoomed on the root), both axes scroll.
   No overscroll containment (2026-11-03): `contain` made the browsers stop a scroll here even with nothing
   to scroll, so the wheel and a finger swipe over the map at the fit never reached the page (the
   dashboard's card could not be scrolled past, Get Pass's step could not be swiped past). Without it the
   browsers' own latching keeps a running gesture on a zoomed map and lets the next one past its edge
   reach the page, as on every nested scroller */
.pmap__viewport {
  height: calc(var(--pmap-fit-h, 320) * 1px + 2 * (var(--md-icon-button-size) + var(--md-spacing-2)));
  overflow-x: auto;
  overflow-y: hidden;
  touch-action: pan-x pan-y;
  scrollbar-width: thin;
  user-select: none;
  -webkit-user-select: none;
}

.pmap--zoomed .pmap__viewport {
  overflow: auto;
}

/* The drag's cursors (viewport.js toggles them): the open hand only while there is something to pan -
   zoomed in, or the fit on the --md-map-min-scale floor -, the fist while a drag is live, on the stalls
   too (the browser may take the cursor from the element under the pointer rather than from the element
   that captured it). The pick mode's disabled stall is pointer-events: none, so the hand shows through
   it; the view mode's keeps the pointer for its hover title, so the fist is set on it as well */
.pmap__viewport--pannable {
  cursor: grab;
}

.pmap__viewport--panning,
.pmap__viewport--panning .pmap__stall,
.pmap__viewport--panning .pmap__stall:disabled {
  cursor: grabbing;
}

.pmap__plane-box {
  box-sizing: content-box;
  width: calc(var(--pmap-w, 0) * var(--pmap-scale, 1) * 1px);
  margin: 0 auto;
  padding: calc(var(--md-icon-button-size) + var(--md-spacing-2)) 0;
}

.pmap__plane {
  position: relative;
  width: calc(var(--pmap-w, 0) * var(--pmap-scale, 1) * 1px);
  height: calc(var(--pmap-h, 0) * var(--pmap-scale, 1) * 1px);
}

.pmap__drawing,
.pmap__stalls,
.pmap__over {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}

/* The three layers are transparent to the pointer: each stall takes it back (below), and so does a band
   with a hover - the icons-only stairs band's title -, so a hover between the stalls reaches the drawing
   (2026-10-31; the stalls layer sat over every band before and no band's title could show) */
.pmap__drawing,
.pmap__stalls,
.pmap__over {
  pointer-events: none;
}

/* Every drawn element: its document units scaled */
.pmap__el {
  position: absolute;
  box-sizing: border-box;
  left: calc(var(--x, 0) * var(--pmap-scale, 1) * 1px);
  top: calc(var(--y, 0) * var(--pmap-scale, 1) * 1px);
  width: calc(var(--w, 0) * var(--pmap-scale, 1) * 1px);
  height: calc(var(--h, 0) * var(--pmap-scale, 1) * 1px);
}

/* The lot's outline and the bands (a building, stairs) */
.pmap__frame,
.pmap__box {
  border: var(--md-map-stroke-wall) solid var(--md-map-wall);
  border-radius: var(--md-map-radius-box);
}

.pmap__box {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--md-spacing-1);
  padding: 0 var(--md-map-box-pad);
  background-color: var(--md-map-band-bg);
  color: var(--md-map-text);
  font-size: var(--md-label-medium-size);
  line-height: var(--md-label-medium-line);
  font-weight: var(--md-label-medium-weight);
  white-space: nowrap;
  overflow: visible;
}

.pmap__box--lead {
  justify-content: flex-start;
}

/* A band with a hover - the stairs band drawn icons only, its words its title - takes the pointer */
.pmap__box[title] {
  pointer-events: auto;
}

.pmap__box-icon {
  flex: 0 0 auto;
  font-size: var(--md-map-icon-size);
  line-height: 1;
}

/* A dashed centreline: its length scales, its stroke does not */
.pmap__line--x {
  border-top: var(--md-map-stroke-line) dashed var(--md-map-line);
}

.pmap__line--y {
  border-left: var(--md-map-stroke-line) dashed var(--md-map-line);
}

/* The cover over a wall where a door or an opening (an entrance, an exit, a ramp) opens: the page's own
   colour, three strokes thick */
.pmap__gap {
  background-color: var(--md-map-bg);
}

.pmap__gap--x {
  height: calc(var(--md-map-stroke-wall) * 3);
  transform: translateY(-50%);
}

.pmap__gap--y {
  width: calc(var(--md-map-stroke-wall) * 3);
  transform: translateX(-50%);
}

/* An arrow (the flow of an aisle, an opening's arrow or ramp icon): centred on its point, turned by --rot */
.pmap__icon {
  width: var(--md-map-icon-size);
  height: var(--md-map-icon-size);
  margin: calc(var(--md-map-icon-size) / -2) 0 0 calc(var(--md-map-icon-size) / -2);
  font-size: var(--md-map-icon-size);
  line-height: 1;
  color: var(--md-map-line);
  transform: rotate(var(--rot, 0deg));
}

/* An opening's icon sits on the aisle's centreline, just inside the wall: its backing stops the dashes
   under the arrow (2026-10-31) */
.pmap__icon--wall {
  color: var(--md-map-wall);
  background-color: var(--md-map-bg);
}

.pmap__text {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--md-map-text);
  font-size: var(--md-label-medium-size);
  line-height: var(--md-label-medium-line);
  font-weight: var(--md-label-medium-weight);
  white-space: nowrap;
  overflow: visible;
}

.pmap__text--muted {
  color: var(--md-map-text-muted);
}

/* An opening's word (Entrance, Exit, Ramp; 2026-10-31): the map's smallest text role, muted like a
   door's word, centred on its point like an icon with no box of its own (its room never pushes the
   frame), on a cover of the page's colour so the centreline stops under it. The .pmap__el sizes come
   from --w / --h, which an opening's word never carries: auto here */
.pmap__text--small {
  width: auto;
  height: auto;
  padding: 0 var(--md-spacing-1);
  border-radius: var(--md-shape-extra-small);
  background-color: var(--md-map-bg);
  color: var(--md-map-text-muted);
  font-size: var(--md-label-small-size);
  line-height: var(--md-label-small-line);
  font-weight: var(--md-label-small-weight);
  letter-spacing: var(--md-label-small-tracking);
  transform: translate(-50%, -50%);
}

.pmap__pillar {
  width: var(--md-map-pillar);
  height: var(--md-map-pillar);
  margin: calc(var(--md-map-pillar) / -2) 0 0 calc(var(--md-map-pillar) / -2);
  background-color: var(--md-map-line);
}

/* A stall: a real button, its number at the back edge and its icon at the aisle edge (the facing class
   sets the direction; space-between parts them); no transition on purpose */
.pmap__stall {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--md-spacing-1);
  margin: 0;
  padding: var(--md-map-stall-inset);
  border: var(--md-map-stroke-line) solid var(--md-map-stall-outline);
  border-radius: var(--md-map-radius);
  background-color: var(--md-map-free-bg);
  color: var(--md-map-text);
  font-family: inherit;
  font-size: var(--md-label-medium-size);
  line-height: var(--md-label-medium-line);
  font-weight: var(--md-label-medium-weight);
  letter-spacing: var(--md-label-medium-tracking);
  white-space: nowrap;
  overflow: hidden;
  cursor: pointer;
  pointer-events: auto;   /* the stalls layer is transparent to the pointer (above): each stall takes it back */
  transition: none;
}

.pmap__stall--e { flex-direction: row; }
.pmap__stall--w { flex-direction: row-reverse; }
.pmap__stall--s { flex-direction: column; }
.pmap__stall--n { flex-direction: column-reverse; }

.pmap__stall-label,
.pmap__stall-icon {
  flex: 0 0 auto;
}

.pmap__stall-icon {
  font-size: var(--md-map-icon-size);
  line-height: 1;
}

.pmap__stall-icon:empty {
  display: none;
}

.pmap__stall--picked {
  background-color: var(--md-map-picked-bg);
  border-color: var(--md-map-picked-bg);
  color: var(--md-map-picked-text);
  font-weight: var(--md-weight-bold);
}

/* One hatch for a hatched building band, a stall that is not available - taken or closed alike (the
   aria word tells them apart; 2026-10-31) - and the dashboard legend's Closed swatch. After .pmap__stall on purpose:
   same specificity, so this background-color beats the free green (the stall keeps its outline) */
.pmap__box--hatched,
.pmap__stall--taken,
.pmap__stall--closed,
.activity__swatch--closed {
  background-color: var(--md-map-closed-bg);
  background-image: repeating-linear-gradient(45deg, var(--md-map-closed-stripe) 0 var(--md-map-hatch-step), transparent var(--md-map-hatch-step) calc(var(--md-map-hatch-step) + var(--md-map-hatch-gap)));
}

.pmap__box--hatched .pmap__box-label {
  padding: 0 var(--md-spacing-1);
  border-radius: var(--md-shape-extra-small);
  background-color: var(--md-map-bg);
}

.pmap__stall--taken,
.pmap__stall--closed {
  color: var(--md-map-taken-text);
  cursor: default;
}

/* A free stall the tag filter leaves out: the free look (green, its tag icon), faded as the others fade
   once one is picked - the same token, one opacity, never stacked - and not tappable (2026-10-31) */
.pmap__stall--filtered {
  opacity: var(--md-map-fade-stall);
  cursor: default;
}

.pmap__stall:disabled {
  pointer-events: none;
}

.pmap__stall:focus-visible {
  outline: calc(var(--md-divider-thickness) * 2) solid var(--md-primary);
  outline-offset: calc(var(--md-spacing-1) / 2);
  z-index: 1;
}

/* Once a stall is picked, everything else steps back - set at once, no fade */
.pmap--picked .pmap__stall:not(.pmap__stall--picked) {
  opacity: var(--md-map-fade-stall);
}

.pmap--picked .pmap__drawing,
.pmap--picked .pmap__over {
  opacity: var(--md-map-fade-drawing);
}

/* ---- The view mode (the client dashboard's Availability view, 2026-10-31; bars.js draws it) ----
   A stall is a button like the pick mode's, but what it shows is the day: its reservations as bars
   across its length on a white track, the day running left to right on a stall facing east or west and
   top to bottom on one facing north or south - the same across the lot, so one eye line reads one time
   (the pick mode's reversed facings are not used here) -, a hairline at the present, and the number
   centred OVER the bars on a small backing in the track's white (--md-map-number-bg), so it always
   reads and the hairline passes under it (2026-11-01; the track comes first in the stall and the label
   span last: tree order is the stacking order, no z-index - one on a child would escape the stall,
   which is no stacking context, and climb over the overlay layer). A click selects the stall for the
   page's details panel: a green ring inside the outline - an inset shadow, under the bars and apart
   from the focus
   ring - and the number in the primary green, bold; one at a time, and nothing else fades (the bars must
   stay readable: the pick mode's pmap--picked is not set here). A closed stall keeps the hatch and still
   selects (the panel says why nothing can be done); a stall with no space, or one outside the manager's
   units (the fade), is disabled - skipped by the keyboard - and keeps its hover title. */
.pmap__stall--view {
  cursor: pointer;
}

/* The body under the bars: white, so a bar reads on neutral and "blank = free" needs no key (a hatched
   stall keeps the hatch: the two classes beat the one) */
.pmap__stall--view.pmap__stall--free,
.pmap__stall--view.pmap__stall--filtered {
  background-color: var(--md-map-track-bg);
}

/* The number: centred on the stall at the stall's own label-medium, hugging its text on a backing in the
   track's white, over the track - so it reads on a green or grey bar and vanishes into an empty track -,
   the hairline passing under it; the pointer goes through it, so the bars keep their hover titles and the
   stall its own (2026-11-01) */
.pmap__stall--view .pmap__stall-label {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  padding: 0 calc(var(--md-spacing-1) / 2);
  border-radius: var(--md-shape-extra-small-half);
  background-color: var(--md-map-number-bg);
  color: var(--md-map-text);
  pointer-events: none;   /* the bars keep their hover titles; the stall's own title shows elsewhere */
}

/* A hatched stall (closed, or no space): no backing on the hatch, the grey number as before */
.pmap__stall--view.pmap__stall--closed .pmap__stall-label {
  background-color: transparent;
  color: var(--md-map-taken-text);
}

/* A stall with no space or outside the manager's units: not selectable, but its title still answers a
   hover (the pick mode's pointer-events: none above would swallow it) */
.pmap__stall--view:disabled {
  pointer-events: auto;
  cursor: default;
}

/* The selected stall: the ring inside the outline, the number green and bold (its label rule sits after
   the hatched one above, so a selected closed stall's number is green too) */
.pmap__stall--view.pmap__stall--selected {
  border-color: var(--md-map-picked-bg);
  box-shadow: inset 0 0 0 var(--md-map-stroke-wall) var(--md-map-picked-bg);
}

.pmap__stall--view.pmap__stall--selected .pmap__stall-label {
  color: var(--md-map-picked-bg);
  font-weight: var(--md-weight-bold);
}

.pmap__track {
  position: absolute;
  inset: var(--md-map-stall-inset);
}

.pmap__bar {
  position: absolute;
  border-radius: var(--md-shape-extra-small-half);
  background-color: var(--md-map-bar-bg);
}

.pmap__bar--over {
  background-color: var(--md-map-bar-over-bg);
}

/* Along the stall's length: --from / --to are fractions of the day's axis; a 15-minute booking keeps a
   wall stroke of width */
.pmap__stall--e .pmap__bar,
.pmap__stall--w .pmap__bar {
  top: 0;
  bottom: 0;
  left: calc(var(--from, 0) * 100%);
  width: calc((var(--to, 0) - var(--from, 0)) * 100%);
  min-width: var(--md-map-stroke-wall);
}

.pmap__stall--n .pmap__bar,
.pmap__stall--s .pmap__bar {
  left: 0;
  right: 0;
  top: calc(var(--from, 0) * 100%);
  height: calc((var(--to, 0) - var(--from, 0)) * 100%);
  min-height: var(--md-map-stroke-wall);
}

/* The present: a hairline across the stall (the stall's overflow clips it at the edges) */
.pmap__now {
  position: absolute;
  background-color: var(--md-map-now);
}

.pmap__stall--e .pmap__now,
.pmap__stall--w .pmap__now {
  top: calc(-1 * var(--md-map-stall-inset));
  bottom: calc(-1 * var(--md-map-stall-inset));
  left: calc(var(--at, 0) * 100%);
  width: var(--md-map-stroke-wall);
  transform: translateX(-50%);
}

.pmap__stall--n .pmap__now,
.pmap__stall--s .pmap__now {
  left: calc(-1 * var(--md-map-stall-inset));
  right: calc(-1 * var(--md-map-stall-inset));
  top: calc(var(--at, 0) * 100%);
  height: var(--md-map-stroke-wall);
  transform: translateY(-50%);
}

/* The hint pill: top-left, top-right on a multi-level map (the picker owns the top-left), gone while zoomed */
.pmap__hint {
  position: absolute;
  top: var(--md-spacing-2);
  left: var(--md-spacing-2);
  z-index: 1;
  padding: var(--md-spacing-1) var(--md-spacing-3);
  border-radius: var(--md-shape-full);
  background-color: var(--md-surface-container-lowest);
  box-shadow: var(--md-elevation-1);
  color: var(--md-on-surface-variant);
  font-size: var(--md-label-medium-size);
  line-height: var(--md-label-medium-line);
  font-weight: var(--md-label-medium-weight);
  white-space: nowrap;
  pointer-events: none;
}

.pmap--levels .pmap__hint {
  left: auto;
  right: var(--md-spacing-2);
}

.pmap--zoomed .pmap__hint {
  display: none;
}

/* The level picker: the white-thumb segmented button, compact, lifted over the map */
.pmap__levels {
  position: absolute;
  top: var(--md-spacing-2);
  left: var(--md-spacing-2);
  z-index: 1;
}

.pmap__levels .segmented-button {
  margin-bottom: 0;
  box-shadow: var(--md-elevation-1);
}

.pmap__levels .segmented-button__item {
  padding-inline: var(--md-spacing-3);
  min-width: calc(var(--md-button-height-medium) - 2 * var(--md-segmented-pad));
}

/* The zoom: round white buttons bottom-right (the end-user app keeps the disc) */
.pmap__zoom {
  position: absolute;
  right: var(--md-spacing-2);
  bottom: var(--md-spacing-2);
  z-index: 1;
  display: flex;
  gap: var(--md-spacing-2);
}

.pmap__zoom-btn {
  background-color: var(--md-surface-container-lowest);
  color: var(--md-on-surface);
  box-shadow: var(--md-elevation-1);
}

.pmap__zoom-btn:hover {
  background-color: var(--md-surface-container-low);
}

.pmap__zoom-btn:disabled {
  opacity: var(--md-opacity-disabled);
  box-shadow: none;
  pointer-events: none;
}

/* ---- ParkHere Assistant (the client portal's AI assistant) ----
   The shared thread (partials/assistant-thread: messages, tool chips, action cards, the file panels,
   the composer), the full page (views/portal/assistant.ejs: the conversations column beside the
   thread) and the dock (partials/assistant-dock: the shell's charcoal side panel, "The dock" below).
   Every value is a token; the dock is --md-portal-dock-width wide (the extra-large component width), the
   viewport's width below 768px. z-index: the dock sits under the drawer scrim (99) and the bar (100)
   and over the page; the terms dialog inside it is a dialog like any other (2000). */
.assistant {
  display: flex;
  flex-direction: column;
  min-height: 0;
  height: 100%;
  color: var(--md-on-surface);
}

.assistant__msg:empty {
  display: none;
}

.assistant__msg {
  padding: var(--md-spacing-3) var(--md-spacing-4) 0;
}

.assistant__thread {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-3);
  padding: var(--md-spacing-4);
  scroll-behavior: smooth;
}

.assistant__thread:focus-visible {
  outline: var(--md-divider-thickness) solid var(--md-primary);
  outline-offset: calc(-1 * var(--md-divider-thickness));
}

.assistant__welcome {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-3);
  padding: var(--md-spacing-4);
  border-radius: var(--md-shape-large);
  background-color: var(--md-surface-container-low);
}

.assistant__welcome-title {
  margin: 0;
  font-size: var(--md-title-medium-size);
  line-height: var(--md-title-medium-line);
  font-weight: var(--md-title-medium-weight);
}

.assistant__welcome p {
  margin: 0;
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  color: var(--md-on-surface-variant);
}

.assistant__starters {
  display: flex;
  flex-wrap: wrap;
  gap: var(--md-spacing-2);
}

/* A starter is one line at the button height (40px, the portal's one height); a label longer than its
   host (the dock, the wizard) wraps into two lines, left-aligned, instead of spilling out of a fixed box */
.assistant__starter {
  min-height: var(--md-button-height-medium);
  max-width: 100%;
  padding: calc((var(--md-button-height-medium) - var(--md-label-large-line)) / 2) var(--md-spacing-3);
  border: var(--md-divider-thickness) solid var(--md-outline-variant);
  border-radius: var(--md-button-radius);
  background: var(--md-surface);
  color: var(--md-on-surface);
  font-size: var(--md-label-large-size);
  line-height: var(--md-label-large-line);
  font-weight: var(--md-label-large-weight);
  text-align: left;
  cursor: pointer;
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.assistant__starter:hover {
  background-color: var(--md-surface-container-high);
}

.assistant__item {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-2);
  max-width: 88%;
}

.assistant__item--user {
  align-self: flex-end;
  align-items: flex-end;
}

.assistant__item--assistant {
  align-self: flex-start;
  align-items: flex-start;
}

.assistant__bubble {
  padding: var(--md-spacing-3) var(--md-spacing-4);
  border-radius: var(--md-shape-large);
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  overflow-wrap: anywhere;
}

.assistant__item--user .assistant__bubble {
  background-color: var(--md-primary-container);
  color: var(--md-on-primary-container);
  border-bottom-right-radius: var(--md-shape-extra-small);
  white-space: pre-wrap;
}

.assistant__item--assistant .assistant__bubble {
  background-color: var(--md-surface-container-low);
  color: var(--md-on-surface);
  border-bottom-left-radius: var(--md-shape-extra-small);
}

/* base.css paints every p on-surface-variant: inside a bubble the prose takes the bubble's own colour,
   like the list items beside it (the grey paragraphs of the docked panel until 2026-10-24) */
.assistant__bubble p {
  margin: 0;
  color: inherit;
}

/* One rhythm between the blocks of an answer (paragraphs, lists, rows, headings): 8px, 12px above a
   heading, 4px under it; :not(:first-child) outranks the lists' own margin: 0 below */
.assistant__bubble > :not(:first-child) {
  margin-top: var(--md-spacing-2);
}

.assistant__bubble > :not(:first-child).assistant__h {
  margin-top: var(--md-spacing-3);
}

.assistant__bubble > .assistant__h + * {
  margin-top: var(--md-spacing-1);
}

/* Real markers: base.css resets every list to none, and a "- " or "1." line the model writes is a
   list (formatText), not an indented paragraph */
.assistant__bubble ul,
.assistant__bubble ol {
  margin: 0;
  padding-left: var(--md-spacing-5);
}

.assistant__bubble ul { list-style: disc; }
.assistant__bubble ol { list-style: decimal; }

.assistant__bubble li + li {
  margin-top: var(--md-spacing-1);
}

/* The shapes the front desk may use (lib/assistant-voice.js, drawn by assistant-format.js): a section
   heading is the site's eyebrow (marketing.css .mk-eyebrow) in the muted colour; the fact rows are the
   action cards' label / value grid at the bubble's size, the label column bounded to 40% of it; a bold
   value takes the bubble's full colour at the bold weight */
.assistant__h {
  margin: 0;
  font-size: var(--md-label-large-size);
  line-height: var(--md-label-large-line);
  font-weight: var(--md-weight-bold);
  letter-spacing: var(--md-letter-spacing-wide);
  text-transform: uppercase;
  color: var(--md-on-surface-variant);
}

.assistant__rows {
  display: grid;
  grid-template-columns: fit-content(40%) minmax(0, 1fr);
  gap: var(--md-spacing-1) var(--md-spacing-4);
  margin: 0;
}

.assistant__rows dt {
  color: var(--md-on-surface-variant);
}

.assistant__rows dd {
  margin: 0;
  color: var(--md-on-surface);
}

.assistant__bubble strong {
  font-weight: var(--md-weight-bold);
  color: var(--md-on-surface);
}

/* Two columns take the width: an item holding rows may span the thread (the bubble still fits its
   content); the compact hosts (the docked panel, the wizard) indent lists 16px */
.assistant__item--assistant:has(.assistant__rows) {
  max-width: 100%;
}

.assistant--compact .assistant__bubble ul,
.assistant--compact .assistant__bubble ol {
  padding-left: var(--md-spacing-4);
}

.assistant__bubble code {
  padding: 0 var(--md-spacing-1);
  border-radius: var(--md-shape-extra-small);
  background-color: var(--md-surface-container-high);
  font-size: var(--md-body-small-size);
}

.assistant__bubble a {
  color: var(--md-primary);
  font-weight: var(--md-label-large-weight);
}

.assistant__file {
  display: inline-flex;
  align-items: center;
  gap: var(--md-spacing-1);
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
  color: var(--md-on-surface-variant);
}

.assistant__file .material-symbols-outlined {
  font-size: var(--md-icon-size-small);
}

.assistant__chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--md-spacing-1);
}

.assistant__chip {
  display: inline-flex;
  align-items: center;
  gap: var(--md-spacing-1);
  height: var(--md-icon-size-medium);
  padding: 0 var(--md-spacing-2);
  border-radius: var(--md-shape-full);
  background-color: var(--md-secondary-container);
  color: var(--md-on-secondary-container);
  font-size: var(--md-label-medium-size);
  font-weight: var(--md-label-medium-weight);
}

.assistant__chip .material-symbols-outlined {
  font-size: var(--md-icon-size-extra-small);
}

.assistant__chip--error {
  background-color: var(--md-error-container);
  color: var(--md-on-error-container);
}

.assistant__chip--running .material-symbols-outlined {
  animation: assistant-spin var(--md-motion-duration-long) linear infinite;
}

@keyframes assistant-spin {
  to { transform: rotate(360deg); }
}

/* The front desk's opener, kept as a muted first line of the turn ("On it, let me pull up DJAF230."),
   and its status line beside the typing dots while the thinker works ("Pulling up that plate's
   history…"); the status line goes when the answer starts (assistant-chat.js liveStatus / liveDelta) */
.assistant__ack {
  margin: 0 0 var(--md-spacing-1);
  padding: 0 var(--md-spacing-1);
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
  color: var(--md-on-surface-variant);
}

.assistant__status {
  display: block;
  padding: 0 0 var(--md-spacing-1);
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
  color: var(--md-on-surface-variant);
}

/* The dots and the status line sit inside the bubble's own padding (no second 12/16px around them) */
.assistant__typing {
  display: inline-flex;
  gap: var(--md-spacing-1);
  padding: var(--md-spacing-1) 0;
}

.assistant__typing span {
  width: var(--md-spacing-2);
  height: var(--md-spacing-2);
  border-radius: var(--md-shape-full);
  background-color: var(--md-on-surface-variant);
  animation: assistant-dot var(--md-motion-duration-long) ease-in-out infinite;
}

.assistant__typing span:nth-child(2) { animation-delay: var(--md-motion-stagger-delay); }
.assistant__typing span:nth-child(3) { animation-delay: calc(var(--md-motion-stagger-delay) * 2); }

@keyframes assistant-dot {
  0%, 100% { opacity: var(--md-opacity-disabled); transform: translateY(0); }
  50% { opacity: 1; transform: translateY(calc(-1 * var(--md-spacing-1))); }
}

/* Action cards: what the assistant did or prepared, rendered from the server's record */
.assistant-card {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-3);
  padding: var(--md-spacing-4);
}

.assistant-card__head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--md-spacing-2);
}

.assistant-card__head .material-symbols-outlined {
  color: var(--md-primary);
  font-size: var(--md-icon-size-medium);
}

.assistant-card__title {
  flex: 1;
  margin: 0;
  font-size: var(--md-title-small-size);
  line-height: var(--md-title-small-line);
  font-weight: var(--md-title-small-weight);
}

/* The action card's state (assistant-chat.js cardHtml, STATUS_TONES: Waiting for your confirmation /
   Running / Done / Failed / Declined / Expired / Replaced): a status chip at the head's end; the head
   wraps, so in the dock's and the wizard's narrow threads a long state drops under the title instead
   of squeezing it, and stays at the right */
.assistant-card__status {
  margin-left: auto;
}

.assistant-card__rows {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--md-spacing-1) var(--md-spacing-4);
  margin: 0;
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
}

.assistant-card__rows dt {
  color: var(--md-on-surface-variant);
}

.assistant-card__rows dd {
  margin: 0;
  overflow-wrap: anywhere;
}

.assistant-card__secret {
  display: flex;
  align-items: center;
  gap: var(--md-spacing-2);
  padding: var(--md-spacing-2) var(--md-spacing-3);
  border-radius: var(--md-shape-small);
  background-color: var(--md-tertiary-container);
  color: var(--md-on-tertiary-container);
}

.assistant-card__secret code {
  flex: 1;
  font-size: var(--md-title-medium-size);
  letter-spacing: var(--md-letter-spacing-default);
}

/* The attached files of a conversation: rows, fixes applied, the corrected file to download */
.assistant__files {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-2);
  padding: var(--md-spacing-3) var(--md-spacing-4);
  border-radius: var(--md-shape-medium);
  border: var(--md-divider-thickness) solid var(--md-outline-variant);
  background-color: var(--md-surface);
}

.assistant__file-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--md-spacing-2);
  font-size: var(--md-body-small-size);
  line-height: var(--md-body-small-line);
}

.assistant__file-row .material-symbols-outlined {
  font-size: var(--md-icon-size-small);
  color: var(--md-on-surface-variant);
}

.assistant__file-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: var(--md-label-large-weight);
}

.assistant__file-fixes {
  width: 100%;
}

.assistant-card__actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--md-spacing-2);
}

/* The pending actions one reply prepared: stacked as one group under one Cancel / Confirm pair */
.assistant-batch {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-3);
}

.assistant-card__table {
  overflow-x: auto;
}

.assistant-card__table .data-table {
  font-size: var(--md-body-small-size);
}

.assistant-card__table .data-table__cell,
.assistant-card__table .data-table__header {
  padding: var(--md-spacing-1) var(--md-spacing-2);
}

/* The composer */
.assistant__composer {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-2);
  padding: var(--md-spacing-3) var(--md-spacing-4) var(--md-spacing-3);
  border-top: var(--md-divider-thickness) solid var(--md-outline-variant);
  background-color: var(--md-surface);
}

.assistant__attach {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-2);
}

/* The box ships hidden and opens from the paperclip; once a file is attached its drop zone and
   the Close button hide too (the chip's remove button is the way out): no display rule above may
   override [hidden] */
.assistant__attach[hidden],
.assistant__attach [hidden] {
  display: none;
}

/* A closed conversation: the composer greys out (the controls are disabled; only "New conversation" moves on) */
/* A closed conversation, or a thread the host could not start (assistant-chat.js setUnavailable: the
   terms declined, a failed status, no connection): the composer greys out */
.assistant--closed .assistant__input-row,
.assistant--closed .assistant__attach,
.assistant--unavailable .assistant__input-row,
.assistant--unavailable .assistant__attach {
  opacity: var(--md-opacity-disabled);
}

.assistant__attach-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--md-spacing-2);
}

.assistant__attach-note {
  margin: 0;
  color: var(--md-on-surface-variant);
}

.assistant__input-row {
  display: flex;
  align-items: flex-end;
  gap: var(--md-spacing-2);
}

.assistant__input-row .text-field {
  flex: 1;
  margin: 0;
}

.assistant__input-row .text-field__textarea {
  max-height: calc(var(--md-text-field-height) * 4);
}

.assistant__foot {
  margin: 0;
  color: var(--md-on-surface-variant);
}

.assistant__foot a {
  color: var(--md-primary);
}

/* The full page: conversations beside the thread from 1024px */
.assistant-page {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--md-spacing-4);
  padding-bottom: var(--md-spacing-10);
}

.assistant-page__side {
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-3);
  padding: var(--md-spacing-4);
  border: var(--md-divider-thickness) solid var(--md-outline-variant);
  border-radius: var(--md-shape-medium);
  background-color: var(--md-surface);
}

.assistant-page__side-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--md-spacing-2);
}

.assistant-page__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--md-spacing-1);
  max-height: calc(var(--md-component-width-medium) * 1.2);
  overflow-y: auto;
}

.assistant-page__row {
  display: flex;
  align-items: center;
  gap: var(--md-spacing-2);
  width: 100%;
  padding: var(--md-spacing-2) var(--md-spacing-3);
  border: none;
  border-radius: var(--md-shape-small);
  background: transparent;
  color: var(--md-on-surface);
  text-align: left;
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  cursor: pointer;
  transition: background-color var(--md-motion-duration-short) var(--md-motion-easing-standard);
}

.assistant-page__row:hover {
  background-color: var(--md-surface-container-high);
}

.assistant-page__row[aria-current="true"] {
  background-color: var(--md-secondary-container);
  color: var(--md-on-secondary-container);
}

/* The conversations column's empty line and the rows' glyphs (client-assistant.js renderList) */
.assistant-page__empty {
  padding: var(--md-spacing-2) var(--md-spacing-3);
  color: var(--md-on-surface-variant);
}

.assistant-page__row .material-symbols-outlined {
  font-size: var(--md-icon-size-small);
}

.assistant-page__row-title {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.assistant-page__row-date {
  flex: 0 0 auto;
  font-size: var(--md-body-small-size);
  color: var(--md-on-surface-variant);
}

.assistant-page__row-delete {
  flex: 0 0 auto;
}

.assistant-page__side-note {
  margin: 0;
  color: var(--md-on-surface-variant);
}

/* The header card's tagline: at the row's end, one line beside the title from the tablet tier (on a
   narrow panel the flex row wraps and the sentence drops under the title as one piece; on a phone
   it may wrap) */
.assistant-page__tagline {
  margin: 0 0 0 auto;
  color: var(--md-on-surface-variant);
  text-align: right;
}

@media (min-width: 768px) {
  .assistant-page__tagline {
    white-space: nowrap;
  }
}

.assistant-page__thread {
  display: flex;
  flex-direction: column;
  min-height: calc(var(--md-component-width-xlarge) * 0.9);
  height: calc(100vh - var(--md-portal-bar-height) - var(--md-spacing-40));
  max-height: calc(var(--md-component-width-xlarge) * 1.25);   /* a tall screen never stretches the thread past this */
  border: var(--md-divider-thickness) solid var(--md-outline-variant);
  border-radius: var(--md-shape-medium);
  background-color: var(--md-surface);
  overflow: hidden;
}

/* /portal/assistant while the account has no card on file (views/portal/assistant.ejs assistantLocked):
   one centred card instead of the conversations and the thread */
.assistant-locked__card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--md-spacing-3);
  max-width: var(--md-component-width-xlarge);
  margin-inline: auto;
  text-align: center;
}

.assistant-locked__icon {
  font-size: var(--md-step-badge-size);
  color: var(--md-primary);
}

.assistant-locked__title,
.assistant-locked__text,
.assistant-locked__note {
  margin: 0;
}

.assistant-locked__text,
.assistant-locked__note {
  color: var(--md-on-surface-variant);
}

.assistant-locked__actions {
  margin-top: var(--md-spacing-2);
}

/* ---- The dock (partials/assistant-dock, layout.ejs after </main>; assistant-dock.js) ----
   mk-section--dark on the element: the dark colour roles (variables.css) and the charcoal background
   and text (marketing.css .mk-section--dark), so the head, the thread, the composer, the cards, the
   chips, the field and the menu recolour through the tokens they already use and the dock is one
   piece with the bar, the rail and the canvas (the owner's call, 2026-10-22). Three tiers, min-width
   only like the shell: below 768px a panel under the bar across the viewport (the bar stays: its
   button closes it); 768-1599px a sheet --md-portal-dock-width wide at the right edge, over the
   page, with elevation and no scrim (the page stays readable and usable; no push there: the pages'
   breakpoints are viewport-based and the panel would be narrower than they assume); from 1600px
   (M3's extra-large window, --md-breakpoint-desktop-xl) the shell's third column, sticky under the
   bar like the rail, the content panel pushed left (layout.css animates the track). Two states on
   <body>: in the sheet tiers body--assistant-overlay (this page only, assistant-dock.js); from 1600px
   body--assistant-open (remembered: the ph_assistant_open cookie, rendered by the server, so the next
   page paints open with no jump - head.ejs's no-transitions covers the first frames). Closed is
   visibility: hidden, delayed on close so the exit plays (the drawer's idiom), never display: none:
   the thread keeps its layout (a running answer keeps streaming into it) and the closed dock is out
   of the tab order and the accessibility tree. Open is transform: none, never translateX(0): the
   thread's first-use terms dialog is position: fixed inside the dock, and a transform would make the
   dock its containing block and clip it (the floating panel did); with none it covers the viewport
   like every dialog, in the dark roles it inherits. The consent banner's strip (--ph-consent-h) is
   bottom padding: the composer stays above the banner and the charcoal runs on under it. z-index 98:
   under the drawer scrim (99) and the bar (100, whose bottom tooltips hang over the dock's head),
   over the page. */
.assistant-dock {
  position: fixed;
  inset: var(--md-portal-bar-height) 0 0 0;
  z-index: 98;
  display: flex;
  padding-bottom: var(--ph-consent-h, 0px);
  visibility: hidden;
  transform: translateX(100%);
  transition: transform var(--md-motion-duration-medium) var(--md-motion-easing-accelerate),
              visibility 0s linear var(--md-motion-duration-medium),
              padding-bottom var(--md-motion-duration-medium) var(--md-motion-easing-standard);
}

.body--assistant-overlay .assistant-dock {
  visibility: visible;
  transform: none;
  transition: transform var(--md-motion-duration-long) var(--md-motion-easing-emphasized),
              visibility 0s,
              padding-bottom var(--md-motion-duration-medium) var(--md-motion-easing-standard);
}

/* The column inside: the head, then the thread, which takes the rest and scrolls on its own. The
   chain dock (a definite height) -> panel (100%) -> .assistant (flex 1, min-height 0) ->
   .assistant__thread (overflow-y auto) gives the thread its height; the composer and the attach box
   stay out of it */
.assistant-dock__panel {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-width: 0;
  min-height: 0;
  height: 100%;
}

.assistant-dock__panel .assistant {
  flex: 1 1 auto;
  min-height: 0;
}

/* The wheel at the end of the thread never scrolls the page under the dock (the rail's rule) */
.assistant-dock .assistant__thread {
  overscroll-behavior: contain;
}

.assistant-dock__head {
  display: flex;
  align-items: center;
  gap: var(--md-spacing-2);
  padding: var(--md-spacing-2) var(--md-spacing-2) var(--md-spacing-2) var(--md-spacing-4);
  border-bottom: var(--md-divider-thickness) solid var(--md-outline-variant);
}

.assistant-dock__mark {
  color: var(--md-primary);
  font-size: var(--md-icon-size-medium);
}

.assistant-dock__title {
  flex: 1;
  margin: 0;
  font-size: var(--md-title-medium-size);
  line-height: var(--md-title-medium-line);
  font-weight: var(--md-title-medium-weight);
}

.assistant-dock__menu {
  position: relative;
}

.assistant-dock__menu-list {
  position: absolute;
  top: 100%;
  right: 0;
  min-width: var(--md-component-width-xsmall);
  padding: var(--md-spacing-2) 0;
  border-radius: var(--md-shape-small);
  background-color: var(--md-surface-container-high);
  box-shadow: var(--md-elevation-2);
  z-index: 1;
}

.assistant-dock__menu-list[hidden] {
  display: none;
}

.assistant-dock__menu-item {
  display: flex;
  align-items: center;
  gap: var(--md-spacing-2);
  width: 100%;
  padding: var(--md-spacing-2) var(--md-spacing-4);
  border: none;
  background: transparent;
  color: var(--md-on-surface);
  font-size: var(--md-body-medium-size);
  line-height: var(--md-body-medium-line);
  text-align: left;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
}

.assistant-dock__menu-item:hover {
  background-color: var(--md-surface-container-highest);
}

.assistant-dock__menu-item .material-symbols-outlined {
  font-size: var(--md-icon-size-small);
  color: var(--md-on-surface-variant);
}

/* On the charcoal the dark tonal ladder runs the other way from the light theme's: container-low
   (#1a1a1a) is darker than the surface (#1E1E1E) by a hair, so the assistant's bubbles and the
   welcome card would vanish into the dock. They step up to container-high, inline code inside them
   to highest, and the outlined action cards and the files block take container under their hairline.
   Nothing else in the thread needs a dark rule: primary, the containers, the outlines and the field
   all resolve through the dark roles. */
.assistant-dock .assistant__item--assistant .assistant__bubble,
.assistant-dock .assistant__welcome {
  background-color: var(--md-surface-container-high);
}

.assistant-dock .assistant__bubble code {
  background-color: var(--md-surface-container-highest);
}

.assistant-dock .card--outlined,
.assistant-dock .assistant__files {
  background-color: var(--md-surface-container);
}

/* The bar's assistant button (partials/header, navbar__action--assistant) reads pressed from the
   body classes per tier, so a page rendered open paints right before any script runs: the Account
   button's tonal pair ("Portal top bar" above), over its hover */
.body--assistant-overlay .site--portal .header .navbar__action--assistant,
.body--assistant-overlay .site--portal .header .navbar__action--assistant:hover {
  background-color: var(--md-secondary-container);
  color: var(--md-on-secondary-container);
}

@media (min-width: 768px) {
  .assistant-dock {
    left: auto;
    width: var(--md-portal-dock-width);
    box-shadow: var(--md-elevation-3);
  }

  /* The snackbar centres on what is left of the viewport beside the dock; .snackbar's own
     translateX(-50%) stays */
  .body--assistant-overlay .snackbar {
    left: calc(50% - var(--md-portal-dock-width) / 2);
  }
}

@media (min-width: 1600px) {
  /* The push tier: the sheet becomes the shell's third column (layout.css sizes and animates the
     track; this clips the fixed-width panel at the viewport edge while the track grows and shrinks,
     so the text never rewraps). clip, not hidden: a focus() on the composer mid-animation cannot
     scroll a clipped box sideways (there would be no scrollbar to undo it). The sheet's class means
     nothing here: a sheet opened on a narrower window is made the column by assistant-dock.js */
  .assistant-dock,
  .body--assistant-overlay .assistant-dock {
    position: sticky;
    grid-column: 3;
    grid-row: 2;
    align-self: start;                /* a grid item stretched to the row has no room to stick */
    inset: auto;
    top: var(--md-portal-bar-height);
    width: auto;                      /* the track's width, 0 while closed */
    height: calc(100vh - var(--md-portal-bar-height));
    height: calc(100svh - var(--md-portal-bar-height));
    z-index: auto;
    padding-bottom: var(--md-portal-gutter);   /* the centred consent banner never reaches this column; the composer clears the edge like the panel does */
    overflow: clip;
    box-shadow: none;
    transform: none;
    visibility: hidden;
    transition: visibility 0s linear var(--md-motion-duration-medium);   /* the track animates (layout.css); the dock hides after it */
  }

  .body--assistant-open .assistant-dock {
    visibility: visible;
    transition: visibility 0s;
  }

  .assistant-dock__panel {
    flex: 0 0 var(--md-portal-dock-width);
    width: var(--md-portal-dock-width);
  }

  .body--assistant-open .site--portal .header .navbar__action--assistant,
  .body--assistant-open .site--portal .header .navbar__action--assistant:hover {
    background-color: var(--md-secondary-container);
    color: var(--md-on-secondary-container);
  }

  .body--assistant-open .snackbar {
    left: calc(50% - var(--md-portal-dock-width) / 2);
  }
}

@media (min-width: 1024px) {
  .assistant-page {
    grid-template-columns: var(--md-component-width-small) minmax(0, 1fr);
    align-items: start;
  }

  .assistant-page__side {
    position: sticky;
    top: calc(var(--md-portal-bar-height) + var(--md-spacing-4));
  }
}

@media (prefers-reduced-motion: reduce) {
  .assistant-dock,
  .body--assistant-overlay .assistant-dock,
  .body--assistant-open .assistant-dock {
    transition: none;
  }

  .assistant__chip--running .material-symbols-outlined,
  .assistant__typing span {
    animation: none;
  }
}

@media print {
  .assistant-dock {
    display: none;
  }
}
