/* =============================================================
   SG — Component layer
   =============================================================
   Sits on top of Bootstrap 5 and the SG token layer. Every rule
   here is markup-first: the same class names work in a Django
   template, a static HTML page and a React component, so a screen
   can move between stacks without being restyled.

   No utility framework. Bootstrap for layout and its own
   components; SG classes for everything Bootstrap has no opinion
   about (heroes, stat cards, page shell).
   ============================================================= */

/* -------------------------------------------------------------
   Status pill
   ------------------------------------------------------------- */
/* The reference labels a state with Bootstrap's `badge rounded-pill`, so
   this is a tone layer over that rather than a bespoke pill. Kept tinted
   with dark text rather than solid: a table with thirty solid badges is
   unreadable. */
.badge.sg-status-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border: 1px solid transparent;
  font-size: var(--sg-text-xs);
  font-weight: 600;
  line-height: 1.4;
  white-space: nowrap;
}
.badge.sg-status-pill.tone-success { background: #EAF4F1; color: #0F6B4B; }
.badge.sg-status-pill.tone-danger  { background: #F8ECED; color: #A32B36; }
.badge.sg-status-pill.tone-warning { background: #F8F3EB; color: #8A5A06; }
.badge.sg-status-pill.tone-info    { background: #E9F4F7; color: #0B6E80; }
.badge.sg-status-pill.tone-geral   { background: var(--sg-bg-tertiary); color: var(--sg-text-secondary); }

/* -------------------------------------------------------------
   Language toggle
   -------------------------------------------------------------
   The two-language switch from the reference app: a 60x32 pill with
   both codes printed on it, so the current language and the one you
   would switch to are BOTH readable at rest. A flag or a globe icon
   makes you click to find out.

   Colours are tokenised — the original hard-coded #4f46e5 for the
   active state, which is how it stayed indigo in a teal tenant.
   ------------------------------------------------------------- */
.sg-lang-toggle {
  position: relative;
  width: 60px;
  height: 32px;
  flex-shrink: 0;
  border-radius: var(--sg-radius-pill);
  background: var(--sg-bg-tertiary);
  border: 2px solid var(--sg-border);
  cursor: pointer;
  transition: background .3s ease, border-color .3s ease;
  display: flex;
  align-items: center;
  padding: 2px;
}

.sg-lang-toggle.is-active {
  background: var(--sg-primary);
  border-color: var(--sg-primary-active);
}

.sg-lang-toggle:focus-visible {
  outline: none;
  box-shadow: 0 0 0 var(--sg-focus-ring)
    color-mix(in srgb, var(--sg-ring) 50%, transparent);
}

.sg-lang-toggle-slider {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: #fff;
  transition: transform .3s ease;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
  position: absolute;
  left: 2px;
  z-index: 2;
}

.sg-lang-toggle.is-active .sg-lang-toggle-slider {
  transform: translateX(28px);
}

.sg-lang-toggle-label {
  font-size: 11px;
  font-weight: 700;
  position: absolute;
  z-index: 1;
  transition: color .3s ease;
  user-select: none;
}

.sg-lang-toggle-label:first-of-type { left: 7px; color: var(--sg-text-secondary); }
.sg-lang-toggle-label:last-of-type  { right: 6px; color: var(--sg-text-muted); }
.sg-lang-toggle.is-active .sg-lang-toggle-label:first-of-type {
  color: color-mix(in srgb, var(--sg-on-primary) 50%, transparent);
}
.sg-lang-toggle.is-active .sg-lang-toggle-label:last-of-type {
  color: var(--sg-on-primary);
}

@media (prefers-reduced-motion: reduce) {
  .sg-lang-toggle,
  .sg-lang-toggle-slider,
  .sg-lang-toggle-label { transition: none; }
}

/* -------------------------------------------------------------
   Notification bell
   ------------------------------------------------------------- */
.sg-notifications {
  position: relative;
}

.sg-notification-toggle {
  width: 34px;
  height: 34px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--sg-text);
  cursor: pointer;
  position: relative;
  font-size: 19px;
  transition: background .15s, transform .15s;
}

.sg-notification-toggle:hover,
.sg-notification-toggle:focus-visible,
.sg-notification-toggle.is-open {
  background: var(--sg-bg-tertiary);
  outline: 0;
  transform: translateY(-1px);
}

/* The count sits half outside the button, so it needs a ring in the
   page colour to stay legible against whatever is behind the navbar. */
.sg-notification-badge {
  position: absolute;
  top: -7px;
  right: -9px;
  display: grid;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  place-items: center;
  border: 2px solid var(--sg-surface);
  border-radius: var(--sg-radius-pill);
  background: var(--sg-danger);
  color: #fff;
  font-size: 9px;
  font-weight: 800;
  line-height: 1;
}

.sg-notifications-panel {
  position: absolute;
  top: calc(100% + 16px);
  right: 0;
  width: min(360px, calc(100vw - 28px));
  background: var(--sg-surface);
  border: 1px solid var(--sg-border);
  border-radius: var(--sg-radius-sm);
  box-shadow: 0 16px 32px rgba(17, 24, 39, .14);
  z-index: 1060;
  overflow: hidden;
  /* Animated with opacity/visibility rather than display, so the panel
     can transition out instead of vanishing. */
  opacity: 0;
  visibility: hidden;
  transform: translateY(-8px);
  transition: opacity .15s, visibility .15s, transform .15s;
}

.sg-notifications-panel.is-open {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

.sg-notifications-head {
  min-height: 60px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 0 18px;
  border-bottom: 1px solid var(--sg-border);
}

.sg-notifications-title {
  margin: 0;
  color: var(--sg-text);
  font-size: var(--sg-text-base);
  font-weight: 500;
}

.sg-notifications-list {
  max-height: 340px;
  overflow-y: auto;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* The notification row — `.mini-activity-notification`.
   -------------------------------------------------------------
   A block button, not a flex row: the title and the line under it
   are both `display: block`, so a long message wraps under the
   title instead of squeezing it.

   Unread is marked by a soft accent fill AND a heavier, accent-
   coloured title — two signals, because a fill two greys apart
   disappears for anyone who cannot separate them. */
.sg-notification-item {
  width: 100%;
  display: block;
  padding: 9px 10px;
  border: 0;
  border-bottom: 1px solid #EDF1F5;
  border-radius: 7px;
  background: #fff;
  color: #172033;
  text-align: left;
  cursor: pointer;
}

.sg-notification-item:last-child { border-bottom: 0; }

.sg-notification-item:hover {
  background: color-mix(in srgb, var(--sg-primary) 6%, #fff);
}

.sg-notification-item[data-por-ler="sim"] {
  background: var(--sg-primary-soft);
}

.sg-notification-item[data-por-ler="sim"] strong {
  color: var(--sg-primary-700);
  font-weight: 800;
}

.sg-notification-item strong,
.sg-notification-item small {
  display: block;
}

.sg-notification-item strong {
  font-size: 11.5px;
  font-weight: 700;
}

.sg-notification-item small {
  margin-top: 3px;
  color: var(--sg-text-muted);
  font-size: 10.5px;
  line-height: 1.45;
}

.sg-notifications-empty {
  min-height: 170px;
  display: grid;
  place-items: center;
  align-content: center;
  gap: 14px;
  color: var(--sg-text-muted);
  font-size: var(--sg-text-sm);
  text-align: center;
  padding: 18px;
}
.sg-notifications-empty i {
  font-size: 48px;
  line-height: 1;
  color: var(--sg-primary-300);
}

.sg-notifications-footer {
  display: flex;
  justify-content: center;
  padding: 10px 12px;
  border-top: 1px solid #D7DCE4;
}

/* -------------------------------------------------------------
   Tab bar
   -------------------------------------------------------------
   From dashboardShared.tsx in the reference app.

   A GRID of equal columns, not a flex row that sizes each tab to its
   own text — equal columns keep the bar from reflowing every time a
   count appears. Above four tabs the columns got narrow enough to cut
   labels mid-word ("Histórico de correcções" cut at 1440px with six
   tabs), so it switches to auto-fit and wraps to a second line
   instead: one line more beats one word less.

   The bar stays quiet. Even the active tab is font-weight 400 — only
   the accent fill marks it. A bold active tab plus a fill is saying
   the same thing twice.
   ------------------------------------------------------------- */
.sg-tabbar {
  display: grid;
  grid-template-columns: repeat(var(--sg-tabbar-count, 4), minmax(0, 1fr));
  gap: 8px;
  margin-bottom: 14px;
  background: var(--sg-surface);
  border: 1px solid var(--sg-border);
  border-radius: var(--sg-radius);
  padding: 10px 12px;
  box-shadow: var(--sg-shadow-xs);
}

/* Five or more tabs: wrap rather than squeeze. */
.sg-tabbar.is-wrapping {
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
}

.sg-tab {
  min-height: 36px;
  padding: 0 13px;
  border-radius: var(--sg-radius-sm);
  border: none;
  background: transparent;
  color: var(--sg-text-muted);
  cursor: pointer;
  font-weight: 400;
  font-size: var(--sg-text-xs);
  line-height: 1.15;
  transition: all .15s;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

.sg-tab:hover:not(.is-active) {
  background: var(--sg-bg-tertiary);
  color: var(--sg-text);
}

.sg-tab.is-active {
  background: var(--sg-primary);
  color: var(--sg-on-primary);
}

.sg-tab:focus-visible {
  outline: none;
  box-shadow: 0 0 0 var(--sg-focus-ring)
    color-mix(in srgb, var(--sg-primary) 40%, transparent);
}

/* The count is RED, not grey. A counter only appears when there is
   something unseen; in grey it passed for decoration, which is exactly
   what it was meant not to be. On the active tab it goes white-on-fill,
   because there red loses contrast and you already know where you are. */
.sg-tab-count {
  min-width: 20px;
  min-height: 20px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--sg-radius-pill);
  padding: 0 6px;
  background: #EF4444;
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
}

.sg-tab.is-active .sg-tab-count {
  background: rgba(255, 255, 255, 0.22);
}

/* A hero with the tab bar directly under it: the two read as one block,
   so the hero drops its bottom margin and the bar tucks up to it. */
.sg-page-hero + .sg-tabbar {
  margin-top: -6px;
}

/* Sub-tabs — a SEGMENTED SWITCH, not a second row of tabs.
   -------------------------------------------------------------
   Rebuilt from the reference's painelModoWrap / painelModo pair.
   The previous underline version was invented and did not exist
   anywhere in the app.

   The whole control is ONE container with a translucent fill, and
   the active segment is a solid white chip inside it. Two loose
   outlined buttons side by side read as two independent actions;
   one container with a moving chip reads as two views of the same
   thing, which is what a sub-tab actually is. */
.sg-subtabbar {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px;
  border-radius: 10px;
  background: var(--sg-bg-tertiary);
  margin-bottom: 14px;
}

/* Inside a hero: the same control, sized to the hero's button height so it
   lines up with any real action beside it in the bar, and filled with a wash
   of the foreground colour instead of a grey. */
.sg-page-hero .sg-subtabbar {
  background: color-mix(in srgb, var(--sg-on-primary) 14%, transparent);
  padding: 6px;
  border-radius: 12px;
  gap: 6px;
  margin-bottom: 0;
}

.sg-page-hero .sg-subtab {
  min-height: 47px;
  height: 47px;
  padding: 0 24px;
  font-size: var(--sg-text-base);
  font-weight: 400;
}

.sg-page-hero .sg-subtab.is-active {
  font-weight: 700;
}

.sg-subtab {
  min-height: 30px;
  height: 30px;
  padding: 0 12px;
  font-size: 12.5px;
  font-weight: 600;
  border: none;
  border-radius: 7px;
  background: transparent;
  color: var(--sg-text-muted);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
  transition: background .15s, color .15s;
}

.sg-page-hero .sg-subtab {
  color: color-mix(in srgb, var(--sg-on-primary) 78%, transparent);
}

.sg-subtab:hover:not(.is-active) {
  color: var(--sg-text);
}

.sg-subtab.is-active {
  background: #fff;
  color: #1f2937;
  font-weight: 700;
  box-shadow: 0 1px 2px rgba(15, 23, 42, .18);
}

.sg-subtab:focus-visible {
  outline: none;
  box-shadow: 0 0 0 var(--sg-focus-ring)
    color-mix(in srgb, var(--sg-primary) 40%, transparent);
}

@media (max-width: 767.98px) {
  /* At 360px a six-tab grid gave six stacked rows. It becomes one
     scrollable row, masked at the right edge so it is visibly
     scrollable rather than looking cut off. */
  .sg-tabbar {
    display: flex;
    grid-template-columns: none;
    flex-wrap: nowrap;
    overflow-x: auto;
    padding: 8px 10px;
    scrollbar-width: none;
    -ms-overflow-style: none;
    scroll-snap-type: x proximity;
    -webkit-mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 24px), transparent 100%);
            mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 24px), transparent 100%);
  }
  .sg-tabbar::-webkit-scrollbar { display: none; }
  .sg-tab {
    flex: 0 0 auto;
    scroll-snap-align: start;
    padding: 0 12px;
  }
  .sg-subtabbar {
    max-width: 100%;
    overflow-x: auto;
    scrollbar-width: none;
  }
  .sg-subtabbar::-webkit-scrollbar { display: none; }
  .sg-subtab { flex: 0 0 auto; }
}

/* -------------------------------------------------------------
   Search filter panel
   -------------------------------------------------------------
   "Filtros de Pesquisa". Two variants, and the difference is about
   how many headings the screen already has:

   `destaque` — a boxed panel with a FLAT accent strip, for when the
     filters ARE the block of the page and that strip is the only
     header there is.
   `embutido` — no box at all, just the fields, for when this lives
     inside a panel that already has a title. Drawing a second box
     there put a grey rectangle on top of a panel with the air of a
     sticker, and gave one screen four headings: hero, tab, panel
     title, and then this.

   The box has NO `overflow: hidden`. It used to, and it clipped
   anything a field opened outside the box — the month calendar and
   the department panel came out decapitated. The rounding is done
   on the header strip instead.
   ------------------------------------------------------------- */
.sg-filter-panel {
  background: var(--sg-surface);
  border-radius: 16px;
  border: 1px solid var(--sg-border);
  margin-bottom: 18px;
  box-shadow: 0 1px 4px rgba(15, 23, 42, 0.06);
}

/* The strip is one line: the toggle on the left, actions on the right.
   Actions like "Actualizar" are not filters, and putting them in the
   grid below left a button jammed against a field or alone on a row. */
.sg-filter-panel-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px 6px 0;
  border-top-left-radius: 15px;
  border-top-right-radius: 15px;
  background: var(--sg-primary);
  color: var(--sg-on-primary);
}

.sg-filter-panel-title {
  flex: 1;
  min-width: 0;
  border: none;
  text-align: left;
  padding: 12px 16px;
  background: transparent;
  color: inherit;
  display: flex;
  align-items: center;
  gap: 9px;
  font-weight: 800;
  font-size: var(--sg-text-base);
  cursor: default;
  font-family: var(--sg-font-sans);
}

.sg-filter-panel-actions {
  display: flex;
  gap: 6px;
  flex-shrink: 0;
}

/* The fields. Columns cap at 240px so four filters do not stretch into
   four half-empty tracks on a wide screen. */
.sg-filter-panel-body {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 240px));
  gap: 14px;
  align-items: end;
  padding: 16px;
}

