/* styles.css – Fichar: identitat visual "consola d'operacions"
   Ink & paper com a base, ambre com a únic accent de marca (el rellotge),
   xifres sempre en monospace perquè és una eina de control horari. */

@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap');

/* ==== Design Tokens ====
   MODE FOSC PER DEFECTE: el bloc :root (sense cap atribut) porta els
   tokens foscos -és el que veu tothom que encara no ha triat res, i
   l'únic mode que hi havia hagut fins ara-. El mode clar és una
   preferència que cada usuari activa des d'"El meu compte" (o la icona de
   la barra); quan ho fa, el servidor afegeix data-theme="light" a <html>
   (vegeu authThemeAttr() a auth.php) i el segon bloc, més avall, el
   sobreescriu. Els valors d'aquest primer bloc són exactament els que hi
   havia al bloc "MODE FOSC FORÇAT" anterior: no s'ha tocat cap color. */
:root {
  /* Els controls natius (icona del calendari als input date, scrollbars...)
     segueixen el tema: sense això, el navegador pinta la icona fosca sobre
     fons fosc (o clara sobre fons clar) i queda pràcticament invisible. */
  color-scheme: dark;

  --font-display: 'Space Grotesk', 'Inter', system-ui, sans-serif;
  --font-body: 'Inter', system-ui, -apple-system, sans-serif;
  --font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  --clr-bg: #14181F;
  --clr-surface: #1E232C;
  --clr-surface-2: #232A35;
  --clr-surface-border: #2E3542;
  --clr-text: #EDEEF0;
  --clr-text-muted: #9AA3B2;
  --clr-muted-soft: rgba(154, 163, 178, 0.14);
  --clr-table-hdr: #232A35;

  --clr-amber: #E2A63A;
  --clr-amber-soft: rgba(226, 166, 58, 0.15);

  --clr-green: #2FA66B;
  --clr-green-soft: rgba(47, 166, 107, 0.15);
  --clr-green-tint: rgba(47, 166, 107, 0.35);
  --clr-red: #E5646F;
  --clr-red-soft: rgba(229, 100, 111, 0.15);
  --clr-info: #6FA8DC;
  --clr-info-soft: rgba(111, 168, 220, 0.15);
  --clr-purple: #A98BD6;
  --clr-purple-soft: rgba(169, 139, 214, 0.18);
  --clr-purple-tint: rgba(169, 139, 214, 0.35);
  --clr-baixa: #E17EB0;
  --clr-baixa-soft: rgba(225, 126, 176, 0.08);
  --clr-baixa-tint: rgba(225, 126, 176, 0.35);
  --clr-festiu: #5FC8F5;
  --clr-festiu-soft: rgba(95, 200, 245, 0.08);
  --clr-festiu-tint: rgba(95, 200, 245, 0.35);
  --clr-teal: #3FB6A3;
  --clr-slate: #8C9BB5;

  /* Mode fosc = text tinta sobre color brillant (millor contrast que blanc-sobre-brillant) */
  --clr-fill-primary: #E2A63A;
  --clr-fill-success: #2FA66B;
  --clr-fill-danger: #E5646F;
  --clr-btn-text: #14181F;

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
  --shadow-md: 0 6px 24px rgba(0, 0, 0, 0.4);
}

/* ==== Light Mode Tokens ====
   Nomès s'aplica quan <html data-theme="light">, marcat pel servidor
   segons la preferència desada de l'usuari (per defecte és fosc, aquest
   bloc no s'activa mai sol). Mateixos valors que hi havia al primer bloc
   "clar" original, ara mogut aquí i condicionat a l'atribut. */
:root[data-theme="light"] {
    color-scheme: light;

    --clr-bg: #F6F4EF;
    --clr-surface: #FFFFFF;
    --clr-surface-2: #F1EEE6;
    --clr-surface-border: #E4E0D5;
    --clr-text: #1B1F27;
    --clr-text-muted: #5B6472;
    --clr-muted-soft: #E4E3E1;
    --clr-table-hdr: #EFEBE1;

    --clr-amber: #B4741F;
    --clr-amber-soft: #F6E9D3;

    --clr-green: #1B7A4E;
    --clr-green-soft: #DFF1E8;
    --clr-green-tint: rgba(27, 122, 78, 0.28);
    --clr-red: #B3323D;
    --clr-red-soft: #FBE7E9;
    --clr-info: #2C5F8A;
    --clr-info-soft: #DCE8F1;
    --clr-purple: #6B4FA0;
    --clr-purple-soft: #EBE4F5;
    --clr-purple-tint: rgba(107, 79, 160, 0.28);
    --clr-baixa: #A6337A;
    --clr-baixa-soft: #FBF0F6;
    --clr-baixa-tint: rgba(166, 51, 122, 0.28);
    --clr-festiu: #1B8FC7;
    --clr-festiu-soft: #E7F4FA;
    --clr-festiu-tint: rgba(27, 143, 199, 0.28);
    --clr-teal: #12786C;
    --clr-slate: #45526B;

    --clr-fill-primary: #8A5A16;
    --clr-fill-success: #1B7A4E;
    --clr-fill-danger: #B3323D;
    --clr-btn-text: #FFFFFF;

    --shadow-sm: 0 1px 2px rgba(27, 31, 39, 0.06);
    --shadow-md: 0 6px 20px rgba(27, 31, 39, 0.08);
}

/* ==== Global Base Styles ==== */
html, body {
  font-family: var(--font-body);
  background-color: var(--clr-bg);
  color: var(--clr-text);
  min-height: 100vh;
  margin: 0;
  padding: 0;
}

body {
  padding-bottom: 3rem;
}

/* ==== Typography ==== */
h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--clr-text);
}

.text-muted {
  color: var(--clr-text-muted) !important;
}

.text-success {
  color: var(--clr-green) !important;
}

.text-danger {
  color: var(--clr-red) !important;
}

.text-info {
  color: var(--clr-info) !important;
}

.text-amber {
  color: var(--clr-amber) !important;
}

/* Panell d'avís suau (p.ex. saldo de vacances pendent al formulari de
   sol·licitud, calendario.php): fons ambre fluix sense vora, perquè
   destaqui de la targeta sense la duresa visual d'un requadre. */
.info-panel {
  background: var(--clr-amber-soft);
  border-radius: 0.75rem;
  padding: 0.75rem 1rem;
}

.info-panel__divider {
  margin-top: 0.6rem;
  padding-top: 0.6rem;
  border-top: 1px solid var(--clr-surface-border);
}

/* Enllaços de text solts ("veure l'històric", "Veure historial"...): el
   blau per defecte de Bootstrap no és de la paleta d'aquesta app (identitat
   d'un sol accent ambre, vegeu la capçalera del fitxer -sense blau-), es
   tenyeixen igual que els botons. Selector d'element (especificitat mínima):
   qualsevol component amb el seu propi color (.btn, badges, .nav-link,
   .notification__meta a...) el continua guanyant sense necessitat de tocar-lo.  */
a {
  color: var(--clr-amber);
}
a:hover, a:focus {
  color: var(--clr-amber);
  text-decoration: underline;
}

.balance-vacation-note {
  color: var(--clr-green);
  font-size: 0.8rem;
  font-weight: 600;
  margin-top: 0.3rem;
}

code, .font-mono {
  font-family: var(--font-mono);
}

/* Sortint d'una edició (p.ex. "Editar" a calendario.php > Vacances), l'enllaç
   salta a l'àncora amb #idFormulari perquè el navegador el porti a dalt de
   tot; com el navbar és sticky-top (~71px), sense aquest marge el
   navegador alinearia el formulari exactament a y=0 i el navbar el
   taparia per sobre —quedant la capçalera i el primer camp amagats. Cal
   afegir aquesta classe a qualsevol altra àncora de formulari (p.ex.
   #festiuFormCard) que tingui el mateix problema. */
.scroll-anchor-offset {
  scroll-margin-top: 5rem;
}

/* ==== Shared Navbar ==== */
.navbar {
  background: #14181F !important;
  border-bottom: 2px solid var(--clr-amber);
  padding: 0.85rem 1rem;
}

.navbar-brand {
  font-family: var(--font-display);
  font-size: 1.25rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: #F6F4EF !important;
}

.brand-icon {
  width: 1.3em;
  height: 1.3em;
  vertical-align: -0.2em;
  margin-right: 0.3em;
}

.brand-icon--sm {
  width: 1em;
  height: 1em;
  vertical-align: -0.15em;
  margin-right: 0;
}

