:root,
[data-theme="light"] {
  --pico-font-size: 100% !important;

  --pico-primary: #204349;
  --pico-primary-background: #204349;
  --pico-primary-border: var(--pico-primary-background);
  --pico-primary-underline: rgba(32, 67, 73, 0.5);
  --pico-primary-hover: #172f34;
  --pico-primary-hover-background: #172f34;
  --pico-primary-hover-border: var(--pico-primary-hover-background);
  --pico-primary-hover-underline: var(--pico-primary-hover);
  --pico-primary-focus: rgba(32, 67, 73, 0.375);
  --pico-primary-inverse: #aca9a9;

  --pico-secondary: #007a79;
  --pico-secondary-background: #007a79;
  --pico-secondary-border: var(--pico-secondary-background);
  --pico-secondary-underline: rgba(0, 122, 121, 0.5);
  --pico-secondary-hover: #005b5b;
  --pico-secondary-hover-background: #005b5b;
  --pico-secondary-hover-border: var(--pico-secondary-hover-background);
  --pico-secondary-hover-underline: var(--pico-secondary-hover);
  --pico-secondary-focus: rgba(0, 122, 121, 0.375);
  --pico-secondary-inverse: #aca9a9;

  --pico-form-element-invalid-border-color: #ff0000;
  --pico-form-element-invalid-active-border-color: #ff0000;
  --pico-form-element-invalid-focus-color: rgba(255, 0, 0, 0.375);
  --pico-form-element-valid-border-color: #27c24c;
  --pico-form-element-valid-active-border-color: #27c24c;
  --pico-form-element-valid-focus-color: rgba(39, 194, 76, 0.375);
  --pico-del-color: #ff0000;
  --pico-ins-color: #27c24c;

  --pico-danger: #ff0000;
  --pico-danger-background: #ff0000;
  --pico-danger-border: var(--pico-danger-background);
  --pico-danger-underline: rgba(255, 0, 0, 0.5);
  --pico-danger-hover: #cc0000;
  --pico-danger-hover-background: #cc0000;
  --pico-danger-hover-border: var(--pico-danger-hover-background);
  --pico-danger-hover-underline: var(--pico-danger-hover);
  --pico-danger-focus: rgba(255, 0, 0, 0.375);
  --pico-danger-inverse: #fff;

  --pico-success: #27c24c;
  --pico-success-background: #27c24c;
  --pico-success-border: var(--pico-success-background);
  --pico-success-underline: rgba(39, 194, 76, 0.5);
  --pico-success-hover: #1f9c3c;
  --pico-success-hover-background: #1f9c3c;
  --pico-success-hover-border: var(--pico-success-hover-background);
  --pico-success-hover-underline: var(--pico-success-hover);
  --pico-success-focus: rgba(39, 194, 76, 0.375);
  --pico-success-inverse: #fff;
}

@media only screen and (prefers-color-scheme: dark) {
  :root:not([data-theme]) {
    --pico-primary: #50a4b2;
    --pico-primary-background: #204349;
    --pico-primary-border: var(--pico-primary-background);
    --pico-primary-underline: rgba(80, 164, 178, 0.5);
    --pico-primary-hover: #7fc2cc;
    --pico-primary-hover-background: #2b565d;
    --pico-primary-hover-border: var(--pico-primary-hover-background);
    --pico-primary-hover-underline: var(--pico-primary-hover);
    --pico-primary-focus: rgba(80, 164, 178, 0.375);
    --pico-primary-inverse: #fff;

    --pico-secondary: #33c9c7;
    --pico-secondary-background: #007a79;
    --pico-secondary-border: var(--pico-secondary-background);
    --pico-secondary-underline: rgba(51, 201, 199, 0.5);
    --pico-secondary-hover: #5ce0de;
    --pico-secondary-hover-background: #009291;
    --pico-secondary-hover-border: var(--pico-secondary-hover-background);
    --pico-secondary-hover-underline: var(--pico-secondary-hover);
    --pico-secondary-focus: rgba(51, 201, 199, 0.375);
    --pico-secondary-inverse: #fff;

    --pico-form-element-invalid-border-color: #ff0000;
    --pico-form-element-invalid-active-border-color: #ff0000;
    --pico-form-element-invalid-focus-color: rgba(255, 0, 0, 0.375);
    --pico-form-element-valid-border-color: #27c24c;
    --pico-form-element-valid-active-border-color: #27c24c;
    --pico-form-element-valid-focus-color: rgba(39, 194, 76, 0.375);
    --pico-del-color: #ff0000;
    --pico-ins-color: #27c24c;

    --pico-success: #27c24c;
    --pico-success-background: #27c24c;
    --pico-success-border: var(--pico-success-background);
    --pico-success-underline: rgba(39, 194, 76, 0.5);
    --pico-success-hover: #1f9c3c;
    --pico-success-hover-background: #1f9c3c;
    --pico-success-hover-border: var(--pico-success-hover-background);
    --pico-success-hover-underline: var(--pico-success-hover);
    --pico-success-focus: rgba(39, 194, 76, 0.375);
    --pico-success-inverse: #fff;
  }
}