/* Embedded: no box, no strip, just the row of fields. */
.sg-filter-panel--embutido {
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  margin-bottom: 16px;
  display: flex;
  align-items: flex-end;
  gap: 14px;
  flex-wrap: wrap;
}

.sg-filter-panel--embutido .sg-filter-panel-body {
  flex: 1 1 auto;
  padding: 0;
}

/* On a phone the panel opens CLOSED and the strip becomes the switch:
   four stacked filters ate half the screen before a single result was
   visible. On a wide screen it is always open and the strip is not
   clickable, exactly as it was. */
@media (max-width: 767.98px) {
  .sg-filter-panel { margin-bottom: 12px; }
  .sg-filter-panel-head { padding: 6px 10px 6px 0; }
  .sg-filter-panel-title {
    padding: 10px 14px;
    font-size: var(--sg-text-sm);
    cursor: pointer;
  }
  .sg-filter-panel-body {
    grid-template-columns: 1fr;
    gap: 10px;
  }
  .sg-filter-panel--embutido { gap: 10px; margin-bottom: 12px; }
  .sg-filter-panel[hidden-body] .sg-filter-panel-body { display: none; }
  /* Sticky only here: on a wide screen there is room to spare and a
     panel glued to the top only stole height from the list. */
  .sg-filter-panel.is-sticky { position: sticky; top: 0; z-index: 20; }
}

/* -------------------------------------------------------------
   Page shell
   -------------------------------------------------------------
   ui.page: max-width 1380px, centred, 28px 24px 48px.
   ------------------------------------------------------------- */
.sg-page {
  max-width: 1380px;
  margin: 0 auto;
  padding: 28px 24px 48px;
  background-color: transparent;
  min-height: 100vh;
}

/* -------------------------------------------------------------
   Button
   -------------------------------------------------------------
   btnBase: 9px 16px, radius 10px, weight 700, 13px.

   The transparent border is load-bearing, not decoration. With
   `border: none` the outlined buttons came out 2px shorter than the
   filled ones, and side by side the step was visible. Every button
   carries a 1px border; only its colour changes.
   ------------------------------------------------------------- */
.sg-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 9px 16px;
  border-radius: 10px;
  border: 1px solid transparent;
  cursor: pointer;
  font-weight: 700;
  font-size: var(--sg-text-sm);
  font-family: var(--sg-font-sans);
  white-space: nowrap;
  transition: opacity .15s;
  line-height: 1.2;
}

.sg-btn:disabled { opacity: .55; cursor: not-allowed; }
.sg-btn:hover:not(:disabled) { opacity: .9; }

.sg-btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 var(--sg-focus-ring)
    color-mix(in srgb, var(--sg-primary) 40%, transparent);
}

.sg-btn--primary {
  background: var(--sg-primary);
  color: var(--sg-on-primary);
  box-shadow: 0 4px 14px var(--sg-primary-shadow-strong);
}

.sg-btn--dark {
  background: var(--sg-primary-900);
  color: #fff;
}

.sg-btn--secondary {
  background: #fff;
  color: #374151;
  border-color: var(--sg-border);
}

/* A soft wash of the accent — the "see details" weight. */
.sg-btn--details {
  padding: 7px 13px;
  background: var(--sg-primary-soft);
  color: var(--sg-primary);
  border-color: var(--sg-primary-border);
}