.navbar-nav .nav-link {
  font-weight: 500;
  color: rgba(246, 244, 239, 0.7) !important;
  padding: 0.5rem 0.9rem !important;
  border-radius: 0.375rem;
  border-bottom: 2px solid transparent;
  transition: color 0.15s ease, border-color 0.15s ease;
  /* Cap entrada del menú no s'ha de partir en dues línies. Sense això, entre
     1200 i 1399px l'insígnia de Feedback queia sota la paraula i la barra
     passava de 71 a 95px d'alçada; el menú desplegat sempre hi cap en una
     línia, de manera que no es guanya res deixant-lo partir. */
  white-space: nowrap;
}

.navbar-nav .nav-link:hover {
  color: #F6F4EF !important;
}

.navbar-nav .nav-link.active {
  color: #F6F4EF !important;
  border-bottom: 2px solid var(--clr-amber);
}

/* El menú es desplega a partir de 992px (navbar-expand-lg), però amb el perfil
   d'administrador -set enllaços més el nom i dos botons- desplegat necessitava
   1085px dins d'un contenidor de 944px: entre 992 i 1199px sobresortia i feia
   que la pàgina sencera es desplacés de costat. Un portàtil de 1024px és prou
   gran per tenir el menú a la vista, així que en comptes de replegar-lo fins a
   1200px (navbar-expand-xl) s'estreny només en aquesta franja. De 1200px
   amunt, on ja hi cabia, no canvia res. */
@media (min-width: 992px) and (max-width: 1199.98px) {
  /* El "nowrap" és imprescindible: sense ell, en comptes de desbordar,
     l'insígnia de Feedback queia sota la paraula i "Vista d'usuari" es partia
     en dues línies, i la barra creixia fins a 91px d'alçada. */
  .navbar-nav .nav-link {
    padding: 0.5rem 0.4rem !important;
    font-size: 0.88rem;
    white-space: nowrap;
  }

  .navbar .nav-user {
    gap: 0.4rem !important;
  }

  .nav-user__name {
    font-size: 0.85rem;
  }

  .navbar .nav-user .btn {
    padding: 0.35rem 0.55rem;
    font-size: 0.78rem;
    white-space: nowrap;
  }
}

/* Peu petit i fix, a baix a la dreta, amb la darrera sincronització */
.app-footer {
  position: fixed;
  bottom: 0;
  right: 0;
  z-index: 1020;
  padding: 0.25rem 0.75rem;
  font-size: 0.72rem;
  color: var(--clr-text-muted);
  background: var(--clr-surface);
  border: 1px solid var(--clr-surface-border);
  border-right: none;
  border-bottom: none;
  border-top-left-radius: 0.5rem;
  box-shadow: var(--shadow-sm);
  white-space: nowrap;
}

.app-footer .cell-mono {
  font-size: 0.72rem;
}

/* El rellotge només substitueix el text a les pantalles estretes */
.app-footer__icon {
  display: none;
}

/* Peu amb les dades de l'empresa: mateix disseny que .app-footer, mirallat
   a baix a l'esquerra. */
.app-footer--company {
  right: auto;
  left: 0;
  border-right: 1px solid var(--clr-surface-border);
  border-left: none;
  border-top-left-radius: 0;
  border-top-right-radius: 0.5rem;
  max-width: min(60vw, 420px);
  overflow: hidden;
  text-overflow: ellipsis;
}

.app-footer--company .cell-mono {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  display: block;
}

@media (max-width: 767.98px) {
  .app-footer {
    padding: 0.2rem 0.5rem;
    font-size: 0.68rem;
  }
  .app-footer .cell-mono {
    font-size: 0.68rem;
  }
  .app-footer__label {
    display: none;
  }
  .app-footer__icon {
    display: inline;
  }
  .app-footer--company {
    max-width: 45vw;
  }
}

/* És un enllaç cap a la pàgina del propi compte, però ha de continuar
   llegint-se com el nom de qui ha entrat, no com un botó més de la barra. */
.nav-user__name {
  font-weight: 600;
  font-size: 0.9rem;
  color: rgba(246, 244, 239, 0.85);
  white-space: nowrap;
  text-decoration: none;
}

.nav-user__name:hover,
.nav-user__name:focus {
  color: var(--clr-amber);
  text-decoration: none;
}

/* Igual que amb els enllaços del menú: entre 1200 i 1392px el botó
   "Vista d'usuari" es partia en dues línies i estirava la barra de 71 a 89px.
   Els botons de la dreta han d'anar sempre en una sola línia. */
.navbar .nav-user .btn {
  white-space: nowrap;
}

/* La barra de navegació és sempre fosca (identitat de marca), independent
   del tema triat per l'usuari. Sense això, qualsevol .btn-outline-secondary
   -Feedback, Vista d'usuari, Sortir, el nou interruptor de tema...- prendria
   els tokens --clr-text/--clr-surface-border que en mode clar són foscos, i
   quedaria pràcticament invisible sobre el fons fosc del navbar. */
.navbar .btn-outline-secondary {
  color: rgba(246, 244, 239, 0.7);
  border-color: rgba(246, 244, 239, 0.3);
}

.navbar .btn-outline-secondary:hover {
  color: #14181F;
  background-color: #F6F4EF;
  border-color: #F6F4EF;
}

/* Interruptor de tema (icona sola, sense text) a la barra de navegació */
.theme-toggle-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.1rem;
  height: 2.1rem;
  padding: 0;
  font-size: 1rem;
  line-height: 1;
}

/* Avís persistent mentre l'admin està veient l'app com un altre usuari */
.impersonation-banner {
  background: var(--clr-amber-soft);
  color: var(--clr-text);
  border-bottom: 2px solid var(--clr-amber);
  padding: 0.5rem 0;
  margin-top: -1.5rem;
  margin-bottom: 1.5rem;
  font-size: 0.9rem;
}

/* Avís persistent per a un compte de baixa en mode només consulta. Si
   també s'està impersonant, va enganxat just a sota de l'avís anterior. */
.read-only-banner {
  background: var(--clr-red-soft);
  color: var(--clr-text);
  border-bottom: 2px solid var(--clr-red);
  padding: 0.5rem 0;
  margin-top: -1.5rem;
  margin-bottom: 1.5rem;
  font-size: 0.9rem;
}

/* ==== Cards ==== */
.card {
  background: var(--clr-surface);
  color: var(--clr-text);
  border: 1px solid var(--clr-surface-border);
  border-radius: 0.75rem;
  box-shadow: var(--shadow-sm);
  padding: 1.75rem;
  transition: box-shadow 0.2s ease;
}

.card:hover {
  box-shadow: var(--shadow-md);
}

/* Dashboard Counts / Accent Displays – llegits com un comptador, no com a titular */
.display-4 {
  font-family: var(--font-mono);
  font-size: 2.75rem;
  font-weight: 600;
  color: var(--clr-amber);
  margin: 0.5rem 0;
}

/* Xifra protagonista d'una rajola (p.ex. balanç net de l'equip): més gran
   que .display-4 perquè és l'única dada de la targeta -sense .cell-mono,
   que xafava la mida (0.92rem) per culpa de tenir la mateixa especificitat
   i venir després al full d'estils; aquí el monospace ja el posa la regla
   mateixa. */
.display-tile-amount {
  font-family: var(--font-mono);
  font-size: 3.5rem;
  font-weight: 700;
  margin: 0.5rem 0;
  line-height: 1.1;
}

/* ==== Tables styling ==== */
/* "overflow: hidden" (hi era pel radi de les cantonades) anul·lava el
   desplaçament horitzontal que aporta .table-responsive de Bootstrap: en
   pantalles estretes les columnes que no hi cabien no es retallaven, quedaven
   directament inabastables. Amagant només l'eix vertical, el radi continua
   retallant les cantonades i l'eix horitzontal torna a poder desplaçar-se. */
.table-responsive {
  border-radius: 0.75rem;
  overflow-x: auto;
  overflow-y: hidden;
  border: 1px solid var(--clr-surface-border);
}

.table {
  margin-bottom: 0;
  background: transparent;
  color: var(--clr-text);
}

/* Bootstrap pinta el fons de cada cel·la amb un box-shadow intern (--bs-table-bg),
   no amb background-color, i només es commuta amb data-bs-theme (no amb
   prefers-color-scheme). Sense anul·lar-lo aquí, aquest box-shadow tapa els
   nostres colors i deixa combinacions com text fosc sobre fons fosc. */
.table th {
  background-color: var(--clr-table-hdr) !important;
  color: var(--clr-text) !important;
  box-shadow: none !important;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.85rem;
  letter-spacing: 0.02em;
  border-bottom: 2px solid var(--clr-surface-border) !important;
  padding: 0.85rem 0.75rem;
}

.table td {
  padding: 0.85rem 0.75rem;
  border-bottom: 1px solid var(--clr-surface-border);
  vertical-align: middle;
  background-color: transparent !important;
  color: var(--clr-text) !important;
  box-shadow: none !important;
}