[data-theme="dark"] {
  --pico-primary: #50a4b2;
  --pico-primary-background: #204349;
  --pico-primary-border: var(--pico-primary-background);
  --pico-primary-underline: rgba(80, 164, 178, 0.5);
  --pico-primary-hover: #7fc2cc;
  --pico-primary-hover-background: #2b565d;
  --pico-primary-hover-border: var(--pico-primary-hover-background);
  --pico-primary-hover-underline: var(--pico-primary-hover);
  --pico-primary-focus: rgba(80, 164, 178, 0.375);
  --pico-primary-inverse: #fff;

  --pico-secondary: #33c9c7;
  --pico-secondary-background: #007a79;
  --pico-secondary-border: var(--pico-secondary-background);
  --pico-secondary-underline: rgba(51, 201, 199, 0.5);
  --pico-secondary-hover: #5ce0de;
  --pico-secondary-hover-background: #009291;
  --pico-secondary-hover-border: var(--pico-secondary-hover-background);
  --pico-secondary-hover-underline: var(--pico-secondary-hover);
  --pico-secondary-focus: rgba(51, 201, 199, 0.375);
  --pico-secondary-inverse: #fff;

  --pico-form-element-invalid-border-color: #ff0000;
  --pico-form-element-invalid-active-border-color: #ff0000;
  --pico-form-element-invalid-focus-color: rgba(255, 0, 0, 0.375);
  --pico-form-element-valid-border-color: #27c24c;
  --pico-form-element-valid-active-border-color: #27c24c;
  --pico-form-element-valid-focus-color: rgba(39, 194, 76, 0.375);
  --pico-del-color: #ff0000;
  --pico-ins-color: #27c24c;

  --pico-danger: #ff0000;
  --pico-danger-background: #ff0000;
  --pico-danger-border: var(--pico-danger-background);
  --pico-danger-underline: rgba(255, 0, 0, 0.5);
  --pico-danger-hover: #cc0000;
  --pico-danger-hover-background: #cc0000;
  --pico-danger-hover-border: var(--pico-danger-hover-background);
  --pico-danger-hover-underline: var(--pico-danger-hover);
  --pico-danger-focus: rgba(255, 0, 0, 0.375);
  --pico-danger-inverse: #fff;

  --pico-success: #27c24c;
  --pico-success-background: #27c24c;
  --pico-success-border: var(--pico-success-background);
  --pico-success-underline: rgba(39, 194, 76, 0.5);
  --pico-success-hover: #1f9c3c;
  --pico-success-hover-background: #1f9c3c;
  --pico-success-hover-border: var(--pico-success-hover-background);
  --pico-success-hover-underline: var(--pico-success-hover);
  --pico-success-focus: rgba(39, 194, 76, 0.375);
  --pico-success-inverse: #fff;
}

.navbarmenu {
  & ul {
    display: block;
    list-style: none;
    margin: 0;
    padding: 0;
    text-align: right;

    & li {
      display: inline-block;
    }
  }
}

.pagination-container {
  display: flex;
  gap: 5px;
  /* Space between squares */
  justify-content: center;
  /* Center the whole block */
  align-items: center;
}

.pagination-item {
  display: flex;
  justify-content: center;
  align-items: center;

  /* FORCE SQUARE SHAPE */
  width: 40px;
  /* Fixed width */
  height: 40px;
  /* Fixed height */
  aspect-ratio: 1 / 1;
  /* Ensures it stays square even if width changes */

  /* Text Styling */
  text-decoration: none;
  color: #333;
  background-color: #f0f0f0;
  border: 1px solid #ddd;
  border-radius: 4px;
  /* Optional: slightly rounded corners */
  font-weight: bold;
  font-size: 14px;
  transition: background-color 0.2s;

  /* Prevent text from breaking layout */
  white-space: nowrap;
  overflow: hidden;
}

body {
  margin: 0px;
  padding: 0px;
  height: 100vh;
  margin-left: auto;
  margin-right: auto;
  background-color: #f5f7fa;
}

.body-container {
  width: 1000px;
  margin-top: 0px;
  margin-left: auto;
  margin-right: auto;
}

/*
 * Standardized input styling, used by every form across the app
 * (macros.html renders all of them). These reproduce Bootstrap 5's
 * .form-control / .form-select look without depending on Bootstrap:
 * the templates render bare elements, so the rules target the
 * elements themselves rather than utility classes.
 *
 * Every selector below is prefixed with :root. That is not scoping —
 * it buys one class-level of specificity, which is what makes these
 * rules beat Pico's own form rules instead of merely tying them. Keep
 * the prefix on anything added here, or Pico wins and the rule looks
 * like it was ignored.
 *
 * Colors go through the custom properties below, so a state (focus,
 * disabled, aria-invalid) only has to redefine the variable.
 */
:root {
  --form-control-padding-y: 0.375rem;
  --form-control-padding-x: 0.75rem;
  --form-control-font-size: 1rem;
  --form-control-radius: 0.375rem;
  --form-control-color: #212529;
  --form-control-bg: #fff;
  --form-control-border-color: #dee2e6;
  --form-control-placeholder-color: #6c757d;
  --form-control-disabled-bg: #e9ecef;
  --form-control-focus-border-color: #86b7fe;
  --form-control-focus-shadow-color: rgba(13, 110, 253, 0.25);
}

/* Text-ish inputs, selects and textareas: Bootstrap's .form-control. */
:root input:not(
    [type="checkbox"],
    [type="radio"],
    [type="range"],
    [type="file"],
    [type="submit"],
    [type="button"],
    [type="reset"]
  ),
:root select,
:root textarea {
  /*
   * Pico pins an explicit height on inputs, which made them taller
   * than the selects; Bootstrap lets the padding size the control.
   */
  height: auto;
  padding: var(--form-control-padding-y) var(--form-control-padding-x);
  font-family: inherit;
  font-size: var(--form-control-font-size);
  font-weight: 400;
  line-height: 1.5;
  color: var(--form-control-color);
  background-color: var(--form-control-bg);
  background-clip: padding-box;
  border: 1px solid var(--form-control-border-color);
  border-radius: var(--form-control-radius);
  box-shadow: none;
  transition:
    border-color 0.15s ease-in-out,
    box-shadow 0.15s ease-in-out;
}

