/* =========================================================================
   Theme tokens — the single source of truth for the application's look.
   Every rule below references these variables; never hard-code a colour,
   radius, shadow or font family elsewhere. To restyle the app, change a
   token here and it propagates everywhere.
   ========================================================================= */
:root {
  /* Brand / accent */
  --color-primary: #2563eb;
  --color-primary-hover: #1d4ed8;
  --color-primary-soft: #eff6ff;
  --color-link-on-dark: #93c5fd;
  --color-on-accent: #fff;

  /* Neutral surfaces */
  --color-bg: #f8fafc;
  --color-surface: #fff;
  --color-surface-alt: #f1f5f9;

  /* Dark surfaces (sidebar, result panel) */
  --color-dark: #0f172a;
  --color-dark-2: #1e293b;

  /* Borders */
  --color-border: #e2e8f0;
  --color-border-strong: #cbd5e1;
  --color-border-subtle: #f1f5f9;

  /* Text on light surfaces */
  --color-text: #1f2937;
  --color-text-muted: #475569;
  --color-text-subtle: #64748b;

  /* Text on dark surfaces */
  --color-on-dark: #e2e8f0;
  --color-on-dark-strong: #f8fafc;
  --color-on-dark-muted: #cbd5e1;
  --color-on-dark-faint: #94a3b8;
  --color-on-dark-chip-bg: rgba(148, 163, 184, 0.18);

  /* State: success */
  --color-success-bg: #ecfdf5;
  --color-success-border: #6ee7b7;
  --color-success-text: #065f46;
  --color-success-accent: #6ee7b7;

  /* State: warning */
  --color-warning-bg: #fffbeb;
  --color-warning-border: #fcd34d;
  --color-warning-text: #92400e;

  /* State: danger */
  --color-danger-bg: #fef2f2;
  --color-danger-border: #fecaca;
  --color-danger-text: #991b1b;

  /* Accent chips */
  --color-accent-bg: #eef2ff;
  --color-accent-border: #c7d2fe;
  --color-accent-text: #3730a3;

  /* Radii */
  --radius-sm: 6px;
  --radius: 8px;
  --radius-lg: 12px;
  --radius-pill: 999px;

  /* Shadows */
  --shadow-card: 0 10px 30px rgba(15, 23, 42, 0.06);
  --shadow-panel: 0 10px 30px rgba(15, 23, 42, 0.12);
  --shadow-pop: 0 8px 24px rgba(15, 23, 42, 0.1);

  /* Typography */
  --font-sans: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
}

body {
  font-family: var(--font-sans);
  color: var(--color-text);
  background: var(--color-bg);
  display: flex;
  min-height: 100vh;
}

/* --- Centered layout (login) --- */
body.centered {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2rem;
}

.card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: 2rem;
  width: 100%;
  max-width: 420px;
  box-shadow: var(--shadow-card);
}

.card h1 {
  margin: 0 0 0.25rem;
  font-size: 1.5rem;
}

.login .btn {
  display: block;
  margin-top: 1.25rem;
  text-align: center;
  text-decoration: none;
}

.login-error {
  margin: 1rem 0 0;
  padding: 0.6rem 0.75rem;
  background: var(--color-danger-bg);
  border: 1px solid var(--color-danger-border);
  border-radius: var(--radius);
  color: var(--color-danger-text);
  font-size: 0.9rem;
}

/* --- Sidebar layout --- */
.sidebar {
  width: 260px;
  background: var(--color-dark);
  color: var(--color-on-dark);
  padding: 1.5rem 1rem;
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}

.sidebar-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}

.sidebar h1 {
  margin: 0;
  font-size: 1.4rem;
  letter-spacing: 0.04em;
}

.menu-toggle {
  display: none;
  background: transparent;
  border: 0;
  width: 44px;
  height: 44px;
  padding: 10px;
  cursor: pointer;
  flex-direction: column;
  justify-content: space-between;
}

.menu-toggle span {
  display: block;
  width: 100%;
  height: 3px;
  background: var(--color-on-dark);
  border-radius: var(--radius-pill);
}

.sidebar nav {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  flex: 1;
}