.table-striped tbody tr:nth-of-type(odd) td {
  background-color: var(--clr-surface-2) !important;
}

/* Fila destacada (p.ex. en clicar un element del calendari, o en obrir
   l'informe mensual sobre el dia d'avui): el JS porta la fila al centre de
   la pantalla i fa DOS parpelleigs a fons ambre clar abans de tornar al
   fons actual. IMPORTANT: s'anima el fons del TR, no de les cel·les, perquè
   més amunt fixem el background i el box-shadow dels TD amb !important (i
   un !important sempre guanya a una animació CSS); mentre dura el flaix
   les cel·les es fan transparents perquè es vegi el flaix del TR.  */
.table-striped tbody tr.row-highlight > td {
  background-color: transparent !important;
}
.table-striped tbody tr.row-highlight {
  animation: rowFlash 1.8s ease-in-out both;
}
@keyframes rowFlash {
  0%, 100% { background-color: transparent; }
  12%, 32% { background-color: rgba(226, 166, 58, 0.5); }
  46%      { background-color: transparent; }
  60%, 80% { background-color: rgba(226, 166, 58, 0.5); }
}
@media (prefers-reduced-motion: reduce) {
  .table-striped tbody tr.row-highlight {
    animation: none;
    background-color: rgba(226, 166, 58, 0.5);
  }
}

/* Variant de .row-highlight per al focus automàtic sobre les vacances més
   properes a avui (calendario.php > pestanya Vacances): mateix parpelleig
   ambre, però un cop acaba es queda tenyida (animation ... both mantè el
   fotograma del 100%) perquè la fila continuï destacant a la llista
   mentre l'administrador la repassa, en lloc de tornar al fons normal. */
.table-striped tbody tr.row-highlight-persist > td {
  background-color: transparent !important;
}
.table-striped tbody tr.row-highlight-persist {
  animation: rowFlashPersist 1.8s ease-in-out both;
}
@keyframes rowFlashPersist {
  0%       { background-color: transparent; }
  12%, 32% { background-color: rgba(226, 166, 58, 0.5); }
  46%      { background-color: var(--clr-amber-soft); }
  60%, 80% { background-color: rgba(226, 166, 58, 0.5); }
  100%     { background-color: var(--clr-amber-soft); }
}
@media (prefers-reduced-motion: reduce) {
  .table-striped tbody tr.row-highlight-persist {
    animation: none;
    background-color: var(--clr-amber-soft);
  }
}

/* Xifres, hores i dates: llegides com a dades, no com a prosa */
.cell-mono {
  font-family: var(--font-mono);
  font-size: 0.92rem;
}

/* ==== Buttons & Inputs ==== */
.btn {
  font-weight: 600;
  padding: 0.5rem 1.25rem;
  border-radius: 0.5rem;
  transition: filter 0.15s ease, transform 0.1s ease;
}

.btn:active {
  transform: translateY(1px);
}

.btn-primary {
  background-color: var(--clr-fill-primary);
  border-color: var(--clr-fill-primary);
  color: var(--clr-btn-text);
}

.btn-primary:hover, .btn-primary:focus {
  background-color: var(--clr-fill-primary);
  border-color: var(--clr-fill-primary);
  color: var(--clr-btn-text);
  filter: brightness(1.1);
}

.btn-success {
  background-color: var(--clr-fill-success);
  border-color: var(--clr-fill-success);
  color: var(--clr-btn-text);
}

.btn-success:hover, .btn-success:focus {
  background-color: var(--clr-fill-success);
  border-color: var(--clr-fill-success);
  color: var(--clr-btn-text);
  filter: brightness(1.1);
}

.btn-danger {
  background-color: var(--clr-fill-danger);
  border-color: var(--clr-fill-danger);
  color: var(--clr-btn-text);
}

.btn-danger:hover, .btn-danger:focus {
  background-color: var(--clr-fill-danger);
  border-color: var(--clr-fill-danger);
  color: var(--clr-btn-text);
  filter: brightness(1.1);
}

.btn-outline-secondary {
  color: var(--clr-text);
  border-color: var(--clr-surface-border);
}

.btn-outline-secondary:hover {
  background-color: var(--clr-surface-2);
  color: var(--clr-text);
}

.btn-outline-info {
  color: var(--clr-info);
  border-color: var(--clr-info);
}

.btn-outline-info:hover, .btn-outline-info:focus {
  background-color: var(--clr-info-soft);
  color: var(--clr-info);
  border-color: var(--clr-info);
}

.btn-link {
  color: var(--clr-amber);
}

/* Botó només d'icona: quadrat, amb el símbol centrat. Manté el color del botó
   (btn-primary, btn-danger…); el SVG hereta el color del text (currentColor). */