:root input::placeholder,
:root textarea::placeholder {
  color: var(--form-control-placeholder-color);
  opacity: 1;
}

:root input:not(
    [type="checkbox"],
    [type="radio"],
    [type="range"],
    [type="file"],
    [type="submit"],
    [type="button"],
    [type="reset"]
  ):focus,
:root select:not([readonly]):focus,
:root textarea:not([readonly]):focus {
  --form-control-border-color: var(--form-control-focus-border-color);
  color: var(--form-control-color);
  background-color: var(--form-control-bg);
  box-shadow: 0 0 0 0.25rem var(--form-control-focus-shadow-color);
  outline: 0;
}

/*
 * Validation states. Pico already flips these on [aria-invalid] (which
 * is what the form templates set) and draws the check/cross icon; only
 * the colors move to Bootstrap's danger/success.
 *
 * The padding rule is the one place that still needs !important: Pico
 * marks the room it reserves for the validation icon as !important, so
 * without this the text jumps sideways when a field turns invalid.
 */
:root :is(input, select, textarea):not([type="checkbox"], [type="radio"])[aria-invalid] {
  padding-inline-start: var(--form-control-padding-x) !important;
}

:root [aria-invalid="true"] {
  --form-control-border-color: #dc3545;
  --form-control-focus-border-color: #dc3545;
  --form-control-focus-shadow-color: rgba(220, 53, 69, 0.25);
}

:root [aria-invalid="false"] {
  --form-control-border-color: #198754;
  --form-control-focus-border-color: #198754;
  --form-control-focus-shadow-color: rgba(25, 135, 84, 0.25);
}

:root fieldset[disabled]
  :is(
    input:not([type="submit"], [type="button"], [type="reset"]),
    select,
    textarea
  ),
:root input:not([type="submit"], [type="button"], [type="reset"])[disabled],
:root select[disabled],
:root textarea[disabled] {
  background-color: var(--form-control-disabled-bg);
  opacity: 1;
}

:root input:not(
    [type="checkbox"],
    [type="radio"],
    [type="range"],
    [type="file"],
    [type="submit"],
    [type="button"],
    [type="reset"]
  )[readonly],
:root select[readonly],
:root textarea[readonly] {
  background-color: var(--form-control-disabled-bg);
}

/*
 * Bootstrap's .form-select: its own chevron on the right, with room
 * reserved for it. Pico draws one too, so this replaces the image and
 * the padding it reserved rather than stacking on top of it.
 */
:root select:not([multiple], [size]) {
  padding-left: var(--form-control-padding-x);
  padding-inline-start: var(--form-control-padding-x);
  padding-right: 2.25rem;
  padding-inline-end: 2.25rem;
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
  background-repeat: no-repeat;
  background-position: right var(--form-control-padding-x) center;
  background-size: 16px 12px;
  appearance: none;
}

/*
 * Bootstrap leaves [type=search] looking like any other text input,
 * while Pico gives it a magnifier and a pill radius. Inputs flagged
 * by validation keep their icon.
 */
:root input:not([type="checkbox"], [type="radio"], [type="range"], [type="file"])[type="search"]:not([aria-invalid]) {
  padding-inline-start: var(--form-control-padding-x);
  background-image: none;
}

:root [type="search"] {
  --pico-border-radius: var(--form-control-radius);
}

:root textarea {
  min-height: calc(1.5em + (var(--form-control-padding-y) * 2) + 2px);
  resize: vertical;
}

/* Bootstrap's .form-control-sm / .form-control-lg sizes. */
:root :is(input, select, textarea).form-control-sm {
  --form-control-padding-y: 0.25rem;
  --form-control-padding-x: 0.5rem;
  --form-control-font-size: 0.875rem;
  --form-control-radius: 0.25rem;
}

:root :is(input, select, textarea).form-control-lg {
  --form-control-padding-y: 0.5rem;
  --form-control-padding-x: 1rem;
  --form-control-font-size: 1.25rem;
  --form-control-radius: 0.5rem;
}

button,
[type="submit"],
[type="button"],
[role="button"] {
  border-radius: 0.6rem;
  font-size: 14px !important;
  padding: 5px;
}

/*
 * Button variants, usable on <button>, [type=submit/button] and
 * [role=button] links/spans anywhere in the app. .btn-primary and
 * .btn-secondary just make Pico's default/.secondary look explicit;
 * .btn-danger is new and should be used for destructive actions
 * (delete, revoke, etc.) so they read as visually distinct.
 */
:is(button, [type="submit"], [type="button"], [role="button"]).btn-primary {
  --pico-background-color: var(--pico-primary-background);
  --pico-border-color: var(--pico-primary-border);
  --pico-color: var(--pico-primary-inverse);
}

:is(button, [type="submit"], [type="button"], [role="button"]).btn-primary:is(
    [aria-current]:not([aria-current="false"]),
    :hover,
    :active,
    :focus
  ) {
  --pico-background-color: var(--pico-primary-hover-background);
  --pico-border-color: var(--pico-primary-hover-border);
  --pico-color: var(--pico-primary-inverse);
}

:is(button, [type="submit"], [type="button"], [role="button"]).btn-primary:focus {
  --pico-box-shadow: 0 0 0 var(--pico-outline-width) var(--pico-primary-focus);
}