.sidebar nav a {
  color: var(--color-on-dark-muted);
  text-decoration: none;
  padding: 0.55rem 0.75rem;
  border-radius: var(--radius-sm);
}

.sidebar nav a:hover {
  background: var(--color-dark-2);
  color: var(--color-on-accent);
}

.sidebar nav a.active {
  background: var(--color-primary);
  color: var(--color-on-accent);
}

.sidebar .user {
  border-top: 1px solid var(--color-dark-2);
  padding-top: 0.75rem;
  font-size: 0.85rem;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.user-name {
  font-weight: 600;
  word-break: break-word;
}

.user-dni {
  color: var(--color-on-dark-faint);
  font-size: 0.75rem;
}

.sidebar .logout {
  color: var(--color-link-on-dark);
  text-decoration: none;
  font-size: 0.8rem;
}

.sidebar .logout:hover {
  text-decoration: underline;
}

/* Build info, filled by app.js from /version. Faint on purpose: it is there for
   support, not for daily reading. It shows on the dark sidebar and on the light
   login card, so only the colour changes with the ground it sits on. */
.versions {
  font-size: 0.7rem;
}

.sidebar .versions {
  color: var(--color-on-dark-faint);
}

.card .versions {
  color: var(--color-text-subtle);
  margin-top: 1rem;
  text-align: center;
}

main {
  flex: 1;
  padding: 2rem 2.5rem;
  min-width: 0;
}

main h2 {
  margin-top: 0;
}

.hint {
  color: var(--color-text-muted);
  font-size: 0.9rem;
  max-width: 680px;
  line-height: 1.5;
}

/* --- Filters form --- */
.filters {
  display: flex;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin: 1.25rem 0;
}

.field {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}

.field label {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--color-text-muted);
}

.field input,
.field select {
  padding: 0.5rem 0.6rem;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius);
  font-size: 0.95rem;
  background: var(--color-surface);
  color: var(--color-text);
}

.btn {
  display: inline-block;
  background: var(--color-primary);
  color: var(--color-on-accent);
  border: 0;
  padding: 0.6rem 1.1rem;
  border-radius: var(--radius);
  font-size: 0.95rem;
  font-weight: 600;
  cursor: pointer;
}

.btn:hover {
  background: var(--color-primary-hover);
}

.btn.small {
  padding: 0.35rem 0.6rem;
  font-size: 0.8rem;
}

.btn.danger {
  background: var(--color-danger-bg);
  color: var(--color-danger-text);
  border: 1px solid var(--color-danger-border);
}

.btn.danger:hover {
  background: var(--color-danger-border);
}

.btn.success {
  background: var(--color-success-bg);
  color: var(--color-success-text);
  border: 1px solid var(--color-success-border);
}

.btn.success:hover {
  background: var(--color-success-border);
}

/* Approvals: one card per request (no wide table, so no horizontal scroll). */
.request-cards {
  list-style: none;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  margin: 0;
}

.request-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: 0.9rem 1.1rem;
}

.rc-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
}

.rc-emp {
  display: flex;
  flex-direction: column;
  line-height: 1.3;
}

.rc-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 1rem;
  margin: 0.5rem 0 0.75rem;
  font-size: 0.9rem;
  color: var(--color-text-muted);
}

.rc-desc {
  font-style: italic;
}

.rc-actions {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
}

.reason-input {
  flex: 1 1 200px;
  min-width: 0;
  padding: 0.5rem 0.6rem;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius);
  font-size: 0.9rem;
  background: var(--color-surface);
  color: var(--color-text);
}

.rc-buttons {
  display: flex;
  gap: 0.4rem;
}

.rc-status {
  display: flex;
  align-items: center;
  gap: 0.6rem 0.9rem;
  flex-wrap: wrap;
  font-size: 0.9rem;
  color: var(--color-text-muted);
}

/* --- Employee type-ahead picker --- */
.user-picker {
  position: relative;
}

.user-picker input[type="search"] {
  min-width: 260px;
}

.user-results {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 20;
  background: var(--color-surface);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius);
  margin-top: 0.2rem;
  box-shadow: var(--shadow-pop);
  overflow: hidden;
}