.btn-icon {
  padding: 0.4rem 0.5rem;
  line-height: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.btn-icon svg {
  display: block;
}

.btn:focus-visible, .form-control:focus-visible, .form-select:focus-visible, a:focus-visible {
  outline: 2px solid var(--clr-amber);
  outline-offset: 2px;
}

/* Input de fitxer amb disseny propi (calendario.php > Permís per hores):
   el <input type="file"> real es queda invisible però accessible (mida
   1px, no display:none) i un <label for="..."> en fa de botó — el text
   del botó el fixem nosaltres en català, en lloc del "Seleccionar
   archivo"/"Choose file" que posa el navegador segons el SEU idioma (no
   el de la pàgina). Clicar el label ja obre el selector, sense JS. */
.file-input__native {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
.file-input__native:focus-visible + label {
  outline: 2px solid var(--clr-amber);
  outline-offset: 2px;
}
.file-input {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
}
.file-input__button {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  cursor: pointer;
  margin: 0;
}
.file-input__name {
  font-size: 0.85rem;
  color: var(--clr-text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 220px;
}

/* Visor en línia del document justificant (calendario.php > Permís per
   hores): s'obre dins la mateixa fila (.stack-attach, vegeu més avall),
   mai a una pestanya nova, i no supera l'amplada de la línia del registre
   perquè viu dins la mateixa cel·la/targeta que la resta de columnes.
   IMPORTANT: el <td> no pot portar padding/vora propis (els de .table td,
   més amunt): amb el .collapse tancat el seu contingut no ocupa espai,
   però el <td> els mantindria igualment i deixaria una línia buida sota
   el registre. Tot el padding viu a .doc-preview, DINS del .collapse. */
.doc-preview-row > td {
  padding: 0 !important;
  border-bottom: none !important;
}
.doc-preview {
  padding: 0.85rem 0.75rem 0.35rem;
  max-width: 100%;
}
.doc-preview__frame {
  display: block;
  width: 100%;
  height: 75vh;
  max-width: 100%;
  border: 1px solid var(--clr-surface-border);
  border-radius: 0.5rem;
  background: #fff;
}
.doc-preview__img {
  display: block;
  max-width: 100%;
  max-height: 75vh;
  border: 1px solid var(--clr-surface-border);
  border-radius: 0.5rem;
  object-fit: contain;
}

/* Previsualització del logotip de l'empresa (Configuració > Empresa): fons
   blanc fix perquè un PNG amb transparència es vegi igual en tema fosc i
   clar, com el paper d'un informe PDF. */
.company-logo-preview {
  display: block;
  height: 48px;
  max-width: 160px;
  padding: 0.25rem 0.5rem;
  border: 1px solid var(--clr-surface-border);
  border-radius: 0.5rem;
  background: #fff;
  object-fit: contain;
}

.form-control, .form-select {
  background-color: var(--clr-surface);
  border: 1px solid var(--clr-surface-border);
  border-radius: 0.5rem;
  padding: 0.6rem 0.75rem;
  color: var(--clr-text);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

/* El padding uniforme d'aquí sobre trepitjava el padding-right que
   Bootstrap reserva perquè el text no envaeixi la fletxa del <select>
   (imatge de fons, no es desplaça amb el padding): el text hi quedava a
   sobre. Es restaura només per als selects, sense tocar els inputs. */
.form-select {
  padding-right: 2.25rem;
}

/* Bootstrap calibra el color per defecte del placeholder per a fons clars;
   sense això, en mode fosc queda pràcticament invisible sobre --clr-surface. */
.form-control::placeholder {
  color: var(--clr-text-muted);
  opacity: 1;
}

.form-control:focus, .form-select:focus {
  background-color: var(--clr-surface);
  border-color: var(--clr-amber);
  box-shadow: 0 0 0 3px var(--clr-amber-soft);
  color: var(--clr-text);
}

/* Camp de cerca que employee-search.js insereix damunt d'un <select
   class="employee-select"> quan hi ha més de 10 empleats (vegeu el fitxer).
   El wrapper no és cap graella nova: hereta l'amplada de la columna on ja
   vivia el <select>. */
.employee-search-wrapper {
  width: 100%;
}

.employee-search-input {
  margin-bottom: 0.4rem;
}

.form-label {
  font-weight: 600;
  font-size: 0.85rem;
  color: var(--clr-text-muted);
}

/* La icona per obrir el calendari/rellotge dels camps de data i hora:
   a plena opacitat i una mica més gran perquè es vegi que és clicable. */
input[type="date"]::-webkit-calendar-picker-indicator,
input[type="time"]::-webkit-calendar-picker-indicator {
  opacity: 1;
  cursor: pointer;
  transform: scale(1.15);
}

/* ==== Option List (grups de radios amb descripció, p.ex. rang d'incidències) ==== */
.option-list {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  max-width: 34rem;
}

.option-row {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  margin: 0;
  padding: 0.8rem 1rem;
  background: var(--clr-surface-2);
  border: 1px solid var(--clr-surface-border);
  border-radius: 0.5rem;
  cursor: pointer;
  transition: border-color 0.15s ease, background-color 0.15s ease;
}

.option-row:hover {
  border-color: var(--clr-amber);
}

.option-row:has(input[type="radio"]:checked) {
  border-color: var(--clr-amber);
  background: var(--clr-amber-soft);
}

.option-row input[type="radio"] {
  flex-shrink: 0;
  margin-top: 0.3rem;
  accent-color: var(--clr-amber);
}

.option-row__body {
  flex: 1;
  min-width: 0;
}

.option-row__title {
  display: block;
  font-weight: 600;
  color: var(--clr-text);
}

.option-row__title .form-control {
  display: inline-block;
  width: 4.5rem;
  padding: 0.15rem 0.5rem;
  font-family: var(--font-mono);
  font-size: 0.9rem;
  text-align: center;
}

.option-row__desc {
  display: block;
  margin-top: 0.15rem;
  font-size: 0.8rem;
  color: var(--clr-text-muted);
}

/* ==== Status Board (Estat en Directe) – element signatura ==== */
.status-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.7rem 0.9rem;
  margin-bottom: 0.6rem;
  background: var(--clr-surface-2);
  border-radius: 0.5rem;
  border-left: 3px solid var(--clr-surface-border);
}

.status-row--working { border-left-color: var(--clr-green); }
.status-row--pending { border-left-color: var(--clr-amber); }
.status-row--lunch { border-left-color: var(--clr-purple); }
.status-row--off { border-left-color: var(--clr-surface-border); }
/* Estats inactius, cadascun amb un color propi (cap en verd, que és el de
   "Treballant"): dia no laborable en blau, vacances/permís en cian i baixa en
   magenta. */
.status-row--no-laborable { border-left-color: var(--clr-info); }
.status-row--vacances { border-left-color: var(--clr-festiu); }
.status-row--baixa { border-left-color: var(--clr-baixa); }

/* Qui no està treballant es veu enfosquit, perquè d'un cop d'ull quedi clar
   qui és actiu ara mateix i qui no. Els estats actius (treballant, dinant,
   fitxatge pendent) queden a plena opacitat i amb el punt que pulsa. */
.status-row--off,
.status-row--no-laborable,
.status-row--vacances,
.status-row--baixa {
  opacity: 0.6;
}

/* Barra de progrés de la jornada d'avui (vista d'empleat): pròpia en comptes
   de .progress de Bootstrap perquè aquesta és sempre blava i no segueix la
   paleta ink/paper/amber de la resta de l'app. */
.workday-progress__track {
  height: 0.5rem;
  border-radius: 999px;
  background: var(--clr-surface-2);
  border: 1px solid var(--clr-surface-border);
  overflow: hidden;
}

.workday-progress__fill {
  height: 100%;
  border-radius: 999px;
  background: var(--clr-green);
  transition: width 0.3s ease;
}

/* Jornada completada: mateix verd amb el to més fort perquè el 100% es
   distingeixi de qualsevol progrés parcial que hi arribi molt a prop. */
.workday-progress__fill--done {
  background: var(--clr-green-tint);
}

/* Llista d'entrades tard del tauler d'administrador (rajola de
   puntualitat): una fila per entrada, enllaçada als fitxatges del dia. */
.late-entries {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.late-entries__row {
  display: grid;
  grid-template-columns: 1fr auto auto auto;
  gap: 1rem;
  align-items: baseline;
  padding: 0.6rem 0.9rem;
  border-radius: 0.5rem;
  border-left: 3px solid var(--clr-amber);
  background: var(--clr-surface-2);
  color: var(--clr-text);
  text-decoration: none;
}

.late-entries__row:hover {
  background: var(--clr-amber-soft);
}

.late-entries__name {
  font-weight: 600;
}

.late-entries__delta {
  min-width: 4.5rem;
  text-align: right;
}

@media (max-width: 575.98px) {
  .late-entries__row {
    grid-template-columns: 1fr auto;
    gap: 0.25rem 1rem;
  }
}

/* Barra de progrés del mes (Resum del mes a Informes i "Les meves hores" al
   tauler): treballat sobre el total del mes sencer, amb una marca on caldria
   ser a hores d'ara. Ambre mentre avança, verd en arribar al total. */
.month-progress {
  margin: 1rem 0;
}

.month-progress__head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.75rem;
  margin-bottom: 0.35rem;
}

.month-progress__track {
  position: relative;
  height: 0.6rem;
  border-radius: 999px;
  background: var(--clr-surface-2);
  border: 1px solid var(--clr-surface-border);
}

.month-progress__fill {
  height: 100%;
  border-radius: 999px;
  background: var(--clr-amber);
}

.month-progress__fill--done {
  background: var(--clr-green);
}

.month-progress__marker {
  position: absolute;
  top: -0.25rem;
  bottom: -0.25rem;
  width: 2px;
  margin-left: -1px;
  border-radius: 1px;
  background: var(--clr-text);
  opacity: 0.55;
}

.workday-progress__label {
  margin-top: 0.35rem;
  text-align: right;
}

/* Desglossament de jornada d'avui dins de "Estat en directe" (vista
   d'empleat): una fila per dada (etiqueta a l'esquerra, valor a la dreta),
   apilades, en comptes de columnes -amb tres columnes estretes el valor amb
   hora de sortida estimada no hi cabia sense trencar-se malament-. */
.live-status-stats__row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.75rem;
  padding: 0.4rem 0;
}

.live-status-stats__row + .live-status-stats__row {
  border-top: 1px solid var(--clr-surface-border);
}

/* Peu de fitxatge dins de "Estat en directe": la llista diu com estàs i això
   és el que ho canvia. Va separat per una línia perquè es llegeixi com una
   acció i no com una fila més de la llista, i el botó ocupa tota l'amplada
   -és l'únic element accionable de la targeta i, en mòbil, el primer que es
   veu del tauler-. */
.punch-panel {
  margin-top: 1.25rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--clr-surface-border);
}

.punch-panel__last {
  color: var(--clr-text-muted);
  font-size: 0.875rem;
  margin-bottom: 0.75rem;
}

.status-row__info {
  flex: 1;
  min-width: 0;
}

.status-row__name {
  font-weight: 600;
  color: var(--clr-text);
}

.status-row__detail {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  color: var(--clr-text-muted);
}

.status-row__label {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  white-space: nowrap;
  color: var(--clr-text-muted);
}

.status-row--working .status-row__label { color: var(--clr-green); }
.status-row--pending .status-row__label { color: var(--clr-amber); }
.status-row--lunch .status-row__label { color: var(--clr-purple); }
.status-row--no-laborable .status-row__label { color: var(--clr-info); }
.status-row--vacances .status-row__label { color: var(--clr-festiu); }
.status-row--baixa .status-row__label { color: var(--clr-baixa); }

/* ==== Vacances pendents d'aprovar (Dashboard, només admin) ==== */
.pending-leaves-card {
  border-left: 3px solid var(--clr-green);
}

.pending-leave {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  padding: 0.7rem 0.9rem;
  background: var(--clr-surface-2);
  border-radius: 0.5rem;
}

.pending-leave + .pending-leave {
  margin-top: 0.6rem;
}

.pending-leave__name {
  font-weight: 600;
  color: var(--clr-text);
}

.pending-leave__detail {
  font-size: 0.85rem;
  color: var(--clr-text-muted);
}

.pending-leave__actions {
  display: flex;
  gap: 0.4rem;
  margin: 0;
}

/* ==== Treball en festiu pendent d'aprovar com a extra (Dashboard, només admin) ==== */
.pending-festius-card {
  border-left: 3px solid var(--clr-festiu);
}

/* ==== Possibles fitxatges duplicats (Dashboard, només admin) ==== */
.duplicates-card {
  border-left: 3px solid var(--clr-red);
}

/* ==== Incidències de fitxatge (Dashboard) ==== */
.incidents-card {
  border-left: 3px solid var(--clr-amber);
}

.incidents-item-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}