:is(button, [type="submit"], [type="button"], [role="button"]).btn-secondary {
  --pico-background-color: var(--pico-secondary-background);
  --pico-border-color: var(--pico-secondary-border);
  --pico-color: var(--pico-secondary-inverse);
}

:is(button, [type="submit"], [type="button"], [role="button"]).btn-secondary:is(
    [aria-current]:not([aria-current="false"]),
    :hover,
    :active,
    :focus
  ) {
  --pico-background-color: var(--pico-secondary-hover-background);
  --pico-border-color: var(--pico-secondary-hover-border);
  --pico-color: var(--pico-secondary-inverse);
}

:is(button, [type="submit"], [type="button"], [role="button"]).btn-secondary:focus {
  --pico-box-shadow: 0 0 0 var(--pico-outline-width) var(--pico-secondary-focus);
}

:is(button, [type="submit"], [type="button"], [role="button"]).btn-danger {
  --pico-background-color: var(--pico-danger-background);
  --pico-border-color: var(--pico-danger-border);
  --pico-color: var(--pico-danger-inverse);
}

:is(button, [type="submit"], [type="button"], [role="button"]).btn-danger:is(
    [aria-current]:not([aria-current="false"]),
    :hover,
    :active,
    :focus
  ) {
  --pico-background-color: var(--pico-danger-hover-background);
  --pico-border-color: var(--pico-danger-hover-border);
  --pico-color: var(--pico-danger-inverse);
}

:is(button, [type="submit"], [type="button"], [role="button"]).btn-danger:focus {
  --pico-box-shadow: 0 0 0 var(--pico-outline-width) var(--pico-danger-focus);
}

:is(button, [type="submit"], [type="button"], [role="button"]).btn-success {
  --pico-background-color: var(--pico-success-background);
  --pico-border-color: var(--pico-success-border);
  --pico-color: var(--pico-success-inverse);
}

:is(button, [type="submit"], [type="button"], [role="button"]).btn-success:is(
    [aria-current]:not([aria-current="false"]),
    :hover,
    :active,
    :focus
  ) {
  --pico-background-color: var(--pico-success-hover-background);
  --pico-border-color: var(--pico-success-hover-border);
  --pico-color: var(--pico-success-inverse);
}

:is(button, [type="submit"], [type="button"], [role="button"]).btn-success:focus {
  --pico-box-shadow: 0 0 0 var(--pico-outline-width) var(--pico-success-focus);
}

.main {
  padding: 2rem 2.5rem;
}

/*
 * App shell: a fixed icon sidebar (primary color background, white
 * icons) plus the page content next to it. Only rendered once the
 * user is authenticated — logged-out visitors just see login.html.
 *
 * The shell itself is pinned to the viewport height and .app-content
 * is the one scrollable region, so long lists/tables scroll inside
 * the content area instead of overflowing past the sidebar and
 * breaking the layout.
 */
.app-shell {
  display: flex;
  height: 100vh;
  overflow: hidden;
}

.app-content {
  flex: 1;
  min-width: 0;
  height: 100vh;
  overflow-y: auto;
}

.sidebar {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex-shrink: 0;
  width: 72px;
  padding: 1.5rem 0;
  gap: 1.5rem;
  background: var(--pico-primary-background);
  position: sticky;
  top: 0;
  height: 100vh;
}

.sidebar-nav,
.sidebar-nav ul {
  width: 100%;
}

/*
 * Pico's `nav ul:first-of-type`/`:last-of-type` rules offset the
 * list with a negative margin (to compensate for its own `nav li`
 * padding) and beat a plain `.sidebar-nav ul` selector on specificity
 * (the :first-of-type/:last-of-type pseudo-classes count same as a
 * class). !important is the reliable way to win that fight.
 */
.sidebar-nav ul {
  list-style: none;
  margin: 0 !important;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0;
}

/*
 * Pico's `aside li` rule (from its off-canvas nav component) adds
 * horizontal padding to every <li> inside an <aside>, which is where
 * the extra right-hand gap on each row came from. Override it with
 * !important since it's the only reliable way to beat a rule that
 * targets the same elements this generically.
 */
.sidebar-nav li {
  width: 100%;
  margin: 0 !important;
  padding: 0 !important;
  box-sizing: border-box;
}

.sidebar-bottom {
  margin-top: auto;
}

.sidebar-link {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 44px;
  margin: 0 !important;
  padding: 0 !important;
  box-sizing: border-box;
  border-radius: 0;
  color: #fff;
  transition: background-color 0.15s ease, color 0.15s ease;
}

.sidebar-link:hover {
  background-color: rgba(255, 255, 255, 0.15);
}

.sidebar-link img,
.sidebar-link svg {
  width: 24px;
  height: 24px;
  object-fit: contain;
}

/*
 * Icons ship as white-on-transparent SVG/PNG assets. Rendering them
 * as a mask (rather than <img>) lets currentColor drive their fill,
 * so the same asset can switch from white to the primary color for
 * the active nav item without needing a second colored file.
 */
.sidebar-icon {
  display: inline-block;
  width: 24px;
  height: 24px;
  background-color: currentColor;
  -webkit-mask-image: var(--icon-url);
  mask-image: var(--icon-url);
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
}

/* Active section: full-width white bar, icon tinted in the primary color. */
.sidebar-link.active {
  background-color: #fff;
  color: var(--pico-primary-background);
}

.sidebar-link.active:hover {
  background-color: #fff;
}