.sg-btn--approve { padding: 7px 13px; background: #16A34A; color: #fff; }
.sg-btn--reject  { padding: 7px 13px; background: #DC2626; color: #fff; }

.sg-btn--mini {
  padding: 8px 12px;
  background: #fff;
  border-color: var(--sg-border);
  color: #374151;
}
.sg-btn--mini-active {
  padding: 8px 12px;
  background: var(--sg-primary);
  border-color: var(--sg-primary);
  color: var(--sg-on-primary);
}

/* Close: a 34px square, not a button with an x in it. */
.sg-btn--close {
  border: none;
  background: var(--sg-divider);
  border-radius: 8px;
  width: 34px;
  height: 34px;
  padding: 0;
  justify-content: center;
  color: var(--sg-text-muted);
  font-size: var(--sg-text-lg);
}

/* --- Hero-bar buttons -------------------------------------------------
   heroBtnBase: ONE measurement for everything living in a hero. Each
   page used to set its own — 47px on Assiduidade and Feriados, 46px on
   Registo Assistido, 42px on Gestão Biométrica — and side by side no two
   were the same. 47px, radius 8, 14px at weight 400, min-width 163px. */
.sg-btn--hero,
.sg-btn--hero-secondary {
  min-height: 47px;
  height: 47px;
  min-width: 163px;
  padding: 0 24px;
  border: 0;
  border-radius: 8px;
  justify-content: center;
  gap: 8px;
  font-size: var(--sg-text-base);
  font-weight: 400;
  line-height: 1;
  transition: all .15s;
}

.sg-btn--hero {
  background: #F8F9FA;
  color: #000;
}

.sg-btn--hero-secondary {
  background: rgba(255, 255, 255, .12);
  color: #fff;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .18);
}

/* Actions that sit ON the accent bar. A white secondary button there
   shouts louder than the title; these read as bar actions. */
.sg-btn--bar {
  padding: 7px 13px;
  font-size: 12.5px;
  background: rgba(255, 255, 255, 0.12);
  border-color: rgba(255, 255, 255, 0.28);
  color: var(--sg-on-primary);
}
.sg-btn--bar-primary {
  padding: 7px 13px;
  font-size: 12.5px;
  background: var(--sg-on-primary);
  border-color: var(--sg-on-primary);
  color: var(--sg-primary);
  font-weight: 800;
}

/* -------------------------------------------------------------
   Page hero
   -------------------------------------------------------------
   ui.heroWrap: a fixed 118px FLAT accent bar, 10px radius, with a
   hairline border and shadow drawn from the accent itself.

   Flat is the point. The reference never gradients a hero, a header
   or a modal head — a gradient is why those three drifted apart, each
   page adding its own overrides.

   The border and shadow read --sg-primary-shadow rather than a fixed
   navy: the background already followed the theme, but those two used
   to stay dark blue all the way round a re-themed hero.
   ------------------------------------------------------------- */
.sg-page-hero {
  width: 100%;
  min-height: 118px;
  height: 118px;
  margin: 0 0 22px;
  padding: 0 28px;
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 18px;
  background: var(--sg-primary);
  color: var(--sg-on-primary);
  border: 1px solid var(--sg-primary-shadow);
  border-radius: 10px;
  box-shadow: 0 8px 18px var(--sg-primary-shadow);
  box-sizing: border-box;
  position: relative;
  overflow: hidden;
}

/* ui.heroTitle: fluid instead of a fixed 25.6px. The clamp maximum IS
   the old value, so nothing changes on a desktop — it only shrinks
   where it did not fit. */
.sg-hero-title {
  margin: 0 0 6px;
  color: var(--sg-on-primary);
  font-size: clamp(18px, 4.6vw, 25.6px);
  line-height: 1.15;
  font-weight: 700;
  display: flex;
  align-items: center;
  gap: 10px;
}

/* ui.heroSub. The reference hard-codes rgba(255,255,255,.76), which
   fails on a light accent; held back from the foreground token instead
   so it flips with it. */
.sg-hero-subtitle {
  margin: 0;
  color: color-mix(in srgb, var(--sg-on-primary) 76%, transparent);
  font-size: clamp(12.5px, 3.4vw, 14px);
  line-height: 1.4;
  font-weight: 400;
}

.sg-hero-actions {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  align-items: center;
}

/* Below 768px the bar stops being a fixed-height row. */
@media (max-width: 767.98px) {
  .sg-page-hero {
    height: auto;
    padding: 22px;
    flex-direction: column;
    align-items: flex-start;
  }
  .sg-btn--hero,
  .sg-btn--hero-secondary {
    min-width: 0;
    flex: 1 1 calc(50% - 5px);
    padding: 0 12px;
    font-size: 12.5px;
  }
  .sg-hero-actions { width: 100%; }
}

/* -------------------------------------------------------------
   Panel
   -------------------------------------------------------------
   ui.panel: radius 18, padding 24, border 1px #f1f5f9, SHADOW_PANEL.
   The border is the FAINT one — a panel is defined by its shadow, and
   a strong border over a shadow reads as two competing edges.
   ------------------------------------------------------------- */
.sg-panel {
  background-color: var(--sg-surface);
  border-radius: var(--sg-radius-lg);
  padding: 24px;
  box-shadow: var(--sg-shadow-md);
  border: 1px solid var(--sg-card-border);
}

.sg-panel-header {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  align-items: flex-start;
  margin-bottom: 20px;
}

/* ui.sectionTitle: 16px at weight 800. Not a typo — the reference's
   section titles are heavy, and 600 reads as a subtitle. */
.sg-panel-title {
  margin: 0 0 4px 0;
  color: var(--sg-text);
  font-size: var(--sg-text-lg);
  font-weight: 800;
}

/* ui.muted */
.sg-muted {
  color: var(--sg-text-subtle);
  font-size: var(--sg-text-sm);
  font-weight: 500;
}

/* ui.painelTabela: a panel holding ONLY a table. No padding, so the
   table meets the edges and its header paints the full width of the
   card like a panel bar, instead of sitting as a dark strip inside a
   white frame. */
.sg-panel--table {
  padding: 0;
  border-radius: 11px;
  border-color: var(--sg-border);
  box-shadow: 0 1px 4px rgba(15, 23, 42, 0.06);
  overflow: hidden;
}

/* -------------------------------------------------------------
   Stat card
   -------------------------------------------------------------
   1:1 with the reference's `.stat-card` and its six `card-*` tones.

   NOTE this is a different object from the plain summary tile in the
   dashboard config (30px/900 value, uppercase label). The two coexist
   in the reference; this is the TONED one, the one the pages use with
   card-primary / card-info / card-success / card-warning / card-danger
   / card-geral, and its numbers are its own: 25px/700 value, 13px/400
   label, 132px floor, 14px radius, 1.5px border.
   ------------------------------------------------------------- */
.sg-stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 14px;
  margin-bottom: 24px;
}

.sg-stat-card {
  background: var(--sg-surface);
  border-radius: 14px;
  padding: 18px 16px;
  /* 1.5px, not 1px: the tone borders have to read through a tinted fill,
     and at 1px they disappeared into it. */
  border: 1.5px solid transparent;
  min-height: 132px;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 8px;
  transition: transform .16s ease, box-shadow .16s ease, background .16s ease,
    border-color .16s ease;
  box-shadow: 0 6px 16px rgba(17, 24, 39, .07);
  animation: sg-fade-up .68s ease both;
}

/* Staggered, so a row arrives as a sequence rather than one block. */
.sg-stat-card:nth-child(1) { animation-delay: .02s; }
.sg-stat-card:nth-child(2) { animation-delay: .08s; }
.sg-stat-card:nth-child(3) { animation-delay: .14s; }
.sg-stat-card:nth-child(4) { animation-delay: .20s; }
.sg-stat-card:nth-child(5) { animation-delay: .26s; }

@keyframes sg-fade-up {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: translateY(0); }
}

.sg-stat-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 10px 22px rgba(17, 24, 39, .11);
}

/* Motion is decoration here; anyone who asked the OS for less of it gets
   the end state directly. */
@media (prefers-reduced-motion: reduce) {
  .sg-stat-card { animation: none; transition: none; }
  .sg-stat-card:hover { transform: none; }
}