.incidents-item-row .incidents-item {
  flex: 1 1 auto;
  min-width: 0;
}

.incidents-item__ack {
  margin: 0;
  flex: 0 0 auto;
}

.incidents-employee {
  background: var(--clr-surface-2);
  border-radius: 0.5rem;
  padding: 0.85rem 1rem;
  height: 100%;
}

.incidents-employee__name {
  font-weight: 600;
  color: var(--clr-text);
  margin-bottom: 0.5rem;
}

.incidents-item {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  padding: 0.3rem 0.4rem;
  margin: 0 -0.4rem;
  border-top: 1px solid var(--clr-surface-border);
  border-radius: 0.375rem;
  text-decoration: none;
}

li:first-child > .incidents-item {
  border-top: none;
}

a.incidents-item:hover {
  background: var(--clr-amber-soft);
}

a.incidents-item:hover .incidents-item__text {
  color: var(--clr-text);
}

.incidents-item__date {
  font-size: 0.75rem;
  color: var(--clr-amber);
  white-space: nowrap;
}

.incidents-item__text {
  font-size: 0.85rem;
  color: var(--clr-text-muted);
}

/* Fila de filtres (Empleats): tots els controls en una sola línia sempre —
   en comptes de deixar-los saltar de línia en pantalles estretes (que
   acabava desordenant "Netejar" i el botó "+"), es deixa fer scroll
   horitzontal només d'aquesta fila. */
.filter-row-scroll {
  overflow-x: auto;
  padding-bottom: 2px;
}

/* ==== Employee List – targetes en lloc de taula densa ==== */
.employee-card {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.9rem 1.1rem;
  margin-bottom: 0.75rem;
  background: var(--clr-surface-2);
  border-radius: 0.75rem;
  border: 1px solid var(--clr-surface-border);
  transition: box-shadow 0.15s ease;
}

.employee-card:hover {
  box-shadow: var(--shadow-sm);
}

.employee-card__avatar {
  flex-shrink: 0;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: var(--clr-amber-soft);
  color: var(--clr-amber);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.95rem;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden; /* perquè la foto de perfil (avatar.php) no sobresurti del cercle */
}

.employee-card__avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Foto de perfil a "El meu compte" (perfil.php): mateixos colors que
   .employee-card__avatar (llista d'empleats), amb una mida pròpia perquè
   allà és el punt focal de la targeta, no una miniatura de fila.
   El retall el fa el CONTENIDOR (overflow: hidden) i no la pròpia <img>:
   així el cercle es manté encara que la imatge sigui vertical o molt
   gran, i no cal aplicar display:flex a un element reemplaçat. */
.profile-photo {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: 1.25rem;
}

.profile-photo__figure {
  flex-shrink: 0;
  width: 96px;
  height: 96px;
  border-radius: 50%;
  overflow: hidden;
  background: var(--clr-amber-soft);
  color: var(--clr-amber);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 2rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--clr-surface-border);
}

.profile-photo__figure img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Els controls en COLUMNA, no en fila: la targeta viu en una columna
   estreta (col-lg-5) i, en fila, els botons feien un wrap desordenat. */
.profile-photo__actions {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.45rem;
  min-width: 0;
}

.profile-photo__hint {
  font-size: 0.8rem;
  color: var(--clr-text-muted);
}

@media (max-width: 420px) {
  .profile-photo {
    flex-direction: column;
    align-items: flex-start;
  }
}

.employee-card__main {
  flex: 1;
  min-width: 0;
}

.employee-card__name {
  font-family: var(--font-display);
  font-weight: 600;
  color: var(--clr-text);
}

/* Icona de Telegram al costat del nom a la llista d'empleats: indica si
   l'empleat té els avisos vinculats (blau) o no (apagada). */
.telegram-status {
  display: inline-flex;
  vertical-align: middle;
  margin-left: 0.35rem;
}

.telegram-status--active {
  color: var(--clr-info);
}

.telegram-status--inactive {
  color: var(--clr-text-muted);
  opacity: 0.45;
}

.employee-card__meta {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  color: var(--clr-text-muted);
  margin-bottom: 0.4rem;
}

.employee-card__schedule {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}

.schedule-badge {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  color: var(--clr-text-muted);
  background: var(--clr-surface);
  border: 1px solid var(--clr-surface-border);
  border-radius: 999px;
  padding: 0.2rem 0.65rem;
  white-space: nowrap;
}

.employee-card__hours {
  flex-shrink: 0;
  text-align: center;
  min-width: 84px;
}

/* Comptador de "Empleats" a la targeta de categoria: és un enllaç (porta al
   llistat filtrat), però ha de tenir exactament el mateix aspecte que la
   resta d'estadístiques de la targeta (sense el blau/subratllat per defecte
   d'un <a>). */
a.employee-card__hours {
  color: inherit;
  text-decoration: none;
}
a.employee-card__hours:hover .cell-mono {
  color: var(--clr-amber);
}

.employee-card__actions {
  flex-shrink: 0;
  display: flex;
  gap: 0.4rem;
}

@media (max-width: 576px) {
  .employee-card {
    flex-wrap: wrap;
  }

  /* Salt de línia forçat: sense ell, la jornada setmanal cabia a la mateixa
     línia que el nom -encongint el bloc principal- i quedava encastada contra
     el correu. Un fill buit de 100% d'amplada empeny tot el que ve després
     (per "order") a una segona fila pròpia. */
  .employee-card::after {
    content: '';
    flex-basis: 100%;
    height: 0;
    order: 1;
  }

  .employee-card__hours {
    text-align: left;
    order: 2;
  }

  .employee-card__actions {
    order: 3;
    margin-left: auto;
  }
}

/* ==== Status Indicators & Pulsing Effects ==== */
.status-indicator {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  flex-shrink: 0;
}

.pulse-green {
  background-color: var(--clr-green);
  box-shadow: 0 0 0 0 rgba(27, 122, 78, 0.5);
  animation: pulse-green-anim 2s infinite;
}

.pulse-orange {
  background-color: var(--clr-amber);
  box-shadow: 0 0 0 0 rgba(180, 116, 31, 0.5);
  animation: pulse-orange-anim 2s infinite;
}

.pulse-purple {
  background-color: var(--clr-purple);
  box-shadow: 0 0 0 0 rgba(107, 79, 160, 0.5);
  animation: pulse-purple-anim 2s infinite;
}

.pulse-gray {
  background-color: var(--clr-text-muted);
}

/* Punts estàtics (sense animació) per als estats inactius de l'estat en
   directe: no són estats "actius" que calgui destacar amb pulsació. */
.status-indicator--no-laborable {
  background-color: var(--clr-info);
}

.status-indicator--vacances {
  background-color: var(--clr-festiu);
}

.status-indicator--baixa {
  background-color: var(--clr-baixa);
}

@keyframes pulse-green-anim {
  0% { box-shadow: 0 0 0 0 rgba(27, 122, 78, 0.5); }
  70% { box-shadow: 0 0 0 6px rgba(27, 122, 78, 0); }
  100% { box-shadow: 0 0 0 0 rgba(27, 122, 78, 0); }
}

@keyframes pulse-orange-anim {
  0% { box-shadow: 0 0 0 0 rgba(180, 116, 31, 0.5); }
  70% { box-shadow: 0 0 0 6px rgba(180, 116, 31, 0); }
  100% { box-shadow: 0 0 0 0 rgba(180, 116, 31, 0); }
}

@keyframes pulse-purple-anim {
  0% { box-shadow: 0 0 0 0 rgba(107, 79, 160, 0.5); }
  70% { box-shadow: 0 0 0 6px rgba(107, 79, 160, 0); }
  100% { box-shadow: 0 0 0 0 rgba(107, 79, 160, 0); }
}

/* ==== Gràfic mensual d'hores (dashboard d'usuari) ====
   Per a cada dia: barra ampla clara = hores esperades (l'objectiu), barra
   estreta ambre a sobre = hores treballades. Dies exempts amb fons verd suau. */
.hours-chart-wrap {
  position: relative;
}

.hours-chart {
  display: flex;
  align-items: stretch;
  gap: 2px;
  height: 190px;
  margin-bottom: 0.75rem;
  /* En tàctil, arrossegar de costat recorre els dies (vegeu el globus de sota);
     amunt i avall continua desplaçant la pàgina i el pessic continua fent zoom. */
  touch-action: pan-y pinch-zoom;
}