/*
 * Tooltip: shows the section title on hover, always to the right of
 * the icon. Uses a dedicated data-nav-tooltip attribute (not Pico's
 * own data-tooltip) because Pico ships a built-in tooltip component
 * on [data-tooltip] that positions itself above the element via
 * ::before — reusing that attribute made both tooltips fire at once
 * and fight over placement.
 */
.sidebar-link[data-nav-tooltip]::after {
  content: attr(data-nav-tooltip);
  position: absolute;
  left: 100%;
  top: 50%;
  margin-left: 0.1rem;
  transform: translateY(-50%);
  background: #646363;
  color: #fff;
  padding: 0.3rem 0.65rem;
  border-radius: 0.35rem;
  font-size: 0.75rem;
  white-space: nowrap;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.15s ease;
  z-index: 1000;
}

.sidebar-link[data-nav-tooltip]:hover::after,
.sidebar-link[data-nav-tooltip]:focus-visible::after {
  opacity: 1;
  visibility: visible;
  text-decoration: none;
}

/* Login page: no card, no background — just the centered form. */
.login {
  background: transparent;
  box-shadow: none;
  border: none;
  max-width: 420px;
  margin: 6rem auto;
  padding: 0;
  text-align: center;
  height: 75vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.login .image {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.login .login-logo {
  max-width: 320px;
  width: 100%;
  margin-bottom: 2rem;
}

.login form {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 1rem;
}

/*
 * List page layout: header (title + primary action) above a plain
 * card holding a decorative filter bar, a data table and pagination.
 */
.list-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1.5rem;
}

.list-header h1 {
  margin: 0;
  font-size: 1.75rem;
  color: #2c3e50;
}

/*
 * The card keeps a tall minimum height even with few rows, mirroring
 * the mockup: the table area grows and pushes the pagination footer
 * to the bottom edge.
 */
.list-card {
  background: #fff;
  border: 1px solid #e5e9f0;
  border-radius: 0.75rem;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  min-height: 65vh;
}

.list-card .overflow-auto {
  flex: 1;
}

.list-card .pagination-footer {
  margin-top: auto;
}

.list-filter-bar {
  padding: 1.25rem 1.5rem;
}

.list-filter-bar input {
  max-width: 260px;
  margin-bottom: 0;
}

.list-table {
  width: 100%;
  border-collapse: collapse;
}

.list-table th {
  text-align: left;
  padding: 0.85rem 1.5rem;
  font-size: 0.85rem;
  color: #8891a4;
  font-weight: 600;
  background-color: #fff;
  border-top: 1px solid #eef1f5;
  border-bottom: 1px solid #eef1f5;
}

.list-table td {
  padding: 1.4rem 1.5rem;
  color: #2c3e50;
  background-color: #fff;
  border-bottom: 1px solid #eef1f5;
  vertical-align: middle;
}

.list-table tbody tr:last-child td {
  border-bottom: none;
}

.list-table .actions-col {
  width: 1%;
  white-space: nowrap;
}

.list-table tbody tr[data-event-category] td {
  color: #fff;
  border-bottom-color: rgba(255, 255, 255, 0.2);
  background-color: var(--event-category-color);
}

.list-table tbody tr[data-event-category="system"] {
  --event-category-color: #a3a7a7;
}

.list-table tbody tr[data-event-category="gateway"] {
  --event-category-color: #4d6f76;
}

.list-table tbody tr[data-event-category="device"] {
  --event-category-color: #14453f;
}

.list-filter-bar select {
  max-width: 220px;
  margin-bottom: 0;
}

.copy-text {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

.copy-text button {
  display: inline-flex;
  flex-shrink: 0;
  background: none;
  border: none;
  margin: 0;
  padding: 0;
  cursor: pointer;
  width: 16px;
}

/*
 * Generic "copied!" tooltip: hidden by default, shown briefly by
 * copy-to-clipboard.js toggling .is-visible on click (not hover,
 * since the feedback needs to appear without waiting for a hover).
 */
[data-copy-text] {
  position: relative;
}

[data-copy-text]::after {
  content: "¡Copiado!";
  position: absolute;
  bottom: 100%;
  left: 50%;
  margin-bottom: 0.4rem;
  transform: translateX(-50%);
  background: #646363;
  color: #fff;
  padding: 0.3rem 0.65rem;
  border-radius: 0.35rem;
  font-size: 0.75rem;
  white-space: nowrap;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.15s ease;
  z-index: 1000;
}

[data-copy-text].is-visible::after {
  opacity: 1;
  visibility: visible;
}

.icon-actions {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.icon-actions a,
.icon-actions button {
  display: inline-flex;
  background: none;
  border: none;
  margin: 0;
  padding: 0;
  cursor: pointer;
  width: 20px;
}

.icon-actions form {
  display: inline-flex;
  align-items: center;
  margin: 0;
}

.icon-actions [type="checkbox"][role="switch"] {
  margin: 0;
}

/*
 * Switch: white track with a light border when off, primary color
 * when on. The thumb is white in both states, so it needs a shadow
 * to stay visible against the white unchecked track.
 */
[type="checkbox"][role="switch"] {
  --pico-switch-background-color: #fff;
  --pico-switch-checked-background-color: var(--pico-primary-background);
  --pico-switch-thumb-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
}

[type="checkbox"][role="switch"]:not(:checked),
[type="checkbox"][role="switch"]:not(:checked):focus {
  --pico-border-color: #d7dce2;
}

/* Switch label whose text mirrors the state (see input_switch macro). */
.switch-label .switch-text-on,
.switch-label input:checked ~ .switch-text-off {
  display: none;
}

.switch-label input:checked ~ .switch-text-on {
  display: inline;
}

.list-card .pagination-footer {
  padding: 1rem 1.5rem;
  border-top: 1px solid #eef1f5;
}

/*
 * Delete confirmation popover, opened from the trash icon via the
 * native Popover API. Positioning next to the trigger button (rather
 * than centered) is handled by popover-anchor.js — inset/margin are
 * reset here so the script's top/left take effect.
 *
 * It starts hidden (opacity/scale) and popover-anchor.js only adds
 * .is-visible after it has already set left/top, so the fade-in
 * transition plays from the *correct* spot instead of flashing at
 * the browser's default top-left position first.
 */
.confirm-popover {
  position: fixed;
  inset: auto;
  margin: 0;
  background-color: #fff;
  color: #2c3e50;
  border: 1px solid #e5e9f0;
  border-radius: 0.85rem;
  padding: 1.5rem;
  width: 320px;
  overflow: visible;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.18);
  opacity: 0;
  transform: scale(0.94) translateY(6px);
  transition:
    opacity 0.16s ease,
    transform 0.16s ease;
}

.confirm-popover.is-visible {
  opacity: 1;
  transform: scale(1) translateY(0);
}

.confirm-popover-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 0.85rem;
}

.confirm-popover-header strong {
  color: #2c3e50;
  font-size: 1.1rem;
}

.confirm-popover-header img {
  width: 18px;
  height: 18px;
}

.confirm-popover p {
  margin: 0 0 1.4rem;
  color: #8891a4;
  font-size: 0.95rem;
  line-height: 1.45;
  text-align: center;
}

.confirm-popover form {
  margin: 0;
}

.confirm-popover form input {
  width: 100%;
  margin-bottom: 0.85rem !important;
}

.confirm-popover-confirm {
  display: block;
  width: 100%;
  margin-bottom: 0.75rem;
}

.confirm-popover-cancel {
  display: block;
  width: 100%;
  background: none;
  border: none;
  padding: 0;
  color: #8891a4;
  text-decoration: underline;
  text-align: center;
  font-size: 0.85rem;
  cursor: pointer;
}

/* Detail/edit form page: back link + title, centered card below. */
.detail-header {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 2rem;
}

.detail-header h1 {
  margin: 0;
  font-size: 1.5rem;
  color: #2c3e50;
}

.detail-back {
  display: inline-flex;
  color: #2c3e50;
}

.detail-form-wrapper {
  height: 65vh;
  display: flex;
  align-items: center;
  justify-content: center;
}

.detail-form-card {
  background: #fff;
  border: 1px solid #e5e9f0;
  border-radius: 0.85rem;
  padding: 2rem;
  width: 100%;
  max-width: 360px;
}

.detail-form-card form {
  display: flex;
  flex-direction: column;
}

/* Pico's [role="group"] joins inputs edge-to-edge like a segmented
   control; the device form just uses it for a row layout, so give
   each field breathing room instead. */
.detail-form-card fieldset[role="group"] {
  gap: 1.25rem;
}

.detail-form-card fieldset[role="group"] > * {
  margin-bottom: 0;
}

/* These groups are just a row layout now (see the gap override
   above), not Pico's joined-input control, so skip the box-shadow
   Pico draws around the whole group when a child gets focus. */
.detail-form-card fieldset[role="group"]:has(:focus) {
  --pico-group-box-shadow: 0 0 0 transparent;
}

.detail-form-card button[type="submit"] {
  margin-top: 0.5rem;
}

/*
 * Long forms (device detail): a wider card that starts at the top and
 * grows with the content instead of centering inside 65vh.
 */
.detail-form-wrapper.detail-form-tall {
  height: auto;
  align-items: flex-start;
  margin: 2rem 0 3rem;
}

.detail-form-card.detail-form-wide {
  max-width: 780px;
}

.detail-form-card hr {
  margin: 0.25rem 0;
}

.detail-section-title {
  margin: 0;
  color: #2c3e50;
  font-weight: 600;
}

/* Inline radio options (e.g. device type), no fieldset chrome. */
.radio-row {
  display: flex;
  gap: 2rem;
  margin: 0;
  padding: 0;
  border: 0;
}

.radio-row legend {
  margin-bottom: 0.5rem;
  color: #2c3e50;
  font-weight: 600;
}

.radio-row label {
  margin: 0;
}

/* Device type: accent the radio in success green instead of the
   default primary color (accent-color reads --pico-primary). */
.radio-row-success input[type="radio"] {
  --pico-primary: var(--pico-success);
}

/* Row of state switches (enabled/power, alerts). */
.switch-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 2.5rem;
}

