/* ──────────────────────────────────────────────────────────────────────
   Layout principal de la Oficina Virtual.
   Grid: sidebar fijo (240px) + main (topbar sticky + content scrolleable).
   Mobile (<768px): sidebar absoluto tipo drawer. Las reglas del drawer
   propio del sidebar viven en sidebar.css (orden de carga).
   ────────────────────────────────────────────────────────────────────── */
body.ov-body-lock { overflow: hidden; }

/* Cuando el drawer mobile está abierto, evitamos el scroll del body para que
   el usuario no pueda "saltar" la página por detrás del backdrop. Se hace por
   CSS en lugar de JS para no agregar interop — :has() está soportado en
   Safari/Chrome/Firefox modernos (>= 2023). */
@media (max-width: 768px) {
    html:has(.ov-shell--drawer-open),
    body:has(.ov-shell--drawer-open) {
        overflow: hidden;
    }
}

.ov-shell {
    display: grid;
    grid-template-columns: var(--ov-sidebar-width) 1fr;
    min-height: 100vh;
    font-family: var(--ov-font);
    background:
        radial-gradient(circle at 100% 0%, rgba(20, 184, 166, 0.07), transparent 38rem),
        radial-gradient(circle at 0% 100%, rgba(99, 102, 241, 0.04), transparent 32rem),
        linear-gradient(180deg, #f7fafc 0%, #eef3f6 100%);
    color: var(--ov-ink-800);
    transition: grid-template-columns var(--ov-transition);
}
.ov-shell--collapsed {
    grid-template-columns: var(--ov-sidebar-width-collapsed) 1fr;
}

.ov-shell__main {
    display: flex;
    flex-direction: column;
    min-width: 0;           /* previene overflow de grid children */
    min-height: 100vh;
}

.ov-content {
    flex: 1;
    padding: 30px 32px 40px;
    max-width: var(--ov-max-content-width);
    width: 100%;
    margin: 0 auto;
    box-sizing: border-box;
}

.ov-shell-loading {
    min-height: 100vh;
    background: #f6fafb;
}

/* Error boundary fallback */
.ov-error-fallback {
    max-width: 500px;
    margin: 80px auto;
    padding: 32px;
    text-align: center;
    background: white;
    border-radius: var(--ov-radius-md);
    border: 1px solid var(--ov-ink-200);
    box-shadow: var(--ov-shadow-sm);
}
.ov-error-fallback h3 {
    margin: 0 0 12px;
    color: var(--ov-ink-900);
    font-size: 18px;
}
.ov-error-fallback p {
    color: var(--ov-ink-500);
    margin-bottom: 20px;
}

/* ── Drawer sidebar en mobile (<768px) ───────────────────────────────── */
/* Por default, el botón hamburguesa y el backdrop están ocultos. En mobile
   el sidebar se convierte en drawer: sale del flujo, posicionado fixed, y se
   muestra solo cuando ov-shell--drawer-open está en el shell. El backdrop
   tapa el resto del shell para enfatizar el focus. */
.ov-mobile-menu-btn {
    display: none;
    position: fixed;
    top: 14px;
    left: 12px;
    z-index: calc(var(--ov-z-topbar) + 10);
    width: 40px;
    height: 40px;
    border-radius: var(--ov-radius-md);
    background: white;
    border: 1px solid var(--ov-border);
    color: var(--ov-ink-800);
    cursor: pointer;
    box-shadow: var(--ov-shadow-sm);
    align-items: center;
    justify-content: center;
    transition: background var(--ov-transition), color var(--ov-transition), border-color var(--ov-transition);
    -webkit-tap-highlight-color: transparent;
}

/* Cuando el drawer está abierto, el botón flota sobre el sidebar oscuro —
   le damos un look acorde para que no parezca un cuadrado blanco perdido. */
.ov-shell--drawer-open .ov-mobile-menu-btn {
    background: rgba(15, 23, 42, 0.6);
    color: white;
    border-color: rgba(255, 255, 255, 0.15);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
}

.ov-mobile-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(15, 23, 42, 0.42);
    backdrop-filter: blur(2px);
    z-index: calc(var(--ov-z-topbar) + 5);
}

@media (max-width: 768px) {
    .ov-shell {
        grid-template-columns: 1fr;           /* el sidebar deja de ocupar grid */
    }
    .ov-shell--collapsed {
        grid-template-columns: 1fr;
    }

    /* Las reglas mobile del .ov-sidebar (position: fixed, transform, etc.) viven
       en sidebar.css para ganar por orden de carga sobre el position: sticky default. */

    .ov-mobile-menu-btn { display: inline-flex; }

    .ov-content { padding: 16px; }
}

/* ── Page header (hero chico por página) ───────────────────────────── */
.ov-page-hero {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 18px;
    margin-bottom: 24px;
    flex-wrap: wrap;
}
.ov-page-title {
    margin: 0;
    font-size: 28px;
    font-weight: 800;
    color: var(--ov-ink-950);
    line-height: 1.15;
    letter-spacing: -0.02em;
    font-family: 'Sora', var(--ov-font);
}
.ov-page-sub {
    margin: 8px 0 0;
    font-size: 14px;
    color: var(--ov-ink-500);
    line-height: 1.5;
}
.ov-page-hero__actions { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