.hours-chart__day {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  border-radius: 3px;
}

.hours-chart__plot {
  position: relative;
  flex: 1;
  border-bottom: 1px solid var(--clr-surface-border);
}

.hours-chart__expected {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  background: var(--clr-info-soft);
  border: 1px solid var(--clr-info);
  border-bottom: none;
  border-radius: 3px 3px 0 0;
  opacity: 0.75;
}

.hours-chart__worked {
  position: absolute;
  bottom: 0;
  left: 22%;
  right: 22%;
  background: var(--clr-amber);
  border-radius: 3px 3px 0 0;
}

.hours-chart__day:hover .hours-chart__worked {
  filter: brightness(1.15);
}

.hours-chart__day:hover .hours-chart__expected {
  border-color: var(--clr-amber);
}

.hours-chart__day--vacation .hours-chart__plot {
  background: var(--clr-green-tint);
  border-radius: 3px 3px 0 0;
}

.hours-chart__day--baixa .hours-chart__plot {
  background: var(--clr-baixa-tint);
  border-radius: 3px 3px 0 0;
}

.hours-chart__day--festiu .hours-chart__plot {
  background: var(--clr-festiu-tint);
  border-radius: 3px 3px 0 0;
}

.hours-chart__label {
  font-family: var(--font-mono);
  font-size: 0.6rem;
  color: var(--clr-text-muted);
  text-align: center;
  padding-top: 3px;
  overflow: hidden;
}

/* ==== Globus del gràfic (només pantalles tàctils) ====
   L'atribut title del navegador només es dispara amb el ratolí, i en un mòbil
   el detall de cada dia (hores treballades, esperades, festiu, permís…) no era
   consultable de cap manera. Aquest globus el mostra en tocar una columna, i
   arrossegant el dit de costat es recorren els dies: amb columnes de 9px,
   encertar-ne una de concreta a la primera és massa demanar.
   Va sota el gràfic, damunt de la llegenda, per no tapar les barres que
   s'estan mirant; la columna triada es ressalta amb un contorn ambre. */
.hours-chart__tip {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 5;
  max-width: 100%;
  padding: 0.4rem 0.65rem;
  background: var(--clr-surface);
  border: 1px solid var(--clr-amber);
  border-radius: 0.5rem;
  box-shadow: var(--shadow-md);
  font-size: 0.78rem;
  line-height: 1.35;
  color: var(--clr-text);
  /* Cap event: així elementFromPoint continua trobant la columna de sota
     mentre s'arrossega el dit per damunt del globus. */
  pointer-events: none;
  /* Amagat amb visibility (no display) perquè es pugui mesurar l'amplada
     abans de centrar-lo sobre la columna. */
  visibility: hidden;
  opacity: 0;
  transition: opacity 0.12s ease;
}

.hours-chart__tip--on {
  visibility: visible;
  opacity: 1;
}

.hours-chart__day--active .hours-chart__plot {
  box-shadow: 0 0 0 1px var(--clr-amber);
  border-radius: 3px 3px 0 0;
}

@media (prefers-reduced-motion: reduce) {
  .hours-chart__tip {
    transition: none;
  }
}

.hours-chart__day--today .hours-chart__label {
  color: var(--clr-amber);
  font-weight: 700;
}

/* En un mòbil el mes sencer es reparteix en uns 300px: cada dia són ~9px de
   columna, menys que l'amplada d'un número de dos dígits. Amagant només els
   dies parells, els números de l'1 al 9 hi cabien i els del 10 endavant no,
   i el "overflow: hidden" els retallava: la fila de números feia un salt
   visible just en passar d'un dígit a dos. Aquí es fa al revés: el número
   pot sortir de la seva columna (queda centrat igualment) i només se
   n'ensenya un de cada cinc, prou separats perquè no en xoqui cap. */
@media (max-width: 576px) {
  .hours-chart {
    height: 150px;
    gap: 1px;
  }

  /* Les tres xifres del resum (treballades/esperades/diferència) en tres
     columnes d'uns 95px: a 1.25rem, "118h 25m" no hi cabia i es partia en dues
     línies desalineades entre columnes. */
  .chart-summary .cell-mono {
    font-size: 1rem !important;
  }

  .chart-summary .small {
    font-size: 0.7rem;
  }

  .hours-chart__label {
    visibility: hidden;
    overflow: visible;
    white-space: nowrap;
    font-size: 0.58rem;
    letter-spacing: -0.02em;
  }

  .hours-chart__day:nth-child(5n+1) .hours-chart__label {
    visibility: visible;
  }

  /* El número d'avui gairebé mai no cau en una de les posicions retolades, i
     acolorir-lo (com es fa en PC) no serviria de res si està amagat: la
     columna del dia en curs es marca amb una fletxa ambre al seu lloc. */
  .hours-chart__day--today .hours-chart__label {
    visibility: visible;
    font-size: 0;
    line-height: 1;
  }

  .hours-chart__day--today .hours-chart__label::before {
    content: '▲';
    font-size: 0.55rem;
    color: var(--clr-amber);
  }

  /* A 9px de columna, un 22% de marge a cada banda deixava la barra d'hores
     treballades en 4px escassos: gairebé no es veia sobre l'esperada. */
  .hours-chart__worked {
    left: 12%;
    right: 12%;
  }
}

/* ==== Alçada del gràfic segons l'espai de la targeta ====
   La targeta de "Les meves hores" porta h-100: en pantalla gran s'estira fins
   a l'alçada de la columna de la dreta (estat en directe + vacances), que
   sempre és més alta. Amb el gràfic clavat a 190px tot aquest espai quedava
   buit sota les estadístiques, així que aquí el gràfic creix amb el que sobra.
   El topall evita barres desproporcionades quan la columna del costat es fa
   molt llarga; el que quedi per sota se'l menja el peu d'estadístiques, que
   baixa al final de la targeta.
   Només a partir de 1200px: entre 992 i 1199 les dues columnes ja hi caben
   però la targeta de la dreta creix molt (tot el text s'hi parteix en dues
   línies), i estirar-hi el gràfic només hi deixava un forat encara més gros
   entre la llegenda i el peu. Per sota de lg les columnes s'apilen i no hi ha
   cap alçada "sobrant": val l'alçada fixa de sempre. */
@media (min-width: 1200px) {
  .hours-card {
    display: flex;
    flex-direction: column;
  }

  .hours-card .hours-chart-wrap {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
    max-height: 34rem;
  }

  .hours-card .hours-chart {
    flex: 1 1 auto;
    height: auto;
    min-height: 190px;
  }

  .hours-card .chart-substats {
    margin-top: auto;
  }
}

/* Nota sota el resum del mes (tauler i Informes): d'on surten les hores
   esperades quan no són la simple suma dels horaris dels dies treballats
   -vegeu sumExpectedAdjustmentSeconds(). Només surt quan hi ha ajust, així
   que es marca amb la vora blava d'informació i no com un avís. El botó
   d'"Entesos" l'amaga per sempre (expected_note_ack.php) i va al final: el
   que s'ha de llegir primer és l'explicació. */
.expected-note {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem 0.9rem;
  margin: 0 0 0.9rem;
  padding: 0.5rem 0.75rem;
  border-left: 3px solid var(--clr-info);
  border-radius: 0 0.4rem 0.4rem 0;
  background: var(--clr-surface-2);
  font-size: 0.8rem;
  line-height: 1.45;
  color: var(--clr-text-muted);
}

.expected-note__text {
  flex: 1 1 14rem;
  margin: 0;
}

.expected-note__ack {
  flex: 0 0 auto;
  margin-left: auto;
}

.chart-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.2rem;
}

.chart-legend__item {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.82rem;
  color: var(--clr-text-muted);
}

.chart-legend__swatch {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 3px;
  flex-shrink: 0;
}

.chart-legend__swatch--worked { background: var(--clr-amber); }
.chart-legend__swatch--expected { background: var(--clr-info-soft); border: 1px solid var(--clr-info); }
.chart-legend__swatch--vacation { background: var(--clr-green-tint); border: 1px solid var(--clr-green); }
.chart-legend__swatch--baixa { background: var(--clr-baixa-tint); border: 1px solid var(--clr-baixa); }
.chart-legend__swatch--festiu { background: var(--clr-festiu-tint); border: 1px solid var(--clr-festiu); }

.chart-substats {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.5rem;
  margin-top: 0.9rem;
  padding-top: 0.9rem;
  border-top: 1px solid var(--clr-surface-border);
  font-size: 0.9rem;
  color: var(--clr-text-muted);
}

.chart-substats strong {
  color: var(--clr-text);
  font-family: var(--font-mono);
}