.user-results:empty {
  display: none;
}

.results-list {
  list-style: none;
  margin: 0;
  padding: 0;
  max-height: 260px;
  overflow-y: auto;
}

.user-result {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  width: 100%;
  text-align: left;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--color-border-subtle);
  padding: 0.5rem 0.75rem;
  cursor: pointer;
  font-size: 0.9rem;
}

.user-result:hover {
  background: var(--color-primary-soft);
}

.user-result .r-dni {
  color: var(--color-text-subtle);
  font-size: 0.8rem;
  font-variant-numeric: tabular-nums;
}

.no-results {
  padding: 0.6rem 0.75rem;
  color: var(--color-text-subtle);
  font-size: 0.85rem;
}

.htmx-indicator {
  opacity: 0;
  color: var(--color-text-muted);
  font-size: 0.85rem;
  transition: opacity 0.2s;
}

.htmx-request .htmx-indicator,
.htmx-indicator.htmx-request {
  opacity: 1;
}

/* --- Results --- */
.summary {
  margin: 0.5rem 0 1rem;
  font-size: 0.95rem;
  color: var(--color-text-muted);
}

/* Result panel shown above the shifts table (employee + range + total) */
.result-panel {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem 1.5rem;
  background: linear-gradient(135deg, var(--color-dark-2), var(--color-dark));
  color: var(--color-on-dark);
  border-radius: var(--radius-lg);
  padding: 1.1rem 1.4rem;
  margin: 0.75rem 0 1.25rem;
  box-shadow: var(--shadow-panel);
  max-width: 900px;
}

.rp-identity {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  min-width: 0;
}

.rp-avatar {
  flex: none;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--color-primary);
  color: var(--color-on-accent);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.2rem;
  font-weight: 700;
}

.rp-who h3 {
  margin: 0;
  font-size: 1.15rem;
  color: var(--color-on-accent);
  word-break: break-word;
}

.rp-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-top: 0.35rem;
}

.rp-chip {
  font-size: 0.75rem;
  background: var(--color-on-dark-chip-bg);
  color: var(--color-on-dark-muted);
  padding: 0.12rem 0.5rem;
  border-radius: var(--radius-pill);
  white-space: nowrap;
}

.rp-stats {
  display: flex;
  gap: 1.75rem;
}

.rp-stat {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}

.rp-label {
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-on-dark-faint);
}

.rp-value {
  font-size: 1rem;
  font-weight: 600;
  color: var(--color-on-dark-strong);
  font-variant-numeric: tabular-nums;
}

.rp-total .rp-value {
  color: var(--color-success-accent);
  font-size: 1.15rem;
}

@media (max-width: 560px) {
  .rp-stats {
    gap: 1.25rem;
  }
}

.table-wrap {
  overflow-x: auto;
  max-width: 900px;
}

/* A data-dense table gets a cap of its own: 900px is the width a five-column
   table wants, and squeezing Marcaciones' seven columns into it leaves every
   one of them cramped. Same escape hatch as `.wp-sub .table-wrap` below. */
.table-wrap.wide {
  max-width: 1200px;
}

table.shifts {
  border-collapse: collapse;
  width: 100%;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  overflow: hidden;
}

table.shifts th,
table.shifts td {
  text-align: left;
  padding: 0.6rem 0.9rem;
  border-bottom: 1px solid var(--color-border);
  font-size: 0.9rem;
}

table.shifts th {
  background: var(--color-surface-alt);
  color: var(--color-text-muted);
  font-weight: 600;
}

th.sortable {
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}

th.sortable:hover {
  background: var(--color-border);
  color: var(--color-text);
}

th.sorted {
  color: var(--color-primary);
}

.sort-ind {
  font-size: 0.7rem;
}

.chip {
  display: inline-block;
  background: var(--color-accent-bg);
  border: 1px solid var(--color-accent-border);
  color: var(--color-accent-text);
  font-size: 0.72rem;
  padding: 0.05rem 0.4rem;
  border-radius: var(--radius-pill);
  margin: 0.1rem 0.15rem 0.1rem 0;
  white-space: nowrap;
}