.switch-row .switch-label {
  margin: 0;
  white-space: nowrap;
}

/* Alerts: fixed 2-column grid instead of the wrapping row, so pairs
   line up (battery/panel, dispenser/sprinkle, communication/reset). */
.switch-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0.75rem 2.5rem;
}

.switch-grid .switch-label {
  margin: 0;
  white-space: nowrap;
}

/* Muted "delete this X" text action under a detail form; the actual
   confirmation happens in the confirm-popover it opens. */
.detail-delete-link {
  display: block;
  width: 100%;
  margin-top: 1.25rem;
  background: none;
  border: none;
  padding: 0;
  color: var(--pico-danger);
  text-decoration: underline;
  text-align: center;
  font-size: 0.85rem;
  cursor: pointer;
}

/* Flat, minimal pagination: no boxes/outlines, just muted numbers
   with the active page in bold dark text and light arrows either side. */
.pagination-nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1.75rem;
  padding: 1rem 0;
}

.pagination-arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: #8891a4;
  text-decoration: none;
  cursor: pointer;
}

.pagination-arrow:hover {
  color: #2c3e50;
}

.pagination-arrow.is-disabled {
  color: #d7dce2;
  pointer-events: none;
}

.pagination-page {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.5rem;
  color: #c3c9d4;
  font-size: 0.95rem;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
}