.sg-stat-icon {
  width: 32px;
  height: 32px;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 15px;
  flex-shrink: 0;
  background: #fff;
  transition: color .15s, background .15s, transform .15s;
}
.sg-stat-card:hover .sg-stat-icon { background: #fff; transform: translateY(-1px); }

.sg-stat-number {
  font-size: 25px;
  font-weight: 700;
  margin: 0;
  line-height: 1;
  color: #182235;
}

.sg-stat-label {
  font-size: 13px;
  font-weight: 400;
  color: var(--sg-text-muted);
  margin: 0;
  line-height: 1.15;
}

.sg-stat-sublabel {
  font-size: 13px;
  font-weight: 400;
  color: var(--sg-text-muted);
  margin: -1px 0 0;
  line-height: 1.15;
}

/* --- The six tones, verbatim. Fill, border, and the icon plate each
       have their own value; the icon is the tone at full strength on a
       near-white plate, which is what keeps a 32px glyph legible over a
       pale fill. --- */
.sg-stat-card.card-primary { background: #E9ECEF; border-color: #D7DDE3; }
.sg-stat-card.card-info    { background: #E9F4F7; border-color: #D4EEF4; }
.sg-stat-card.card-success { background: #EAF4F1; border-color: #D4EBDD; }
.sg-stat-card.card-warning { background: #F8F3EB; border-color: #F2DFC5; }
.sg-stat-card.card-danger  { background: #F8ECED; border-color: #F0D1D1; }
.sg-stat-card.card-geral   { background: #F7F8FA; border-color: #E1E5EB; }

.sg-stat-card.card-primary:hover { background: #DCE8F9; border-color: #AFC8EF; }
.sg-stat-card.card-info:hover    { background: #D9EEF4; border-color: #ABD9E5; }
.sg-stat-card.card-success:hover { background: #DCECE7; border-color: #ABCFC2; }
.sg-stat-card.card-warning:hover { background: #EFE4D4; border-color: #E2C49D; }
.sg-stat-card.card-danger:hover  { background: #F0DCDD; border-color: #E4AEB1; }
.sg-stat-card.card-geral:hover   { background: #E2E7EE; border-color: #C8D0DC; }

.sg-stat-card.card-primary .sg-stat-icon { background: #EAF4FF; color: #4388F5; }
.sg-stat-card.card-info .sg-stat-icon    { background: #ECFEFF; color: #0DB8D4; }
.sg-stat-card.card-success .sg-stat-icon { background: #ECFDF5; color: #10B981; }
.sg-stat-card.card-warning .sg-stat-icon { background: #FFF7E6; color: #F59E0B; }
.sg-stat-card.card-danger .sg-stat-icon  { background: #FEF2F2; color: #EF4444; }
.sg-stat-card.card-geral .sg-stat-icon   { background: #F3F4F6; color: #6B7280; }

/* -------------------------------------------------------------
   Chip
   -------------------------------------------------------------
   ui.chip: 6px 12px, pill, accent wash with an accent border.
   ------------------------------------------------------------- */
.sg-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border-radius: var(--sg-radius-pill);
  background-color: var(--sg-primary-soft);
  color: var(--sg-primary);
  font-weight: 600;
  font-size: var(--sg-text-sm);
  border: 1px solid var(--sg-primary-border);
}

.sg-chips-wrap {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

/* -------------------------------------------------------------
   Form field
   -------------------------------------------------------------
   ui.label + ui.input.
   ------------------------------------------------------------- */
.sg-field {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

/* ui.label: 12px, weight 700, #475569, UPPERCASE, 0.04em, 5px below. */
.sg-field-label {
  display: block;
  font-weight: 700;
  margin-bottom: 5px;
  color: var(--sg-text-secondary);
  font-size: var(--sg-text-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* ui.input. The height is FIXED on purpose: a native <select>, an
   <input> and a <button> with the same padding do not come out the same
   height, and in a filter row that showed — the box beside it sat a few
   pixels lower and the labels stopped lining up. */
.sg-input {
  width: 100%;
  height: 40px;
  padding: 0 12px;
  line-height: 38px;
  border-radius: var(--sg-radius-sm);
  border: 1px solid var(--sg-border);
  box-sizing: border-box;
  font-size: var(--sg-text-base);
  color: var(--sg-text);
  background: #fff;
  outline: none;
  font-family: var(--sg-font-sans);
}

.sg-input:focus {
  border-color: var(--sg-primary-border);
  box-shadow: 0 0 0 var(--sg-focus-ring) var(--sg-primary-shadow-soft);
}

.sg-input:disabled {
  background: var(--sg-bg-secondary);
  color: var(--sg-text-muted);
  cursor: not-allowed;
}

/* A textarea is the same field with room to grow. */
textarea.sg-input {
  height: auto;
  min-height: 84px;
  padding: 9px 12px;
  line-height: 1.45;
  resize: vertical;
}

.sg-field-hint {
  color: var(--sg-text-muted);
  font-size: var(--sg-text-xs);
  line-height: 1.35;
  margin: 5px 0 0;
}

/* ui.filtrosGrid: a row of fields that splits itself over as many
   columns as fit. Empty tracks collapse, so two fields or five always
   fill the width instead of bunching to the left. */
.sg-fields-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 14px;
  align-items: end;
}

/* -------------------------------------------------------------
   Empty state
   -------------------------------------------------------------
   ui.emptyCell: centred, 40px 24px, #94a3b8, 14px.
   ------------------------------------------------------------- */
.sg-empty {
  text-align: center;
  padding: 40px 24px;
  color: var(--sg-text-subtle);
  font-size: var(--sg-text-base);
}

.sg-empty-icon {
  display: block;
  font-size: 40px;
  line-height: 1;
  margin-bottom: 12px;
  color: var(--sg-primary-300);
}

/* -------------------------------------------------------------
   Alert
   -------------------------------------------------------------
   Bootstrap's `.alert alert-*`. Borderless at weight 500 — the fill
   and the dark text carry it, so it does not need an outline too.

   The 13px size and 10px radius are NOT Bootstrap's defaults: every
   alert in the reference carries `style={{ fontSize: 13,
   borderRadius: 10 }}` inline, on every single call site. Baking
   them into the class is the whole point — an alert should not need
   two inline overrides to look like the others.
   ------------------------------------------------------------- */
.alert {
  border: none;
  border-radius: 10px;
  font-size: 13px;
  font-weight: 500;
  margin-bottom: 0;
}

.alert-success { background-color: #D1E7DD; color: #0F5132; }
.alert-danger,
.alert-error   { background-color: #F8D7DA; color: #842029; }
.alert-warning { background-color: #FFF3CD; color: #664D03; }
.alert-info    { background-color: #D1ECF1; color: #055160; }

/* -------------------------------------------------------------
   Modal
   -------------------------------------------------------------
   Two heads, because the reference has two, and they are not
   interchangeable:

   `branded`  .tf-user-dialog-head — a 108px ACCENT-FILLED head with
              a 42px icon badge, for a dialog that is the subject of
              the screen (editing an account, a record).
   `plain`    .module-modal-head — a 54px light head with a hairline
              rule, for a form inside a module.

   Both are FLAT. The reference never gradients a modal head any more
   than it gradients a hero — that gradient is why heads and heroes
   drifted apart in the first place.
   ------------------------------------------------------------- */
.sg-overlay {
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, .6);
  z-index: 1060;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}

.sg-modal {
  width: min(580px, calc(100vw - 32px));
  max-height: calc(100vh - 24px);
  overflow: auto;
  background: var(--sg-surface);
  border-radius: 20px;
  position: relative;
  box-shadow: 0 24px 60px rgba(0, 0, 0, .25);
}

/* The module form: narrower shadow, 12px radius, clipped so the head's
   rule meets the edges. */
.sg-modal--plain {
  width: 100%;
  max-width: 760px;
  max-height: 92vh;
  display: flex;
  flex-direction: column;
  border-radius: 12px;
  overflow: hidden;
  box-shadow: 0 24px 70px rgba(15, 23, 42, .28);
}

.sg-modal--wide { width: min(1080px, calc(100vw - 32px)); }

/* Close sits ON the dialog, not in the head — so it stays put whichever
   head is used. */
.sg-modal-close {
  position: absolute;
  top: 12px;
  right: 12px;
  width: 34px;
  height: 34px;
  border-radius: 10px;
  border: 1px solid var(--sg-border);
  background: #fff;
  color: var(--sg-text-muted);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1;
}
.sg-modal-close:hover { background: var(--sg-bg-secondary); }

/* --- Branded head: accent-filled, with the icon badge. --- */
.sg-modal-head {
  display: grid;
  grid-template-columns: 38px minmax(0, 1fr);
  gap: 14px;
  align-items: center;
  /* 108px in the reference's one call site, which was sized for a title
     plus an email underneath. Without a subtitle that is a lot of empty
     band, so the height is a floor that the content can undercut. */
  min-height: 84px;
  padding: 16px 24px;
  border-bottom: 1px solid var(--sg-divider);
  background: var(--sg-primary);
  color: var(--sg-on-primary);
  border-radius: 20px 20px 0 0;
}

.sg-modal-badge {
  width: 38px;
  height: 38px;
  border-radius: 12px;
  background: rgba(255, 255, 255, .14);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  color: var(--sg-on-primary);
}

.sg-modal-head h2 {
  margin: 0 0 4px;
  font-size: 18px;
  font-weight: 800;
  color: var(--sg-on-primary);
}

.sg-modal-head p {
  margin: 0;
  padding-right: 34px;
  font-size: 13px;
  color: color-mix(in srgb, var(--sg-on-primary) 65%, transparent);
}

/* The branded dialog's body is recessed, so the accent head reads as a
   band above it rather than as a stripe on a white sheet. */
.sg-modal-body {
  display: grid;
  gap: 10px;
  padding: 12px 18px 18px;
  background: var(--sg-bg-secondary);
}

/* --- Plain head: 54px, hairline rule, 16px/800 title. --- */
.sg-modal-head--plain {
  display: flex;
  align-items: center;
  justify-content: space-between;
  grid-template-columns: none;
  min-height: 54px;
  padding: 0 18px;
  border-bottom: 1px solid #E5E7EB;
  border-radius: 0;
  background: transparent;
  color: var(--sg-text);
  flex-shrink: 0;
}

.sg-modal-head--plain h2 {
  margin: 0;
  color: #172235;
  font-size: 16px;
  font-weight: 800;
}

.sg-modal-head--plain .sg-modal-head-icon { color: #2F6DF6; }

.sg-modal--plain .sg-modal-body {
  padding: 18px;
  gap: 12px;
  background: transparent;
  overflow-y: auto;
}

@media (max-width: 767.98px) {
  .sg-modal--plain .sg-modal-body { padding: 14px; }
}

.sg-modal-actions {
  display: flex;
  gap: 12px;
  padding: 0 18px 18px;
}

/* --- Details grid, for a read-only dialog. --- */
.sg-details-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 14px;
  margin-bottom: 20px;
}

.sg-detail-card {
  background-color: var(--sg-surface);
  border: 1px solid #E5E7EB;
  border-radius: 12px;
  padding: 14px 16px;
}

.sg-detail-card-title {
  margin: 0 0 10px;
  color: #334155;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
}

.sg-detail-item {
  margin-bottom: 8px;
  color: var(--sg-text-secondary);
  font-size: 13px;
}

/* -------------------------------------------------------------
   Table
   -------------------------------------------------------------
   ui.table / ui.th / ui.td, verbatim.

   Column headings are the quietest text on the page — 11px, 700,
   uppercase, muted, on a #f8fafc strip. They are read once to
   orient and then never again, so a bold dark header row only
   competes with the data it labels.
   ------------------------------------------------------------- */
.sg-table-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.sg-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--sg-text-sm);
}

.sg-table th {
  text-align: left;
  padding: 10px 14px;
  border-bottom: 1px solid var(--sg-border);
  color: var(--sg-text-muted);
  font-size: var(--sg-text-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  white-space: nowrap;
  background: var(--sg-bg-secondary);
}

.sg-table td {
  padding: 12px 14px;
  color: var(--sg-text-body);
  vertical-align: middle;
  border-bottom: 1px solid var(--sg-divider);
}

.sg-table tbody tr:last-child td { border-bottom: 0; }
.sg-table tbody tr:hover { background: var(--sg-bg-secondary); }

/* Numbers align right with tabular figures, so digits line up in a
   column instead of jittering by glyph width. */
.sg-table .is-numeric {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* A trailing action column that shrinks to its content. */
.sg-table .sg-table-actions {
  text-align: right;
  white-space: nowrap;
  width: 1%;
}

/* ui.emptyCell — the empty state lives INSIDE the table, so the
   header stays visible and the layout does not jump. */
.sg-table-empty {
  text-align: center;
  padding: 40px 24px;
  color: var(--sg-text-subtle);
  font-size: var(--sg-text-base);
}

/* --- Table variants -----------------------------------------------------
   Every form the reference actually uses.

   Row tints are the exact values its pages set inline, promoted to
   classes so a tinted row stops being six different hexes across six
   screens.
   ----------------------------------------------------------------------- */

/* Compact, for a dense report. */
.sg-table--sm th { padding: 7px 10px; }
.sg-table--sm td { padding: 8px 10px; }

/* Zebra. Applied to odd rows so the first row stays plain white. */
.sg-table--striped tbody tr:nth-child(odd) { background: var(--sg-bg-secondary); }

/* Rounded corners. They come from the corner CELLS: a radius on the table
   itself is clipped away by border-collapse. */
.sg-table--rounded {
  border-collapse: separate;
  border-spacing: 0;
}
.sg-table--rounded thead tr:first-child th:first-child { border-top-left-radius: 10px; }
.sg-table--rounded thead tr:first-child th:last-child  { border-top-right-radius: 10px; }
.sg-table--rounded .sg-row-total td:first-child { border-bottom-left-radius: 10px; }
.sg-table--rounded .sg-row-total td:last-child  { border-bottom-right-radius: 10px; }

/* --- Row tones. The tint marks the row; the text stays readable. --- */
.sg-table tr.row-success { background: #DCFCE7; }
.sg-table tr.row-danger  { background: #FEE2E2; }
.sg-table tr.row-warning { background: #FFF7ED; }
.sg-table tr.row-info    { background: #EFF6FF; }
.sg-table tr.row-muted   { background: #F1F5F9; }

/* A tinted row must not lose its tint under the hover rule. */
.sg-table tbody tr.row-success:hover { background: #CFF7DC; }
.sg-table tbody tr.row-danger:hover  { background: #FBD5D5; }
.sg-table tbody tr.row-warning:hover { background: #FDEDD8; }
.sg-table tbody tr.row-info:hover    { background: #E0EDFE; }
.sg-table tbody tr.row-muted:hover   { background: #E7EDF4; }

/* The total row closes the table the way the header opens it: filled with
   the accent, so it reads as a summary rather than one more record. */
.sg-table .sg-row-total td {
  background: var(--sg-primary);
  color: var(--sg-on-primary);
  font-weight: 700;
  border-bottom: 0;
}
.sg-table tbody tr.sg-row-total:hover td { background: var(--sg-primary); }

/* --- Below 576px each row becomes a card. Nine columns take 836px; on a
       360px screen the table could only be read by dragging it sideways,
       and even then with no header in view to say which number was which.
       The first cell becomes the card's title; the rest are label/value
       pairs read from data-label. --- */
@media (max-width: 575.98px) {
  .sg-table--cards thead { display: none; }
  .sg-table--cards,
  .sg-table--cards tbody,
  .sg-table--cards tr,
  .sg-table--cards td { display: block; width: 100%; }

  .sg-table--cards tr {
    border: 1px solid var(--sg-border);
    border-radius: 12px;
    margin-bottom: 10px;
    padding: 10px 12px;
    background: var(--sg-surface);
  }

  .sg-table--cards td {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    border: 0 !important;
    padding: 4px 0 !important;
    white-space: normal !important;
    text-align: right;
  }

  .sg-table--cards td::before {
    content: attr(data-label);
    color: var(--sg-text-muted);
    font-size: var(--sg-text-xs);
    font-weight: 600;
    text-align: left;
    flex: 0 0 auto;
  }

  .sg-table--cards td:first-child {
    justify-content: flex-start;
    text-align: left;
    padding-bottom: 8px !important;
    margin-bottom: 4px;
    border-bottom: 1px solid var(--sg-divider) !important;
  }
  .sg-table--cards td:first-child::before { content: none; }
}

/* -------------------------------------------------------------
   List cards
   -------------------------------------------------------------
   The other list form. Where a table puts records in columns,
   this puts each record in its own row-card: an icon, a title and
   a subtitle, a state badge, and the row's actions.

   It is the right shape when a record has two or three facts and
   an action rather than eight comparable columns — Feriados,
   Empresas, Turnos. A table of three columns wastes a header row
   to label what the subtitle already says.
   ------------------------------------------------------------- */

/* The search box above the list. */
.sg-search-container {
  background: var(--sg-surface);
  border: 1px solid #E5E7EB;
  border-radius: 12px;
  padding: 1rem 1.25rem;
  margin-bottom: 1.25rem;
}

.sg-list-card {
  background: var(--sg-surface);
  border: 1px solid #E5E7EB;
  border-radius: 10px;
  padding: 0.875rem 1rem;
  margin-bottom: 0.5rem;
  transition: all 0.2s ease;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 0.875rem;
}

/* The lift is the affordance — it is what says the whole row is
   clickable, not just the title inside it. */
.sg-list-card:hover {
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
  transform: translateY(-1px);
}

@media (prefers-reduced-motion: reduce) {
  .sg-list-card { transition: none; }
  .sg-list-card:hover { transform: none; }
}

.sg-list-card-icon {
  width: 40px;
  height: 40px;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.1rem;
  flex-shrink: 0;
}

.sg-list-card-info {
  flex: 1 1 auto;
  min-width: 0;
}

.sg-list-card-info h6 {
  margin: 0;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--sg-text);
}

.sg-list-card-info p {
  margin: 0;
  font-size: 0.8rem;
  color: var(--sg-text-muted);
}

/* State badges. Green for active, grey for inactive — the grey is
   the point: an inactive row should recede, not shout in red. */
.sg-badge-activo {
  background: #D1FAE5;
  color: #065F46;
  font-size: 0.7rem;
  font-weight: 600;
  padding: 0.25rem 0.5rem;
  border-radius: 6px;
  white-space: nowrap;
}

.sg-badge-inactivo {
  background: #F3F4F6;
  color: #6B7280;
  font-size: 0.7rem;
  font-weight: 600;
  padding: 0.25rem 0.5rem;
  border-radius: 6px;
  white-space: nowrap;
}

/* Row actions: square, outlined, quiet until hovered. */
.sg-list-actions {
  display: inline-flex;
  gap: 0.375rem;
  flex-shrink: 0;
}

.sg-action-btn {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  border: 1px solid #E5E7EB;
  background: transparent;
  color: var(--sg-text);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: all 0.2s;
  text-decoration: none;
  cursor: pointer;
  padding: 0;
}

.sg-action-btn:hover {
  background: #3B82F6;
  color: #fff;
  border-color: #3B82F6;
}

/* The destructive one turns red, so it is distinguishable at the
   moment of the click and not only by its icon. */
.sg-action-btn.is-danger:hover {
  background: #EF4444;
  border-color: #EF4444;
  color: #fff;
}

/* A count strip above a list: "18 activos · 3 inactivos". */
.sg-stats-bar {
  display: flex;
  gap: 1.5rem;
  margin-bottom: 1rem;
  flex-wrap: wrap;
}

.sg-stats-bar .sg-stat {
  font-size: 0.85rem;
  color: var(--sg-text-muted);
}

.sg-stats-bar .sg-stat strong {
  color: var(--sg-text);
  font-weight: 700;
}

.sg-page-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 1rem;
  padding-top: 1.25rem;
  margin-bottom: 1rem;
}

.sg-page-header h1 {
  font-size: 1.5rem;
  font-weight: 700;
  margin: 0;
}

/* --- Cell emphasis ------------------------------------------------------
   The reference colours individual CELLS by value, not whole rows: a
   negative balance is red, a positive one green, an absence count over
   its threshold red, an incomplete count amber. The row stays neutral,
   so the eye lands on the number that is wrong rather than on a whole
   band of colour.

   Use a row tint for what the RECORD is; use a cell tone for what a
   NUMBER is.
   ----------------------------------------------------------------------- */
.sg-table .cell-strong { font-weight: 700; }
.sg-table .cell-good { color: #16A34A; font-weight: 800; }
.sg-table .cell-bad  { color: #B91C1C; font-weight: 800; }
.sg-table .cell-warn { color: #F59E0B; font-weight: 700; }

/* The first column is the row's name: bold, and it keeps no data-label
   because in the card layout it becomes the card's title. */
.sg-table td:first-child { font-weight: 700; }

/* The total row's first cell is uppercase, so it reads as a summary
   label rather than as one more record name. */
.sg-table .sg-row-total td:first-child {
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* -------------------------------------------------------------
   Overview card (donut)
   -------------------------------------------------------------
   The home page's composition card: a ring, the total in its
   middle, and a list whose dots are the SAME colours as the ring's
   slices.

   The ring is plain SVG rather than a chart library, so the same
   markup renders in a Django template. Geometry matches: 58% inner
   radius, starting at twelve o'clock.

   The rule that matters: ONE list of slices feeds the ring, the
   list AND the total. There is no second list, which is what stops
   the ring and the numbers beside it from disagreeing.
   ------------------------------------------------------------- */
.sg-overview-grid {
  display: grid;
  gap: 16px;
  margin-bottom: 16px;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

@media (max-width: 1100px) {
  .sg-overview-grid { grid-template-columns: 1fr; }
}

.sg-overview-card {
  display: flex;
  flex-direction: column;
  height: 218.65px;
  min-height: 218.65px;
  padding: 20px;
  border: 1px solid var(--sg-border);
  border-radius: 16px;
  background: var(--sg-surface);
  color: #1F2937;
  font-size: var(--sg-text-base);
  box-shadow: 0 6px 18px var(--sg-primary-shadow-soft);
  overflow: hidden;
}

.sg-overview-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  height: 54px;
  min-height: 54px;
  margin-bottom: 18px;
  padding-bottom: 12px;
  border-bottom: 2px solid var(--sg-primary-shadow);
}

.sg-overview-head h6 {
  display: flex;
  align-items: center;
  flex: 1 1 auto;
  min-width: 0;
  height: 40.8px;
  margin: 0;
  gap: 8px;
  color: #111827;
  font-size: .85rem;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
}

.sg-overview-head h6 i {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 18px;
  width: 18px;
  height: 18px;
  line-height: 1;
  font-size: 15px;
  color: #1F2937;
}

/* Each card's rule and icon carry their own tone, so the three read as
   three subjects rather than three copies. */
.sg-overview-head.is-present { border-bottom-color: rgba(59, 130, 246, .15); }
.sg-overview-head.is-late    { border-bottom-color: rgba(245, 158, 11, .18); }
.sg-overview-head.is-absent  { border-bottom-color: rgba(239, 68, 68, .16); }
.sg-overview-head.is-present h6 i { color: #3B82F6; }
.sg-overview-head.is-late    h6 i { color: #F59E0B; }
.sg-overview-head.is-absent  h6 i { color: #EF4444; }

/* "Ver todos" — a small accent-filled chip, NOT a full button. It lives
   in a 54px head beside a title; anything with real button padding
   pushes the title out of the row. */
.sg-overview-action {
  flex-shrink: 0;
  align-self: center;
  min-height: 30px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  border: 0;
  border-radius: 6px;
  background: var(--sg-primary);
  color: var(--sg-on-primary);
  padding: 6px 10px;
  font-size: .7rem;
  font-weight: 400;
  text-decoration: none;
  cursor: pointer;
  font-family: var(--sg-font-sans);
  white-space: nowrap;
}

.sg-overview-action:hover {
  background: var(--sg-primary-hover);
  color: var(--sg-on-primary);
}

/* Body: a fixed 100px ring column beside a flexible list. */
.sg-overview-body {
  display: grid;
  grid-template-columns: 100px minmax(0, 1fr);
  align-items: center;
  gap: 22px;
  flex: 1 1 auto;
  min-height: 0;
}

.sg-overview-donut {
  position: relative;
  width: 100px;
  height: 100px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  border-radius: var(--sg-radius-pill);
}

.sg-overview-donut svg {
  position: absolute;
  inset: 0;
  z-index: 0;
}

.sg-overview-donut span {
  position: relative;
  z-index: 1;
  color: #1F2937;
  font-size: 1.3rem;
  font-weight: 700;
  line-height: 1;
}

.sg-overview-donut small {
  position: relative;
  z-index: 1;
  margin-top: 2px;
  color: #9CA3AF;
  font-size: .58rem;
  font-weight: 400;
}

/* --- The list. Rows are separated by a hairline, so three lines read as
       three figures rather than as a paragraph. --- */
.sg-overview-list {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-width: 0;
  font-size: .78rem;
}

.sg-overview-list a {
  min-height: 28px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  border-bottom: 1px solid #F3F4F6;
  color: inherit;
  font-size: 14px;
  text-decoration: none;
  cursor: pointer;
}

.sg-overview-list a:last-child { border-bottom: 0; }

.sg-overview-list a > div {
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 8px;
}

/* The label is quiet and truncates; the figure never does. */
.sg-overview-list a span:not(.dot) {
  min-width: 0;
  color: #6B7280;
  font-weight: 400;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sg-overview-list strong {
  flex: 0 0 auto;
  color: #1F2937;
  font-size: .78rem;
  font-weight: 600;
}

/* 7px. The dot takes its colour inline, from the row — the same value the
   ring slice uses. It used to come from a separate CSS class, which is how
   a legend dot ended up a different colour from its slice. */
.sg-overview-list .dot {
  width: 7px;
  height: 7px;
  flex: 0 0 7px;
  border-radius: 999px;
}

@media (max-width: 1100px) {
  .sg-overview-card { height: auto; min-height: 0; }
  .sg-overview-head { height: auto; min-height: 0; }
}

/* Phone: the fixed 218.65px card with overflow:hidden and a nowrap title
   silently CLIPPED the action button and the right edge of the list below
   ~430px — measured at 33px of overflow on a 320px card. The height is
   released and the ring tightened so the same design simply fits. */
@media (max-width: 575.98px) {
  .sg-overview-card { height: auto; min-height: 0; padding: 16px; }
  .sg-overview-head {
    height: auto;
    min-height: 0;
    gap: 8px;
    margin-bottom: 14px;
    align-items: center;
  }
  .sg-overview-head h6 {
    height: auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .sg-overview-body { grid-template-columns: 84px minmax(0, 1fr); gap: 14px; }
  .sg-overview-donut { width: 84px; height: 84px; }
}

/* -------------------------------------------------------------
   Row list
   -------------------------------------------------------------
   The house's real list form for records — `.tf-user-row` /
   `people-employee-row`. Holidays and Colaboradores both use it,
   and neither is a `<table>`.

   A row is a GRID CARD, not a table row: a leading avatar or date
   badge, a name block, a details strip, and icon actions. Each page
   sets its own column template because the middle strip differs —
   Holidays runs `52px minmax(220px,1fr) minmax(145px,auto) auto`,
   Colaboradores `42px minmax(190px,1.1fr) minmax(480px,2.4fr) auto`
   — but the frame, spacing, border and shadow are shared, which is
   what makes two different lists still look like one product.

   Use a `Table` when columns are meant to be COMPARED down the page
   (hours, totals). Use this when each row is a RECORD you open.
   ------------------------------------------------------------- */
.sg-row-list {
  display: grid;
  gap: 10px;
  padding: 12px;
}

.sg-row {
  display: grid;
  /* Set per list. The default is the Colaboradores template. */
  grid-template-columns: var(--sg-row-cols, 42px minmax(190px, 1.1fr) minmax(480px, 2.4fr) auto);
  align-items: center;
  gap: 14px;
  min-height: 78px;
  padding: 12px 16px;
  border: 1px solid #DFE7F0;
  border-radius: 10px;
  background: var(--sg-surface);
  box-shadow: 0 2px 7px rgba(23, 34, 53, .05);
  cursor: pointer;
}

/* The row being edited is filled with the accent's palest wash, so it
   stays findable after the form below it takes the focus. */
.sg-row.is-selected { background: var(--sg-primary-soft); }

/* Inactive records stay legible but recede — dimmed, not hidden, and
   not coloured, since inactive is not an error. */
.sg-row.is-inactive { opacity: 0.6; }
.sg-row.is-inactive img { filter: grayscale(1); }

/* A circular avatar for a person. */
.sg-row-avatar {
  width: 42px;
  height: 42px;
  border-radius: 50%;
  object-fit: cover;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-weight: 700;
  font-size: 13px;
}

/* A rounded-square badge for a date — month over day. */
.sg-row-badge {
  width: 42px;
  height: 42px;
  display: grid;
  place-items: center;
  gap: 1px;
  border-radius: 10px;
  background: #EEF2FF;
  color: #1F2937;
  line-height: 1;
}

.sg-row-badge span {
  color: var(--sg-text-muted);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .04em;
  text-transform: uppercase;
}

.sg-row-badge strong {
  color: #1F2937;
  font-size: 18px;
  font-weight: 800;
}

.sg-row-title {
  color: #1F2937;
  font-size: 14px;
  font-weight: 700;
  display: flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sg-row-meta {
  margin-top: 3px;
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: center;
  color: var(--sg-text-muted);
  font-size: 12px;
  font-weight: 400;
}

/* A state tag beside the name. Small, uppercase, outlined — it labels
   the record without competing with it. */
.sg-row-tag {
  padding: 1px 8px;
  border-radius: 20px;
  font-size: 10px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  flex-shrink: 0;
  white-space: nowrap;
}

.sg-row-tag.is-inactive {
  background: #FEE2E2;
  color: #B91C1C;
  border: 1px solid #FECACA;
}

.sg-row-tag.is-active {
  background: #D1FAE5;
  color: #065F46;
  border: 1px solid #A7F3D0;
}

.sg-row-actions {
  display: inline-flex;
  gap: 6px;
  justify-content: flex-end;
}

/* The empty list. */
.sg-row-empty {
  padding: 40px;
  text-align: center;
  color: var(--sg-text-subtle);
  font-size: 14px;
}

/* Below 768px the details strip is dropped and the row becomes
   badge + name, which is all that fits without truncating the name. */
@media (max-width: 767.98px) {
  .sg-row {
    grid-template-columns: var(--sg-row-cols-mobile, 42px minmax(0, 1fr));
    min-height: 0;
    padding: 12px 14px;
  }
}

/* -------------------------------------------------------------
   Picker modal
   -------------------------------------------------------------
   "Selecionar Funcionário" — a search box, optional filters, and a
   scrollable list you pick one row from.

   This is the answer to a `<select>` with four hundred options. A
   native select cannot be searched past its first letter, shows no
   secondary line (department, company) and gives no result count,
   so on a real roster it becomes a scroll hunt.

   The list is capped at 380px on purpose: it has to be obviously
   scrollable, and the search box has to stay in view while you
   type — a list that grows to fill the dialog pushes the box off
   the top exactly when it is being used.
   ------------------------------------------------------------- */
.sg-picker {
  max-width: 560px;
  padding: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.sg-picker-head {
  padding: 20px 22px 14px;
  border-bottom: 1px solid var(--sg-divider);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
}

.sg-picker-title {
  font-weight: 800;
  font-size: 16px;
  color: var(--sg-text);
  margin: 0;
}

/* The result count, under the title. It is what tells you whether the
   filter did anything — without it you cannot tell an empty result from
   a slow one. */
.sg-picker-count {
  font-size: 12px;
  color: var(--sg-text-subtle);
  margin: 2px 0 0;
}

.sg-picker-filters {
  padding: 14px 22px;
  background: var(--sg-bg-secondary);
  border-bottom: 1px solid var(--sg-divider);
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.sg-picker-search {
  width: 100%;
  padding: 10px 14px;
  border-radius: 8px;
  border: 1px solid var(--sg-border);
  font-size: 14px;
  outline: none;
  font-family: inherit;
  box-sizing: border-box;
  background: var(--sg-surface);
  color: var(--sg-text);
}

.sg-picker-search:focus {
  border-color: var(--sg-primary-border);
  box-shadow: 0 0 0 var(--sg-focus-ring) var(--sg-primary-shadow-soft);
}

.sg-picker-filter-grid {
  display: grid;
  gap: 10px;
}

.sg-picker-filter-grid select {
  width: 100%;
  padding: 9px 12px;
  border-radius: 8px;
  border: 1px solid var(--sg-border);
  font-size: 13px;
  outline: none;
  font-family: inherit;
  box-sizing: border-box;
  background: var(--sg-surface);
  color: var(--sg-text);
}

.sg-picker-list {
  overflow-y: auto;
  max-height: 380px;
}

.sg-picker-row {
  padding: 12px 22px;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 12px;
  border-bottom: 1px solid var(--sg-bg-secondary);
  background: transparent;
  width: 100%;
  border-left: 0;
  border-right: 0;
  border-top: 0;
  text-align: left;
}

.sg-picker-row:hover { background: var(--sg-bg-secondary); }

/* The selected row is filled AND carries a dot. The fill alone is two
   greys apart from the hover state. */
.sg-picker-row.is-selected { background: var(--sg-primary-soft); }

.sg-picker-avatar {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: #E2E8F0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  font-weight: 700;
  color: var(--sg-text);
  flex-shrink: 0;
}

.sg-picker-row-name {
  font-weight: 700;
  font-size: 14px;
  color: var(--sg-text);
  margin: 0;
}

.sg-picker-row-meta {
  font-size: 12px;
  color: var(--sg-text-subtle);
  margin: 0;
}

.sg-picker-dot {
  margin-left: auto;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--sg-primary);
  flex-shrink: 0;
}

.sg-picker-empty {
  text-align: center;
  padding: 40px 24px;
  color: var(--sg-text-subtle);
  font-size: 14px;
}

/* -------------------------------------------------------------
   Toast
   -------------------------------------------------------------
   A mensagem passageira, servida por src/web-components/sg-toast.js.

   Escrito em CSS e JavaScript simples em vez de uma biblioteca
   React, porque um template Django não monta uma. É a mesma regra
   do <campo-data>: se só serve React, não serve a casa.

   Canto fixo em cima à direita, em todas as aplicações. Um toast
   que aparece em baixo à esquerda num ecrã e em cima à direita
   noutro lê-se como um tipo de mensagem diferente.
   ------------------------------------------------------------- */
/* A pilha é posicionada pelo JS, não por flex: cada toast é absoluto e
   recebe o seu próprio transform, que é o que permite colapsar uns sobre os
   outros e expandir ao passar o rato. */
.sg-toaster {
  position: fixed;
  top: 16px;
  right: 16px;
  z-index: 9999;
  width: 356px;
  max-width: calc(100vw - 32px);
  pointer-events: none;
  transition: height .2s ease;
}

.sg-toast {
  pointer-events: auto;
  position: absolute;
  top: 0;
  right: 0;
  width: 100%;
  box-sizing: border-box;
  /* O de trás encolhe e recua a partir do topo, para espreitar sob o da
     frente em vez de crescer para baixo. */
  transform-origin: top center;
  transition: transform .22s cubic-bezier(.21,1.02,.73,1),
              opacity .2s ease;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 14px 16px;
  border-radius: 8px;
  background: #fff;
  border: 1px solid var(--sg-border);
  box-shadow: 0 4px 12px rgba(15, 23, 42, .12);
  font-size: 13px;
  color: var(--sg-text);
  animation: sg-toast-in .18s ease both;
}

/* A entrada só anima a opacidade: a posição vem do transform que o JS
   escreve, e animar as duas coisas fazia o toast saltar ao aparecer. */
@keyframes sg-toast-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.sg-toast.is-leaving {
  opacity: 0 !important;
  transition: opacity .18s ease;
}

@media (prefers-reduced-motion: reduce) {
  .sg-toast { animation: none; }
  .sg-toast.is-leaving { transition: none; }
}

/* Cada nível tem preenchimento E ícone. Um sucesso e um erro não podem ser a
   mesma caixa com palavras diferentes — e a cor sozinha não chega para quem
   não separa o verde do vermelho. */
.sg-toast.is-success { background: #ECFDF5; border-color: #A7F3D0; color: #065F46; }
.sg-toast.is-error   { background: #FEF2F2; border-color: #FECACA; color: #991B1B; }
.sg-toast.is-warning { background: #FFFBEB; border-color: #FDE68A; color: #92400E; }
.sg-toast.is-info    { background: #EFF6FF; border-color: #BFDBFE; color: #1E40AF; }

.sg-toast-icon {
  font-size: 15px;
  line-height: 1.35;
  flex-shrink: 0;
}

.sg-toast-body {
  flex: 1 1 auto;
  min-width: 0;
}

.sg-toast-title {
  margin: 0;
  font-weight: 500;
  line-height: 1.4;
}

.sg-toast-desc {
  margin: 2px 0 0;
  font-size: 12px;
  opacity: .8;
  line-height: 1.4;
}

.sg-toast-action {
  flex-shrink: 0;
  align-self: center;
  border: 1px solid currentColor;
  background: transparent;
  color: inherit;
  border-radius: 6px;
  padding: 4px 10px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  font-family: var(--sg-font-sans);
}

/* Meio fora da caixa, em cima à esquerda — onde a referência o põe. */
.sg-toast-close {
  position: absolute;
  top: -8px;
  left: -8px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 1px solid var(--sg-border);
  background: #fff;
  color: var(--sg-text-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  cursor: pointer;
  padding: 0;
  box-shadow: 0 1px 3px rgba(15, 23, 42, .12);
}

.sg-toast-close:hover { color: var(--sg-text); }

/* -------------------------------------------------------------
   Breadcrumb
   -------------------------------------------------------------
   A barra "Página inicial > Registo Assistido", colada ao topo por
   cima do conteúdo.

   `top: 0` e não `top: var(--navbar-height)`: o breadcrumb fica
   ACIMA do <main> na coluna do shell, não dentro dele, por isso já
   está preso pelo layout. Chegou a dizer `top: var(--navbar-height)`
   enquanto essa variável não existia em lado nenhum — resolvia para
   `auto` e o sticky não fazia nada. Agora que a variável existe, um
   deslocamento aqui empurraria a barra para cima do conteúdo.

   São duas camadas de cinzento de propósito: a faixa exterior em
   #F9FAFB e a lista em #F3F4F6, com o fio a separar — é isso que a
   despega do conteúdo quando este rola por baixo.
   ------------------------------------------------------------- */
.sg-breadcrumb-bar {
  position: sticky;
  top: 0;
  z-index: 1015;
  background: var(--sg-bg-secondary);
  border-bottom: 1px solid var(--sg-border);
  padding: 0.5rem 1rem;
  margin: 0;
}

.sg-breadcrumb {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  list-style: none;
  background: var(--sg-bg-tertiary);
  padding: 0.1rem 1rem;
  margin: 0;
  font-size: 14px;
  border-radius: 0;
  border-bottom: 1px solid var(--sg-border);
}

/* O separador é um ">" a sério, escrito pelo CSS, não um caractere na
   marcação — assim não é lido em voz alta pelo leitor de ecrã nem
   copiado com o texto. */
.sg-breadcrumb-item + .sg-breadcrumb-item::before {
  content: '>';
  color: var(--sg-text-muted);
  font-weight: 500;
  padding: 0 0.5rem;
}

.sg-breadcrumb-item {
  font-size: 14px;
  display: flex;
  align-items: center;
}

.sg-breadcrumb-item a {
  color: #3B82F6;
  text-decoration: none;
  font-weight: 500;
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
}

.sg-breadcrumb-item a:hover {
  color: #1D4ED8;
  text-decoration: underline;
}

/* O último não é uma ligação: é onde já se está. Um link para a página
   actual não leva a lado nenhum e engana quem navega por teclado. */
.sg-breadcrumb-item.is-active {
  color: var(--sg-text-muted);
  font-weight: 500;
}

/* -------------------------------------------------------------
   Sidebar
   -------------------------------------------------------------
   O menu lateral: itens agrupados por secção, um estado activo
   preenchido com o acento, e um modo recolhido que deixa só os
   ícones.

   Duas coisas foram MEDIDAS no resultado, não copiadas das regras:

   1. O item é #1F2937 liso. A folha de origem declara #526073 com
      um gradiente, mas é sobreposta mais à frente na própria
      cascata — copiar a regra em vez do resultado foi o que fez a
      primeira tentativa sair errada.
   2. Os ícones são font-weight 900. O Bootstrap Icons é uma fonte
      de um só peso, por isso o 900 faz o browser sintetizar um
      negrito — traços mais grossos. Os ícones do desenho computam
      900 e os nossos computavam 400, e era só isso que os fazia
      parecer lavados ao lado da referência, com o mesmo glifo, cor
      e tamanho.

   Não há transição na largura: com 300ms havia tempo de sobra para
   se ver o texto dos itens a ser espremido enquanto ela mudava.
   ------------------------------------------------------------- */
.sg-sidebar {
  width: var(--sg-sidebar-width);
  min-height: calc(100vh - 56px);
  background-color: var(--sg-surface);
  position: sticky;
  top: 56px;
  overflow-y: auto;
  flex-shrink: 0;
  transition: none;
  z-index: 1020;
  padding: 12px 18px 18px;
  border-right: 1px solid #E5E7EB;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .1);
  display: flex;
  flex-direction: column;
}

.sg-sidebar.is-collapsed {
  width: 72px;
  padding: 12px 10px 18px;
}

.sg-sidebar-nav {
  padding: 0;
  margin: 0;
  list-style: none;
}

/* O rótulo da secção. Pequeno e esbatido: separa sem competir com os
   itens que rotula. */
.sg-sidebar-heading {
  margin: 14px 0 6px;
  padding: 0 12px;
  color: var(--sg-text-muted);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  white-space: nowrap;
}

.sg-sidebar.is-collapsed .sg-sidebar-heading {
  /* Recolhido não há espaço para a palavra; fica um fio a separar, que é a
     informação que resta: onde é que um grupo acaba. */
  overflow: hidden;
  text-indent: -999px;
  height: 1px;
  margin: 12px 8px;
  padding: 0;
  background: var(--sg-border);
}

.sg-sidebar-link {
  color: #1F2937;
  height: 34px;
  padding: 0 12px;
  margin: 0 0 3px;
  border-radius: 8px;
  font-weight: 400;
  font-size: 13px;
  line-height: 1.15;
  transition: background .15s, color .15s, box-shadow .15s, transform .15s;
  display: flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  width: 100%;
  border: 0;
  background: transparent;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
}

.sg-sidebar-link i {
  display: inline-grid;
  place-items: center;
  width: 24px;
  height: 24px;
  font-size: 16px;
  line-height: 1;
  flex-shrink: 0;
  /* Um TOM do acento, não a cor em bruto: o 700 da escada é escuro o
     suficiente para se ler sobre branco e já pertence à família escolhida,
     por isso deixa de chocar quando alguém troca de cor. */
  color: var(--sg-primary-700);
  font-weight: 900;
}

.sg-sidebar-link:hover {
  background-color: var(--sg-primary-50);
  color: #1F2937;
  transform: translateX(2px);
}

.sg-sidebar-link.is-active {
  background: var(--sg-primary);
  color: var(--sg-on-primary);
  font-weight: 400;
  box-shadow: 0 4px 12px var(--sg-primary-shadow);
}

.sg-sidebar-link.is-active:hover {
  background: var(--sg-primary-hover);
  color: var(--sg-on-primary);
}

.sg-sidebar-link.is-active i,
.sg-sidebar-link:hover i {
  color: inherit;
}

@media (prefers-reduced-motion: reduce) {
  .sg-sidebar-link { transition: none; }
  .sg-sidebar-link:hover { transform: none; }
}

/* Um contador à direita do rótulo — pedidos por decidir, por exemplo. */
.sg-sidebar-count {
  margin-left: auto;
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  border-radius: 999px;
  background: #EF4444;
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.sg-sidebar-link.is-active .sg-sidebar-count {
  background: rgba(255, 255, 255, .22);
}

.sg-sidebar.is-collapsed .sg-sidebar-label,
.sg-sidebar.is-collapsed .sg-sidebar-count { display: none; }
.sg-sidebar.is-collapsed .sg-sidebar-link { justify-content: center; padding: 0; }

/* O rodapé do menu: o interruptor de manutenção e o "Recolher". */
.sg-sidebar-footer {
  margin-top: auto;
  padding-top: 14px;
  border-top: 1px solid var(--sg-border);
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.sg-sidebar-collapse {
  display: flex;
  align-items: center;
  gap: 10px;
  height: 34px;
  padding: 0 12px;
  border: 0;
  background: transparent;
  color: var(--sg-text-muted);
  font-size: 13px;
  border-radius: 8px;
  cursor: pointer;
  white-space: nowrap;
}
.sg-sidebar-collapse:hover { background: var(--sg-bg-tertiary); color: var(--sg-text); }

/* Abaixo de 992px passa a gaveta: fora do ecrã, com um véu por cima do
   conteúdo quando abre. */
.sg-sidebar-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background-color: rgba(0, 0, 0, 0.5);
  z-index: 1019;
}
.sg-sidebar-overlay.is-open { display: block; }

@media (max-width: 991.98px) {
  .sg-sidebar {
    position: fixed;
    top: 56px;
    left: calc(-1 * var(--sg-sidebar-width));
    height: calc(100vh - 56px);
    transition: left .2s ease;
  }
  .sg-sidebar.is-open { left: 0; }
}

/* --- Cabeçalho de marca ---------------------------------------------------
   A faixa do cabeçalho preenchida com o acento, como nas tabelas da
   Assiduidade. É a variação que fecha a tabela por cima do mesmo modo que a
   linha de total a fecha por baixo.

   Um pouco mais alta do que uma linha de dados — é isso que separa a faixa
   do corpo sem precisar de um filete. Nunca mais alta do que um separador da
   barra de subtabs, senão a tabela passa a pesar mais no ecrã do que a
   navegação.

   Combina com `.sg-table--rounded` para os cantos de cima, e com
   `.sg-panel--table` para a faixa pintar a largura toda do cartão em vez de
   ficar uma tira escura dentro de uma moldura branca.
   ----------------------------------------------------------------------- */
.sg-table--brand thead th {
  padding: 9px 12px;
  background: var(--sg-primary);
  color: var(--sg-on-primary);
  font-size: 11.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  border-bottom: 1px solid var(--sg-primary);
  white-space: nowrap;
}

/* Uma coluna ordenável é um botão: tem de o parecer e de responder ao
   teclado. O galão fica sempre visível, esbatido enquanto não estiver a
   ordenar — se só aparecesse ao passar o rato, ninguém descobriria que a
   coluna se pode ordenar. */
.sg-table--brand thead th.is-sortable {
  cursor: pointer;
  user-select: none;
}

.sg-table--brand thead th.is-sortable:hover {
  background: var(--sg-primary-hover);
}

.sg-table-sort {
  margin-left: 4px;
  color: var(--sg-on-primary);
  font-weight: 700;
}

.sg-table-sort.is-idle { opacity: 0.55; }