table.shifts tr:last-child td {
  border-bottom: 0;
}

/* Registros: the justification badges are the one elastic column. Uncapped, a
   long type name -- or two on the same day -- takes its width out of the date
   column, which then breaks a date across two lines. Capped, the badges stack
   inside their own cell and every other column keeps its natural width. */
.shifts .justif-col {
  width: 9rem;
}

/* Marcaciones has the same one elastic column, in the shape of the area chips:
   one per area, so a person in three areas would otherwise widen the column for
   the whole table. Capped, the chips stack inside their own cell. */
.shifts .areas-col {
  width: 12rem;
}

/* And a date or a clock is never the column that gives: below the width the
   table needs, .table-wrap scrolls rather than breaking one over two lines. */
.shifts .nowrap-cell {
  white-space: nowrap;
}

/* --- Per-day rows + drill-down --- */
.toggle-col,
.toggle-cell {
  width: 2.2rem;
  text-align: center;
}

.day-toggle {
  background: transparent;
  border: 0;
  cursor: pointer;
  font-size: 0.9rem;
  color: var(--color-primary);
  line-height: 1;
  padding: 0.15rem 0.3rem;
}

.day-toggle:hover {
  color: var(--color-primary-hover);
}

.day-row td {
  font-weight: 500;
}

/* A day in the range with no scans: shown but visually receded. */
.day-row.empty-day td {
  color: var(--color-text-subtle);
  font-weight: 400;
  background: var(--color-surface-alt);
}

.day-detail > td {
  background: var(--color-bg);
  padding: 0.4rem 0.9rem 0.8rem;
}

table.shifts.inner {
  border: 1px solid var(--color-border);
  margin: 0.25rem 0;
}

table.shifts.inner th {
  background: var(--color-surface-alt);
  font-weight: 600;
}

.badge {
  display: inline-block;
  font-size: 0.7rem;
  padding: 0.1rem 0.4rem;
  border-radius: var(--radius-pill);
  margin-left: 0.35rem;
}

.badge.open {
  background: var(--color-warning-bg);
  border: 1px solid var(--color-warning-border);
  color: var(--color-warning-text);
}

/* Justification chips in Registros: individual (green) vs general (indigo). */
.badge.justified {
  background: var(--color-success-bg);
  border: 1px solid var(--color-success-border);
  color: var(--color-success-text);
  margin-left: 0;
  margin-right: 0.25rem;
}

.badge.justified.general {
  background: var(--color-accent-bg);
  border-color: var(--color-accent-border);
  color: var(--color-accent-text);
}

/* Justification-request status: pending (amber), approved (green), rejected (red). */
.badge.status-pending {
  background: var(--color-warning-bg);
  border: 1px solid var(--color-warning-border);
  color: var(--color-warning-text);
  margin-left: 0;
}

.badge.status-approved {
  background: var(--color-success-bg);
  border: 1px solid var(--color-success-border);
  color: var(--color-success-text);
  margin-left: 0;
}

.badge.status-disapproved {
  background: var(--color-danger-bg);
  border: 1px solid var(--color-danger-border);
  color: var(--color-danger-text);
  margin-left: 0;
}

code {
  background: var(--color-border);
  padding: 0.1rem 0.35rem;
  border-radius: var(--radius-sm);
  font-size: 0.85em;
  white-space: nowrap;
}

.alert {
  max-width: 680px;
  padding: 0.9rem 1.1rem;
  border-radius: var(--radius);
  font-size: 0.9rem;
  background: var(--color-danger-bg);
  border: 1px solid var(--color-danger-border);
  color: var(--color-danger-text);
}

.alert.forbidden {
  background: var(--color-warning-bg);
  border-color: var(--color-warning-border);
  color: var(--color-warning-text);
}

.alert.empty {
  background: var(--color-bg);
  border-color: var(--color-border);
  color: var(--color-text-muted);
  margin-top: 0.75rem;
}

.alert.ok {
  background: var(--color-success-bg);
  border-color: var(--color-success-border);
  color: var(--color-success-text);
  margin-top: 0.75rem;
}