.pagination-page:hover {
  color: #2c3e50;
}

.pagination-page.is-active {
  color: #2c3e50;
}

/*
 * Farms module (pond list): farm selector in the header, pill-shaped
 * search box and the pond card grid inside the list card.
 */
.farm-select-group {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.farm-select {
  width: 240px;
  margin-bottom: 0;
}

/* Square button sized to sit next to the farm select. */
.farm-manage-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  border-radius: 0.35rem;
  background-color: var(--pico-primary-background);
  color: #fff;
  transition: opacity 0.15s ease;
}

.farm-manage-link:hover {
  opacity: 0.85;
}

.farm-manage-icon {
  display: inline-block;
  width: 20px;
  height: 20px;
  background-color: currentColor;
  -webkit-mask-image: var(--icon-url);
  mask-image: var(--icon-url);
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
}

.pond-search input {
  width: 100%;
  max-width: 320px;
}

/*
 * align-content: start keeps a lone row of cards at its natural
 * height — flex: 1 makes the grid fill the tall list card so the
 * pagination footer stays pinned to the bottom edge.
 */
.pond-grid {
  flex: 1;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
  gap: 1.25rem;
  align-content: start;
  padding: 0.5rem 1.5rem 1.5rem;
}

.pond-card {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  min-height: 170px;
  padding: 1rem;
  border-radius: 0.35rem;
  background-color: #a5a5a5;
  color: #fff;
  text-align: center;
  text-decoration: none;
  transition: background-color 0.15s ease;
}

.pond-card:hover {
  background-color: #949494;
  text-decoration: none;
}

.pond-card strong {
  font-size: 0.95rem;
}

.pond-card span {
  font-size: 0.85rem;
}

.pond-card-create {
  background-color: var(--pico-primary-background);
  font-size: 1.75rem;
  font-weight: 700;
}

/* Edit/delete icons pinned to the card's top-right corner. Icons use
   the same mask technique as .sidebar-icon so the white assets take
   their color from currentColor. */
.pond-card-actions {
  position: absolute;
  top: 0.6rem;
  right: 0.6rem;
  display: flex;
  gap: 0.5rem;
}

.pond-card-actions a,
.pond-card-actions button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  margin: 0;
  padding: 0;
  cursor: pointer;
}

.pond-card-icon {
  display: inline-block;
  width: 16px;
  height: 16px;
  background-color: white;
  -webkit-mask-image: var(--icon-url);
  mask-image: var(--icon-url);
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
}

/*
 * Pond devices view: back + pond name on the left, "Dispositivos"
 * with the feeder/waterwise tabs on the right, then a grid with the
 * add card and one card per linked device.
 */
.devices-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  margin: 60px 0;
}

.devices-header .detail-header {
  margin-bottom: 0;
}

.devices-tabs {
  text-align: right;
}

.devices-tabs strong {
  display: block;
  color: #2c3e50;
  margin-bottom: 0.6rem;
}

/* Compact nav_tabs variant inside the pond devices header: hugs the
   right edge instead of spanning the page. */
.devices-tabs .nav-root {
  width: auto;
  display: inline-flex;
  margin-bottom: 0;
}

.devices-tabs .nav-item {
  padding: 10px 18px;
  font-size: 0.85rem;
}

.device-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 1.25rem;
  align-content: start;
}

/* The add card is a <button> (it opens the popover), so undo Pico's
   button chrome; its font-size rule is !important, hence this one. */
.device-add-card {
  border: none;
  min-height: 170px;
  font-size: 1.75rem !important;
}

.device-card {
  background: #e9e9e9;
  border-radius: 0.5rem;
  padding: 1.25rem 1rem;
  display: flex;
  flex-direction: column;
  text-align: center;
}

.device-card > strong {
  color: #2c3e50;
  font-size: 0.9rem;
}

.device-card-sub {
  color: #8891a4;
  font-size: 0.8rem;
  margin-bottom: 1rem;
}

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

.device-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: #fff;
  border-radius: 999px;
  padding: 0.3rem 0.4rem 0.3rem 0.85rem;
  font-size: 0.75rem;
  color: #2c3e50;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
  min-height: 26px;
}

.device-row-status {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}

.device-row-value {
  border: 1px solid #d7dce2;
  border-radius: 999px;
  padding: 0.05rem 0.6rem;
  font-size: 0.7rem;
  color: #8891a4;
  background: #fff;
}

.device-dot {
  width: 15px;
  height: 15px;
  border-radius: 50%;
}

.device-dot.ok {
  background: var(--pico-success);
}

.device-dot.bad {
  background: var(--pico-danger);
}

/*
 * Horizontal tab menu at the top of the device list card. Tabs keep a
 * single row with horizontal scroll on narrow screens instead of
 * wrapping; the active tab uses the dark brand background.
 */
.nav-root {
  display: flex;
  width: 100%;
  background-color: #fff;
  border-bottom: 1px solid #e9ecef;
  margin-bottom: 1rem;
  overflow-x: auto;
  white-space: nowrap;
}

.nav-item {
  padding: 15px 25px;
  cursor: pointer;
  color: #555;
  font-weight: 500;
  position: relative;
  flex: 0 0 auto;
  transition: all 0.3s ease;
}