/* ==== Progress Bars ==== */
.progress {
  height: 0.6rem;
  border-radius: 0.5rem;
  background-color: var(--clr-surface-2);
  overflow: hidden;
}

/* ==== Balanç mensual: files d'estat ====
   Vora de color + delta com a xifra gran i protagonista (en comptes
   d'enterrat en text mut), amb la barra com a confirmació secundària. */
.srow {
  display: flex;
  gap: 1rem;
  align-items: center;
  padding: 0.85rem 1rem;
  border-left: 3px solid var(--status-color, var(--clr-surface-border));
  background: var(--clr-surface-2);
  border-radius: 0.4rem;
  margin-bottom: 0.6rem;
}
.srow:last-child { margin-bottom: 0; }
.srow--behind { --status-color: var(--clr-amber); }
.srow--ontrack { --status-color: var(--clr-info); }
.srow--ahead { --status-color: var(--clr-green); }

.srow-main { flex: 1; min-width: 0; }
.srow-name { font-weight: 600; font-size: 0.92rem; margin-bottom: 0.15rem; }
.srow-sub { font-size: 0.78rem; color: var(--clr-text-muted); }

.srow-bar {
  width: 100%;
  height: 0.35rem;
  border-radius: 0.3rem;
  background: var(--clr-surface-border);
  overflow: hidden;
  margin-top: 0.4rem;
}
.srow-bar > span {
  display: block;
  height: 100%;
  background: var(--status-color);
}

.srow-delta {
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 1.05rem;
  white-space: nowrap;
  color: var(--status-color, var(--clr-text));
  text-align: right;
}
.srow-delta small {
  display: block;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 0.68rem;
  color: var(--clr-text-muted);
}

.srow-empty .srow-sub { font-style: italic; }

/* ==== Badges (usats fora del status board, p.ex. autoritzat/vacances) ==== */
.badge.bg-success { background-color: var(--clr-fill-success) !important; color: var(--clr-btn-text) !important; }
.badge.bg-danger { background-color: var(--clr-fill-danger) !important; color: var(--clr-btn-text) !important; }
.badge.bg-primary { background-color: var(--clr-fill-primary) !important; color: var(--clr-btn-text) !important; }
.badge.bg-pendent { background-color: var(--clr-amber-soft) !important; color: var(--clr-amber) !important; border: 1px dashed var(--clr-amber); }
.badge.bg-baixa { background-color: var(--clr-baixa) !important; color: var(--clr-btn-text) !important; }

/* ==== Avisos per a l'empleat (Dashboard) ====
   Decisions de l'administrador que l'usuari ha de confirmar perquè
   desapareguin: el color de la vora esquerra de cada avís diu si és una
   aprovació (verd), un rebuig (vermell) o informatiu (blau). */
.notifications-card {
  border-left: 3px solid var(--clr-amber);
}

.notification {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  padding: 0.7rem 0.9rem;
  background: var(--clr-surface-2);
  border-radius: 0.5rem;
  border-left: 3px solid var(--clr-info);
}

.notification + .notification {
  margin-top: 0.6rem;
}

.notification--success { border-left-color: var(--clr-green); }
.notification--danger { border-left-color: var(--clr-red); }

.notification__title {
  font-weight: 600;
  color: var(--clr-text);
}

.notification__body {
  font-size: 0.9rem;
  color: var(--clr-text);
}

.notification__meta {
  font-size: 0.8rem;
  color: var(--clr-text-muted);
}

/* Enllaç ("Veure-ho"...) dins d'un avís: el blau per defecte de Bootstrap
   no s'adapta al tema fosc (fons fosc + blau viu = poc contrast/es veu
   malament). --clr-info ja està calibrat per als dos temes. */
.notification__meta a {
  color: var(--clr-info);
}
.notification__meta a:hover {
  color: var(--clr-info);
  text-decoration: underline;
}

.notification__actions {
  display: flex;
  gap: 0.4rem;
  margin: 0;
  flex: 0 0 auto;
}

/* ==== Feedback dels empleats ==== */
.feedback-card {
  border-left: 3px solid var(--clr-purple);
}

.feedback-badge {
  border: 1px solid transparent;
}
/* "Ignorat": distintiu apagat (gris), perquè no es confongui amb "Pendent"
   (ambre) tot i que tots dos són estats no resolts. */
.badge.bg-ignorat {
  background-color: var(--clr-surface-2) !important;
  color: var(--clr-text-muted) !important;
  border: 1px solid var(--clr-surface-border);
}

.feedback-badge--solicitud { background-color: var(--clr-green-soft) !important; color: var(--clr-green) !important; border-color: var(--clr-green); }
.feedback-badge--problema { background-color: var(--clr-red-soft) !important; color: var(--clr-red) !important; border-color: var(--clr-red); }
.feedback-badge--millora { background-color: var(--clr-info-soft) !important; color: var(--clr-info) !important; border-color: var(--clr-info); }
.feedback-badge--disseny { background-color: var(--clr-purple-soft) !important; color: var(--clr-purple) !important; border-color: var(--clr-purple); }

.feedback-item {
  padding: 0.8rem 0.9rem;
  background: var(--clr-surface-2);
  border-radius: 0.5rem;
  border-left: 3px solid var(--clr-purple);
}

.feedback-item + .feedback-item {
  margin-top: 0.7rem;
}

/* Un cop resolt, el comentari passa a segon pla però continua consultable */
.feedback-item--solucionat,
.feedback-item--ignorat {
  border-left-color: var(--clr-surface-border);
  opacity: 0.7;
}

.feedback-item__head {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin-bottom: 0.35rem;
}

.feedback-item__title {
  font-weight: 600;
  color: var(--clr-text);
}

.feedback-item__body {
  font-size: 0.92rem;
  color: var(--clr-text);
  margin-bottom: 0.35rem;
}

.feedback-item__meta {
  font-size: 0.8rem;
  color: var(--clr-text-muted);
}

.feedback-item__actions {
  display: flex;
  gap: 0.4rem;
  margin: 0.6rem 0 0;
}

/* S'hi arriba des de l'avís del dashboard: parpelleja per localitzar-lo */
.feedback-item--focus {
  animation: feedbackFlash 1.8s ease-in-out both;
}
@keyframes feedbackFlash {
  0%, 100% { background-color: var(--clr-surface-2); }
  12%, 32% { background-color: var(--clr-amber-soft); }
  46%      { background-color: var(--clr-surface-2); }
  60%, 80% { background-color: var(--clr-amber-soft); }
}
@media (prefers-reduced-motion: reduce) {
  .feedback-item--focus {
    animation: none;
    background-color: var(--clr-amber-soft);
  }
}

/* ==== Navegació de mes (◄ Desembre 2025 ►) ====
   El nom del mes i l'any han d'anar sempre en una sola línia: els mesos
   llargs ("Desembre", "Setembre") es partien del seu any en contenidors
   estrets i el salt de línia empenyia el botó de mes següent a sota,
   descompensant tota la fila. El conjunt tampoc no es parteix; si no hi cap,
   el navegador ja el deixa fora del text adjacent perquè la fila contenidora
   sí que fa wrap. */
.month-nav {
  flex-wrap: nowrap;
}

.month-nav .btn,
.month-nav__label {
  white-space: nowrap;
}

/* Botó "+" que expandeix/retreu un formulari plegat (gira 45° = ×) */
.collapse-toggle {
  font-weight: 700;
  line-height: 1;
  transition: transform 0.15s ease;
}
.collapse-toggle[aria-expanded="true"] {
  transform: rotate(45deg);
}

/* ==== Alerts ==== */
.alert-success { background-color: var(--clr-green-soft); color: var(--clr-green); border-color: transparent; }
.alert-danger { background-color: var(--clr-red-soft); color: var(--clr-red); border-color: transparent; }
/* Sense això queia al blau clar per defecte de Bootstrap, aliè al tema
   (fosc/clar) de l'app: un botó .btn-outline-secondary a sobre (pensat per
   al fons fosc habitual) hi quedava pràcticament invisible. */
.alert-info { background-color: var(--clr-info-soft); color: var(--clr-info); border-color: transparent; }

/* ==== Taules denses → llista de targetes en mòbil ====
   Una taula de sis o vuit columnes no cap en una pantalla de mòbil: només se
   n'hi veien les primeres i la resta quedava fora. Les taules marcades amb
   .table-stack es repleguen sota 768px en una targeta per fila, amb el nom de
   la columna (atribut data-label del TD) a l'esquerra i el valor a la dreta.
   Tot viu dins del media query: en PC la taula es continua veient igual.

   Convencions de marcatge:
     data-label="…"     → etiqueta de la columna davant del valor
     .stack-head        → capçalera de la targeta (sense etiqueta, destacada)
     .stack-head-aside  → dada secundària a la dreta de la capçalera
     .stack-half        → mitja amplada, per aparellar dues dades curtes
     .stack-attach      → fila auxiliar que s'enganxa sota la targeta anterior */