/* --- Section card --- */
/* The one container a screen puts its content in: a titled card on the page
   background. Every screen uses it, at the same width as .table-wrap so a table
   never has to scroll inside its own card. */
.section-card {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  max-width: 900px;
  margin: 0 0 1.5rem;
  padding: 1.25rem 1.5rem;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
}

/* The gap is the card's rhythm, so its children bring no margins of their own --
   otherwise the last one doubles up with the padding below it. Spelled out per
   construct rather than as `> *`, so the reset outranks each construct's own
   margin wherever that rule happens to sit in this file. */
.section-card > h3,
.section-card > h4,
.section-card > dl,
.section-card > .hint,
.section-card > .filters,
.section-card > .stat-grid,
.section-card > .alert {
  margin: 0;
}

/* A heading and the hint under it read as one unit, tighter than the rhythm. */
.section-card > h3 + .hint {
  margin-top: -0.75rem;
}

/* htmx swaps its results into these; until it does, an empty one must not open a
   gap. Out of flow entirely, so the gap around it goes too. */
.section-card > div:empty {
  display: none;
}

/* Inside a card the alert is already bounded by the card. */
.section-card .alert {
  max-width: none;
}

dl.profile {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 0.75rem 1.5rem;
  margin: 0;
}

dl.profile > div {
  min-width: 0;
}

dl.profile dt {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-text-subtle);
  margin-bottom: 0.2rem;
}

dl.profile dd {
  margin: 0;
  color: var(--color-text);
  word-break: break-word;
}

/* Trabajo: the running head-count pinned to a heading in the área tree. */
.wp-count {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--color-text-subtle);
  background: var(--color-surface-alt);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  padding: 0.05rem 0.5rem;
  font-variant-numeric: tabular-nums;
}

/* --- Stat cards --- */
/* A row of big-number tiles. Shared: the day's three conditions on Trabajo, the
   per-type justification counts on Inicio and Registros. The --in / --done /
   --absent modifiers colour the day conditions; a plain .stat-card is neutral. */
.stats-title {
  margin: 1.25rem 0 0;
  font-size: 1.05rem;
  color: var(--color-text);
}

.stat-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin: 0.75rem 0 1.5rem;
}

.stat-card {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  min-width: 130px;
  padding: 0.7rem 1.1rem;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-left: 4px solid var(--color-border-strong);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
}

.stat-num {
  font-size: 1.6rem;
  font-weight: 700;
  line-height: 1;
  color: var(--color-text);
  font-variant-numeric: tabular-nums;
}

.stat-label {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-text-subtle);
}

.stat-card--in {
  border-left-color: var(--color-primary);
}

.stat-card--in .stat-num {
  color: var(--color-primary);
}

.stat-card--done {
  border-left-color: var(--color-success-border);
}

.stat-card--done .stat-num {
  color: var(--color-success-text);
}

.stat-card--absent {
  border-left-color: var(--color-danger-border);
}

.stat-card--absent .stat-num {
  color: var(--color-danger-text);
}

/* --- Justification types screen --- */
/* A .section-card whose "add" form is a full-bleed tinted band, so the card
   lays out its own padding row by row instead of carrying it as a block. */
.type-section {
  gap: 0;
  padding: 0;
  /* Keeps the tinted form strip inside the rounded corners. */
  overflow: hidden;
}

.type-section > h3 {
  margin: 0;
  padding: 1.15rem 1.5rem 0;
}

.type-section > h3 + .hint {
  margin: 0.4rem 0 0;
  padding: 0 1.5rem;
}

/* The add form: a tinted band between the heading and the list it feeds, so it
   reads as "what you can add here" rather than as a filter over the list. */
.type-form {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.75rem;
  margin: 1.15rem 0 0;
  padding: 0.9rem 1.5rem;
  background: var(--color-surface-alt);
  border-top: 1px solid var(--color-border);
  border-bottom: 1px solid var(--color-border);
}

/* The name shares the leftover width with the description, which gets twice the
   pull -- it is the field that actually needs the room. */
.type-form .field {
  flex: 1 1 11rem;
  min-width: 0;
}

.type-form .field-wide {
  flex: 2 1 14rem;
}