.nav-item:hover {
  background-color: #d5d5d5;
}

.nav-item.active {
  background-color: #184048;
  color: #fff;
}

.nav-item.active:hover {
  background-color: #0f2d33;
}

@media (max-width: 768px) {
  .nav-root {
    flex-wrap: nowrap;
  }

  .nav-item {
    width: auto;
  }
}

.list-filter-bar form {
  display: flex;
  gap: 1rem;
  margin: 0;
}

.location-cell {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  font-size: 0.85rem;
  white-space: nowrap;
}

/*
 * Live events panel (live-events.html + live-events.js): floating
 * chat-like feed pinned to the bottom-right corner of every
 * authenticated page. Color code per event category: gray = system,
 * primary = device, secondary = gateway. The status dot doubles as
 * the SSE connection indicator (live / reconnecting / down) and is
 * shown both on the collapsed bubble and inside the panel header.
 */
.live-events {
  position: fixed;
  right: 1.5rem;
  bottom: 1.5rem;
  z-index: 1200;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.75rem;
}

.live-events-toggle {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  border-radius: 50% !important;
  border: none;
  margin: 0;
  background: var(--pico-primary-background);
  color: #fff;
  cursor: pointer;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
}

.live-events-toggle:hover {
  background: var(--pico-primary-hover-background);
}

.live-events-badge {
  position: absolute;
  top: -4px;
  right: -4px;
  min-width: 20px;
  height: 20px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--pico-danger-background);
  color: #fff;
  font-size: 0.7rem;
  font-weight: 700;
  line-height: 20px;
  text-align: center;
  box-sizing: border-box;
}

/* Connection indicator: green pulsing = live, amber = reconnecting,
   red = down. On the bubble it sits on the bottom-right edge. */
.live-events-status-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
}

.live-events-toggle .live-events-status-dot {
  position: absolute;
  bottom: 2px;
  right: 2px;
  border: 2px solid #fff;
  width: 12px;
  height: 12px;
}

.live-events-status-dot[data-status="live"] {
  background: var(--pico-success);
  animation: live-events-pulse 2s ease-out infinite;
}

.live-events-status-dot[data-status="reconnecting"] {
  background: #f0ad4e;
}

.live-events-status-dot[data-status="down"] {
  background: var(--pico-danger);
}

@keyframes live-events-pulse {
  0% {
    box-shadow: 0 0 0 0 rgba(39, 194, 76, 0.55);
  }
  70% {
    box-shadow: 0 0 0 7px rgba(39, 194, 76, 0);
  }
  100% {
    box-shadow: 0 0 0 0 rgba(39, 194, 76, 0);
  }
}

.live-events-panel {
  display: flex;
  flex-direction: column;
  width: 340px;
  max-width: calc(100vw - 3rem);
  max-height: min(480px, calc(100vh - 9rem));
  background: #fff;
  border: 1px solid #e5e9f0;
  border-radius: 0.85rem;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.18);
  overflow: hidden;
}

.live-events-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.85rem 1rem;
  border-bottom: 1px solid #eef1f5;
}

.live-events-title {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}

.live-events-title strong {
  color: #2c3e50;
  font-size: 0.95rem;
}

.live-events-status {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}

.live-events-status-label {
  color: #8891a4;
  font-size: 0.75rem;
}

.live-events-close {
  display: inline-flex;
  background: none;
  border: none;
  margin: 0;
  padding: 0.25rem;
  color: #8891a4;
  cursor: pointer;
}

.live-events-close:hover {
  color: #2c3e50;
}

.live-events-feed {
  flex: 1;
  overflow-y: auto;
  list-style: none;
  margin: 0;
  padding: 0;
}

.live-events-empty {
  margin: 0;
  padding: 1.25rem 1rem;
  color: #8891a4;
  font-size: 0.85rem;
  text-align: center;
}

.live-events-item {
  border-bottom: 1px solid #eef1f5;
}

.live-events-item:last-child {
  border-bottom: none;
}

/* Per-category accent color, consumed by the dot and the expanded
   detail's left border. */
.live-events-cat-system {
  --live-events-cat-color: #8891a4;
}

.live-events-cat-device {
  --live-events-cat-color: var(--pico-primary);
}

.live-events-cat-gateway {
  --live-events-cat-color: var(--pico-secondary);
}

.live-events-row {
  display: flex;
  align-items: flex-start;
  gap: 0.65rem;
  padding: 0.7rem 1rem;
}

.live-events-cat-dot {
  width: 10px;
  height: 10px;
  margin-top: 0.3rem;
  border-radius: 50%;
  flex-shrink: 0;
  background: var(--live-events-cat-color);
}

.live-events-body {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  min-width: 0;
}

.live-events-message {
  color: #2c3e50;
  font-size: 0.85rem;
  line-height: 1.35;
  overflow-wrap: anywhere;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.live-events-meta {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  color: #8891a4;
  font-size: 0.75rem;
}

.live-events-meta .live-events-origin {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.live-events-footer {
  padding: 0.65rem 1rem;
  border-top: 1px solid #eef1f5;
}

.live-events-footer a {
  color: #8891a4;
  font-size: 0.8rem;
}

.live-events-footer {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.75rem;
}

.live-events-demo {
  background: none;
  border: none;
  margin: 0;
  padding: 0;
  color: #8891a4;
  font-size: 0.8rem !important;
  text-decoration: underline;
  cursor: pointer;
  white-space: nowrap;
}

.live-events-demo:hover {
  color: #2c3e50;
}
