﻿/* ===========================================================================
   Attendance ATEASE - design system
   =========================================================================== */
:root {
  --aae-primary: #16233a;
  --aae-primary-rgb: 22, 35, 58;
  --aae-primary-2: #2a3f63;
  --aae-primary-ink: #ffffff;
  --aae-accent: #2c5fb3;
  --aae-grad: linear-gradient(135deg, #16233a 0%, #2a3f63 55%, #2c5fb3 130%);
  --aae-grad-dark: linear-gradient(175deg, #16233a 0%, #16233a 12%, #2a3f63 100%);

  --aae-bg: #f5f7fb;
  --aae-surface: #ffffff;
  --aae-ink: #0f172a;
  --aae-muted: #64748b;
  --aae-line: #e6e9f0;

  --aae-sidebar-bg: #0f172a;
  --aae-sidebar-fg: rgba(255,255,255,.78);
  --aae-sidebar-active: #1e293b;

  --aae-topbar-h: 62px;
  --aae-sidebar-w: 262px;
  --aae-sidebar-mini-w: 74px;
  --aae-radius: 16px;
  --aae-shadow: 0 1px 2px rgba(15,23,42,.06), 0 10px 30px rgba(15,23,42,.06);
  --aae-shadow-lg: 0 20px 55px rgba(15,23,42,.18);
}

* { box-sizing: border-box; }

/* Registered-trademark mark on the wordmark */
.aae-reg { font-size: .7em; vertical-align: super; margin-left: 2px; font-weight: 700; opacity: 1; line-height: 0; }

body {
  background: var(--aae-bg);
  color: var(--aae-ink);
  font-family: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
  letter-spacing: -0.01em;
}

/* ---------- Buttons ---------- */
.btn { border-radius: 10px; font-weight: 600; }
.btn-primary {
  background-image: var(--aae-grad);
  border: none;
  box-shadow: 0 6px 16px rgba(var(--aae-primary-rgb), .30);
}
.btn-primary:hover, .btn-primary:focus { filter: brightness(1.05); box-shadow: 0 8px 22px rgba(var(--aae-primary-rgb), .40); }
.btn-dark { background: #0f172a; border-color: #0f172a; }
.btn-lg { padding: .7rem 1.1rem; }

/* ---------- Forms ---------- */
.form-label { font-weight: 600; font-size: .82rem; color: #334155; }
.form-control, .form-select {
  border-radius: 10px; border-color: var(--aae-line); padding: .58rem .8rem;
}
.form-control:focus, .form-select:focus {
  border-color: var(--aae-primary-2);
  box-shadow: 0 0 0 .2rem rgba(var(--aae-primary-rgb), .18);
}
.input-group-text { border-radius: 10px; background: #f1f5f9; border-color: var(--aae-line); color: var(--aae-muted); }
.input-group > .form-control { border-top-left-radius: 0; border-bottom-left-radius: 0; }
.input-group > .input-group-text:first-child { border-top-right-radius: 0; border-bottom-right-radius: 0; }

/* ---------- Cards ---------- */
.card {
  border: 1px solid var(--aae-line);
  box-shadow: var(--aae-shadow);
  border-radius: var(--aae-radius);
  background: var(--aae-surface);
}

/* ===========================================================================
   Auth (login / register / verify)
   =========================================================================== */
.aae-login-wrap {
  min-height: 100vh; display: flex; align-items: center; justify-content: center;
  padding: 1.25rem; position: relative; overflow: hidden;
  background: var(--aae-grad);
}
.aae-login-wrap::before, .aae-login-wrap::after {
  content: ""; position: absolute; border-radius: 50%; filter: blur(10px); opacity: .35;
}
.aae-login-wrap::before { width: 420px; height: 420px; background: #a78bfa; top: -140px; right: -120px; }
.aae-login-wrap::after  { width: 360px; height: 360px; background: #22d3ee; bottom: -140px; left: -110px; }

.aae-login-card {
  width: 100%; max-width: 430px; border: none; border-radius: 22px;
  box-shadow: var(--aae-shadow-lg); position: relative; z-index: 1;
  backdrop-filter: blur(2px);
}
.aae-login-card.wide { max-width: 640px; }

.aae-login-brand { text-align: center; margin-bottom: 1.6rem; }
.aae-login-brand .bi {
  font-size: 2rem; width: 62px; height: 62px; line-height: 62px; border-radius: 18px;
  display: inline-block; color: #fff; background: var(--aae-grad);
  box-shadow: 0 10px 24px rgba(var(--aae-primary-rgb), .35); margin-bottom: .6rem;
}
.aae-login-brand .name { font-weight: 800; font-size: 1.55rem; letter-spacing: -.02em; }
.aae-login-brand .tag { color: var(--aae-muted); font-size: .85rem; }

/* ---------------------------------------------------------------------------
   Sign in and registration: the product on the left, the form on the right.

   A form alone on a gradient says nothing about what it is a form for. Somebody
   arriving from a search, a card or a colleague's message lands here first, and
   the panel beside it is the only chance to say what they are signing in to.

   Everything in that panel is text and shapes — no screenshot, no illustration
   file. An image would be one more thing to keep true as the product changes,
   and it would be the heaviest thing on the page somebody loads on mobile data.

   Below 992px the panel goes entirely and the card is what it always was. On a
   phone the form IS the page: the marketing would push it under the fold, and
   nobody thumbing in a password wants to scroll past a feature list first.
   --------------------------------------------------------------------------- */
/* The gradient and its two blurred shapes stay on .aae-login-wrap, which already had them. This is
   only the layout inside — nesting a second one produced a second pair of blobs, and they showed
   as a dark rectangle behind the card. */
.aae-auth-inner {
  position: relative; z-index: 1; width: 100%; max-width: 1180px; margin: 0 auto;
  display: grid; grid-template-columns: 1fr; gap: 2.5rem; align-items: center;
}

.aae-auth-pitch { display: none; color: #fff; }
.aae-auth-pitch .brand { display: flex; align-items: center; gap: .9rem; text-decoration: none; color: inherit; }
.aae-auth-pitch .brand img { width: 62px; height: 62px; border-radius: 18px; background: #fff; padding: 6px; }
.aae-auth-pitch .brand .name { font-weight: 800; font-size: 1.9rem; letter-spacing: -.02em; line-height: 1.1; }
.aae-auth-pitch .brand .tag { font-size: .9rem; opacity: .82; }

.aae-auth-pitch h1 {
  font-weight: 800; font-size: clamp(2rem, 2.6vw, 2.7rem); letter-spacing: -.025em;
  line-height: 1.15; margin: 2.2rem 0 .9rem;
}
.aae-auth-pitch .lede { font-size: 1.02rem; line-height: 1.6; opacity: .88; max-width: 34rem; margin-bottom: 2rem; }

.aae-auth-points { list-style: none; padding: 0; margin: 0; display: grid; gap: 1.05rem; }
.aae-auth-points li { display: flex; align-items: center; gap: .9rem; font-size: 1rem; }
.aae-auth-points .ico {
  flex: 0 0 auto; width: 40px; height: 40px; border-radius: 13px; display: grid; place-items: center;
  background: rgba(255, 255, 255, .16); font-size: 1.05rem;
}

/* The card keeps its own width; the grid decides where it sits. */
.aae-auth-inner .aae-login-card { margin: 0 auto; }

@media (min-width: 992px) {
  .aae-auth-inner { grid-template-columns: 1.05fr 1fr; gap: 3.5rem; }
  .aae-auth-pitch { display: block; }
  .aae-auth-inner .aae-login-card { margin: 0; max-width: 480px; }
  .aae-auth-inner .aae-login-card.wide { max-width: 640px; }

  /* The brand is said once, and on a wide screen the panel says it. Repeating it above the form put
     the same three lines twice on one screen. */
  .aae-auth-inner .aae-login-brand { display: none !important; }

  /* Home used to go with it, on the reasoning that the panel's logo links home too. In practice
     nobody reads a logo as a way out, so both the sign-in and register cards had a way BACK and no
     way HOME on the one screen size most people use. It stays.

     Pushed to the right-hand end of its row, away from "Back to sign in": they go to different
     places, and two links touching read as one pair of choices about the same thing.

     Both links lose their bottom margin below. The row centres its children on their MARGIN box, so
     one link carrying a 0.6rem bottom margin and the other none sat about five pixels apart — which
     is exactly what it looked like. Zero on both, and they line up because nothing is tilting them.

     Right-aligned as its own block, not merely with margin-left:auto. On the register card it sits
     in a flex row beside the other link and an auto margin is enough; on the sign-in card it is
     alone and not in a row at all, where an auto margin on an inline box does nothing. Made a block
     only as wide as its text, the auto margin carries it right in both. */
  .aae-auth-inner .aae-home-link {
    display: flex; width: fit-content; margin-left: auto;
  }

  /* Specific enough to win. ".aae-login-card .aae-back-link" further down this file sets a 0.6rem
     bottom margin, matches on two classes exactly as a shorter rule here would, and comes later —
     so the obvious selector lost by position and the links stayed four pixels apart. */
  .aae-auth-inner .aae-login-card .aae-home-link,
  .aae-auth-inner .aae-login-card .aae-back-link { margin-bottom: 0; }

  /* …and the card's own heading takes their place. */
  .aae-auth-inner .aae-auth-heading { display: block !important; }
}

/* Centring is safe for the tall registration form too: the wrapper is min-height, not height, so a
   form taller than the window grows the page instead of hanging off the top of it. */

/* ---------- "Cannot reach the server": covers the whole window, sidebar included ---------- */
.aae-offline {
  position: fixed; inset: 0; z-index: 2000;       /* above the sidebar, header and Bootstrap modals */
  display: flex; align-items: center; justify-content: center;
  padding: 1.5rem; overflow-y: auto;
  background: var(--aae-bg);
}
.aae-offline-card {
  width: 100%; max-width: 440px; text-align: center;
  background: var(--aae-surface); border: 1px solid var(--aae-line); border-radius: 20px;
  padding: 2.5rem 2rem; box-shadow: 0 20px 50px rgba(15,23,42,.08);
}
.aae-offline-icon {
  width: 64px; height: 64px; border-radius: 50%; margin: 0 auto 1rem;
  display: flex; align-items: center; justify-content: center;
  background: var(--bs-danger-bg-subtle); color: var(--bs-danger); font-size: 1.75rem;
}
body.aae-offline-open { overflow: hidden; }

/* ---------- Dashboard: section labels, and the pending-approval cards ---------- */
.aae-dash-section {
  font-size: .72rem; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  color: var(--aae-muted); margin-bottom: .65rem;
}
/* Register: punched on a weekly off or holiday — the same teal the app's calendar uses. */
.aae-offwork { background: #C7EEEA !important; color: #115E59 !important; }

/* Every stat card the same width; a short last row keeps that width instead of stretching. */
.aae-kpi-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 1rem; }
.aae-appr .card-header { background: transparent; border-bottom-color: var(--aae-line); }
/* Tinted only when something is actually waiting, so an amber card always means "act on me". */
.aae-appr.waiting { border-color: var(--bs-warning-border-subtle); }
.aae-appr.waiting .card-header { background: var(--bs-warning-bg-subtle); border-bottom-color: var(--bs-warning-border-subtle); }

/* ===========================================================================
   App shell
   =========================================================================== */
.aae-layout { display: flex; min-height: 100vh; }

.aae-sidebar {
  width: var(--aae-sidebar-w); background: var(--aae-grad-dark); color: var(--aae-sidebar-fg);
  position: fixed; top: 0; bottom: 0; left: 0; overflow-y: auto; z-index: 1040;
  transition: transform .22s ease; border-right: 1px solid rgba(255,255,255,.04);
}
.aae-brand { display: flex; align-items: center; gap: .75rem; padding: 1.1rem 1.25rem; color: #fff; }
/* Direct child only â€” otherwise the pin button's icon inherits the gradient tile. */
.aae-brand > .bi {
  font-size: 1.35rem; width: 40px; height: 40px; line-height: 40px; text-align: center;
  border-radius: 12px; background: var(--aae-grad); box-shadow: 0 6px 16px rgba(var(--aae-primary-rgb), .4);
  flex: 0 0 auto;
}
.aae-brand .brand-name { font-weight: 800; letter-spacing: -.02em; }
.aae-brand .brand-tag { font-size: .68rem; color: #7c8aa5; }

.aae-sidebar .nav-link {
  color: var(--aae-sidebar-fg); display: flex; align-items: center; gap: .8rem;
  padding: .58rem 1.25rem; margin: 1px .6rem; border-radius: 10px; font-size: .9rem; font-weight: 500;
}
.aae-sidebar .nav-link .bi { font-size: 1.05rem; opacity: .9; }
.aae-sidebar .nav-link:hover { background: rgba(255,255,255,.06); color: #fff; }
.aae-sidebar .nav-link.active { background: var(--aae-grad); color: #fff; box-shadow: 0 8px 20px rgba(var(--aae-primary-rgb), .35); }
.aae-sidebar .nav-section { letter-spacing: .08em; font-size: .66rem; color: #5b6982; }

/* Where the favourites end and the menu proper begins.
   A heading labels what follows it and says nothing about where it stops, so on a sidebar that
   opens with Dashboard in both blocks there was no telling the shortcut from the real item. Inset
   to the same gutter as the rows so it reads as part of the list rather than across it. */
.aae-sidebar .nav-split {
  height: 1px; margin: .55rem 1.25rem; background: rgba(255, 255, 255, .12);
}
/* In the minimised rail the rows are 46px squares centred by auto margins; a rule inset to the
   full-width gutter would sit off to one side of them. */
.aae-layout.mini .aae-sidebar .nav-split { margin-left: auto; margin-right: auto; width: 46px; }

.aae-main {
  flex: 1; margin-left: var(--aae-sidebar-w); display: flex; flex-direction: column; min-width: 0;
  transition: margin-left .18s ease;
}
.aae-topbar {
  height: var(--aae-topbar-h); background: rgba(248,249,252,.92); backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--aae-line); display: flex; align-items: center; gap: 1rem;
  padding: 0 1.4rem; position: sticky; top: 0; z-index: 1030;
}
.aae-content { padding: 1.6rem; flex: 1; }

.aae-avatar {
  width: 34px; height: 34px; border-radius: 50%; background: var(--aae-grad); color: #fff;
  display: inline-flex; align-items: center; justify-content: center; font-weight: 700; font-size: .85rem;
  box-shadow: 0 4px 10px rgba(var(--aae-primary-rgb), .35);
}

/* ---------- KPI cards ---------- */
.kpi-card { border: 1px solid var(--aae-line); transition: transform .15s ease, box-shadow .15s ease; }
.kpi-card:hover { transform: translateY(-3px); box-shadow: var(--aae-shadow-lg); }
.kpi-icon {
  width: 50px; height: 50px; border-radius: 14px; display: inline-flex; align-items: center;
  justify-content: center; font-size: 1.35rem; color: #fff;
}
.kpi-icon.text-bg-primary { background: var(--aae-grad) !important; }
.kpi-value { font-size: 1.7rem; font-weight: 800; line-height: 1; letter-spacing: -.02em; }
.kpi-label { font-weight: 500; }

/* ---------- Badges ---------- */
.badge { font-weight: 600; border-radius: 8px; padding: .4em .6em; }

/* ---------- Section headings ---------- */
.card h2.h6 { font-weight: 700; letter-spacing: -.01em; }

/* ---------- Photos ---------- */
.org-photo-box {
  border: 1px dashed var(--aae-line); border-radius: 14px; height: 132px;
  display: flex; align-items: center; justify-content: center; overflow: hidden; background: #f8fafc;
}
/* contain (not cover) so logos keep their aspect ratio and never stretch */
.org-photo-box img { width: 100%; height: 100%; object-fit: contain; padding: 8px; background: #fff; }
.org-thumb { width: 38px; height: 38px; border-radius: 9px; object-fit: contain; background: #fff; padding: 2px; border: 1px solid var(--aae-line); }
.org-thumb-empty {
  display: inline-flex; width: 36px; height: 36px; border-radius: 9px;
  background: #eef2f7; color: #94a3b8; align-items: center; justify-content: center;
}

/* ---------- Modern search box ---------- */
.aae-search { position: relative; width: 300px; max-width: 100%; }
.aae-search > i {
  position: absolute; left: .9rem; top: 50%; transform: translateY(-50%);
  color: #94a3b8; font-size: .95rem; pointer-events: none; transition: color .15s ease;
}
.aae-search > input {
  width: 100%; height: 44px; padding: .5rem 1rem .5rem 2.5rem;
  border: 1px solid var(--aae-line); border-radius: 12px; background: #fff;
  color: var(--aae-ink); font-size: .92rem;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.aae-search > input::placeholder { color: #9aa4b2; }
.aae-search > input:focus {
  outline: none; border-color: var(--aae-primary-2);
  box-shadow: 0 0 0 .2rem rgba(var(--aae-primary-rgb), .15);
}
.aae-search:focus-within > i { color: var(--aae-primary); }
.aae-search > input::-webkit-search-cancel-button { cursor: pointer; }

/* ---------- Tabulator: clean, modern, no sort chrome ---------- */
.tabulator { border: none; background: transparent; font-size: .9rem; }
.tabulator .tabulator-header {
  border: none; border-bottom: 1px solid var(--aae-line); background: transparent;
  font-size: .8rem; font-weight: 600; color: #64748b; letter-spacing: 0; text-transform: none;
}
.tabulator .tabulator-header .tabulator-col { background: transparent; border-right: none; }
.tabulator .tabulator-header .tabulator-col .tabulator-col-content { padding: 12px; }
.tabulator .tabulator-header .tabulator-col .tabulator-col-title { white-space: nowrap; text-overflow: ellipsis; }

.tabulator .tabulator-row { border-bottom: 1px solid #f1f5f9; transition: background .12s ease; }
.tabulator .tabulator-row.tabulator-row-even { background: transparent; }
.tabulator .tabulator-row:hover { background: #f8fafc !important; }
.tabulator .tabulator-row:last-child { border-bottom: none; }
.tabulator .tabulator-cell { padding: 12px; border-right: none; }
.tabulator .tabulator-placeholder { color: #94a3b8; font-size: .9rem; }
.tabulator, .tabulator .tabulator-tableholder { max-width: 100%; }

/* Thumbnail cells must not clip / ellipsis the image */
.tabulator .tabulator-cell.cell-thumb {
  padding: 6px; overflow: visible; text-overflow: clip;
}

/* Responsive-collapse chevron + the hidden-columns panel */
.tabulator .tabulator-responsive-collapse { border-top: 1px solid var(--aae-line); background: #f8fafc; padding: .5rem .75rem; }
.tabulator .tabulator-responsive-collapse table tr td:first-of-type { color: #64748b; font-weight: 600; padding-right: .75rem; }
.tabulator .tabulator-cell .tabulator-responsive-collapse-toggle { color: var(--aae-primary); font-weight: 700; }

/* Pagination footer */
.tabulator .tabulator-footer {
  background: transparent; border-top: 1px solid var(--aae-line);
  padding: .6rem .25rem 0; color: var(--aae-muted); font-size: .85rem;
}
.tabulator .tabulator-footer .tabulator-page {
  border: 1px solid var(--aae-line); border-radius: 8px; margin: 0 2px; padding: .25rem .6rem;
  background: #fff; color: var(--aae-ink);
}
.tabulator .tabulator-footer .tabulator-page.active { background: var(--aae-grad); color: #fff; border-color: transparent; }
.tabulator .tabulator-footer .tabulator-page:disabled { opacity: .45; }
.tabulator .tabulator-footer .tabulator-page-size { border-radius: 8px; border: 1px solid var(--aae-line); padding: .2rem .4rem; }

/* Never let a page scroll sideways because of a grid.
   clip rather than hidden: both stop the sideways scroll, but hidden quietly turns the whole content
   area into a scroll container, and anything sticky inside it then pins to a box that never scrolls —
   which is why no grid heading on the site could stay in view. clip cuts the overflow without that. */
.aae-content { overflow-x: clip; }
.aae-content .card-body { overflow-x: auto; }

/* A grid's column headings stay in view under the top bar while a long list scrolls — past twenty
   rows of a hundred, nobody remembers which column is Phone and which is Department.
   Three things were each enough to stop it, so all three are undone for grids on a page: the card's
   sideways scroll above, and Tabulator's own overflow:hidden on the grid. Grids fit their columns
   and collapse the rest onto a second line, so none of them needs either to stay within the page.
   Not inside a popup: a popup body is its own scroller with no top bar to sit under. */
.card-body:has(> .tabulator):not(.modal .card-body) { overflow: visible; }
.tabulator:not(.modal .tabulator) { overflow: visible; }
.tabulator:not(.modal .tabulator) > .tabulator-header {
  position: sticky; top: var(--aae-topbar-h); z-index: 20;
}

/* ---------- Modal polish (themed header) ---------- */
.modal-content { box-shadow: var(--aae-shadow-lg); overflow: hidden; }
.modal-header {
  background: var(--aae-grad); color: #fff; border-bottom: none; padding: .9rem 1.25rem;
}
.modal-header .modal-title { font-weight: 700; letter-spacing: -.01em; color: #fff; }
.modal-header .btn-close { filter: invert(1) grayscale(1) brightness(2); opacity: .9; }
/* Secondary text in a title bar — a date range beside a name, a caption beside a title. Bootstrap's
   grey is written for a white ground and all but disappears on the gradient, so here it is the header's
   own white, a step softer than the title. Bootstrap marks these colours !important, hence this does. */
.modal-header .text-secondary,
.modal-header .text-muted,
.modal-header .text-body-secondary { color: rgba(255, 255, 255, .85) !important; }
.modal-footer { border-top: 1px solid var(--aae-line); padding: .8rem 1.25rem; }
.modal-body { padding: 1rem 1.25rem; }
.modal-body hr { border-color: var(--aae-line); opacity: 1; margin: .35rem 0; }

/* Scrollable modal body */
.modal-body.scroll-body { max-height: 66vh; overflow-y: auto; }

/* A table in a popup keeps its column headings while its rows scroll — a day-by-day list of a month
   is thirty rows, and by the tenth nobody remembers which column was In and which was Out.
   Pulled up by the body's own top padding (1rem, set on .modal-body): a heading pinned at top:0 sits
   that far down, and rows showed through the strip above it. Keep the two values together. */
.modal-body thead th {
  position: sticky; top: -1rem; z-index: 2;
  background: var(--aae-surface);
  box-shadow: inset 0 -1px 0 var(--aae-line);
}

/* Tighter form rhythm */
.modal-body .row > [class*="col-"] { padding-top: .35rem; padding-bottom: .35rem; }

/* ===========================================================================
   Outlined field with a notched label that sits ON the border.
   Markup: <div class="aae-field"><input class="form-control" placeholder=" "><label>Caption</label></div>
   (label must come AFTER the control)
   =========================================================================== */
.aae-field { position: relative; }

.aae-field > .form-control,
.aae-field > .form-select {
  height: 46px;
  padding: .6rem .75rem;
  border-radius: 10px;
}
.aae-field > textarea.form-control { height: auto; min-height: 46px; padding-top: .7rem; }

.aae-field > label {
  position: absolute; left: .6rem; top: 50%; transform: translateY(-50%);
  margin: 0; padding: 0 .3rem; background: #fff; color: #94a3b8;
  font-size: .95rem; font-weight: 400; line-height: 1; pointer-events: none;
  max-width: calc(100% - 1.6rem); overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
  transition: top .14s ease, font-size .14s ease, color .14s ease, font-weight .14s ease;
}

/* Raised (notched) when focused, filled, a select/date/time, or forced via .raised */
.aae-field > .form-control:focus ~ label,
.aae-field > .form-control:not(:placeholder-shown) ~ label,
.aae-field > .form-select ~ label,
.aae-field > input[type="time"] ~ label,
.aae-field > input[type="date"] ~ label,
.aae-field.raised > label {
  top: 0; font-size: .74rem; font-weight: 600; color: var(--aae-primary);
}
/* All raised captions use the brand colour (matches the modal title bar) */
.aae-field > .form-control:disabled { background: #f8fafc; }

.aae-field > .form-control:focus,
.aae-field > .form-select:focus { border-color: var(--aae-input-focus); }

/* Input-group + notched field (e.g. +91 prefix, password eye) */
.input-group > .aae-field { flex: 1 1 auto; }
.input-group > .aae-field:not(:first-child) > .form-control { border-top-left-radius: 0; border-bottom-left-radius: 0; }
.input-group > .aae-field:not(:last-child) > .form-control { border-top-right-radius: 0; border-bottom-right-radius: 0; }
.input-group > .aae-field > label { z-index: 5; }
.input-group-text { height: 46px; }

/* Small caps section labels inside forms */
.modal-body .fw-semibold.text-secondary.small { letter-spacing: .06em; }

/* ---------- Buttons / switches ---------- */
.btn-sm { border-radius: 8px; }
.form-switch .form-check-input:checked { background-color: var(--aae-primary); border-color: var(--aae-primary); }
.form-check-input:focus { box-shadow: 0 0 0 .2rem rgba(var(--aae-primary-rgb), .18); }

/* ---------- Responsive ---------- */
.aae-backdrop { display: none; position: fixed; inset: 0; background: rgba(2,6,23,.45); z-index: 1039; }
.aae-backdrop.show { display: block; }

@media (min-width: 992px) { .aae-backdrop { display: none !important; } }

@media (max-width: 991.98px) {
  .aae-sidebar { transform: translateX(-100%); box-shadow: var(--aae-shadow-lg); }
  .aae-sidebar.open { transform: translateX(0); }
  .aae-main { margin-left: 0; }
}

/* ---------- Read-only (subscription lapsed, inside the view grace window) ---------- */
.aae-ro-banner {
  display: flex; align-items: flex-start; gap: .6rem;
  margin: 1rem 1.5rem -0.25rem;
  padding: .75rem 1rem;
  border: 1px solid #fcd34d;
  border-left: 4px solid #f59e0b;
  border-radius: 10px;
  background: #fffbeb;
  color: #78350f;
  font-size: .9rem;
  line-height: 1.45;
}
.aae-ro-banner .bi { font-size: 1.05rem; line-height: 1.35; color: #b45309; }

/* The API rejects the write anyway; this just stops the user from trying. */
body.aae-ro #addBtn,
body.aae-ro [data-action="edit"],
body.aae-ro [data-action="delete"],
body.aae-ro .aae-write { display: none !important; }

@media (max-width: 991.98px) { .aae-ro-banner { margin: .75rem 1rem -0.25rem; } }

/* ---------- Autofill: Chrome paints its own background, which broke the outlined field ---------- */
.aae-field > .form-control:-webkit-autofill,
.aae-field > .form-control:-webkit-autofill:hover,
.aae-field > .form-control:-webkit-autofill:focus,
.aae-field > .form-select:-webkit-autofill {
  -webkit-box-shadow: 0 0 0 100px #fff inset;
  box-shadow: 0 0 0 100px #fff inset;
  -webkit-text-fill-color: #0f172a;
  caret-color: #0f172a;
  transition: background-color 100000s ease-in-out 0s;
}
/* Autofilled inputs are never :placeholder-shown, so the label must raise too */
.aae-field > .form-control:-webkit-autofill ~ label { top: 0; font-size: .74rem; font-weight: 600; color: var(--aae-primary); }

/* ---------- Form section heading ---------- */
.aae-section {
  display: flex; align-items: center; gap: .75rem;
  margin: 1.6rem 0 .25rem;
  font-size: .72rem; font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
  color: #94a3b8; white-space: nowrap;
}
.aae-section::after { content: ""; flex: 1 1 auto; height: 1px; background: #e2e8f0; }

/* ---------- Password field with the eye tucked inside the outline ---------- */
.aae-field.has-suffix > .form-control { padding-right: 2.75rem; }
.aae-field > .field-suffix {
  position: absolute; right: .35rem; top: 50%; transform: translateY(-50%);
  border: 0; background: transparent; color: #94a3b8;
  width: 2rem; height: 2rem; border-radius: 8px; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center;
}
.aae-field > .field-suffix:hover { color: var(--aae-primary); background: #f1f5f9; }

/* A date field in a filter bar, beside the small selects. The 46px form field towers over them.
   Sized to match the select next to it as this site draws it — not Bootstrap's stock small size,
   because the .form-control/.form-select rule near the top of this file restyles the small controls
   too (10px corners, .58rem padding). Matching Bootstrap left the date a step shorter than its
   neighbour. The caption sits above as a plain label here, so there is no floating label to seat. */
.aae-field.aae-field-sm > .form-control {
  height: auto;
  padding: .58rem .8rem; font-size: .875rem;
  border-radius: 10px;
}
.aae-field.aae-field-sm.has-suffix > .form-control { padding-right: 2.4rem; }
.aae-field.aae-field-sm > .field-suffix { width: 1.8rem; height: 1.8rem; right: .3rem; font-size: .85rem; }

/* ---------- Inline notice (e.g. "confirm your email") ---------- */
.aae-notice {
  display: flex; gap: .7rem; align-items: flex-start;
  padding: .8rem .9rem; border-radius: 12px;
  border: 1px solid #bfdbfe; background: #eff6ff; color: #1e3a5f;
}
.aae-notice > .bi { font-size: 1.1rem; color: #2563eb; line-height: 1.3; }

/* ---------- Map picker (Leaflet) ---------- */
/* Sized off the viewport so the modal footer ("Use this location") is never pushed below the fold. */
.aae-map {
  height: clamp(240px, 46vh, 460px);
  border-radius: 12px;
  border: 1px solid #e2e8f0;
  overflow: hidden;
  z-index: 0;              /* keep tiles under the modal chrome */
}
#mapPickerModal .modal-dialog { max-height: calc(100vh - 2rem); }
#mpResults { max-height: 160px; overflow-y: auto; }
.leaflet-container { font: inherit; }
@media (max-width: 767.98px) { .aae-map { height: clamp(220px, 38vh, 320px); } }

/* ---------- Input groups must never wrap ----------
   Bootstrap's .input-group wraps by default. On a narrow phone the .aae-field dropped to its own
   line, stranding the prefix icon / eye button on the line above. */
.input-group { flex-wrap: nowrap; }              /* fallback for browsers without :has() */
.input-group:has(> .aae-field) { flex-wrap: nowrap; }
.aae-field { min-width: 0; }

/* ---------- Toolbar: search + primary action ---------- */
.aae-toolbar { display: flex; justify-content: flex-end; align-items: center; gap: .5rem; flex-wrap: wrap; }

/* ---------- Tabulator footer: counter and pager need breathing room ---------- */
.tabulator .tabulator-footer {
  display: flex; flex-wrap: wrap; align-items: center; gap: .5rem 1rem;
  padding: .6rem .25rem 0;
}
.tabulator .tabulator-footer .tabulator-page-counter { margin: 0 1rem 0 0; }
.tabulator .tabulator-footer .tabulator-paginator { display: flex; flex-wrap: wrap; align-items: center; gap: .35rem; }

/* ---------- Install-as-app button ---------- */
#installApp[hidden] { display: none !important; }

/* ---------- Phones ---------- */
@media (max-width: 575.98px) {
  .aae-content { padding: 1rem .75rem; }
  .aae-topbar { padding: 0 .85rem; gap: .6rem; }
  .aae-topbar h1 { font-size: 1.05rem; }
  .card-body { padding: .85rem; }

  .aae-toolbar { flex-direction: column; align-items: stretch; }
  .aae-toolbar .aae-search { width: 100%; }
  .aae-toolbar .btn { width: 100%; }

  /* Let the grid scroll inside its card instead of widening the page. */
  .tabulator { font-size: .85rem; }
  .tabulator .tabulator-header .tabulator-col .tabulator-col-content { padding: 10px 8px; }
  .tabulator .tabulator-footer { justify-content: space-between; }

  .aae-login-brand .name { font-size: 1.3rem; }
  .aae-login-card .card-body { padding: 1.5rem 1.15rem; }
  .aae-ro-banner { margin: .75rem .75rem -0.25rem; }
}

/* =========================================================================
   Sidebar: minimisable icon rail with a lock, and a hidden scrollbar
   ========================================================================= */

/* The aside no longer scrolls; the nav list inside it does. */
.aae-sidebar { display: flex; flex-direction: column; overflow: hidden; }
.aae-nav-wrap { position: relative; flex: 1 1 auto; min-height: 0; }
.aae-nav-scroll { height: 100%; overflow-y: auto; overflow-x: hidden; overscroll-behavior: contain; padding: .25rem 0 2.25rem; }

/* Scrollbar removed by request â€” the chevrons below replace it. */
.aae-nav-scroll { scrollbar-width: none; -ms-overflow-style: none; }
.aae-nav-scroll::-webkit-scrollbar { width: 0; height: 0; }

/* "There is more this way" affordance: a fade the menu scrolls under, plus a chevron.
   One at each end, each shown only when that end still has content. */
.aae-scroll-hint {
  position: absolute; left: 0; right: 0; height: 42px; z-index: 2;
  display: flex; justify-content: center;
  border: 0; color: #cbd5e1; cursor: pointer;
}
.aae-scroll-hint[hidden] { display: none; }
.aae-scroll-hint:hover { color: #fff; }
.aae-scroll-hint .bi { font-size: 1.05rem; }

.aae-scroll-hint.down {
  bottom: 0; align-items: flex-end; padding-bottom: .3rem;
  background: linear-gradient(to bottom, transparent 0%, var(--aae-scrim) 60%, var(--aae-scrim) 100%);
}
.aae-scroll-hint.up {
  top: 0; align-items: flex-start; padding-top: .3rem;
  background: linear-gradient(to top, transparent 0%, var(--aae-scrim) 60%, var(--aae-scrim) 100%);
}
.aae-scroll-hint.down .bi { animation: aae-nudge 1.6s ease-in-out infinite; }
@keyframes aae-nudge { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(3px); } }
@media (prefers-reduced-motion: reduce) { .aae-scroll-hint .bi { animation: none; } }

/* The pin. Pinned = the rail stays open; unpinned = it minimises and opens on hover. */
.aae-pin {
  margin-left: auto; border: 0; background: transparent; color: #7c8aa5;
  width: 30px; height: 30px; border-radius: 8px; flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  transition: color .15s ease, background .15s ease;
}
.aae-pin .bi { font-size: 1rem; }
.aae-pin:hover { background: rgba(255,255,255,.10); color: #fff; }
.aae-pin[aria-pressed="true"] { color: #cbd5e1; }
.aae-brand .brand-text { min-width: 0; }

/* ---- Minimised rail (desktop only: hover is meaningless on touch) ---- */
@media (min-width: 992px) {
  .aae-layout.mini .aae-sidebar { width: var(--aae-sidebar-mini-w); }
  .aae-layout.mini .aae-main { margin-left: var(--aae-sidebar-mini-w); }

  .aae-sidebar { transition: width .18s ease, transform .22s ease; }

  /* Remove the text and the pin from layout entirely, then centre what is left.
     `width: 0` is not enough for .nav-label: a <span> is inline, and inline boxes ignore width and
     overflow, so the label kept its full text width and shoved every icon off-centre. */
  .aae-layout.mini .aae-sidebar .nav-label { display: none; }
  .aae-layout.mini .aae-sidebar .brand-text,
  .aae-layout.mini .aae-sidebar .aae-pin {
    display: none;
  }
  /* display:none, not height:0 â€” a zero-height section header still contributes its text width to
     the list, which widens every row and pushes the icons out of the rail. */
  .aae-layout.mini .aae-sidebar .nav-section { display: none; }

  /* Fixed square, centred by auto margins. Nothing here depends on how wide the <ul> ends up. */
  .aae-layout.mini .aae-sidebar .nav-link {
    width: 46px; margin-left: auto; margin-right: auto;
    justify-content: center; padding: .58rem 0; gap: 0;
  }
  .aae-layout.mini .aae-brand { padding-left: 0; padding-right: 0; gap: 0; justify-content: center; }

  /* Slimmer affordances: a 42px scrim swallows the first menu row on a 74px rail. */
  .aae-layout.mini .aae-scroll-hint { height: 28px; }

  /* Hover (or keyboard focus) re-opens it, floating over the content rather than pushing it. */
  .aae-layout.mini:not(.hover-off) .aae-sidebar:hover,
  .aae-layout.mini:not(.hover-off) .aae-sidebar:focus-within {
    width: var(--aae-sidebar-w);
    box-shadow: var(--aae-shadow-lg);
  }
  .aae-layout.mini:not(.hover-off) .aae-sidebar:hover .nav-label,
  .aae-layout.mini:not(.hover-off) .aae-sidebar:focus-within .nav-label { display: inline; }
  .aae-layout.mini:not(.hover-off) .aae-sidebar:hover .brand-text,
  .aae-layout.mini:not(.hover-off) .aae-sidebar:focus-within .brand-text { display: block; }
  .aae-layout.mini:not(.hover-off) .aae-sidebar:hover .aae-pin,
  .aae-layout.mini:not(.hover-off) .aae-sidebar:focus-within .aae-pin { display: inline-flex; }

  .aae-layout.mini:not(.hover-off) .aae-sidebar:hover .nav-link,
  .aae-layout.mini:not(.hover-off) .aae-sidebar:focus-within .nav-link {
    width: auto; margin-left: .6rem; margin-right: .6rem;
    justify-content: flex-start; padding: .58rem 1.25rem; gap: .8rem;
  }
  .aae-layout.mini:not(.hover-off) .aae-sidebar:hover .nav-section,
  .aae-layout.mini:not(.hover-off) .aae-sidebar:focus-within .nav-section { display: list-item; }
  .aae-layout.mini:not(.hover-off) .aae-sidebar:hover .aae-scroll-hint,
  .aae-layout.mini:not(.hover-off) .aae-sidebar:focus-within .aae-scroll-hint { height: 42px; }
  .aae-layout.mini:not(.hover-off) .aae-sidebar:hover .aae-brand,
  .aae-layout.mini:not(.hover-off) .aae-sidebar:focus-within .aae-brand {
    padding-left: 1.25rem; padding-right: 1.25rem; gap: .75rem; justify-content: flex-start;
  }
}
/* On phones the drawer is the interaction; never minimise it. */
@media (max-width: 991.98px) {
  .aae-layout.mini .aae-sidebar { width: var(--aae-sidebar-w); }
  .aae-layout.mini .aae-main { margin-left: 0; }
  .aae-pin { display: none; }
}

/* =========================================================================
   Appearance: colour mode, fonts, grid styling
   Every colour below must be a variable. A hard-coded hex is a bug in dark mode.
   ========================================================================= */
:root {
  --aae-font: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --aae-font-size: 15px;
  --aae-font-weight: 400;
  --aae-focus-ring: rgba(var(--aae-primary-rgb), .22);
  --aae-primary-soft: rgba(var(--aae-primary-rgb), .10);
  --aae-primary-dark: #0f1a2c;
  --aae-primary-tint: #e3e9f2;
  --aae-primary-tint-2: #c9d3e3;
  --aae-primary-tint-3: #eef2f7;

  /* Surfaces referenced by components; overridden wholesale in dark mode. */
  --aae-surface-2: #f8fafc;
  --aae-input-bg: #ffffff;
  --aae-input-ink: #0f172a;
  /* Field borders dark enough to see at a glance; the field being typed in turns Atease red. */
  --aae-input-line: #7b8494;
  --aae-input-focus: #e24b4a;
  --aae-input-focus-ring: rgba(226,75,74,.18);
  --aae-label: #94a3b8;
  /* Three distinct steps so the eye can rank them: header > alternate row > base row.
     Previously the header reused --aae-surface-2, which is also the stripe colour, so a striped
     grid had a header indistinguishable from every other row. */
  --aae-grid-header-bg: #dde3ee;
  --aae-grid-header-line: #b9c3d6;
  --aae-row-alt: #f2f5fa;
  --aae-row-hover: #e8edf6;
  --aae-grid-line: #f1f5f9;
  --aae-grid-line-w: 1px;
  --aae-cell-pad: 12px;
  --aae-scrim: rgba(11,18,32,.97);
}

html[data-mode="dark"] {
  --aae-bg: #0b1220;
  --aae-surface: #131c2e;
  --aae-surface-2: #1a2438;
  --aae-ink: #e6ebf5;
  --aae-muted: #94a3b8;
  --aae-line: #26324a;

  --aae-input-bg: #0f1728;
  --aae-input-ink: #e6ebf5;
  --aae-input-line: #8a96ad;
  --aae-label: #7c8aa5;
  --aae-grid-header-bg: #223050;
  --aae-grid-header-line: #33456b;
  --aae-row-alt: #182238;
  --aae-row-hover: #1f2b47;
  --aae-grid-line: #222e46;
  --aae-scrim: rgba(5,9,17,.97);
}
html[data-mode="dark"] { color-scheme: dark; }

body { font-family: var(--aae-font); font-size: var(--aae-font-size); font-weight: var(--aae-font-weight); }

/* ---- Surfaces that were hard-coded white ---- */
.card, .modal-content, .dropdown-menu { background-color: var(--aae-surface); color: var(--aae-ink); }
.card { border-color: var(--aae-line); }
.modal-content { border: 1px solid var(--aae-line); }
.dropdown-menu { border-color: var(--aae-line); }
.dropdown-item { color: var(--aae-ink); }
.dropdown-item:hover, .dropdown-item:focus { background-color: var(--aae-surface-2); color: var(--aae-ink); }

.form-control, .form-select { background-color: var(--aae-input-bg); color: var(--aae-input-ink); border-color: var(--aae-input-line); }
.form-control:focus, .form-select:focus {
  background-color: var(--aae-input-bg); color: var(--aae-input-ink);
  border-color: var(--aae-input-focus); box-shadow: 0 0 0 .2rem var(--aae-input-focus-ring);
}
.form-control::placeholder { color: var(--aae-label); }
.form-control:disabled, .form-control[readonly] { background-color: var(--aae-surface-2); color: var(--aae-muted); }
.input-group-text { background-color: var(--aae-surface-2); color: var(--aae-muted); border-color: var(--aae-line); }
.form-text { color: var(--aae-muted); }
hr { border-color: var(--aae-line); opacity: 1; }

/* The notched label sits on the border, so its background must match the field, not "white". */
.aae-field > label { background: var(--aae-input-bg); color: var(--aae-label); }
.aae-field > .form-control:disabled { background: var(--aae-surface-2); }
.aae-field > .form-control:-webkit-autofill,
.aae-field > .form-control:-webkit-autofill:hover,
.aae-field > .form-control:-webkit-autofill:focus,
.aae-field > .form-select:-webkit-autofill {
  -webkit-box-shadow: 0 0 0 100px var(--aae-input-bg) inset;
  box-shadow: 0 0 0 100px var(--aae-input-bg) inset;
  -webkit-text-fill-color: var(--aae-input-ink);
  caret-color: var(--aae-input-ink);
}

.aae-search > input { background: var(--aae-input-bg); color: var(--aae-ink); border-color: var(--aae-input-line); }
.aae-search > input:focus { border-color: var(--aae-input-focus); box-shadow: 0 0 0 .2rem var(--aae-input-focus-ring); }
/* Tinted with the tenant's own accent rather than a fixed colour, so it follows whatever they pick
   on the Appearance page. Kept light — the bar carries the page title and the account menu, and a
   saturated strip there would fight the content underneath it for attention. */
.aae-topbar {
  background: color-mix(in srgb, var(--aae-primary) 10%, var(--aae-surface));
  border-bottom-color: color-mix(in srgb, var(--aae-primary) 22%, var(--aae-line));
}

/* Buttons follow the chosen accent, including its contrasting ink. */
.btn-primary {
  --bs-btn-bg: var(--aae-primary); --bs-btn-border-color: var(--aae-primary); --bs-btn-color: var(--aae-primary-ink);
  --bs-btn-hover-bg: var(--aae-primary-dark); --bs-btn-hover-border-color: var(--aae-primary-dark); --bs-btn-hover-color: var(--aae-primary-ink);
  --bs-btn-active-bg: var(--aae-primary-dark); --bs-btn-active-border-color: var(--aae-primary-dark);
  --bs-btn-disabled-bg: var(--aae-primary); --bs-btn-disabled-border-color: var(--aae-primary);
}
.btn-outline-primary {
  --bs-btn-color: var(--aae-primary); --bs-btn-border-color: var(--aae-primary);
  --bs-btn-hover-bg: var(--aae-primary); --bs-btn-hover-border-color: var(--aae-primary); --bs-btn-hover-color: var(--aae-primary-ink);
}
a { color: var(--aae-primary); }
.btn-outline-secondary { --bs-btn-color: var(--aae-muted); --bs-btn-border-color: var(--aae-line); }
.text-secondary { color: var(--aae-muted) !important; }

/* The sidebar scroll scrim must follow the sidebar, not a fixed navy. */
/* The scroll scrim already reads --aae-scrim, which the dark theme overrides. Restating the
   gradient here would flatten the up-arrow's upward fade, so it is deliberately not repeated. */

/* =========================================================================
   Tabulator: stripes, border weight, density
   ========================================================================= */
.tabulator { color: var(--aae-ink); }
.tabulator .tabulator-header { background: transparent; border-bottom-color: var(--aae-line); color: var(--aae-muted); }
.tabulator .tabulator-row { background: transparent; border-bottom: var(--aae-grid-line-w) solid var(--aae-grid-line); }
.tabulator .tabulator-row:hover { background: var(--aae-row-hover); }
.tabulator .tabulator-row .tabulator-cell { padding: var(--aae-cell-pad); border-right: none; }
.tabulator .tabulator-footer { color: var(--aae-muted); border-top-color: var(--aae-line); }
.tabulator .tabulator-placeholder { color: var(--aae-muted); }

/* Zebra striping. Applied to even rows so the first row keeps the card's own surface. */
html[data-grid-striped="1"] .tabulator .tabulator-row:nth-child(even) { background: var(--aae-row-alt); }
html[data-grid-striped="1"] .tabulator .tabulator-row:nth-child(even):hover { background: var(--aae-row-hover); }

html[data-grid-border="none"]   { --aae-grid-line-w: 0px; }
html[data-grid-border="light"]  { --aae-grid-line-w: 1px; }
html[data-grid-border="medium"] { --aae-grid-line-w: 2px; }
html[data-grid-border="thick"]  { --aae-grid-line-w: 3px; }
html[data-grid-border="medium"], html[data-grid-border="thick"] { --aae-grid-line: var(--aae-line); }

/* Vertical rules only once the borders are asked for. */
html[data-grid-border="medium"] .tabulator .tabulator-cell,
html[data-grid-border="thick"]  .tabulator .tabulator-cell { border-right: var(--aae-grid-line-w) solid var(--aae-grid-line) !important; }

html[data-grid-density="compact"] { --aae-cell-pad: 6px 10px; }
html[data-grid-density="normal"]  { --aae-cell-pad: 12px; }
html[data-grid-density="relaxed"] { --aae-cell-pad: 18px 12px; }

/* ---- Swatches on the appearance page ---- */
.aae-swatch {
  border: 2px solid transparent; border-radius: 14px; padding: .6rem; cursor: pointer;
  background: var(--aae-surface); width: 100%; text-align: left;
}
.aae-swatch:hover { border-color: var(--aae-line); }
.aae-swatch.selected { border-color: var(--aae-primary); box-shadow: 0 0 0 .2rem var(--aae-focus-ring); }
.aae-swatch .bar { height: 34px; border-radius: 9px; margin-bottom: .4rem; }
.aae-swatch .label { font-size: .78rem; color: var(--aae-muted); }
.aae-preview-card { border: 1px solid var(--aae-line); border-radius: 12px; padding: 1rem; background: var(--aae-surface); }

/* ---------- Per-page help ---------- */
.aae-help-btn { width: 32px; height: 32px; border-radius: 50%; padding: 0; line-height: 1; }
.aae-help { width: 420px; background: var(--aae-surface); color: var(--aae-ink); }
.aae-help .offcanvas-header { border-bottom: 1px solid var(--aae-line); }
.aae-help .offcanvas-body { font-size: .92rem; line-height: 1.6; }
.aae-help h6 { font-weight: 700; margin: 1.25rem 0 .35rem; font-size: .82rem; text-transform: uppercase; letter-spacing: .06em; color: var(--aae-muted); }
.aae-help h6:first-child { margin-top: 0; }
.aae-help ul { padding-left: 1.1rem; margin-bottom: .75rem; }
.aae-help li { margin-bottom: .3rem; }
.aae-help kbd { background: var(--aae-surface-2); color: var(--aae-ink); border: 1px solid var(--aae-line); border-radius: 5px; padding: .1rem .35rem; font-size: .8rem; }
.aae-help .tip { border-left: 3px solid var(--aae-primary); background: var(--aae-primary-soft); padding: .6rem .8rem; border-radius: 0 8px 8px 0; margin: .75rem 0; }
@media (max-width: 575.98px) { .aae-help { width: 100%; } }

/* =========================================================================
   Modals: no sideways scroll, consistent footer buttons
   ========================================================================= */

/* Bootstrap's .row uses negative margins; inside a padded modal body that can push a pixel or two
   past the edge and summon a horizontal scrollbar for content that already fits. */
.modal-body { overflow-x: hidden; }
.modal-body > .row { --bs-gutter-x: 1rem; margin-left: 0; margin-right: 0; }
.modal-body > .row > [class^="col"], .modal-body > .row > [class*=" col"] { min-width: 0; }

/* A tinted footer separates the actions from the form above it, and the two buttons match in size
   on every page â€” an over-wide Save next to a narrow Cancel reads as a mistake. */
.modal-footer {
  background: var(--aae-surface-2);
  border-top: 1px solid var(--aae-line);
  border-radius: 0 0 calc(var(--aae-radius) - 4px) calc(var(--aae-radius) - 4px);
  gap: .5rem;
}
.modal-footer > .btn { min-width: 116px; margin: 0; }
.modal-footer .btn-outline-secondary {
  background: var(--aae-surface);
  border-color: var(--aae-line);
  color: var(--aae-ink);
}
.modal-footer .btn-outline-secondary:hover { background: var(--aae-line); color: var(--aae-ink); }

/* =========================================================================
   Tabulator header: tinted, bold, centred, ruled
   ========================================================================= */
.tabulator .tabulator-header {
  background: var(--aae-grid-header-bg);
  border-bottom: 2px solid var(--aae-grid-header-line);
  border-radius: 10px 10px 0 0;
  font-weight: 700;
  color: var(--aae-ink);
  font-size: .8rem;
}
.tabulator .tabulator-header .tabulator-col { background: transparent; border-right: 1px solid var(--aae-grid-header-line); }
.tabulator .tabulator-header .tabulator-col:last-child { border-right: none; }
.tabulator .tabulator-header .tabulator-col .tabulator-col-content { padding: 9px 10px; }
.tabulator .tabulator-header .tabulator-col .tabulator-col-title {
  text-align: center; white-space: nowrap; text-overflow: ellipsis; font-weight: 700;
}

/* Rows sit tighter by default; the Appearance page can still loosen them. */
:root { --aae-cell-pad: 8px 12px; }
html[data-grid-density="compact"] { --aae-cell-pad: 5px 10px; }
html[data-grid-density="normal"]  { --aae-cell-pad: 8px 12px; }
html[data-grid-density="relaxed"] { --aae-cell-pad: 14px 12px; }
.tabulator .tabulator-row { min-height: 0; }
.tabulator .tabulator-row .tabulator-cell { padding: var(--aae-cell-pad); }

/* =========================================================================
   Toasts â€” custom, theme-aware. Bottom-right, newest on top.
   ========================================================================= */
.aae-toasts {
  position: fixed; right: 1rem; bottom: 1rem; z-index: 1090;
  display: flex; flex-direction: column-reverse; gap: .6rem;
  max-width: min(420px, calc(100vw - 2rem)); pointer-events: none;
}
.aae-toast {
  pointer-events: auto; position: relative; overflow: hidden;
  display: grid; grid-template-columns: auto 1fr auto; align-items: start; gap: .7rem;
  padding: .8rem .9rem; border-radius: 12px;
  background: var(--aae-surface); color: var(--aae-ink);
  border: 1px solid var(--aae-line); border-left: 4px solid var(--aae-toast-accent, var(--aae-primary));
  box-shadow: 0 12px 32px rgba(15,23,42,.16);
  font-size: .9rem; line-height: 1.45;
  animation: aae-toast-in .22s cubic-bezier(.2,.8,.2,1);
}
.aae-toast.leaving { animation: aae-toast-out .18s ease forwards; }
@keyframes aae-toast-in  { from { opacity: 0; transform: translateX(18px) scale(.98); } }
@keyframes aae-toast-out { to   { opacity: 0; transform: translateX(18px) scale(.98); } }

.aae-toast-icon { font-size: 1.1rem; line-height: 1.35; color: var(--aae-toast-accent); }
.aae-toast-body { min-width: 0; word-break: break-word; }
.aae-toast-body strong { font-weight: 700; }
.aae-toast-close {
  border: 0; background: transparent; color: var(--aae-muted); padding: 0;
  width: 22px; height: 22px; border-radius: 6px; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center; font-size: .75rem;
}
.aae-toast-close:hover { background: var(--aae-surface-2); color: var(--aae-ink); }

/* Life-remaining bar, so an auto-dismissing toast never vanishes without warning. */
.aae-toast-bar {
  position: absolute; left: 0; bottom: 0; height: 2px; width: 100%;
  background: var(--aae-toast-accent); transform-origin: left;
  animation: aae-toast-bar linear forwards;
}
@keyframes aae-toast-bar { from { transform: scaleX(1); } to { transform: scaleX(0); } }

.aae-toast.success { --aae-toast-accent: #16a34a; }
.aae-toast.error   { --aae-toast-accent: #dc2626; }
.aae-toast.warn    { --aae-toast-accent: #d97706; }
.aae-toast.info    { --aae-toast-accent: var(--aae-primary); }

@media (prefers-reduced-motion: reduce) {
  .aae-toast, .aae-toast.leaving, .aae-toast-bar { animation: none; }
}
@media (max-width: 575.98px) {
  .aae-toasts { left: .75rem; right: .75rem; bottom: .75rem; max-width: none; }
}

/* =========================================================================
   Custom confirm / alert dialog
   ========================================================================= */
.aae-dialog .modal-content { border-radius: 16px; overflow: hidden; }
.aae-dialog .modal-footer { justify-content: center; }
.aae-dialog .modal-footer > .btn { min-width: 108px; }

.aae-dialog-icon {
  width: 56px; height: 56px; margin: 0 auto; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center; font-size: 1.6rem;
}
.aae-dialog-icon.danger  { background: rgba(220,38,38,.12);  color: #dc2626; }
.aae-dialog-icon.warning { background: rgba(217,119,6,.12);  color: #d97706; }
.aae-dialog-icon.success { background: rgba(22,163,74,.12);  color: #16a34a; }
.aae-dialog-icon.primary { background: var(--aae-primary-soft); color: var(--aae-primary); }

/* Bootstrap has no .btn-danger override in our theme; keep it readable in dark mode. */
.aae-dialog .btn-danger { --bs-btn-bg: #dc2626; --bs-btn-border-color: #dc2626; --bs-btn-hover-bg: #b91c1c; --bs-btn-hover-border-color: #b91c1c; }
.aae-dialog .btn-warning { --bs-btn-bg: #d97706; --bs-btn-border-color: #d97706; --bs-btn-color: #fff; --bs-btn-hover-color: #fff; }

/* ---------- Nav items for pages that do not exist yet ----------
   Rendered as <span>, not <a href="#">: no status-bar target on hover, no jump to top on click. */
.aae-sidebar .nav-link.pending {
  color: #56637a; cursor: default; user-select: none;
}
.aae-sidebar .nav-link.pending:hover { background: transparent; color: #56637a; }
.aae-sidebar .nav-link.pending .bi { opacity: .55; }
.aae-sidebar .nav-soon {
  margin-left: auto; font-size: .6rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: #7c8aa5; background: rgba(255,255,255,.06); border-radius: 5px; padding: .12rem .32rem; line-height: 1.3;
}
/* In the icon rail there is no room for the badge, and a dimmed icon already says "not yet". */
@media (min-width: 992px) {
  .aae-layout.mini .aae-sidebar .nav-soon { display: none; }
  .aae-layout.mini:not(.hover-off) .aae-sidebar:hover .nav-soon,
  .aae-layout.mini:not(.hover-off) .aae-sidebar:focus-within .nav-soon { display: inline-block; }
}

/* ---------- Profile photo ---------- */
.aae-photo-ring {
  width: 96px; height: 96px; flex: 0 0 auto; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  overflow: hidden; background: var(--aae-grad); color: #fff;
  border: 3px solid var(--aae-surface); box-shadow: 0 6px 18px rgba(15,23,42,.18);
}
.aae-photo-ring > img { width: 100%; height: 100%; object-fit: cover; }
.aae-photo-initials { font-size: 2rem; font-weight: 700; line-height: 1; }

/* The topbar avatar carries either a letter or a photo; the photo must fill the circle. */
.aae-avatar { overflow: hidden; padding: 0; }
.aae-avatar > img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ---------- "Back to sign in" on the registration card ---------- */
.aae-back-link {
  display: inline-flex; align-items: center; gap: .4rem;
  font-size: .85rem; font-weight: 600; text-decoration: none;
  color: var(--aae-muted); margin-bottom: .75rem;
}
.aae-back-link:hover { color: var(--aae-primary); }

/* ---------- Avatars ---------- */
.aae-photo-ring.sm { width: 72px; height: 72px; border-width: 2px; }
.aae-photo-ring.sm .aae-photo-initials { font-size: 1.5rem; }

.aae-grid-avatar {
  width: 34px; height: 34px; border-radius: 50%; overflow: hidden;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--aae-grad); color: #fff; font-weight: 700; font-size: .8rem;
  vertical-align: middle;
}
.aae-grid-avatar > img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Deleted tenants stay readable but visibly inert in the platform console. */
.tabulator .tabulator-row.row-deleted { opacity: .55; }
.tabulator .tabulator-row.row-deleted .tabulator-cell { text-decoration: line-through; text-decoration-color: rgba(220,38,38,.5); }
.tabulator .tabulator-row.row-deleted .badge { text-decoration: none; }

/* =========================================================================
   Date picker â€” always dd/MM/yyyy, never the browser's locale
   ========================================================================= */
.aae-datepicker {
  position: absolute; z-index: 1085; width: 268px; padding: .6rem;
  background: var(--aae-surface); color: var(--aae-ink);
  border: 1px solid var(--aae-line); border-radius: 12px;
  box-shadow: 0 16px 40px rgba(15,23,42,.18);
  font-size: .88rem;
}
.aae-datepicker .dp-head { display: flex; align-items: center; gap: .3rem; margin-bottom: .5rem; }
.aae-datepicker .dp-title { display: flex; gap: .3rem; flex: 1; }
.aae-datepicker .dp-month, .aae-datepicker .dp-year {
  flex: 1; min-width: 0; border: 1px solid var(--aae-line); border-radius: 8px;
  background: var(--aae-input-bg); color: var(--aae-ink); padding: .25rem .35rem; font-weight: 600; font-size: .85rem;
}
.aae-datepicker .dp-nav {
  border: 0; background: transparent; color: var(--aae-muted);
  width: 28px; height: 28px; border-radius: 8px; line-height: 1;
}
.aae-datepicker .dp-nav:hover { background: var(--aae-surface-2); color: var(--aae-ink); }

.aae-datepicker .dp-weekdays,
.aae-datepicker .dp-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.aae-datepicker .dp-weekdays span {
  text-align: center; font-size: .68rem; font-weight: 700; color: var(--aae-muted);
  text-transform: uppercase; padding: .25rem 0;
}
.aae-datepicker .dp-cell {
  height: 32px; border: 0; border-radius: 8px; background: transparent; color: var(--aae-ink);
  font-size: .85rem; line-height: 1;
}
.aae-datepicker .dp-empty { visibility: hidden; }
.aae-datepicker .dp-cell:hover:not(:disabled) { background: var(--aae-surface-2); }
.aae-datepicker .dp-today { box-shadow: inset 0 0 0 1px var(--aae-primary-2); font-weight: 700; }
.aae-datepicker .dp-selected { background: var(--aae-primary); color: var(--aae-primary-ink); font-weight: 700; }
.aae-datepicker .dp-selected:hover { background: var(--aae-primary-dark); }
.aae-datepicker .dp-disabled { color: var(--aae-muted); opacity: .35; cursor: not-allowed; }

.aae-datepicker .dp-foot {
  display: flex; justify-content: space-between; margin-top: .5rem;
  padding-top: .5rem; border-top: 1px solid var(--aae-line);
}
.aae-datepicker .dp-link {
  border: 0; background: transparent; color: var(--aae-primary);
  font-size: .82rem; font-weight: 600; padding: .15rem .35rem; border-radius: 6px;
}
.aae-datepicker .dp-link:hover { background: var(--aae-primary-soft); }
.aae-datepicker .dp-clear { color: var(--aae-muted); }

/* A half-typed date is a mistake, not a value. */
.aae-field > .form-control.is-invalid { border-color: #dc2626; }

/* A locked field is disabled, but must not look broken â€” it looks authoritative. */
.aae-field > .form-control.locked { background: var(--aae-surface-2); color: var(--aae-muted); cursor: not-allowed; }

/* =========================================================================
   Organisation cards â€” a row cannot show a logo, a map and a geofence
   ========================================================================= */
.aae-org-grid {
  display: grid; gap: 1rem;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
}

.org-card { overflow: hidden; display: flex; flex-direction: column; }
.org-card.is-inactive { opacity: .72; }
.org-card .card-body { padding: .9rem 1rem .6rem; }

.org-card-mapwrap { position: relative; height: 150px; background: var(--aae-surface-2); }
.org-card-map { position: absolute; inset: 0; z-index: 0; }
.org-card-map.no-pin,
.org-card-map.map-failed {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  color: var(--aae-muted); background: var(--aae-surface-2);
}
.org-card-map.no-pin .bi { font-size: 1.6rem; }
/* Leaflet paints its own panes; keep them inside the rounded card. */
.org-card-mapwrap .leaflet-container { background: var(--aae-surface-2); }

.org-card-maplink {
  position: absolute; right: .5rem; top: .5rem; z-index: 500;
  width: 30px; height: 30px; border-radius: 8px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--aae-surface); color: var(--aae-ink);
  box-shadow: 0 2px 8px rgba(15,23,42,.2); text-decoration: none;
}
.org-card-maplink:hover { color: var(--aae-primary); }

.org-card-logo {
  width: 44px; height: 44px; flex: 0 0 auto; border-radius: 10px;
  object-fit: contain; background: var(--aae-surface); padding: 3px;
  border: 1px solid var(--aae-line);
}
.org-card-logo.placeholder-logo {
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--aae-muted); background: var(--aae-surface-2);
}
.org-card-title {
  font-size: 1rem; font-weight: 700; margin: 0; line-height: 1.3;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.min-w-0 { min-width: 0; }

.org-card-facts {
  display: grid; grid-template-columns: auto 1fr; gap: .15rem .6rem;
  margin: 0; font-size: .82rem;
}
.org-card-facts dt { color: var(--aae-muted); font-weight: 600; }
.org-card-facts dd { margin: 0; color: var(--aae-ink); overflow-wrap: anywhere; }

.org-card-actions {
  display: flex; gap: .5rem; justify-content: flex-end;
  background: var(--aae-surface-2); border-top: 1px solid var(--aae-line);
  padding: .6rem 1rem;
}

/* Read-only tenants keep the map and the facts; they lose the buttons. */
body.aae-ro .org-card-actions { display: none; }

/* ---------- Shared empty state ---------- */
.aae-empty {
  grid-column: 1 / -1;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: .35rem; padding: 3rem 1rem; text-align: center;
  border: 1px dashed var(--aae-line); border-radius: var(--aae-radius);
  background: var(--aae-surface); color: var(--aae-ink);
}
.aae-empty > .bi { font-size: 2rem; color: var(--aae-muted); margin-bottom: .25rem; }

/* ---------- Employee documents tab ---------- */
/* The nav-tabs sit above the scrolling modal body, so they must not scroll away with it. */
#empModal .nav-tabs { border-bottom-color: var(--aae-line); }
#empModal .nav-tabs .nav-link { color: var(--aae-muted); border: none; border-bottom: 2px solid transparent; }
#empModal .nav-tabs .nav-link:hover { color: var(--aae-ink); }
#empModal .nav-tabs .nav-link.active {
  color: var(--aae-primary);
  background: transparent;
  border-bottom-color: var(--aae-primary);
}
#docsCount { font-weight: 600; opacity: .75; }

.aae-doc-table thead th {
  background: var(--aae-grid-header-bg);
  color: var(--aae-ink);
  font-size: .8rem;
  text-transform: uppercase;
  letter-spacing: .03em;
  border-bottom: 1px solid var(--aae-line);
}
.aae-doc-table tbody tr:nth-child(even) { background: var(--aae-row-alt); }
.aae-doc-table td, .aae-doc-table th { border-color: var(--aae-line); }
.aae-doc-table .btn-link { text-decoration: none; }
.aae-doc-table .btn-link:hover { text-decoration: underline; }
/* ---------- Day bar (dashboard date chooser) ----------
   A chip, a two-way stepper and a Today pill. The calendar it opens marks the days that actually
   have data, so nobody steps backwards through an empty month looking for records. */
.aae-daybar { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }

.aae-daychip {
  display: inline-flex; align-items: center; gap: .55rem;
  background: var(--aae-surface); border: 1px solid var(--aae-line); border-radius: .7rem;
  padding: .55rem .95rem; font-weight: 600; color: var(--aae-ink); font-size: .95rem;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.aae-daychip:hover { border-color: var(--aae-primary); }
.aae-daychip i { color: var(--aae-muted); }

/* Stacked chevrons, one control: the day moves in one direction or the other and nowhere else. */
.aae-daystep { display: inline-flex; flex-direction: column; border: 1px solid var(--aae-line);
  border-radius: .6rem; overflow: hidden; background: var(--aae-surface); }
.aae-daystep button {
  border: 0; background: transparent; color: var(--aae-muted);
  padding: .05rem .5rem; line-height: 1.15; font-size: .8rem;
}
.aae-daystep button:hover:not(:disabled) { background: var(--aae-surface-2); color: var(--aae-ink); }
.aae-daystep button:disabled { opacity: .35; }
.aae-daystep button + button { border-top: 1px solid var(--aae-line); }

.aae-daycal {
  position: absolute; z-index: 1080; width: 288px; padding: .75rem;
  background: var(--aae-surface); border: 1px solid var(--aae-line); border-radius: .8rem;
  box-shadow: 0 14px 38px rgba(15, 23, 42, .16);
}
.aae-daycal .dc-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: .5rem; }
.aae-daycal .dc-title { font-weight: 600; font-size: .93rem; }
.aae-daycal .dc-nav { border: 0; background: transparent; color: var(--aae-muted); padding: .2rem .45rem; border-radius: .4rem; }
.aae-daycal .dc-nav:hover { background: var(--aae-surface-2); color: var(--aae-ink); }

.aae-daycal .dc-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.aae-daycal .dc-dow { text-align: center; font-size: .7rem; color: var(--aae-muted); padding: .25rem 0; }

.aae-daycal .dc-day {
  position: relative; border: 0; background: transparent; border-radius: 50%;
  aspect-ratio: 1; font-size: .82rem; color: var(--aae-ink);
  display: flex; align-items: center; justify-content: center;
}
.aae-daycal .dc-day:hover:not(:disabled) { background: var(--aae-surface-2); }
.aae-daycal .dc-day:disabled { color: var(--aae-muted); opacity: .4; }
.aae-daycal .dc-day.today { font-weight: 700; }
.aae-daycal .dc-day.sel { background: var(--aae-ink); color: #fff; font-weight: 600; }

/* The dot is the whole point: it says this day has attendance before you open it. */
.aae-daycal .dc-dot {
  position: absolute; bottom: 3px; left: 50%; transform: translateX(-50%);
  width: 4px; height: 4px; border-radius: 50%; background: #1f9d57;
}
.aae-daycal .dc-day.sel .dc-dot { background: #fff; }

/* ---------- Punch day (one employee, one day) ----------
   Mirrors the phone's own history so the two read the same: a coloured spine per kind of absence,
   the out and the return paired on one card, and the time away worked out rather than left to the
   reader to subtract. */
/* The card stays plain and the TIME carries the colour — the phone's own treatment, and the better
   one. Washing the whole card was tried first and made every row a block of colour: with three or
   four segments on a busy day the page became bands of green, purple and red with the times lost
   inside them. Tinting only the time puts the colour exactly where the eye already goes, and the
   card goes back to being a card.

   Mixed against the surface rather than hard-coded, so one declaration serves both themes. */
.pd-card {
  display: flex; gap: .75rem; align-items: stretch;
  background: var(--aae-surface); border: 1px solid var(--aae-line);
  border-radius: .7rem; padding: .7rem .85rem; margin-bottom: .5rem;
}
.pd-spine { width: 4px; border-radius: 2px; flex: 0 0 4px; }
.pd-body { flex: 1; min-width: 0; }

.pd-line { display: flex; align-items: center; gap: .6rem; }
.pd-line + .pd-line { margin-top: .25rem; }

/* The one thing that carries the segment's colour. A chip rather than coloured text: coloured
   digits on white are hard to read at this size, and it is the KIND of absence being shown, not a
   warning about the number itself. */
.pd-time {
  font-weight: 700; font-size: 1rem; font-variant-numeric: tabular-nums;
  background: color-mix(in srgb, var(--pd-tone, transparent) 16%, transparent);
  border-radius: .45rem; padding: .1rem .45rem; margin: -.1rem 0;
  /* Still a fixed column so the times line up down the card, with the padding inside it. */
  min-width: 3.4rem; box-sizing: content-box; text-align: center;
}
.pd-label { font-size: .68rem; letter-spacing: .06em; color: var(--aae-muted); min-width: 2.1rem; }

/* The reason is the point of an out punch, so it takes the room the labels give up. */
.pd-reason { margin-left: auto; text-align: right; font-size: .9rem; }
.pd-dur {
  margin-left: auto; background: var(--aae-surface-2, #f1f5f9); color: var(--aae-muted);
  border-radius: .5rem; padding: .12rem .5rem; font-size: .8rem; font-weight: 600;
}
.pd-flag { margin-top: .35rem; font-size: .8rem; color: #d8352f; }

/* The punch-day header sits on the gradient, so its subtitle must be light, not slate. */
/* Sits beside the name on the gradient header, so it is light and clearly the lesser of the two. */
#punchDayModal .pd-meta {
  color: rgba(255,255,255,.78); font-size: .84rem; font-weight: 500; margin-left: .55rem;
}

/* ---------- Punch log grid ----------
   fitColumns sizes the columns to the element, then the vertical scrollbar appears and takes ~15px
   back — which is enough to trigger a horizontal scrollbar on a table whose columns already fit.
   The overflow is that scrollbar's width and nothing else, so it is hidden rather than scrolled. */
#activityTable .tabulator-tableholder { overflow-x: hidden; }

/* The vertical scrollbar overlays the last column; without this the meridiem in "6:21 PM" is cut. */
#activityTable .tabulator-row .tabulator-cell:last-child { padding-right: 1rem; }

/* =========================================================================
   Employee calendar — one person's month, the way the phone draws it
   ========================================================================= */
.aae-ecal .ec-month { display: flex; align-items: center; justify-content: space-between; margin-bottom: .75rem; }
.aae-ecal .ec-month-title { font-weight: 700; font-size: 1.15rem; }
.aae-ecal .ec-nav {
  border: 1px solid var(--aae-line); background: var(--aae-surface); color: var(--aae-ink);
  width: 2.2rem; height: 2.2rem; border-radius: 10px; display: inline-flex; align-items: center; justify-content: center;
}
.aae-ecal .ec-nav:hover:not(:disabled) { border-color: var(--aae-primary); color: var(--aae-primary); }
.aae-ecal .ec-nav:disabled { opacity: .35; }

.aae-ecal .ec-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: .5rem; }
.aae-ecal .ec-stat { background: var(--aae-surface-2); border: 1px solid var(--aae-line); border-radius: 12px; padding: .5rem .75rem; }
.aae-ecal .ec-stat-label { font-size: .68rem; font-weight: 600; letter-spacing: .06em; color: var(--aae-muted); text-transform: uppercase; }
.aae-ecal .ec-stat-value { font-size: 1.35rem; font-weight: 700; line-height: 1.2; }
.aae-ecal .ec-hours { font-size: .85rem; color: var(--aae-muted); margin: .5rem 0 .75rem; }

/* Sunday first, seven columns. Rows size to their squares, so a week with no badges stays short. */
.aae-ecal .ec-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 6px; transition: opacity .15s; }
.aae-ecal .ec-dow { text-align: center; font-size: .75rem; font-weight: 600; color: #334155; padding: .15rem 0; }
.aae-ecal .ec-dow.sun { color: #C0392B; }

.aae-ecal .ec-sq {
  position: relative; min-height: 3.4rem; border: 0; border-radius: 10px; padding: .35rem .15rem .3rem;
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  font: inherit; text-align: center; cursor: pointer; box-shadow: inset 0 0 0 0 transparent;
  transition: box-shadow .12s ease, transform .12s ease;
}
.aae-ecal .ec-sq.idle { cursor: default; }
.aae-ecal button.ec-sq:hover { transform: translateY(-1px); box-shadow: 0 3px 10px rgba(15,23,42,.12); }
.aae-ecal .ec-sq.today { box-shadow: inset 0 0 0 2px #0E2A47; }
/* The chosen date wears the brand ring, outside the square, so it never hides today's own outline. */
.aae-ecal .ec-sq.sel { outline: 3px solid var(--aae-primary); outline-offset: 2px; }
.aae-ecal .ec-num { font-weight: 600; font-size: .95rem; line-height: 1.2; }
.aae-ecal .ec-tick { position: absolute; top: 3px; right: 6px; font-size: .7rem; font-weight: 700; }
.aae-ecal .ec-badge {
  display: inline-block; color: #fff; font-size: .62rem; font-weight: 600; line-height: 1.35;
  padding: 0 .35rem; border-radius: 6px; white-space: nowrap; max-width: 100%; overflow: hidden; text-overflow: ellipsis;
}

.aae-ecal .ec-legend { display: flex; flex-wrap: wrap; gap: .35rem 1rem; margin-top: 1rem; font-size: .78rem; color: var(--aae-muted); }
.aae-ecal .ec-leg { display: inline-flex; align-items: center; gap: .35rem; }
.aae-ecal .ec-sw { width: 14px; height: 14px; border-radius: 4px; display: inline-block; }

/* The chosen date's detail. Stays in view beside a long month on a wide screen. */
.aae-ecal .ec-detail {
  position: sticky; top: 0; background: var(--aae-surface); border: 1px solid var(--aae-line);
  border-radius: 14px; padding: 1rem;
}
.aae-ecal .ec-day-head { display: flex; align-items: flex-start; justify-content: space-between; gap: .75rem; }
.aae-ecal .ec-weekday { font-size: .72rem; font-weight: 600; letter-spacing: .08em; color: var(--aae-muted); }
.aae-ecal .ec-date { font-size: 1.2rem; font-weight: 700; }
.aae-ecal .ec-chip { font-size: .8rem; font-weight: 600; padding: .3rem .7rem; border-radius: 999px; white-space: nowrap; }
.aae-ecal .ec-notes { margin-top: .4rem; font-size: .85rem; color: #B45309; }
.aae-ecal .ec-day-stats {
  display: grid; grid-template-columns: repeat(5, auto); justify-content: space-between; gap: .5rem;
  background: #0E2A47; color: #fff; border-radius: 12px; padding: .65rem .85rem; margin: .8rem 0;
}
.aae-ecal .ec-day-stats .ec-stat-label { color: rgba(255,255,255,.65); }
.aae-ecal .ec-day-value { font-weight: 700; font-size: .95rem; white-space: nowrap; }
.aae-ecal .ec-day-stats .ec-day-value[style*="#15803D"] { color: #6EE7A0 !important; }
.aae-ecal .ec-day-stats .ec-day-value[style*="#2c5fb3"] { color: #6FB0F0 !important; }
.aae-ecal .ec-nopunch { margin-top: .8rem; color: var(--aae-muted); font-size: .9rem; }
.aae-ecal .ec-empty { text-align: center; color: var(--aae-muted); padding: 2.5rem 1rem; }
.aae-ecal .ec-empty .bi { font-size: 2rem; display: block; margin-bottom: .5rem; opacity: .6; }

@media (max-width: 575.98px) {
  .aae-ecal .ec-stats { grid-template-columns: repeat(2, 1fr); }
  .aae-ecal .ec-grid { gap: 3px; }
  .aae-ecal .ec-sq { min-height: 2.9rem; }
  .aae-ecal .ec-badge { font-size: .55rem; padding: 0 .2rem; }
  .aae-ecal .ec-day-stats { grid-template-columns: repeat(3, auto); }
}

/* Register: an organisation's heading row above its staff. */
.aae-reg-group > td {
  background: var(--aae-primary-tint) !important; color: var(--aae-primary); font-weight: 700; font-size: .82rem;
  padding: .35rem .6rem !important; border-left: 0; border-right: 0;
}
/* The label rides with the sticky name column, so it stays readable while the dates scroll sideways. */
.aae-reg-group-label { position: sticky; left: .6rem; }
.aae-reg-group-count { font-weight: 500; color: var(--aae-primary); }

/* ---------- Stale results: the filters have moved on, the grid has not ----------
   Amber, like the read-only banner: a state to notice, not a failure. The grid keeps its rows and
   loses a little contrast, so it still reads as the previous answer rather than as an empty one. */
.aae-stale {
  display: flex; align-items: center; gap: .6rem;
  margin-bottom: .6rem; padding: .55rem .85rem;
  border: 1px solid #fcd9a4; border-radius: 12px;
  background: #fff8ec; color: #92400e; font-size: .88rem;
}
.aae-stale .bi { font-size: 1rem; }
.aae-stale .btn { --bs-btn-padding-y: .2rem; --bs-btn-padding-x: .7rem; box-shadow: none; }
.aae-stale-dim { opacity: .5; transition: opacity .15s ease; }

/* Two nudges and it stops. A control that pulses for ever is a control people stop seeing. */
.aae-stale-glow { animation: aae-stale-pulse 1.1s ease-out 2; }
@keyframes aae-stale-pulse {
  0%, 100% { box-shadow: 0 6px 16px rgba(var(--aae-primary-rgb), .30); }
  50% { box-shadow: 0 0 0 .35rem rgba(var(--aae-primary-rgb), .28); }
}
@media (prefers-reduced-motion: reduce) { .aae-stale-glow { animation: none; } }

/* Report actions in the top bar — Print, PDF, Excel. Solid and labelled, as the Atease accounts module
   draws them: red for PDF and green for Excel are how people already read those formats. */
.aae-hbtn {
  height: 32px; padding: 0 11px; border-radius: 9px; border: 0; cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px;
  color: #fff; font-size: 12.5px; font-weight: 700; letter-spacing: .02em;
  transition: filter .15s, opacity .15s;
}
.aae-hbtn .bi { font-size: 15px; line-height: 1; }
.aae-hbtn .spinner-border { width: 14px; height: 14px; border-width: 2px; }
.aae-hbtn:hover:not(:disabled) { filter: brightness(1.12); }
.aae-hbtn:disabled { opacity: .55; cursor: default; }
.aae-hbtn-pdf { background: #c0392b; }
.aae-hbtn-xls { background: #1d7145; }
/* Print sits on the dark header, where its old navy (#0E2A47) was the header's own colour and the
   button read as a hole. Light and outlined instead: visible, and not a third format colour. */
.aae-hbtn-print { background: rgba(255, 255, 255, .16); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .5); }
.aae-hbtn-print:hover:not(:disabled) { background: rgba(255, 255, 255, .28); filter: none; }
/* On a phone the bar is tight — the colour and the icon still carry the meaning. */
@media (max-width: 560px) {
  .aae-hbtn-t { display: none; }
  .aae-hbtn { padding: 0 9px; }
}

/* Attendance Register cells — drawn like the calendar's days: the colour, one mark, small notes. */
#grid td.aae-rc {
  text-align: center; vertical-align: middle; padding: .3rem .1rem; line-height: 1.1;
  border-color: var(--bs-body-bg); border-width: 2px;    /* a gap between days, like the calendar's tiles */
}
#grid td.aae-rc.clickable { cursor: pointer; }
#grid td.aae-rc.clickable:hover { filter: brightness(.95); }
.aae-rc-main { font-weight: 700; font-size: .82rem; }
.aae-rc-marks { display: flex; justify-content: center; gap: 2px; margin-top: 1px; font-size: .6rem; font-weight: 800; letter-spacing: .01em; }

.aae-rl { display: inline-flex; align-items: center; gap: .35rem; color: var(--aae-muted); }
.aae-rl-chip {
  display: inline-flex; align-items: center; justify-content: center; min-width: 1.9rem; height: 1.35rem;
  padding: 0 .3rem; border-radius: 6px; font-weight: 700; font-size: .72rem;
}
.aae-rl-mark { font-weight: 800; font-size: .8rem; min-width: .9rem; text-align: center; }

/* Employee calendar — refinements. Later in the file, so these win over the first draft above. */
.aae-ecal .ec-month-title { font-size: 1.25rem; letter-spacing: -.01em; }

.aae-ecal .ec-stat {
  position: relative; overflow: hidden; background: var(--aae-surface);
  border: 1px solid var(--aae-line); border-radius: 12px; padding: .55rem .8rem .55rem 1rem;
  box-shadow: 0 1px 2px rgba(15, 23, 42, .04);
}
.aae-ecal .ec-stat::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px; background: var(--ec-accent, var(--aae-line));
}
.aae-ecal .ec-stat-value { font-size: 1.5rem; }

.aae-ecal .ec-grid { gap: 8px; }
.aae-ecal .ec-dow {
  background: var(--aae-surface-2); border-radius: 8px; padding: .3rem 0;
  font-size: .7rem; letter-spacing: .06em; text-transform: uppercase; color: #334155;
}
.aae-ecal .ec-dow.sun { color: #C0392B; }

.aae-ecal .ec-sq {
  min-height: 4rem; border-radius: 12px; padding: .45rem .2rem .35rem; gap: 3px;
  box-shadow: inset 0 0 0 1px rgba(15, 23, 42, .05);
}
.aae-ecal button.ec-sq:hover { transform: translateY(-2px); box-shadow: 0 6px 14px rgba(15, 23, 42, .12); }
.aae-ecal .ec-sq.today { box-shadow: inset 0 0 0 2px #0E2A47; }
.aae-ecal .ec-sq.sel { outline: 3px solid var(--aae-primary); outline-offset: 2px; }
/* A day that has not come yet is an outline, not a block — the month's real days stand out from it. */
.aae-ecal .ec-sq.future { background: transparent; box-shadow: inset 0 0 0 1px #E2E8F0; border: 1px dashed transparent; }
.aae-ecal .ec-sq.future .ec-num { color: #B8C4D2 !important; font-weight: 500; }
.aae-ecal .ec-num { font-size: 1.02rem; font-weight: 700; }

.aae-ecal .ec-tick {
  top: 5px; right: 5px; width: 15px; height: 15px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: rgba(255, 255, 255, .65); font-size: .62rem;
}
.aae-ecal .ec-badge { border-radius: 999px; padding: .02rem .4rem; font-size: .6rem; letter-spacing: .01em; }

@media (max-width: 575.98px) {
  .aae-ecal .ec-grid { gap: 4px; }
  .aae-ecal .ec-sq { min-height: 3.2rem; border-radius: 9px; }
  .aae-ecal .ec-tick { width: 12px; height: 12px; top: 3px; right: 3px; }
}

/* Employee calendar — fits the screen. Later in the file, so these win over the rules above. */

/* The four totals on one line each: label left, figure right. Half the height of label-over-figure. */
.aae-ecal .ec-stat { display: flex; align-items: center; justify-content: space-between; gap: .5rem; padding: .4rem .7rem .4rem .95rem; }
.aae-ecal .ec-stat-value { font-size: 1.3rem; line-height: 1; }
.aae-ecal .ec-month { margin-bottom: .5rem; }
.aae-ecal .ec-month-title { font-size: 1.15rem; }
.aae-ecal .ec-nav { width: 2rem; height: 2rem; }
.aae-ecal .ec-hours { margin: .4rem 0 .5rem; font-size: .8rem; }
.aae-ecal .ec-grid { gap: 6px; }
.aae-ecal .ec-dow { padding: .2rem 0; }

/* Six weeks always fit. Each day takes an equal share of the height left once the popup's title bar,
   the month switcher, the totals and the weekday band are counted out — never taller than it looks
   good, never too short to read. A badge sits beside another rather than beneath it, so a busy day
   does not stretch its whole week. */
.aae-ecal .ec-sq {
  min-height: clamp(2.5rem, calc((100vh - 350px) / 6 - 6px), 4rem);
  padding: .3rem .15rem .25rem; gap: 2px;
}
.aae-ecal .ec-num { font-size: .95rem; }
.aae-ecal .ec-sq { flex-direction: column; justify-content: flex-start; }
.aae-ecal .ec-sq .ec-badge { font-size: .56rem; padding: 0 .3rem; }
.aae-ecal .ec-sq { flex-wrap: nowrap; }
.aae-ecal .ec-badges { display: flex; flex-wrap: wrap; justify-content: center; gap: 2px; max-width: 100%; }

.aae-ecal .ec-legend { margin-top: .9rem; font-size: .74rem; gap: .3rem .8rem; }
.aae-ecal .modal-body, #empCalModal .modal-body { padding-top: .8rem; padding-bottom: .8rem; }

/* Employee calendar — the popup itself gives back height too, so a six-week month fits a laptop screen. */
#empCalModal .modal-dialog { margin-top: .6rem; margin-bottom: .6rem; min-height: calc(100% - 1.2rem); }
#empCalModal .modal-dialog-scrollable { max-height: calc(100% - 1.2rem); height: calc(100% - 1.2rem); }
#empCalModal .modal-header { padding-top: .6rem; padding-bottom: .6rem; }
#empCalModal .modal-body { padding-top: .6rem; padding-bottom: .6rem; }
.aae-ecal .ec-stats { gap: .4rem; }
.aae-ecal .ec-hours { margin: .3rem 0 .35rem; }
.aae-ecal .ec-grid { gap: 5px; }
.aae-ecal .ec-sq { min-height: clamp(2.15rem, calc((100vh - 300px) / 6 - 5px), 4rem); padding: .22rem .12rem .2rem; }
.aae-ecal .ec-num { font-size: .92rem; line-height: 1.15; }

/* Print on a popup's gradient title bar: navy would sink into the purple, so it goes light and clear. */
.modal-header .aae-hbtn-onbar { background: rgba(255, 255, 255, .18); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .45); }
.modal-header .aae-hbtn-onbar:hover:not(:disabled) { background: rgba(255, 255, 255, .28); filter: none; }

/* ---------- Audit Logs ---------- */
.aae-audit-scroll { max-height: calc(100vh - 17rem); min-height: 12rem; }
.aae-audit thead th { position: sticky; top: 0; z-index: 2; background: var(--bs-tertiary-bg, #f8f9fa); font-size: .78rem;
  text-transform: uppercase; letter-spacing: .03em; color: var(--bs-secondary-color); white-space: nowrap; }
.aae-audit td { font-size: .85rem; vertical-align: top; padding-top: .45rem; padding-bottom: .45rem; }
.aae-audit tbody tr[data-i] { cursor: pointer; }
.aae-audit-act { display: inline-block; padding: .12rem .5rem; border-radius: 999px; font-size: .78rem; font-weight: 600; white-space: nowrap; }
.aae-audit-chg { line-height: 1.35; overflow-wrap: anywhere; }
.aae-audit-chg s { text-decoration-thickness: 1px; }
.aae-audit-detail thead th { font-size: .75rem; text-transform: uppercase; color: var(--bs-secondary-color); }
.aae-audit-detail tr.aae-audit-changed td { background: #FFF7E0; }
/* A phone has no room for five columns: each entry becomes a small card — when and who on top, then
   what, the record, and the changes. */
@media (max-width: 767.98px) {
  .aae-audit-scroll { max-height: none; }
  .aae-audit thead { display: none; }
  .aae-audit, .aae-audit tbody, .aae-audit tr, .aae-audit td { display: block; width: 100% !important; }
  .aae-audit tr[data-i] { display: grid; grid-template-columns: auto 1fr; column-gap: .5rem; padding: .55rem .85rem;
    border-bottom: 1px solid var(--bs-border-color); }
  .aae-audit td { border: 0 !important; padding: .08rem 0 !important; background: transparent !important; }
  .aae-audit tr[data-i] td:nth-child(1) { font-size: .75rem; color: var(--bs-secondary-color); }
  .aae-audit tr[data-i] td:nth-child(2) { font-size: .75rem; color: var(--bs-secondary-color); text-align: right; }
  .aae-audit tr[data-i] td:nth-child(n+3) { grid-column: 1 / -1; }
}
/* ---------- Hub pages (Settings, Reports): grouped link tiles ---------- */
.aae-tiles-group + .aae-tiles-group { margin-top: 1.5rem; }
.aae-tiles-title { font-size: .75rem; font-weight: 700; text-transform: uppercase; letter-spacing: .06em;
  color: var(--bs-secondary-color); margin: 0 0 .6rem .15rem; }
.aae-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 17rem), 1fr)); gap: .75rem; }
.aae-tile { display: flex; align-items: center; gap: .8rem; padding: .85rem 1rem; border-radius: .9rem;
  background: var(--bs-body-bg); border: 1px solid var(--bs-border-color-translucent);
  color: inherit; text-decoration: none; transition: transform .12s, box-shadow .12s, border-color .12s; }
a.aae-tile:hover, a.aae-tile:focus-visible { transform: translateY(-1px); border-color: rgba(var(--aae-primary-rgb), .45);
  box-shadow: 0 .4rem 1rem rgba(15, 23, 42, .08); color: inherit; }
.aae-tile.pending { opacity: .6; }
.aae-tile-icon { flex: none; width: 2.5rem; height: 2.5rem; border-radius: .7rem; display: grid; place-items: center;
  background: rgba(var(--aae-primary-rgb), .1); color: var(--aae-primary-2); font-size: 1.2rem; }
.aae-tile-text { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.aae-tile-label { font-weight: 600; }
.aae-tile-note { font-size: .8rem; color: var(--bs-secondary-color); line-height: 1.3; }
.aae-tile-badge { font-size: .72rem; color: var(--aae-primary-2); margin-top: .2rem; font-weight: 600; }
.aae-tile-go { color: var(--bs-secondary-color); flex: none; }


/* ---------- Sidebar flyouts (Reports, Settings) — see nav-flyout.js ---------- */
.aae-sidebar .aae-flyout-caret { margin-left: auto; font-size: .7rem !important; opacity: .55 !important; transition: transform .15s; }
.aae-sidebar li.flyout-open > .nav-link:not(.active) { background: rgba(255,255,255,.08); color: #fff; }
.aae-sidebar li.subnav-open .aae-flyout-caret { transform: rotate(90deg); }
@media (min-width: 992px) {
  .aae-layout.mini .aae-sidebar .aae-flyout-caret { display: none; }
  .aae-layout.mini:not(.hover-off) .aae-sidebar:hover .aae-flyout-caret,
  .aae-layout.mini:not(.hover-off) .aae-sidebar:focus-within .aae-flyout-caret { display: inline-block; }
}

.aae-flyout { position: fixed; z-index: 1085; width: 290px; max-height: calc(100vh - 16px); overflow-y: auto;
  background: #fff; color: #0f172a; border-radius: .9rem; padding: .5rem;
  border: 1px solid rgba(15, 23, 42, .08); box-shadow: 0 1rem 2.5rem rgba(15, 23, 42, .22);
  animation: aae-flyout-in .12s ease-out; }
@keyframes aae-flyout-in { from { opacity: 0; transform: translateX(-4px); } to { opacity: 1; transform: none; } }
.aae-flyout-title { font-weight: 700; font-size: .95rem; padding: .35rem .6rem .15rem; }
.aae-flyout-head { font-size: .66rem; text-transform: uppercase; letter-spacing: .06em; color: #64748b;
  font-weight: 700; margin: .55rem .6rem .2rem; }
.aae-flyout-item, .aae-flyout-all { display: flex; align-items: center; gap: .6rem; padding: .42rem .6rem;
  border-radius: .55rem; color: #0f172a; text-decoration: none; font-size: .9rem; }
.aae-flyout-item i, .aae-flyout-all i { color: var(--aae-primary-2); width: 1.1rem; text-align: center; }
a.aae-flyout-item:hover, a.aae-flyout-item:focus-visible, .aae-flyout-all:hover, .aae-flyout-all:focus-visible {
  background: rgba(var(--aae-primary-rgb), .1); color: var(--aae-primary); outline: none; }
.aae-flyout-item.active { background: rgba(var(--aae-primary-rgb), .14); color: var(--aae-primary); font-weight: 600; }
.aae-flyout-item.pending { opacity: .55; }
.aae-flyout-item .nav-soon { margin-left: auto; }
.aae-flyout-all { border-top: 1px solid #eef0f4; margin-top: .45rem; padding-top: .6rem; border-radius: 0 0 .55rem .55rem;
  color: var(--aae-primary-2); font-weight: 600; }
/* A quiet line at the foot of a panel — "Drag a line to reorder". It is an instruction read once. */
.aae-flyout-foot { border-top: 1px solid #eef0f4; margin-top: .45rem; padding: .5rem .6rem .15rem;
  font-size: .74rem; color: #94a3b8; }

/* ---------- Favourites: dragging one into place ----------
   The row keeps its pointer, because clicking it is still what it is mainly for. The grip appears
   on hover instead and says the row can be picked up — an affordance that costs nothing until it
   is looked for. The row being carried fades, so the gap it will drop into stays readable. */
/* The sidebar gives every icon in a nav-link opacity .9, which outranks a lone class — hence the
   longer selector here. Without it the grips sit visible down the rail whether or not anyone is
   looking for them. */
.fav-grip, .aae-sidebar .nav-link .bi.fav-grip {
  margin-left: auto; opacity: 0; font-size: .95em; transition: opacity .12s ease;
}
.fav-row:hover .fav-grip,
.aae-sidebar .fav-row:hover .nav-link .bi.fav-grip,
.aae-flyout-item:hover .fav-grip { opacity: .5; cursor: grab; }
.fav-dragging, .aae-sidebar li.fav-row.fav-dragging { opacity: .4; }
.aae-sidebar li.fav-row > .nav-link { padding-right: .55rem; }
/* Nothing to grip in the folded rail: there is no row to see it against. */
.aae-layout.mini .aae-sidebar .fav-grip { display: none; }
.aae-layout.mini:not(.hover-off) .aae-sidebar:hover .fav-grip { display: inline; }

/* Phone drawer: the same list, inline under its item. */
.aae-subnav { list-style: none; padding: 0 0 .35rem; }
.aae-subnav-head { font-size: .62rem; text-transform: uppercase; letter-spacing: .06em; color: rgba(255,255,255,.42);
  padding: .5rem 0 .15rem 2.9rem; }
.aae-subnav-item { display: flex; align-items: center; gap: .55rem; margin: 0 .6rem; padding: .34rem .8rem .34rem 2.3rem;
  color: rgba(255,255,255,.74); text-decoration: none; font-size: .86rem; border-radius: .5rem; }
.aae-subnav-item i { width: 1rem; text-align: center; opacity: .85; }
a.aae-subnav-item:hover { color: #fff; background: rgba(255,255,255,.06); }
.aae-subnav-item.active { color: #fff; background: rgba(255,255,255,.1); font-weight: 600; }
.aae-subnav-item.pending { opacity: .5; }
.aae-subnav-all { color: #a5b4fc; font-weight: 600; margin-top: .2rem; }.aae-sidebar li.flyout-open > .nav-link:focus { outline: none; box-shadow: none; }
.aae-sidebar li.flyout-open > .nav-link.active:focus { box-shadow: 0 8px 20px rgba(var(--aae-primary-rgb), .35); }
/* Daily Attendance: every row opens that day's punches. */
.aae-daygrid .tabulator-row { cursor: pointer; }
.aae-daylink { color: var(--aae-primary); font-weight: 600; }
.aae-daygrid .tabulator-row:hover .aae-daylink { text-decoration: underline; }
/* Organisation form: weekly off day picker (Sun … Sat). */
.aae-daypick { display: flex; flex-wrap: wrap; gap: .4rem; }
.aae-daypick .btn { min-width: 3.4rem; border-radius: 999px; padding: .3rem .7rem; font-size: .85rem; }
/* ---------- Dashboard stat cards (grouped figures, one per row) ---------- */
/* Capped rather than 1fr: on a past date only one card is drawn, and a stretched card the width of
   the screen makes four figures look like the whole page. */
.aae-stat-grid { display: grid; gap: .75rem; justify-content: start;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 20rem)); }
.aae-stat-card { border-radius: 1rem; }

/* The same colour down the left edge that the Daily Attendance totals carry, so the two screens
   read as one product rather than two. The colour is the card's own — the one its icon already
   uses — set as --aae-accent by statCard(); a card that sets none keeps the plain border.

   ::before with overflow:hidden rather than border-left, because a 4px border would square off the
   1rem corner it runs into and leave a notch at each end. */
.aae-stat-card { position: relative; overflow: hidden; }
.aae-stat-card::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px;
  background: var(--aae-accent, transparent);
}
/* The body clears the bar so a long title does not start on top of it. */
.aae-stat-card .card-body { padding-left: 1.15rem; }
a.aae-stat-card:hover { border-color: rgba(var(--aae-primary-rgb), .45); box-shadow: 0 .4rem 1rem rgba(15, 23, 42, .08); }
.aae-stat-card .card-body { padding: .85rem 1rem 1rem; }
.aae-stat-head { display: flex; align-items: center; gap: .55rem; margin-bottom: .5rem; }
.aae-stat-title { font-weight: 600; font-size: .95rem; }
.aae-stat-row { display: flex; align-items: baseline; gap: .5rem; padding: .22rem 0; }
.aae-stat-row + .aae-stat-row { border-top: 1px dashed var(--bs-border-color-translucent); }
.aae-stat-label { color: var(--bs-secondary-color); font-size: .86rem; }
.aae-stat-hint { color: var(--bs-secondary-color); opacity: .8; font-size: .74rem; margin-left: .35rem; }
.aae-stat-value { margin-left: auto; font-weight: 600; font-size: 1.15rem; line-height: 1.2; }
.aae-stat-row.strong .aae-stat-value { font-size: 1.6rem; }
.aae-stat-row.strong .aae-stat-label { color: var(--bs-body-color); font-weight: 600; }
.aae-stat-aside { font-size: .78rem; font-weight: 600; color: #d97706; margin-left: .35rem; }
.aae-stat-aside::before { content: "("; }
.aae-stat-aside::after { content: ")"; }
.aae-stat-foot { margin-top: .5rem; padding-top: .45rem; border-top: 1px solid var(--bs-border-color-translucent);
  font-size: .76rem; color: #b45309; }a.aae-stat-row.linked { color: inherit; text-decoration: none; }
a.aae-stat-row.linked:hover { background: rgba(var(--aae-primary-rgb), .07); border-radius: .45rem; }
a.aae-stat-row.linked:hover .aae-stat-label { color: var(--aae-primary); }
.aae-stat-go { font-size: .7rem; color: var(--bs-secondary-color); margin-left: .4rem; align-self: center; }
/* The single organisation's logo in the topbar — see mountOrgLogo() in layout.js. */
.aae-org-logo { height: 30px; max-width: 120px; object-fit: contain; border-radius: .35rem; display: block; }
/* A share of the screen rather than a fixed 84px: the ceiling has to fall with the width, or a
   narrow handset spends a fifth of its header on a logo and pushes the account menu off the end. */
@media (max-width: 575.98px) { .aae-org-logo { height: 24px; max-width: min(84px, 20vw); } }
/* Back, beside the title on every page but the Dashboard. Escape does the same — wireBack() in layout.js. */
.aae-back { flex: none; width: 38px; height: 38px; display: grid; place-items: center; border-radius: 10px;
  color: inherit; margin-left: -.35rem; }
.aae-back:hover { background: rgba(15, 23, 42, .07); color: inherit; }
.aae-back svg { width: 22px; height: 22px; }
/* ---------- Report page (report.html?r=…) ---------- */
.aae-rep-scroll { max-height: calc(100vh - 15rem); min-height: 10rem; }
.aae-rep thead th { position: sticky; top: 0; z-index: 2; background: var(--bs-tertiary-bg, #f8f9fa); font-size: .76rem;
  text-transform: uppercase; letter-spacing: .03em; color: var(--bs-secondary-color); white-space: nowrap; }
.aae-rep td { font-size: .86rem; }
.aae-rep tfoot td { position: sticky; bottom: 0; background: #F1F5F9; border-top: 2px solid var(--bs-border-color); }
.aae-rep .aae-rep-wide { min-width: 11rem; }
/* ---------- Office & personal documents ---------- */
.aae-od-renewed { opacity: .6; }
/* Searchable multi-select (multi-pick.js): chips + type-to-find list. */
.aae-mpick { position: relative; }
.aae-mpick-box { display: flex; flex-wrap: wrap; align-items: center; gap: .3rem; min-height: 2.6rem; max-height: 7.5rem; overflow-y: auto;
  padding: .3rem .5rem; border: 1px solid var(--aae-input-line); border-radius: .5rem; background: var(--bs-body-bg); cursor: text; }
.aae-mpick-box:focus-within { border-color: var(--aae-input-focus); box-shadow: 0 0 0 .2rem var(--aae-input-focus-ring); }
.aae-mpick-chips { display: contents; }
.aae-mpick-chip { display: inline-flex; align-items: center; gap: .2rem; background: var(--aae-primary-tint); color: var(--aae-primary); border-radius: 1rem;
  padding: .1rem .2rem .1rem .6rem; font-size: .82rem; white-space: nowrap; }
.aae-mpick-chip button { border: 0; background: transparent; color: var(--aae-primary); font-size: 1rem; line-height: 1; padding: 0 .3rem; border-radius: 1rem; }
.aae-mpick-chip button:hover { background: var(--aae-primary-tint-2); }
.aae-mpick-input { flex: 1 1 8rem; min-width: 8rem; border: 0; outline: 0; font-size: .9rem; padding: .2rem; background: transparent; }
.aae-mpick-list { position: absolute; left: 0; right: 0; top: calc(100% + 2px); z-index: 1060; max-height: 14rem; overflow-y: auto;
  background: var(--bs-body-bg); border: 1px solid var(--bs-border-color); border-radius: .5rem; box-shadow: 0 .5rem 1.25rem rgba(15, 23, 42, .12); }
.aae-mpick-opt { display: flex; flex-direction: column; padding: .4rem .7rem; cursor: pointer; font-size: .88rem; line-height: 1.25; }
.aae-mpick-opt small { color: #64748B; font-size: .74rem; }
.aae-mpick-opt:hover, .aae-mpick-opt.active { background: var(--aae-primary-tint-3); }
.aae-mpick-none { padding: .5rem .7rem; color: #94A3B8; font-size: .85rem; }/* A two-line grid cell — a title with its type under it. Tabulator lays a cell's children out in a row. */
.aae-cell-stack { display: flex; flex-direction: column; min-width: 0; line-height: 1.25; white-space: normal; }/* Report pages: an organisation heading row, like the Attendance Register's. */
.aae-rep tr.aae-rep-group td { background: var(--aae-primary-tint); color: var(--aae-primary); font-weight: 600; font-size: .84rem; padding-top: .4rem; padding-bottom: .4rem; }
.aae-rep .aae-rep-group-n { font-weight: 400; color: var(--aae-primary); margin-left: .5rem; font-size: .76rem; }/* Report grid: the organisation heading drawn like the Attendance Register's. */
.aae-rep-grid .tabulator-group { background: var(--aae-primary-tint); color: var(--aae-primary); font-weight: 600; border-top: 1px solid var(--aae-primary-tint-2); }
.aae-rep-grid .tabulator-group .aae-rep-group-n { font-weight: 400; color: var(--aae-primary); margin-left: .5rem; font-size: .8em; }
.aae-rep-grid .tabulator-footer .tabulator-calcs-holder { background: #F1F5F9; }
/* Visits inside an official errand's card in the day-punches popup. */
.pd-visit { margin: .35rem 0 .15rem .15rem; padding: .35rem .55rem; border-left: 2px dashed #93B4E6; background: #F4F8FE; border-radius: 0 .45rem .45rem 0; }
/* The VISIT tag. It was a solid blue block with the word jammed into it, which read as a cut-off
   heading rather than a label; as a rounded chip in the quieter pair of the same blue it sits beside
   the time the way the Matched chip sits at the other end of the row. */
.pd-visit .pd-label { display: inline-flex; align-items: center; gap: .25rem; min-width: 0;
  padding: .1rem .45rem; border-radius: 999px; background: #E3EDFA; color: #2C5FB3;
  font-weight: 700; font-size: .62rem; letter-spacing: .08em; }
.pd-visit .pd-label::before { content: "\F3E7"; font-family: bootstrap-icons; font-size: .7rem;
  letter-spacing: 0; font-weight: 400; }
/* The place: the fact of the row, so it reads as text rather than as a caption. */
.pd-visit .pd-reason { font-weight: 600; color: #16233a; }
.pd-visit-addr { font-size: .78rem; color: #475569; margin-top: .1rem; }
.pd-visit-note { font-size: .8rem; color: #0f172a; margin-top: .1rem; }
.pd-visit-links { display: flex; gap: .9rem; font-size: .78rem; margin-top: .2rem; }
.pd-visit-links a, .pd-visit-links .btn-link { font-size: .78rem; text-decoration: none; }
/* A break taken during that errand — the same inset row as a visit, in the amber the register marks
   a long break with, so the two are plainly different kinds of thing inside one trip. */
.pd-break { border-left-color: #E3BE7A; background: #FDF6E9; }
.pd-break .pd-label { background: #FAECD2; color: #8A5B10; }
.pd-break .pd-label::before { content: "\F2E7"; }
.pd-break .pd-reason { font-weight: 500; color: #8A5B10; }
/* Report grid: long column titles wrap onto a second line instead of being cut with an ellipsis. */
.aae-rep-grid.tabulator .tabulator-header .tabulator-col .tabulator-col-title { white-space: normal; text-overflow: clip; overflow-wrap: normal; line-height: 1.2; }
/* Every grid: columns never fold away; a table wider than its card scrolls sideways. */
.tabulator .tabulator-tableholder { overflow-x: auto; }
/* Titles in Title Case on every page: the page heading, popups and the help panel. */
#aae-page-title, .modal-title, .offcanvas-title { text-transform: capitalize; }

/* A focused field's caption follows its border into red. */
.aae-field > .form-control:focus ~ label, .aae-field > .form-select:focus ~ label { color: var(--aae-input-focus); }

/* ---------- Brand: the Atease logo in place of the fingerprint ---------- */
.nowrap { white-space: nowrap; }
.aae-brand { gap: .5rem; padding-left: .85rem; padding-right: .75rem; }
.aae-brand-home { display: flex; align-items: center; gap: .6rem; min-width: 0; flex: 1 1 auto; color: inherit; text-decoration: none; }
.aae-brand-home:hover, .aae-brand-home:focus-visible { color: inherit; opacity: .92; }
.aae-brand-logo { width: 38px; height: 38px; flex: 0 0 auto; border-radius: 11px; background: #fff; padding: 3px; object-fit: contain; }
/* The name on one line, whatever the sidebar's width. */
.aae-brand .brand-name { white-space: nowrap; font-size: .92rem; }
.aae-brand .brand-tag { line-height: 1.3; }
.aae-login-brand .aae-brand-logo { width: 64px; height: 64px; border-radius: 18px; padding: 5px; margin-bottom: .6rem;
  box-shadow: 0 10px 24px rgba(var(--aae-primary-rgb), .25); }
@media (min-width: 992px) {
  .aae-layout.mini .aae-brand-home { flex: 0 0 auto; gap: 0; }
  .aae-layout.mini:not(.hover-off) .aae-sidebar:hover .aae-brand,
  .aae-layout.mini:not(.hover-off) .aae-sidebar:focus-within .aae-brand { padding-left: .85rem; padding-right: .75rem; gap: .5rem; }
  .aae-layout.mini:not(.hover-off) .aae-sidebar:hover .aae-brand-home,
  .aae-layout.mini:not(.hover-off) .aae-sidebar:focus-within .aae-brand-home { flex: 1 1 auto; gap: .6rem; }
}

/* ---------- Header account: org logo + company, "User: login" under it, Sign out beside ---------- */
.aae-account { display: flex; align-items: center; gap: .55rem; text-align: left; padding: .2rem .45rem; border: 0; max-width: 22rem; }
.aae-account:hover, .aae-account:focus-visible, .aae-account[aria-expanded="true"] { background: var(--aae-surface-2); }
.aae-account #aae-org-logo:empty { display: none; }
/* The stand-in for the logo, on phones only. Hidden here, switched on in the narrow-screen block. */
.aae-account-icon { display: none; color: inherit; }
.aae-account-text { display: flex; flex-direction: column; min-width: 0; line-height: 1.2; }
.aae-account-company { font-weight: 600; font-size: .9rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--aae-ink); }
.aae-account-user { display: flex; align-items: center; gap: .3rem; font-size: .74rem; color: var(--aae-muted); white-space: nowrap; }
.aae-account-user #aae-username { font-weight: 600; color: var(--aae-ink); overflow: hidden; text-overflow: ellipsis; }
.aae-account .aae-avatar { width: 18px; height: 18px; box-shadow: none; flex: 0 0 auto; }
.aae-account-caret { font-size: .7rem; color: var(--aae-muted); }
.aae-signout { white-space: nowrap; }

/* Who is signed in, at the top of the account menu. Not an item: there is nothing to press, and a
   hover highlight would say there was.

   Only where the button above cannot say it itself. On a wide screen the button already reads
   "SK Software… / User: admin" and this repeated it word for word directly underneath; on a phone
   the button is the logo alone, and this is the only thing that names the login. The rule below it
   carries the same class, so it goes and comes with it rather than being left at the top. */
.aae-account-head { display: none; padding: .55rem 1rem .35rem; max-width: 16rem; }
.aae-account-rule { display: none; }
@media (max-width: 767.98px) {
  .aae-account-text { display: none; }
  .aae-account-head, .aae-account-rule { display: block; }
}

/* ---------- Theme chrome (--aae-grad-dark, set by theme.js): the side menu and the header share it ---------- */
.aae-sidebar .nav-link:hover,
.aae-sidebar li.flyout-open > .nav-link:not(.active) { background: rgba(255,255,255,.14); color: #fff; }
.aae-sidebar .nav-link:hover .bi { opacity: 1; }
.aae-sidebar .nav-link.active,
.aae-sidebar .nav-link.active:hover { background: rgba(255,255,255,.24); color: #fff; box-shadow: inset 3px 0 0 #fff, 0 6px 16px rgba(0,0,0,.18); }
.aae-sidebar li.flyout-open > .nav-link.active:focus { box-shadow: 0 6px 16px rgba(0,0,0,.28); }
a.aae-subnav-item:hover { background: rgba(255,255,255,.14); }
.aae-subnav-item.active { background: rgba(255,255,255,.22); }
.aae-subnav-all { color: #fff; }
a.aae-flyout-item:hover, a.aae-flyout-item:focus-visible, .aae-flyout-all:hover, .aae-flyout-all:focus-visible {
  background: var(--aae-primary-tint); color: var(--aae-primary); }
.aae-flyout-item.active { background: var(--aae-primary-tint-2); color: var(--aae-primary); }

.aae-topbar { background: var(--aae-grad-dark); border-bottom-color: rgba(255,255,255,.06); color: #fff; }
.aae-topbar #aae-page-title, .aae-topbar .aae-back { color: #fff; }
.aae-topbar .aae-back:hover { background: rgba(255,255,255,.12); color: #fff; }
.aae-topbar .btn-light { background: rgba(255,255,255,.1); border-color: rgba(255,255,255,.14); color: #fff; }
.aae-topbar .btn-light:hover, .aae-topbar .btn-light:focus-visible { background: rgba(255,255,255,.2); color: #fff; }
.aae-topbar .aae-account:hover, .aae-topbar .aae-account:focus-visible, .aae-topbar .aae-account[aria-expanded="true"] { background: rgba(255,255,255,.1); }
.aae-topbar .aae-account-company, .aae-topbar .aae-account-user #aae-username { color: #fff; }
.aae-topbar .aae-account-user, .aae-topbar .aae-account-caret { color: rgba(255,255,255,.72); }
.aae-topbar .aae-org-logo { background: #fff; padding: 2px; }
.aae-topbar .text-secondary, .aae-topbar .text-muted { color: rgba(255,255,255,.72) !important; }
/* …but not inside the account menu, which is a white panel that happens to hang off the header.
   "Signed in as admin" was being painted header-white on menu-white and read as a blank row under
   the company name. The menu keeps the page's own greys. */
.aae-topbar .dropdown-menu .text-secondary { color: var(--aae-muted) !important; }
.aae-topbar .dropdown-menu .text-muted { color: var(--aae-muted) !important; }
/* Greys written for a near-black menu disappear on a coloured one; white at a lower strength works on every theme. */
.aae-brand .brand-tag { color: rgba(255,255,255,.7); }
.aae-sidebar .nav-section { color: rgba(255,255,255,.55); }
.aae-pin { color: rgba(255,255,255,.7); }
.aae-sidebar .nav-link.pending, .aae-sidebar .nav-link.pending:hover { color: rgba(255,255,255,.45); }
.aae-subnav-head { color: rgba(255,255,255,.55); }
/* Sign out: the icon alone. */
.aae-signout { width: 34px; height: 34px; padding: 0; display: inline-grid; place-items: center; }

/* ---------- Appearance: custom-colour swatch and the phone app preview ---------- */
.aae-swatch-custom { display: block; cursor: pointer; margin: 0; }
.aae-swatch-custom input[type="color"] { display: block; width: 100%; height: 34px; border: 0; padding: 0; border-radius: 9px;
  margin-bottom: .4rem; background: transparent; cursor: pointer; }
.aae-swatch-custom input[type="color"]::-webkit-color-swatch-wrapper { padding: 0; }
.aae-swatch-custom input[type="color"]::-webkit-color-swatch { border: 0; border-radius: 9px; }

.aae-phone { --ph-chrome: #075985; --ph-accent: #0369a1; width: 250px; border-radius: 34px; padding: 9px; background: #111827;
  box-shadow: 0 1rem 2.5rem rgba(15,23,42,.25); font-family: Poppins, system-ui, sans-serif; }
.aae-phone .ph-screen { border-radius: 26px; overflow: hidden; background: #f4f5f8; color: #1a1a24; font-size: 11px; }
.aae-phone .ph-status { display: flex; justify-content: space-between; padding: 6px 14px 2px; background: var(--ph-chrome); color: #fff; font-size: 10px; }
.aae-phone .ph-bar { display: flex; justify-content: space-between; align-items: center; padding: 6px 14px 8px; background: var(--ph-chrome); color: #fff; }
.aae-phone .ph-title { font-weight: 700; font-size: 14px; }
.aae-phone .ph-icons { display: flex; align-items: center; gap: 8px; }
.aae-phone .ph-avatar { width: 22px; height: 22px; border-radius: 50%; background: rgba(255,255,255,.22); display: grid; place-items: center; font-size: 10px; font-weight: 700; }
.aae-phone .ph-head { background: var(--ph-chrome); color: #fff; padding: 2px 14px 12px; border-radius: 0 0 16px 16px; }
.aae-phone .ph-company { font-size: 9px; color: rgba(255,255,255,.72); }
.aae-phone .ph-row { display: flex; justify-content: space-between; align-items: flex-end; margin-top: 2px; }
.aae-phone .ph-name { font-weight: 600; font-size: 13px; }
.aae-phone .ph-sub { font-size: 8.5px; color: rgba(255,255,255,.66); letter-spacing: .02em; }
.aae-phone .ph-stat { text-align: right; }
.aae-phone .ph-big { font-weight: 700; font-size: 15px; }
.aae-phone .ph-card { margin: 10px 12px 0; background: #fff; border-radius: 14px; padding: 10px; box-shadow: 0 1px 2px rgba(0,0,0,.06); }
.aae-phone .ph-clock { text-align: center; font-weight: 700; font-size: 22px; color: var(--ph-chrome); }
.aae-phone .ph-grid { display: grid; grid-template-columns: repeat(3, 1fr); text-align: center; margin-top: 4px; }
.aae-phone .ph-grid small { display: block; font-size: 7.5px; color: #6b7280; letter-spacing: .04em; }
.aae-phone .ph-grid b { font-size: 11px; }
.aae-phone .ph-button { margin: 10px 12px 0; border-radius: 12px; background: #e24b4a; color: #fff; text-align: center; font-weight: 600; padding: 9px; font-size: 12px; }
.aae-phone .ph-list { margin: 10px 12px 0; background: #fff; border-radius: 12px; padding: 4px 10px; }
.aae-phone .ph-item { display: flex; align-items: center; gap: 6px; padding: 5px 0; font-size: 10px; border-bottom: 1px solid #f1f2f6; }
.aae-phone .ph-item:last-child { border-bottom: 0; }
.aae-phone .ph-dot { width: 7px; height: 7px; border-radius: 50%; background: #1f9d57; }
.aae-phone .ph-dot.out { background: #c98a12; }
.aae-phone .ph-muted { color: #6b7280; margin-left: auto; }
.aae-phone .ph-tabs { display: flex; justify-content: space-around; margin-top: 12px; background: #fff; border-top: 1px solid #e8eaef; padding: 6px 4px 8px; }
.aae-phone .ph-tabs span { display: flex; flex-direction: column; align-items: center; gap: 1px; font-size: 8.5px; color: #6b7280; padding: 3px 10px; border-radius: 10px; }
.aae-phone .ph-tabs i { font-size: 13px; }
.aae-phone .ph-tabs span.on { background: var(--ph-chrome); color: #fff; }

/* ---------- Theme gradients: side menu, header, grid headers (all set by theme.js) ---------- */
:root {
  --aae-grad-header: linear-gradient(90deg, #16233a 0%, #2a3f63 70%, #2c5fb3 140%);
  --aae-scrim-top: rgba(22,35,58,.97);
  --aae-grid-head-grad: linear-gradient(90deg, #16233a 0%, #2a3f63 60%, #2c5fb3 140%);
  --aae-grid-head-ink: #ffffff;
}
.aae-topbar { background: var(--aae-grad-header); }
.aae-scroll-hint.up { background: linear-gradient(to top, transparent 0%, var(--aae-scrim-top) 60%, var(--aae-scrim-top) 100%); }

.tabulator .tabulator-header {
  background: var(--aae-grid-head-grad);
  border-bottom: 0;
  color: var(--aae-grid-head-ink);
}
.tabulator .tabulator-header .tabulator-col,
.tabulator .tabulator-header .tabulator-col.tabulator-sortable:hover,
.tabulator .tabulator-header .tabulator-col.tabulator-sortable.tabulator-col-sorter-element:hover { background: transparent; color: var(--aae-grid-head-ink); }
.tabulator .tabulator-header .tabulator-col { border-right-color: rgba(255,255,255,.18); }
.tabulator .tabulator-header .tabulator-col .tabulator-col-title { color: var(--aae-grid-head-ink); }
.tabulator .tabulator-header .tabulator-col .tabulator-col-content .tabulator-col-sorter .tabulator-arrow { border-bottom-color: rgba(255,255,255,.6); }
.aae-doc-table thead th { background: var(--aae-grid-head-grad); color: var(--aae-grid-head-ink); border-color: rgba(255,255,255,.18); }

/* Dashboard cards: title on its own line, then the icon beside the figures — no empty band under the title. */
.aae-stat-card .card-body { padding: .7rem .95rem .75rem; }
.aae-stat-head { margin-bottom: .35rem; min-height: 0; }
.aae-stat-body { display: flex; align-items: flex-start; gap: .8rem; }
.aae-stat-body > .kpi-icon { flex: 0 0 auto; margin-top: .15rem; }
.aae-stat-rows { flex: 1 1 auto; min-width: 0; }
.aae-stat-rows > .aae-stat-row:first-child { padding-top: 0; }
/* Tighter: the title sits right above the figures, the icon centres on them, and the big number no
   longer pushes the first line down with its own line height. */
.aae-stat-card .card-body { padding: .6rem .9rem .6rem; }
.aae-stat-head { margin-bottom: .1rem; line-height: 1.2; }
.aae-stat-title { font-size: .9rem; }
.aae-stat-body { align-items: center; gap: .75rem; }
.aae-stat-body > .kpi-icon { width: 42px; height: 42px; font-size: 1.15rem; border-radius: 12px; margin-top: 0; }
.aae-stat-row { align-items: center; padding: .12rem 0; line-height: 1.15; }
.aae-stat-row.strong .aae-stat-value { font-size: 1.35rem; line-height: 1.1; }
.aae-stat-value { font-size: 1.05rem; line-height: 1.1; }
.aae-stat-row { padding: .18rem 0; }
.aae-stat-head { margin-bottom: .2rem; }

/* A starred page. Amber only when it IS one — an outline star that is always amber would say every
   page is a favourite, which is the one thing the colour is there to distinguish. */
.aae-fav-on { color: #f59e0b !important; }
.aae-fav-on:hover { color: #d97706 !important; }

/* Face match badge (components/face.js): green Matched, red Not matched, grey when not compared. */
.aae-face { display: inline-flex; align-items: center; gap: .25rem; border: 1px solid transparent; border-radius: 999px;
  padding: .05rem .5rem; font-size: .72rem; font-weight: 600; line-height: 1.5; white-space: nowrap; background: none; }
button.aae-face { cursor: pointer; }
.aae-face.ok { color: #157347; background: #e7f6ee; border-color: #b7e3c8; }
.aae-face.bad { color: #b42318; background: #fdecea; border-color: #f5c2bd; }
.aae-face.none { color: #6b7280; background: #f3f4f6; border-color: #e5e7eb; }
button.aae-face:hover { filter: brightness(.96); text-decoration: underline; }

/* ---------- Tasks ---------- */
.aae-chip-stat { background: var(--aae-surface, #fff); border: 1px solid var(--aae-line); border-radius: 999px; padding: .3rem .85rem; display: inline-flex; gap: .45rem; align-items: baseline; }
.aae-chip-stat strong { font-size: 1.05rem; }

/* ---------- Field map ---------- */
.aae-fm { display: grid; grid-template-columns: 20rem 1fr; gap: .75rem; }
@media (max-width: 991.98px) { .aae-fm { grid-template-columns: 1fr; } .aae-fm-list { max-height: 16rem; } }
.aae-fm-list { overflow-y: auto; max-height: calc(100vh - 12rem); }
.aae-fm-map { height: calc(100vh - 12rem); min-height: 22rem; border-radius: .75rem; }
.aae-fm-mapcard { overflow: hidden; }
.aae-fm-row.active { background: var(--aae-primary-tint, #e3e9f2); color: inherit; border-color: transparent; }
.aae-fm-dot { display: inline-block; width: .65rem; height: .65rem; border-radius: 50%; margin-right: .35rem; flex: 0 0 auto; vertical-align: middle; }
.aae-fm-marker { background: none; border: 0; }
.aae-fm-pin { display: grid; place-items: center; width: 34px; height: 34px; border-radius: 50%; background: var(--pin); color: #fff;
  font: 700 12px/1 system-ui, sans-serif; border: 3px solid #fff; box-shadow: 0 2px 8px rgba(15,23,42,.35); }
.aae-fm-pin.stale { opacity: .55; filter: grayscale(.4); }

/* A stat card whose rows link elsewhere links from its heading instead. */
a.aae-stat-head:hover .aae-stat-title { color: var(--aae-primary); }


/* Licence end date in the header: quiet normally, amber in the last 30 days, red once lapsed. */
.aae-licence { align-items: center; font-size: .78rem; color: var(--bs-secondary-color); white-space: nowrap;
  padding: .2rem .55rem; border-radius: 999px; border: 1px solid var(--bs-border-color-translucent); }
.aae-licence.warn { color: #b45309; background: #fef3c7; border-color: #fcd34d; }
.aae-licence.bad { color: #b91c1c; background: #fee2e2; border-color: #fca5a5; }
/* Active employees against the licence, on the Employees page. */
.aae-seats { font-size: .8rem; font-weight: 600; padding: .2rem .6rem; border-radius: 999px; white-space: nowrap;
  background: rgba(var(--aae-primary-rgb), .08); color: var(--aae-primary); }
.aae-seats.full { background: #fee2e2; color: #b91c1c; }

/* Task proof: photos in a grid, a voice note full width. */
.aae-proof-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: .6rem; }
.aae-proof-photo { display: block; aspect-ratio: 1; border-radius: .6rem; overflow: hidden; border: 1px solid var(--bs-border-color); }
.aae-proof-photo img { width: 100%; height: 100%; object-fit: cover; }
.aae-proof-audio { grid-column: 1 / -1; }

/* The header is the dark theme gradient: the licence chip reads in light text there. Amber and red keep
   their own filled backgrounds, which stay readable on any header. */
.aae-topbar .aae-licence:not(.warn):not(.bad) { color: rgba(255, 255, 255, .9); background: rgba(255, 255, 255, .1);
  border-color: rgba(255, 255, 255, .35); }
.aae-topbar .aae-licence { font-weight: 500; }

/* Back office header (its <header> sits directly in <body>): the outline buttons and the user badge were
   dark on the dark theme gradient. Light text and borders instead. */
body > header.aae-topbar .btn-outline-secondary,
body > header.aae-topbar .btn-outline-primary,
body > header.aae-topbar .btn-outline-dark {
  color: #fff; border-color: rgba(255, 255, 255, .55); background: rgba(255, 255, 255, .06);
}
body > header.aae-topbar .btn-outline-secondary:hover,
body > header.aae-topbar .btn-outline-primary:hover,
body > header.aae-topbar .btn-outline-dark:hover {
  color: var(--aae-primary); background: #fff; border-color: #fff;
}
body > header.aae-topbar .badge.text-bg-dark {
  background: rgba(255, 255, 255, .16) !important; color: #fff !important; border: 1px solid rgba(255, 255, 255, .3);
}
body > header.aae-topbar .h5, body > header.aae-topbar .h5 .text-primary { color: #fff !important; }

/* Register: the logo beside the title rather than above it. Stacked, the icon, the heading and the
   line under it took a third of the card before a single field was reached. */
.aae-login-card .aae-login-brand { display: flex; align-items: center; gap: 1rem; text-align: left; margin-bottom: 1.1rem; }
.aae-login-card .aae-login-brand .aae-brand-logo { width: 54px; height: 54px; margin: 0; flex: 0 0 auto; }
.aae-login-card .aae-login-brand .name { font-size: 1.35rem; line-height: 1.2; }
.aae-login-card .aae-login-brand .tag { font-size: .84rem; }
.aae-login-card .aae-back-link { margin-bottom: .6rem; }
.aae-login-card .card-body { padding-top: 1.5rem; }
@media (max-width: 420px) { .aae-login-card .aae-login-brand .name { font-size: 1.15rem; } }

/* The brand on sign-in and register leads back to the public home page. */
a.aae-login-brand { text-decoration: none; color: inherit; }
a.aae-login-brand:hover .name { color: var(--aae-primary); }
.aae-home-link { display: inline-flex; align-items: center; gap: .35rem; font-size: .85rem; font-weight: 600;
  color: var(--aae-muted); text-decoration: none; margin-bottom: .4rem; }
.aae-home-link:hover { color: var(--aae-primary); }

/* ---------- Punch Corrections: requests waiting for a decision ----------
   A panel that asks, not a line that informs: amber edge, a bell, the count in words, and each request
   as its own card with the three answers as full-size buttons. */
.aae-req-panel { background: #fffaf0; border: 1px solid #f5d68a; border-left: 5px solid #f0a92a; border-radius: 16px;
  padding: 16px 18px; box-shadow: 0 .6rem 1.4rem rgba(201, 138, 18, .12); }
.aae-req-head { display: flex; gap: 12px; align-items: center; margin-bottom: 12px; }
.aae-req-bell { flex: 0 0 42px; height: 42px; border-radius: 13px; display: grid; place-items: center; font-size: 1.15rem;
  background: #f0a92a; color: #fff; box-shadow: 0 .4rem .9rem rgba(240, 169, 42, .35); animation: aae-req-ring 2.4s ease-in-out 1; }
@keyframes aae-req-ring { 0%, 100% { transform: rotate(0); } 10% { transform: rotate(14deg); } 20% { transform: rotate(-12deg); }
  30% { transform: rotate(8deg); } 40% { transform: rotate(-5deg); } 50% { transform: rotate(0); } }
.aae-req-title { font-weight: 700; font-size: 1.05rem; color: #7a4d07; }
.aae-req-sub { font-size: .84rem; color: #8a6a2e; }

.aae-req { display: grid; gap: 12px 18px; align-items: center; background: #fff; border: 1px solid #f1e3c2;
  border-radius: 14px; padding: 14px 16px; margin-top: 10px; transition: box-shadow .2s ease, border-color .2s ease; }
.aae-req:hover { box-shadow: 0 .5rem 1.2rem rgba(22, 35, 58, .08); }
.aae-req.viewing { border-color: var(--aae-primary); box-shadow: 0 0 0 3px rgba(var(--aae-primary-rgb), .15); }
@media (min-width: 1100px) { .aae-req { grid-template-columns: minmax(12rem, 1.1fr) minmax(12rem, 1fr) minmax(10rem, 1.2fr) auto; } }
@media (min-width: 700px) and (max-width: 1099px) { .aae-req { grid-template-columns: 1fr 1fr; } .aae-req-actions { grid-column: 1 / -1; } }

.aae-req-who { display: flex; gap: 10px; align-items: center; }
.aae-req-avatar { flex: 0 0 40px; height: 40px; border-radius: 50%; display: grid; place-items: center; font-weight: 700;
  font-size: .85rem; background: rgba(var(--aae-primary-rgb), .1); color: var(--aae-primary); }
.aae-req-name { font-weight: 700; font-size: 1rem; }
.aae-req-ask { font-size: .8rem; color: var(--bs-secondary-color); }

.aae-req-what { display: flex; gap: 10px; align-items: center; }
.aae-req-dir { display: inline-flex; align-items: center; gap: .35rem; font-weight: 700; font-size: .8rem; padding: .35rem .7rem;
  border-radius: 999px; white-space: nowrap; }
.aae-req-dir.in { background: #e3f6ec; color: #1f9d57; }
.aae-req-dir.out { background: #fdecec; color: #c93b3a; }
.aae-req-when { font-weight: 700; font-size: 1rem; }
.aae-req-when span { font-weight: 500; font-size: .85rem; color: var(--bs-secondary-color); margin-left: .25rem; }
.aae-req-type { font-size: .8rem; color: var(--bs-secondary-color); }

.aae-req-why { font-size: .92rem; font-style: italic; color: #334155; background: #f6f8fb; border-radius: 10px; padding: 8px 12px; }
.aae-req-why span { display: block; font-style: normal; font-size: .7rem; font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; color: var(--bs-secondary-color); margin-bottom: 2px; }

.aae-req-actions { display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end; }
.aae-req-actions .btn { font-weight: 600; padding: .45rem .95rem; border-radius: 10px; }

/* ---------- Tasks: one toolbar instead of three rows ---------- */
.aae-taskbar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; background: var(--aae-surface, #fff);
  border: 1px solid var(--aae-line); border-radius: 14px; padding: 8px 10px; }
.aae-seg { display: inline-flex; flex-wrap: wrap; gap: 4px; background: #f1f4f9; border-radius: 11px; padding: 4px; }
.aae-seg button { border: 0; background: transparent; color: #475569; font-weight: 600; font-size: .84rem;
  padding: .38rem .75rem; border-radius: 8px; display: inline-flex; align-items: center; gap: .4rem; transition: background .15s ease, color .15s ease; }
.aae-seg button b { font-weight: 700; font-size: .78rem; min-width: 1.4rem; padding: .05rem .4rem; border-radius: 999px;
  background: rgba(15, 23, 42, .08); color: inherit; text-align: center; }
.aae-seg button:hover { background: rgba(255, 255, 255, .8); color: var(--aae-primary); }
.aae-seg button.active { background: #fff; color: var(--aae-primary); box-shadow: 0 .15rem .5rem rgba(15, 23, 42, .12); }
.aae-seg button.active b { background: var(--aae-primary); color: #fff; }
.aae-seg button.danger { color: #c93b3a; }
.aae-seg button.danger b { background: #fdecec; color: #c93b3a; }
.aae-seg button.danger.active b { background: #c93b3a; color: #fff; }
.aae-taskbar-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-left: auto; flex: 1 1 26rem; justify-content: flex-end; }
.aae-taskbar-tools .aae-search { flex: 1 1 14rem; max-width: 22rem; }
.aae-taskbar-tools .form-select { width: auto; flex: 0 1 13rem; }
@media (max-width: 700px) { .aae-taskbar-tools { margin-left: 0; justify-content: stretch; } .aae-taskbar-tools .aae-search { max-width: none; } }

/* Request cards shared by every approval page: the pill takes a tone, not only in/out. */
.aae-req-dir.info { background: rgba(var(--aae-primary-rgb), .1); color: var(--aae-primary); }
.aae-req-dir.warn { background: #fdf0d9; color: #a36b0c; }
.aae-req-warn { font-style: normal; font-size: .8rem; color: #a36b0c; margin-top: 6px; }
.aae-req-none { display: flex; gap: 12px; align-items: center; background: #f3fbf6; border: 1px solid #cfead9;
  border-radius: 14px; padding: 16px 18px; }
.aae-req-none > i { font-size: 1.6rem; color: #1f9d57; }
.aae-req-none b { display: block; }
.aae-req-none span { font-size: .85rem; color: var(--bs-secondary-color); }
.aae-seg button.warn { color: #a36b0c; }
.aae-seg button.warn b { background: #fdf0d9; color: #a36b0c; }
.aae-seg button.warn.active b { background: #c98a12; color: #fff; }
.aae-req-detail { display: block; font-style: normal; color: #334155; }
.aae-seg button.good { color: #1f7a47; }
.aae-seg button.good b { background: #e3f6ec; color: #1f7a47; }
.aae-seg button.good.active b { background: #1f9d57; color: #fff; }
/* A date range sitting in the bar: small labels, fixed-width fields. */
.aae-range-label { font-size: .8rem; font-weight: 600; color: var(--bs-secondary-color); margin: 0; }
.aae-range-field { width: 9.5rem; flex: 0 0 auto; }

/* Dashboard: four stat cards to a row on a desktop, two on a tablet, one on a phone. They used to be
   capped at 20rem each, which left three to a row and a gap at the end. */
.aae-stat-grid { grid-template-columns: 1fr; justify-content: stretch; }
@media (min-width: 640px) { .aae-stat-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1200px) { .aae-stat-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
/* A section a card scrolls to lands below the sticky header, not under it. */
.aae-anchor { scroll-margin-top: 80px; }

/* ---- clickable thumbnails ---- */
.aae-click { cursor: pointer; }
img.org-thumb.aae-click:hover { outline: 2px solid var(--bs-primary); outline-offset: 1px; }

/* ---- mobile number with country code (dial-picker.js) ---- */
.aae-dial-group { position: relative; flex-wrap: nowrap; }
.aae-dial-btn {
  display: inline-flex; align-items: center; gap: .35rem;
  border: 1px solid var(--bs-border-color); background: var(--bs-tertiary-bg);
  border-top-right-radius: 0; border-bottom-right-radius: 0; padding: 0 .6rem; font-weight: 600;
}
.aae-dial-btn .bi { font-size: .7rem; opacity: .6; }
.aae-dial-btn:focus-visible { box-shadow: 0 0 0 .2rem rgba(var(--bs-primary-rgb), .25); }
.aae-flag { width: 22px; height: 15px; border-radius: 2px; flex: none; box-shadow: 0 0 0 1px rgba(0,0,0,.12); }
.aae-dial-menu {
  position: absolute; top: calc(100% + 4px); left: 0; z-index: 1060; min-width: 260px;
  list-style: none; margin: 0; padding: .3rem; background: var(--bs-body-bg);
  border: 1px solid var(--bs-border-color); border-radius: .6rem; box-shadow: 0 10px 28px rgba(2,6,23,.16);
}
.aae-dial-menu li {
  display: flex; align-items: center; gap: .6rem; padding: .45rem .6rem; border-radius: .4rem; cursor: pointer; outline: none;
}
.aae-dial-menu li:hover, .aae-dial-menu li:focus { background: var(--bs-tertiary-bg); }
.aae-dial-menu li[aria-selected="true"] { font-weight: 600; }
.aae-dial-name { flex: 1; }
.aae-dial-code { color: var(--bs-secondary-color); font-variant-numeric: tabular-nums; }
/* The code and the number are two boxes side by side, not one joined box: joined, the number's
   focus and error outline ran into the code button and read as overlapping. */
.input-group.aae-dial-group { gap: 8px; }
.aae-dial-group > .aae-dial-btn {
  height: 46px; border-radius: 10px !important; margin: 0 !important; background: var(--bs-body-bg);
}
.aae-dial-group > .aae-field > .form-control { border-radius: 10px !important; margin: 0 !important; }

/* ---- Getting Started (getting-started.js) ---- */
.aae-gs { border-left: 4px solid var(--aae-primary); }
.aae-gs-bar { height: 6px; border-radius: 3px; }
.aae-gs-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.aae-gs-list li {
  display: flex; align-items: center; gap: 12px; padding: 8px 10px; border-radius: 10px;
  border: 1px solid var(--bs-border-color-translucent);
}
.aae-gs-list li.next { border-color: var(--aae-primary); background: rgba(var(--bs-primary-rgb), .05); }
.aae-gs-list li.done { opacity: .72; }
.aae-gs-mark {
  flex: none; width: 28px; height: 28px; border-radius: 50%; display: grid; place-items: center;
  font-weight: 600; font-size: .85rem; background: var(--bs-tertiary-bg); color: var(--bs-secondary-color);
}
.aae-gs-list li.next .aae-gs-mark { background: var(--aae-primary); color: #fff; }
.aae-gs-list li.done .aae-gs-mark { background: #16a34a; color: #fff; }
.aae-gs-text { flex: 1; min-width: 0; }
.aae-gs-title { font-weight: 600; }
.aae-gs-list li.done .aae-gs-title { text-decoration: line-through; text-decoration-color: rgba(0,0,0,.25); }
.aae-gs-why { font-size: .82rem; color: var(--bs-secondary-color); }
.aae-gs-ok { color: #16a34a; font-weight: 600; font-size: .85rem; flex: none; }
.aae-gs-list .btn { flex: none; white-space: nowrap; }
.aae-gs-trophy { font-size: 1.8rem; color: #16a34a; }
@media (max-width: 575.98px) {
  .aae-gs-list li { flex-wrap: wrap; }
  .aae-gs-text { flex: 1 1 calc(100% - 44px); }   /* the button drops under the words, not beside them */
  .aae-gs-list li .btn, .aae-gs-ok { margin-left: 40px; }
}

/* ---- Guided tour (tour.js) ---- */
.aae-tour { position: fixed; inset: 0; z-index: 1090; }
.aae-tour-spot {
  position: fixed; border-radius: 12px; pointer-events: none;
  box-shadow: 0 0 0 9999px rgba(11, 18, 32, .62), 0 0 0 3px var(--aae-primary);
  transition: left .25s, top .25s, width .25s, height .25s;
}
.aae-tour-centre .aae-tour-spot { box-shadow: 0 0 0 9999px rgba(11, 18, 32, .62); }
.aae-tour-pop {
  position: fixed; width: min(340px, calc(100vw - 24px)); background: var(--bs-body-bg); color: var(--bs-body-color);
  border-radius: 14px; padding: 16px 16px 12px; box-shadow: 0 18px 50px rgba(0,0,0,.35);
  transition: left .25s, top .25s;
}
.aae-tour-x { position: absolute; top: 12px; right: 12px; font-size: .7rem; }
.aae-tour-step { color: var(--aae-primary); font-weight: 600; letter-spacing: .02em; margin-bottom: 2px; }
.aae-tour-text { font-size: .9rem; color: var(--bs-secondary-color); }

/* ---- Menu search (menu-search.js) ---- */
.aae-msearch .modal-dialog { margin-top: 8vh; }
.aae-msearch .modal-content { border-radius: 14px; overflow: hidden; }
.aae-msearch-head { display: flex; align-items: center; gap: 10px; padding: 10px 14px; border-bottom: 1px solid var(--bs-border-color); }
.aae-msearch-head .bi-search { color: var(--bs-secondary-color); }
.aae-msearch-head .form-control { border: 0; box-shadow: none; padding-left: 0; font-size: 1.02rem; }
.aae-msearch-head kbd { font-size: .7rem; background: var(--bs-tertiary-bg); color: var(--bs-secondary-color); }
.aae-msearch-list { list-style: none; margin: 0; padding: 0; }
.aae-msearch-list li[data-i] {
  display: flex; align-items: center; gap: 12px; padding: 9px 10px; border-radius: 10px; cursor: pointer;
}
.aae-msearch-list li[data-i] > .bi { font-size: 1.1rem; color: var(--aae-primary); width: 22px; text-align: center; }
.aae-msearch-list li.active, .aae-msearch-list li[data-i]:hover { background: rgba(var(--bs-primary-rgb), .08); }
.aae-msearch-label { font-weight: 600; }
.aae-msearch-note { font-size: .8rem; color: var(--bs-secondary-color); }
.aae-msearch-group { font-size: .72rem; color: var(--bs-secondary-color); white-space: nowrap; }
.aae-msearch-none { padding: 18px; text-align: center; color: var(--bs-secondary-color); }
@media (max-width: 575.98px) { .aae-msearch-group { display: none; } }

/* Every select keeps room on the right for its arrow. The shared ".form-control, .form-select" padding
   above set all four sides alike, so a narrow select (the Holidays year, a page size) drew its arrow
   over the text. */
.form-select, .aae-field > .form-select { padding-right: 2.25rem; background-position: right .7rem center; }
.form-select-sm { padding-right: 2rem; background-position: right .55rem center; }

/* A dashboard figure that needs looking at (Face not matched). */
.aae-stat-row.bad .aae-stat-label, .aae-stat-row.bad .aae-stat-value { color: var(--bs-danger); font-weight: 600; }

/* A card that is not reporting the day but asking for a decision (Approvals). Its words go red —
   the title and the name of each queue — and the figures are left alone. The red is saying one
   thing, that something is waiting to be decided; a red number would say the number was wrong.

   The row selector carries the extra class on purpose: the leading line is .strong, whose own label
   rule is three classes deep, and a shorter selector here lost to it — so the first queue, the one
   that matters most, was the only one left black. */
.aae-stat-urgent .aae-stat-title { color: var(--bs-danger); }
.aae-stat-urgent .aae-stat-row .aae-stat-label { color: var(--bs-danger); }
/* Report lines that open something (Face Check → the selfie). */
.aae-rep-clickable .tabulator-row { cursor: pointer; }

/* Punch selfie beside the profile photo (face.js openSelfie). */
.aae-face-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.aae-face-fig { margin: 0; }
.aae-face-fig img { width: 100%; height: 52vh; max-height: 420px; object-fit: contain; border-radius: 12px; background: var(--bs-tertiary-bg); }
.aae-face-fig figcaption { margin-top: 6px; font-size: .82rem; font-weight: 600; color: var(--bs-secondary-color); }
.aae-face-none { height: 52vh; max-height: 420px; border-radius: 12px; background: var(--bs-tertiary-bg); display: grid; place-content: center; gap: 6px; color: var(--bs-secondary-color); }
.aae-face-none .bi { font-size: 2.2rem; }
@media (max-width: 575.98px) { .aae-face-fig img, .aae-face-none { height: 34vh; } }

/* Every popup keeps its footer (Save, Close) on screen. Its content is held to the window's height and
   the middle scrolls — what Bootstrap's modal-dialog-scrollable does, applied to all of them, since most
   popups here were written without it and a long one pushed Save below the bottom of a laptop screen. */
.modal-content { max-height: calc(100dvh - 2 * var(--bs-modal-margin, 1.75rem)); }
.modal-body { overflow-y: auto; min-height: 0; }

/* Save moved into the dark header (layout.js toTopbar): light, and plainly the thing to press. */
.aae-topbar-save { background: #fff; color: var(--aae-primary, #1e3a8a); border: 0; font-weight: 600; }
.aae-topbar-save:hover, .aae-topbar-save:focus { background: #eef2ff; color: var(--aae-primary, #1e3a8a); }
.aae-topbar-save:disabled { background: rgba(255,255,255,.55); color: rgba(30,58,138,.6); }

/* Back office → Storage */
.aae-storage-row { cursor: pointer; }
.aae-storage-row:hover { background: rgba(var(--bs-primary-rgb), .05); }
.aae-storage-row.open { background: rgba(var(--bs-primary-rgb), .07); }
.aae-storage-detail td { background: var(--bs-tertiary-bg); }
.aae-storage-chip { display: inline-flex; align-items: center; padding: 4px 10px; border-radius: 999px;
  background: var(--bs-body-bg); border: 1px solid var(--bs-border-color); font-size: .82rem; }

/* Header Save, final: a solid colour of its own, so it reads on a dark header and a light one alike
   (overrides the white version above). */
.aae-topbar .aae-topbar-save {
  background: #16a34a; color: #fff; border: 1px solid #15803d; font-weight: 600;
  box-shadow: 0 2px 6px rgba(22, 163, 74, .35); padding-left: .9rem; padding-right: .9rem;
}
.aae-topbar .aae-topbar-save:hover, .aae-topbar .aae-topbar-save:focus { background: #15803d; color: #fff; }
.aae-topbar .aae-topbar-save:disabled { background: #86c79c; border-color: #86c79c; color: #fff; box-shadow: none; }

/* A settings page's Cancel / Save (layout.js toFooter): the popups' footer, held at the bottom of the
   screen while the form scrolls above it. */
.aae-page-footer {
  position: sticky; bottom: 0; z-index: 20;
  display: flex; justify-content: flex-end; align-items: center; gap: 10px;
  margin: 18px -4px 0; padding: 12px 16px;
  background: var(--bs-body-bg); border: 1px solid var(--bs-border-color); border-radius: 14px;
  box-shadow: 0 -6px 18px rgba(15, 23, 42, .08);
}
.aae-page-footer .btn { min-width: 110px; }
.aae-page-footer .aae-page-cancel { background: var(--bs-body-bg); border: 1px solid var(--bs-border-color); }

/* A card's own Cancel / Save, where a page has two independent forms (My Profile): the popup footer
   inside the card. */
.aae-card-actions {
  display: flex; justify-content: flex-end; gap: 10px;
  margin: 18px -16px -16px; padding: 12px 16px;
  border-top: 1px solid var(--bs-border-color); background: var(--bs-tertiary-bg);
  border-radius: 0 0 var(--bs-card-inner-border-radius, 14px) var(--bs-card-inner-border-radius, 14px);
}
.aae-card-actions .btn { min-width: 110px; }
.aae-page-cancel { background: var(--bs-body-bg); border: 1px solid var(--bs-border-color); }
.aae-page-cancel:hover { background: var(--bs-tertiary-bg); border-color: var(--bs-secondary-border-subtle, #cbd5e1); }

/* Dashboard "⟳ Updated 5:30 pm": the licence pill's shape, and a button. */
.aae-asof { gap: .35rem; cursor: pointer; background: transparent; font-family: inherit; line-height: 1.4; }
.aae-topbar .aae-asof:hover { background: rgba(255, 255, 255, .2); }
.aae-spinning { display: inline-block; animation: aae-spin .8s linear infinite; }
@keyframes aae-spin { to { transform: rotate(360deg); } }
/* A header title never breaks onto a second line; it gives way with an ellipsis instead. */
.aae-topbar #aae-page-title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
/* The title is the last thing to give way: the pills beside it shorten first. */
.aae-topbar #aae-page-title { flex: 0 0 auto; overflow: visible; }
@media (max-width: 1279.98px) {
  .aae-asof-word { display: none; }
  .aae-topbar .aae-licence:not(.aae-asof) { max-width: 13.5rem; overflow: hidden; text-overflow: ellipsis; display: inline-block; }
}
.aae-licence .lic-short { display: none; }
@media (max-width: 1279.98px) {
  .aae-topbar .aae-licence:not(.aae-asof) { max-width: none; overflow: visible; display: inline-flex; }
  .aae-licence .lic-long { display: none; }
  .aae-licence .lic-short { display: inline; }
}

/* ---------- The header on a phone ----------
   The account menu is the only way to Sign out, to the profile and to the password, and it was being
   pushed clean off the right edge: the title above is pinned to flex: 0 0 auto so it never gives
   way, which is right on a desktop — the pills beside it shorten first — and wrong here, where
   there is nothing left to shorten.

   So on a narrow screen the order of sacrifice is reversed. The title truncates, the licence pill
   stands down (nobody reads a renewal date on a phone, and it is on the dashboard anyway), and the
   account keeps its place at the end of the row. Matters twice over now: the Office tab in the
   Android app is this same header in a 412-pixel web view. */
@media (max-width: 767.98px) {
  /* min-width: 0 is the whole of it, and leaving it out is why this row kept overflowing by a
     hair. A flex item's default minimum is its MIN-CONTENT width, so the title would truncate to
     "Dashbo…" — the longest word it holds — and then refuse to give another pixel, however little
     room was left. Everything to its right then went over the edge, and whichever control happened
     to be last was the one cut in half. With the floor removed the title absorbs the shortfall at
     any width, which is what it is for: nobody needs to read the page name on a phone that is
     already showing the page. */
  .aae-topbar #aae-page-title { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .aae-topbar .aae-licence:not(.aae-asof) { display: none !important; }

  /* The refresh pill keeps its arrow and loses the time. It was the widest thing in the row after
     the title — about 95px for "⟳ 8:34 am" — and the row was over by less than twenty. The arrow
     still says what the control does, and the dashboard prints the date it is reporting on in the
     card directly below, so the time was the one piece of this header repeated elsewhere on screen. */
  .aae-topbar .aae-asof #dashAsOf { display: none; }
  .aae-topbar .aae-asof { padding-left: .5rem; padding-right: .5rem; }

  /* And now the right-hand group is pinned again, deliberately. It is the title that gives way,
     never these: a search button at half width is not a smaller button, it is a broken one. */
  .aae-topbar .ms-auto { gap: .5rem !important; flex: 0 0 auto; }
  .aae-topbar .aae-account { flex: 0 0 auto; max-width: none; }

  .aae-topbar .ms-auto > .dropdown { min-width: 0; }

  /* The logo stays, smaller. Taking it out of the row was the wrong trade: it is the tenant's own
     mark and the only thing in this header that says whose workspace this is. Dropping the time
     from the refresh pill above bought about sixty pixels, which is enough to carry it whole.
     Capped as a share of the screen as well as in pixels, because the file is a tenant's upload and
     the next one will be a different shape. */
  .aae-topbar .aae-org-logo { height: 22px; max-width: min(72px, 18vw); }

  /* The icon is only for a company that has no logo on file — with the name hidden at this width
     the button would otherwise be empty. Never both. */
  .aae-account-icon { display: block; font-size: 1.4rem; line-height: 1; }
  .aae-account #aae-org-logo:not(:empty) ~ .aae-account-icon { display: none; }

  /* The account sits inside a .dropdown wrapper, and the wrapper is what the row was shrinking:
     it gave way to 47px while the button inside it kept its 60, so the company icon spilled over
     the sign-out button beside it. The wrapper holds its width too. */
  .aae-topbar .ms-auto > .dropdown { flex: 0 0 auto; }

  /* And the caret goes. It costs ten pixels this row has no room for, and a company logo that
     opens a menu needs no arrow to say so. */
  .aae-topbar .aae-account-caret { display: none; }

  /* Sign out moves into the account menu. Shaving pixels off this row only ever buys enough width
     for the handset it was measured on — the next one is narrower and the button goes over the edge
     again. A menu cannot run out of room. */
  .aae-topbar .aae-signout { display: none; }
}

/* The other half of that: the menu item is for narrow screens only, because on a desktop the
   button beside the menu is already there and two ways to sign out in one corner is one too many. */
@media (min-width: 768px) { .aae-signout-item { display: none; } }

/* ---------- City type-ahead (components/city-input.js) ----------
   Anchored to the field's own wrapper rather than the page, so it travels with the field when a
   dialog scrolls. Above the modal's own stacking context — a suggestion list drawn underneath the
   popup it belongs to is the classic way this goes wrong. */
.aae-city-panel {
  position: absolute; top: 100%; left: 0; right: 0; z-index: 1080;
  margin-top: .2rem; max-height: 15rem; overflow-y: auto;
  background: var(--aae-surface, #fff);
  border: 1px solid var(--aae-line, #e2e8f0); border-radius: .5rem;
  box-shadow: 0 .6rem 1.4rem rgba(2, 6, 23, .14);
}
.aae-city-opt {
  display: flex; align-items: center; justify-content: space-between; gap: .5rem;
  width: 100%; padding: .45rem .7rem; border: 0; background: none; text-align: left;
  font-size: .9rem; color: var(--aae-ink, #0f172a);
}
.aae-city-opt:hover, .aae-city-opt.active { background: var(--aae-surface-2, #f1f5f9); }

/* Says where an unverified name came from, so nobody treats a colleague's typo as an official
   spelling. Quiet, because most of them are perfectly good towns. */
.aae-city-new {
  font-size: .68rem; color: var(--aae-muted, #64748b); white-space: nowrap;
}

/* "Cochin → Kochi". Says what choosing this will actually put in the box, because a field that
   rewrites itself without explanation reads as a fault rather than a kindness. */
.aae-city-alias { font-size: .78rem; color: var(--aae-muted, #64748b); }

/* Dashboard punch log: action on top, time away under it, in the height one line used to take. */
#activityTable .tabulator-cell { padding-top: 5px; padding-bottom: 5px; }
.aae-log-act { min-width: 0; line-height: 1.2; }
.aae-log-main { font-size: .86rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.aae-log-away { font-size: .7rem; color: var(--bs-secondary-color); margin-top: 1px; }
/* Tighter still, so a row with the time-away line is no taller than one without. */
#activityTable .tabulator-row .tabulator-cell { padding-top: 3px; padding-bottom: 3px; }
#activityTable .tabulator-row { min-height: 34px; }
.aae-log-act { line-height: 1.1; }
.aae-log-main { font-size: .84rem; }
.aae-log-away { font-size: .66rem; margin-top: 0; }

/* The Matched badge keeps to the right-hand edge on every line. A reason or a duration already pushes
   it there; a lone punch-in has neither, and its badge sat just after "IN", out of line with the rest. */
.pd-face { margin-left: auto; }
.pd-line :is(.pd-reason, .pd-dur) ~ .pd-face { margin-left: 0; }
/* Back office: "252.9 MB" on one line, so the Space Used card is no taller than its neighbours. */
[data-kpi="spaceUsed"] { white-space: nowrap; font-size: 1.35rem; }

/* Date picker: Sunday and company holidays in red, the way a wall calendar reads. The selected day
   keeps its own colours — a holiday that is also the chosen date must still look chosen. */
.aae-datepicker .dp-weekdays span:first-child { color: #dc2626; }
.aae-datepicker .dp-cell.dp-sunday:not(.dp-selected) { color: #dc2626; }
.aae-datepicker .dp-cell.dp-holiday:not(.dp-selected) { color: #dc2626; font-weight: 700; }
/* The dot sits under the number without moving it. In the flow it pushed the date up, and a holiday
   stood a line higher than the days beside it. */
.aae-datepicker .dp-cell { position: relative; }
.aae-datepicker .dp-cell.dp-holiday:not(.dp-selected)::after {
  content: ""; position: absolute; left: 50%; bottom: 4px; transform: translateX(-50%);
  width: 4px; height: 4px; border-radius: 50%; background: #dc2626;
}
.aae-datepicker .dp-cell.dp-disabled { color: var(--bs-secondary-color); }

/* Attendance Register: a day whose selfie did not match the profile photo carries a red corner. It is
   the one mark that may mean somebody else punched, and as a small "▴" beside L and NE it was missed. */
#grid td.aae-rc.aae-rc-face { position: relative; }
#grid td.aae-rc.aae-rc-face::after {
  content: ""; position: absolute; top: 0; right: 0;
  border-top: 12px solid #dc2626; border-left: 12px solid transparent;
}
/* The same corner on its legend chip, so the key and the grid show the same thing. */
.aae-rl-face { position: relative; background: #fee2e2; border: 1px solid #fca5a5; }
.aae-rl-face::after {
  content: ""; position: absolute; top: 0; right: 0;
  border-top: 9px solid #dc2626; border-left: 9px solid transparent;
}

/* Deciding several requests at once. The bar sits under the panel head, where somebody who has just
   read "4 leave requests are waiting" looks next; the tick lives beside the person, not in a column
   of its own, so the card keeps its four-part shape at every width. */
.aae-req-bulk { display: flex; align-items: center; gap: 10px 14px; flex-wrap: wrap;
  background: #fff6e4; border: 1px solid #f1e3c2; border-radius: 12px; padding: 8px 12px; margin-bottom: 4px; }
.aae-req-all { display: inline-flex; align-items: center; gap: .45rem; font-weight: 600; font-size: .88rem;
  color: #7a4d07; margin: 0; cursor: pointer; }
.aae-req-count { font-size: .82rem; color: #8a6a2e; }
.aae-req-bulk-actions { display: flex; gap: 8px; margin-left: auto; }
.aae-req-bulk-actions .btn { font-weight: 600; border-radius: 9px; }
.aae-req-pick { flex: 0 0 auto; width: 1.1rem; height: 1.1rem; margin: 0; cursor: pointer; }
.aae-req.picked { border-color: #f0a92a; box-shadow: 0 0 0 3px rgba(240, 169, 42, .18); }

/* The day's lateness, said on the punch it belongs to: amber for a late arrival, the same colour the
   register's L mark uses, so the two screens plainly describe one thing. */
.pd-mark { display: inline-flex; align-items: center; font-weight: 700; font-size: .72rem;
  padding: .12rem .5rem; border-radius: 999px; background: #fdf0d9; color: #a36b0c; white-space: nowrap; }

/* The employee's month, in a card of its own. The squares sat straight on the popup's background,
   which left the grid reading as loose furniture beside the figures above it rather than as one
   panel; the weekday strip and the squares belong to each other and now say so. */
.aae-ecal .ec-grid-wrap {
  background: var(--aae-surface); border: 1px solid var(--aae-line); border-radius: 16px;
  padding: .85rem; box-shadow: 0 .35rem 1rem rgba(22, 35, 58, .05);
}
/* Four figures, or five on a month that has visits — the row fits itself to however many there are. */
.aae-ecal .ec-stats { grid-template-columns: repeat(auto-fit, minmax(5.4rem, 1fr)); }
@media (max-width: 575.98px) { .aae-ecal .ec-stats { grid-template-columns: repeat(2, 1fr); } }

/* ---------- Header: nothing is allowed to push Sign out off the edge ----------
   A page with three of its own buttons (Print, PDF, Excel), the licence pill and a long company
   name filled the bar and the sign-out button fell off the right of it. The rule is an order of
   yielding: the title gives way first, then the company name, then the licence — and the round
   buttons and Sign out never shrink, because a control you cannot reach is worse than a truncated
   word. */
.aae-topbar { min-width: 0; }
.aae-topbar > .ms-auto { min-width: 0; flex: 0 1 auto; }
.aae-topbar h1 {
  min-width: 0; flex: 0 1 auto; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.aae-topbar #aae-topbar-actions { flex: 0 0 auto; }
.aae-topbar .aae-help-btn, .aae-topbar .aae-signout { flex: 0 0 auto; }
.aae-topbar .dropdown { min-width: 0; }
.aae-account { flex: 0 1 auto; min-width: 0; }

/* Narrower than a wide desktop: the title steps down and the account text gives up room before the
   licence does, since the company name is already on screen in the sidebar. */
@media (max-width: 1499.98px) {
  .aae-topbar h1 { font-size: 1.02rem; }
  .aae-account { max-width: 14rem; }
  .aae-topbar { gap: .7rem; }
}
@media (max-width: 1299.98px) {
  .aae-topbar h1 { font-size: .96rem; }
  .aae-account { max-width: 11rem; }
}

/* A button standing in a row of notched fields matches their height, so the row reads as one band
   rather than a line of boxes with a short one in it. */
.aae-tall { height: 46px; }

/* Print, PDF and Excel: a size smaller, and the words drop away before the header runs out of room.
   The colour and the icon carry the meaning — red is the PDF, green the workbook — so on a laptop
   the three take about a third of the width they did, which is what was pushing Sign out off. */
.aae-hbtn { height: 30px; padding: 0 9px; gap: 5px; font-size: .82rem; }
.aae-hbtn .bi { font-size: 14px; }
@media (max-width: 1499.98px) {
  .aae-hbtn-t { display: none; }
  .aae-hbtn { padding: 0 8px; }
}

/* ---------- Totals strip ----------
   The tile the employee calendar uses for a month, made general: label and figure on one line with
   a colour down the left edge. Half the height of a label-over-figure card, which matters on a page
   whose point is the grid underneath — six of those cards were taking a band of the screen to say
   six short things. */
.aae-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr)); gap: .5rem; }
.aae-stat {
  position: relative; overflow: hidden; display: flex; align-items: center; justify-content: space-between;
  gap: .5rem; background: var(--aae-surface); border: 1px solid var(--aae-line); border-radius: 12px;
  padding: .4rem .7rem .4rem .95rem; box-shadow: 0 1px 2px rgba(15, 23, 42, .04);
}
.aae-stat::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px;
  background: var(--aae-accent, var(--aae-line));
}
.aae-stat-label { font-size: .68rem; font-weight: 600; letter-spacing: .06em; color: var(--aae-muted); text-transform: uppercase; }
.aae-stat-value { font-size: 1.3rem; font-weight: 700; line-height: 1; white-space: nowrap; }
@media (max-width: 575.98px) { .aae-stats { grid-template-columns: repeat(2, 1fr); } }

/* A tile that has a second thing to say — "2 out · 1,35,000" under the label. Stacked rather than
   crowded onto the one line, because the figure on the right is what the tile is for and a second
   value beside it competes with it. The tile stays the same height when the line is absent. */
.aae-stat-text { display: flex; flex-direction: column; gap: .1rem; min-width: 0; }
.aae-stat-sub {
  font-size: .72rem; color: var(--aae-muted); line-height: 1.2;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ---------- The app's own tooltip ----------
   Drawn by tooltip.js from the same `title` attributes the pages already carry, because the
   browser's version is a grey system label in the operating system's font that cannot be styled and
   wraps a long one — a register cell's whole day — wherever it likes. Dark, rounded, in our own
   type, with a width it will not exceed. */
.aae-tip {
  position: fixed; z-index: 3000; max-width: 22rem; pointer-events: none;
  background: #16233a; color: #fff; border-radius: 10px; padding: .4rem .6rem;
  font-size: .78rem; line-height: 1.35; font-weight: 500; text-align: left;
  box-shadow: 0 .5rem 1.2rem rgba(15, 23, 42, .25);
  opacity: 0; transform: translateY(-2px); transition: opacity .12s ease, transform .12s ease;
}
.aae-tip.on { opacity: 1; transform: none; }
/* A small tail, on whichever side the tip ended up. */
.aae-tip::after {
  content: ""; position: absolute; left: 50%; margin-left: -5px; border: 5px solid transparent;
  top: -10px; border-bottom-color: #16233a;
}
.aae-tip.above::after { top: auto; bottom: -10px; border-bottom-color: transparent; border-top-color: #16233a; }

/* The tooltip was the header's own navy, so on the header it vanished into it — a label you can
   only read against half the app is not a label. A deeper ink than any surface it can appear over,
   with a hairline edge and a stronger shadow, so it reads as something lifted off the page whether
   the page behind it is white or navy. */
.aae-tip {
  background: #0B1524;
  border: 1px solid rgba(255, 255, 255, .16);
  box-shadow: 0 .6rem 1.4rem rgba(2, 8, 20, .45);
}
.aae-tip::after { border-bottom-color: #0B1524; }
.aae-tip.above::after { border-bottom-color: transparent; border-top-color: #0B1524; }

/* ---------- The register's day cells say they open something ----------
   A slightly darker tint on hover was the only hint, which on a pale green square reads as nothing
   at all. Daily Attendance underlines the employee on hover; a day cell does the same to the figure
   it carries, and takes a ring in the brand colour so the whole square is plainly the target. */
#grid td.aae-rc.clickable:hover {
  filter: brightness(.97);
  box-shadow: inset 0 0 0 2px var(--aae-primary);
}
#grid td.aae-rc.clickable:hover .aae-rc-main { text-decoration: underline; text-underline-offset: 2px; }
/* The employee's name opens their month — it is a link, so it behaves like one. */
#grid a[data-emp]:hover { text-decoration: underline !important; }

/* ---------- Field map: a day's route ----------
   The numbered stop, the distance on each leg, and the line under the toolbar saying what the day
   added up to. The numbers are on the pins because "which came first" is the question a route map
   is opened with. */
.aae-fm-stop span {
  display: grid; place-items: center; width: 22px; height: 22px; border-radius: 50%;
  background: var(--stop, #2c5fb3); color: #fff; font-size: .7rem; font-weight: 700;
  box-shadow: 0 0 0 2px #fff, 0 .15rem .4rem rgba(15, 23, 42, .35);
}
.aae-fm-leg span {
  display: inline-block; transform: translate(-50%, -50%); white-space: nowrap;
  background: rgba(255, 255, 255, .92); color: #2c5fb3; border: 1px solid #cfdcf3;
  border-radius: 999px; padding: 0 .35rem; font-size: .66rem; font-weight: 700;
}
.aae-fm-route {
  background: var(--aae-surface-2); border: 1px solid var(--aae-line); border-left: 4px solid #2c5fb3;
  border-radius: 10px; padding: .4rem .7rem;
}

/* Import: the drop area. A dashed box says "put it here" in a way a bare file input does not, and
   the file input stays inside it so there is one place to look rather than two. */
.aae-drop {
  border: 2px dashed var(--aae-line); border-radius: 14px; padding: 1rem; text-align: center;
  color: var(--aae-muted); transition: border-color .15s, background .15s;
}
.aae-drop.over { border-color: var(--aae-primary); background: var(--aae-primary-tint); }
.aae-drop > .bi { font-size: 1.6rem; display: block; margin-bottom: .25rem; opacity: .7; }