.type-form .field input {
  width: 100%;
}

.type-form .btn {
  flex: none;
}

.type-body {
  padding: 1.25rem 1.5rem;
}

/* The card's padding already sets the message off from the form above it. */
.type-body .alert {
  margin-top: 0;
}

/* Only when a message is actually showing does the list need pushing down --
   the message div sits there empty the rest of the time. */
.type-body > div:not(:empty) + div {
  margin-top: 0.75rem;
}

/* --- Areas page --- */
/* Org hierarchy — a collapsible tree of areas. Each node is a native
   <details>, so it expands/collapses with no JS. */
.org-tree {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  margin-top: 1rem;
  max-width: 900px;
}

.area-node {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
}

/* Nested subareas render inside .area-children with a lighter surface so the
   nesting reads without borrowing the top card's weight. */
.area-node .area-node {
  background: var(--color-surface-alt);
}

.an-head {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.7rem 0.9rem;
  cursor: pointer;
  list-style: none;
  border-radius: var(--radius-lg);
}

/* Hide the default disclosure triangle across engines. */
.an-head::-webkit-details-marker {
  display: none;
}

.an-head:hover {
  background: var(--color-surface-alt);
}

.area-node .area-node .an-head:hover {
  background: var(--color-border-subtle);
}

.an-caret {
  flex: none;
  width: 0;
  height: 0;
  border-left: 6px solid var(--color-text-subtle);
  border-top: 5px solid transparent;
  border-bottom: 5px solid transparent;
  transition: transform 0.15s ease;
}

.area-node[open] > .an-head .an-caret {
  transform: rotate(90deg);
}

.an-name {
  font-size: 1rem;
  font-weight: 600;
  color: var(--color-text);
  margin-right: auto;
}

.an-counts {
  display: flex;
  gap: 0.35rem;
  flex-wrap: wrap;
  justify-content: flex-end;
}

.an-badge {
  font-size: 0.72rem;
  padding: 0.1rem 0.5rem;
  border-radius: var(--radius-pill);
  white-space: nowrap;
  background: var(--color-surface-alt);
  border: 1px solid var(--color-border);
  color: var(--color-text-muted);
}

.an-badge.subtree {
  background: var(--color-accent-bg);
  border-color: var(--color-accent-border);
  color: var(--color-accent-text);
}

.an-body {
  padding: 0 0.9rem 0.9rem;
}

.an-empty {
  margin: 0.25rem 0 0;
}

/* Direct members as compact chips in a responsive grid. */
.member-grid {
  list-style: none;
  margin: 0.25rem 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 0.4rem;
}

.member-chip {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.35rem 0.5rem;
  background: var(--color-surface);
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius);
}

.mc-avatar {
  flex: none;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--color-primary);
  color: var(--color-on-accent);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.85rem;
  font-weight: 700;
}

.mc-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.mc-name {
  font-size: 0.85rem;
  color: var(--color-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.mc-dni {
  font-size: 0.72rem;
  color: var(--color-text-subtle);
  font-variant-numeric: tabular-nums;
}

/* --- Trabajo, área tree: extends .area-node / .area-children above (it must
   come after those rules to override .an-badge). Every node starts collapsed;
   its badges are the subtree totals, the tables inside are its direct members,
   and subáreas nest below them. --- */

/* Client-side person / área search. */
.wp-searchbar {
  margin-top: -0.5rem;
}

.wp-search-count {
  align-self: center;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--color-text-muted);
  font-variant-numeric: tabular-nums;
}

.wp-search-count--none {
  color: var(--color-danger-text);
}

/* While filtering, the área badges still report the whole day, so the tree says
   plainly that it is showing a subset. */
.wp-filtering .wp-tree {
  padding-left: 0.6rem;
  border-left: 3px solid var(--color-primary);
}

/* An open node splits in two, and the two must not read alike:
   - .wp-people  — the área's OWN people: a recessed tinted tray.
   - .wp-subareas — its subáreas: cards standing on the parent's surface.
   So the rule the eye learns is "tinted tray = gente, tarjeta = área". */
.wp-people {
  margin: 0.25rem 0 0;
  padding: 0.1rem 0.85rem 0.85rem;
  background: var(--color-surface-alt);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
}

.wp-subareas {
  margin: 1rem 0 0;
}

/* The search (static/js/workplace.js) hides parts of the tree with the [hidden]
   attribute. Spelled out here so a future `display:` on any of these cannot
   silently outrank the UA rule and break the filter. */
.wp-area[hidden],
.wp-people[hidden],
.wp-subareas[hidden],
.wp-sub[hidden] {
  display: none;
}

/* Which half you are looking at, said once at the top of each. */
.wp-part-label {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0.85rem 0 0.6rem;
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-text-subtle);
}