@media (max-width: 767.98px) {
  /* La vora i el radi del contenidor doblaven la vora de cada targeta */
  .table-responsive:has(.table-stack) {
    border: none;
    border-radius: 0;
    overflow: visible;
  }

  .table-stack,
  .table-stack > tbody {
    display: block;
    width: 100%;
  }

  .table-stack > thead {
    display: none;
  }

  .table-stack > tbody > tr {
    display: flex;
    flex-wrap: wrap;
    margin-bottom: 0.7rem;
    border: 1px solid var(--clr-surface-border);
    border-radius: 0.6rem;
    overflow: hidden;
  }

  .table-stack > tbody > tr > td {
    display: flex;
    flex: 1 1 100%;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.45rem 0.85rem;
    text-align: right;
    overflow-wrap: break-word;
    border-bottom: 1px solid var(--clr-surface-border);
  }

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

  .table-stack > tbody > tr > td[data-label]::before {
    content: attr(data-label);
    flex: 0 0 auto;
    max-width: 45%;
    font-family: var(--font-display);
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    text-align: left;
    color: var(--clr-text-muted);
  }

  /* Amb targetes separades el ratllat alternat no aporta res i, a més, deixava
     files fosques i clares amb la mateixa vora. S'exclou la fila que parpelleja
     (row-highlight): el flaix s'anima sobre el TR i necessita cel·les
     transparents per veure's. Els colors semàntics de cada pàgina (vacances,
     baixa, incidència…) tenen més pes i continuen manant. */
  .table-stack > tbody > tr:not(.row-highlight):not(.row-highlight-persist) > td {
    background-color: var(--clr-surface-2) !important;
  }

  .table-stack > tbody > tr > td.stack-head,
  .table-stack > tbody > tr > td.stack-head-aside {
    font-family: var(--font-display);
    font-size: 0.95rem;
    font-weight: 700;
  }

  /* Els "order" fan que la capçalera de la targeta no depengui de l'ordre de
     les columnes a la taula: a fitxatges, per exemple, la columna "#" va abans
     que "Empleat", però qui identifica la fila és el nom i ha d'anar primer. */
  .table-stack > tbody > tr > td.stack-head {
    order: -2;
    flex: 1 1 auto;
    justify-content: flex-start;
    text-align: left;
  }

  .table-stack > tbody > tr > td.stack-head-aside {
    order: -1;
    flex: 0 1 auto;
    justify-content: flex-end;
    padding-left: 0;
    font-weight: 600;
    color: var(--clr-text-muted) !important;
  }

  .table-stack > tbody > tr > td.stack-half {
    flex: 1 1 50%;
  }

  /* Cel·les amb un formulari o botons: l'etiqueta va a sobre i el contingut
     ocupa tota l'amplada. Al costat de l'etiqueta hi quedava mitja línia
     escassa i els botons es partien pel mig ("Des / ar"). */
  .table-stack > tbody > tr > td.stack-block {
    flex-direction: column;
    align-items: stretch;
    gap: 0.3rem;
    text-align: left;
  }

  .table-stack > tbody > tr > td.stack-block::before {
    max-width: none;
  }

  .table-stack > tbody > tr > td.stack-half + .stack-half {
    border-left: 1px solid var(--clr-surface-border);
  }

  /* Botons d'acció: sense etiqueta i alineats a la dreta de la targeta */
  .table-stack > tbody > tr > td.stack-actions {
    justify-content: flex-end;
    flex-wrap: wrap;
    gap: 0.4rem;
  }

  /* Contingut en bloc dins d'una cel·la (un formulari, una llista de
     propostes…): ha d'anar en un sol contenidor perquè ocupi tot l'espai que
     queda a la dreta de l'etiqueta; si no, cada fill s'hi posaria al costat. */
  .table-stack > tbody > tr > td > form,
  .table-stack > tbody > tr > td > .stack-value {
    flex: 1 1 auto;
    min-width: 0;
  }

  /* Fila auxiliar de tota l'amplada (un formulari plegable, típicament): no és
     una targeta, s'enganxa sota l'anterior sense vora ni etiquetes. */
  .table-stack > tbody > tr.stack-attach {
    display: block;
    margin: -0.7rem 0 0.7rem;
    border: none;
    border-radius: 0;
    overflow: visible;
  }

  .table-stack > tbody > tr.stack-attach > td {
    display: block;
    padding: 0;
    border: none;
    text-align: left;
    background-color: transparent !important;
  }
}

/* ==== Taules d'etiqueta i valor (TH + TD per fila) en mòbil ====
   Cas de "Estat de la sincronització": en dues columnes estretes, l'etiqueta
   es partia en tres línies i el valor en unes quantes més. Sota 768px
   l'etiqueta passa a sobre del valor i tots dos ocupen l'amplada sencera. */
@media (max-width: 767.98px) {
  .table-keyvalue,
  .table-keyvalue > tbody,
  .table-keyvalue > tbody > tr,
  .table-keyvalue > tbody > tr > th,
  .table-keyvalue > tbody > tr > td {
    display: block;
    width: 100%;
  }

  .table-keyvalue > tbody > tr > th {
    padding: 0.6rem 0.25rem 0.1rem;
    border-bottom: none !important;
    background-color: transparent !important;
    font-size: 0.72rem;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--clr-text-muted) !important;
  }

  .table-keyvalue > tbody > tr > td {
    padding: 0 0.25rem 0.6rem;
  }
}

/* ==== Pestanyes de Configuració ====
   A diferència de la barra de navegació (sempre fosca), aquestes pestanyes
   viuen dins del contingut i han de seguir el tema (clar/fosc) com la resta
   de la pàgina. */
.settings-tabs {
  border-bottom: 1px solid var(--clr-surface-border);
  flex-wrap: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
}

.settings-tabs .nav-link {
  color: var(--clr-text-muted);
  font-weight: 600;
  font-size: 0.92rem;
  padding: 0.65rem 1rem;
  border: none;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  white-space: nowrap;
  background: transparent;
}

.settings-tabs .nav-link:hover {
  color: var(--clr-text);
}

.settings-tabs .nav-link.active {
  color: var(--clr-amber);
  border-bottom-color: var(--clr-amber);
  background: transparent;
}

/* Subpestanyes dins d'un grup (p.ex. "Empresa"): pastilles petites, per
   distingir-les visualment del primer nivell (settings-tabs, subratllat). */
.settings-subtabs {
  flex-wrap: wrap;
  gap: 0.4rem;
}

.settings-subtabs .nav-link {
  color: var(--clr-text-muted);
  font-weight: 600;
  font-size: 0.85rem;
  padding: 0.35rem 0.85rem;
  border: 1px solid var(--clr-surface-border);
  border-radius: 999px;
  background: transparent;
}

.settings-subtabs .nav-link:hover {
  color: var(--clr-text);
}

.settings-subtabs .nav-link.active {
  color: var(--clr-btn-text);
  background: var(--clr-amber);
  border-color: var(--clr-amber);
}

/* ==== Responsive Adjustments ==== */
@media (max-width: 992px) {
  body {
    padding: 0.5rem;
  }
  .card {
    padding: 1.25rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  .pulse-green, .pulse-orange, .pulse-purple, .card, .btn {
    animation: none !important;
    transition: none !important;
  }
}

/* Avís de fons durant una sincronització llarga (p.ex. Google Calendar):
   atenua tota la pàgina i mostra un missatge fix perquè l'usuari sàpiga
   que ha d'esperar sense que sembli que l'app s'ha penjat. */
.gcal-sync-overlay {
  position: fixed;
  inset: 0;
  z-index: 2000;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(2px);
}
.gcal-sync-overlay__box {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 1.25rem 1.75rem;
  background: var(--clr-surface);
  border: 1px solid var(--clr-surface-border);
  border-radius: 0.75rem;
  color: var(--clr-text);
  box-shadow: 0 0.5rem 1.5rem rgba(0, 0, 0, 0.35);
}
.gcal-sync-overlay__clock {
  width: 1.75rem;
  height: 1.75rem;
  animation: gcalSyncTick 1.4s linear infinite;
}
.gcal-sync-overlay__text {
  font-weight: 600;
}
@keyframes gcalSyncTick {
  0%, 100% { transform: rotate(-8deg); }
  50%      { transform: rotate(8deg); }
}
@media (prefers-reduced-motion: reduce) {
  .gcal-sync-overlay__clock {
    animation: none;
  }
}