/* A subárea keeps the card surface at every depth, so it never dissolves into
   the tray above it — this overrides the Áreas tree's tinted nesting, whose
   hover shade would now be too dark against a card. */
.wp-area .area-node {
  background: var(--color-surface);
  border-color: var(--color-border-strong);
}

.wp-area .area-node .an-head:hover {
  background: var(--color-surface-alt);
}

/* Wider than the Áreas tree: these nodes carry tables, not member chips. */
.wp-area .area-children {
  margin: 0;
  padding-left: 0.75rem;
  gap: 0.5rem;
}

/* The subáreas badge counts structure, not people, so it takes the accent
   palette — clearly apart from the three state colours next to it. */
.wp-badge--sub {
  background: var(--color-accent-bg);
  border-color: var(--color-accent-border);
  color: var(--color-accent-text);
}

/* State-coloured count badges in the área header, matching the stat cards. */
.wp-badge--in {
  background: var(--color-primary-soft);
  border-color: var(--color-primary);
  color: var(--color-primary);
}

.wp-badge--done {
  background: var(--color-success-bg);
  border-color: var(--color-success-border);
  color: var(--color-success-text);
}

.wp-badge--absent {
  background: var(--color-danger-bg);
  border-color: var(--color-danger-border);
  color: var(--color-danger-text);
}

/* The three conditions inside the people tray, each on a state-coloured rail. */
.wp-sub {
  margin-top: 0.75rem;
  padding-left: 0.7rem;
  border-left: 3px solid var(--color-border-strong);
}

.wp-sub-title {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0 0 0.4rem;
  font-size: 0.8rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-text-muted);
}

.wp-sub-empty {
  margin: 0;
}

.wp-sub--in {
  border-left-color: var(--color-primary);
}

.wp-sub--in .wp-sub-title {
  color: var(--color-primary);
}

.wp-sub--done {
  border-left-color: var(--color-success-border);
}

.wp-sub--done .wp-sub-title {
  color: var(--color-success-text);
}

.wp-sub--absent {
  border-left-color: var(--color-danger-border);
}

.wp-sub--absent .wp-sub-title {
  color: var(--color-danger-text);
}

/* Inside the tray the tables carry the node's width rather than the standalone
   .table-wrap cap. `table.shifts` already brings its own card surface and
   border, which is what lifts it off the tray's tint. */
.wp-sub .table-wrap {
  max-width: none;
}

/* A node deep in the tree has little room left, so its tables tighten up. */
.wp-area .wp-area .shifts th,
.wp-area .wp-area .shifts td {
  padding: 0.35rem 0.5rem;
}

/* Subareas: indented under the parent with a guide rail, recursively. */
.area-children {
  margin: 0.75rem 0 0 0.4rem;
  padding-left: 0.8rem;
  border-left: 2px solid var(--color-border-strong);
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

@media (max-width: 768px) {
  body {
    flex-direction: column;
    min-height: 100vh;
  }

  .sidebar {
    width: 100%;
    padding: 0.6rem 1rem;
    gap: 0.5rem;
    position: sticky;
    top: 0;
    z-index: 10;
  }

  .sidebar h1 {
    font-size: 1.15rem;
  }

  .menu-toggle {
    display: flex;
  }

  .sidebar nav,
  .sidebar .user {
    display: none;
  }

  .sidebar.open nav,
  .sidebar.open .user {
    display: flex;
    flex-direction: column;
  }

  main {
    padding: 1rem;
  }
}
