﻿@tailwind base;
@tailwind components;
@tailwind utilities;

/* Fuente de respaldo con métricas ajustadas para evitar el salto de layout
   (especialmente notorio en los tamaños grandes, como text-display de 72px)
   mientras carga Gilroy. */
@font-face {
    font-family: "Gilroy Fallback";
    src: local("Arial");
    size-adjust: 97%;
    ascent-override: 94%;
    descent-override: 24%;
    line-gap-override: 0%;
}

.UIScroll {
    @apply [&::-webkit-scrollbar]:w-2 [&::-webkit-scrollbar-track]:rounded-full [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:bg-ghost;
}

.input {
    @apply appearance-none border border-zinc-200 bg-zinc-50 transition-all focus:border-current-500 focus:bg-white focus:outline-none focus:ring-4 focus:ring-current-500/10 dark:border-zinc-800 dark:bg-zinc-900 dark:text-zinc-200 dark:placeholder-zinc-500 dark:focus:bg-zinc-950;
}

.textbox {
    @apply input block w-full rounded-xl p-3 text-sm text-zinc-900 dark:text-white;
}

.textbox-premium {
    @apply textbox rounded-2xl p-4 shadow-sm;
}

.selection-card {
    @apply inline-flex w-full cursor-pointer items-center justify-between rounded-2xl border border-line bg-surface p-5 text-body text-ink-2 transition-colors hover:border-line-strong hover:bg-surface-alt peer-checked:border-ink peer-checked:bg-ink/5 peer-checked:text-ink;
}

.slider-premium {
    @apply w-full cursor-pointer appearance-none bg-transparent accent-ink transition-colors;
}

    .slider-premium::-webkit-slider-runnable-track {
        @apply h-1.5 w-full appearance-none rounded-sm bg-track;
    }

    .slider-premium::-moz-range-track {
        @apply h-1.5 w-full appearance-none rounded-sm bg-track border-none;
    }

    .slider-premium::-webkit-slider-thumb {
        @apply -mt-[5px] h-4 w-4 appearance-none rounded-full border-2 border-solid border-ink bg-surface transition-transform;
    }

    .slider-premium::-moz-range-thumb {
        @apply h-4 w-4 appearance-none rounded-full border-2 border-solid border-ink bg-surface transition-transform;
    }

.label-light {
    @apply text-ink-2;
}

.label-title {
    @apply text-ink;
}

@keyframes fade-in {
    from {
        opacity: 0;
        transform: translateY(-10px);
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}

@keyframes fadeIn {
    from {
        opacity: 0;
        transform: scale(0.95);
    }

    to {
        opacity: 1;
        transform: scale(1);
    }
}

@keyframes backdropFadeIn {
    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

@keyframes spin {
    to {
        transform: rotate(360deg);
    }
}

.animate-fade-in {
    animation: fade-in 0.3s ease-in-out;
}

.modal-appear {
    animation: fadeIn 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}

.backdrop-appear {
    animation: backdropFadeIn 0.2s ease-out;
}

.spinner {
    animation: spin 1s linear infinite;
}

.loader-simple {
    width: 15px;
    height: 15px;
    border: 2px solid currentColor;
    border-bottom-color: transparent;
    border-radius: 50%;
    display: inline-block;
    box-sizing: border-box;
    animation: rotation-simple 0.75s linear infinite;
    vertical-align: middle;
}

@keyframes rotation-simple {
    0% {
        transform: rotate(0deg);
    }

    100% {
        transform: rotate(360deg);
    }
}

@media (hover: none) and (pointer: coarse) {

    /* Estilos para la barra de desplazamiento bajo la clase HiddenScroll */
    .UIScroll::-webkit-scrollbar {
        width: 0px !important;
    }
}

:root {
    /* Los tokens se guardan como CANALES RGB sueltos ("R G B"), no como hex.
       Es la única forma de que Tailwind v3 pueda inyectar alfa: el config los
       consume como rgb(var(--token) / <alpha-value>), y así funcionan tanto
       `bg-current-800` como `bg-current-800/40`. Si guardas un hex aquí, el
       modificador de opacidad se descarta en silencio.
       Para usar un token en CSS suelto hay que envolverlo: rgb(var(--gim-ink)). */
    /* Neutros */
    --gim-canvas: 230 230 230; /* #E6E6E6 */
    --gim-shell: 247 247 247; /* #F7F7F7 */
    --gim-surface: 255 255 255; /* #FFFFFF */
    --gim-surface-alt: 250 250 250; /* #FAFAFA */
    --gim-ink: 10 10 10; /* #0A0A0A */
    --gim-ink-2: 92 92 92; /* #5C5C5C */
    --gim-muted: 154 154 154; /* #9A9A9A */
    --gim-line: 236 236 236; /* #ECECEC */
    --gim-line-strong: 221 221 221; /* #DDDDDD */
    --gim-track: 239 239 239; /* #EFEFEF */
    --gim-ghost: 214 214 214; /* #D6D6D6 */
    /* Semánticos (§2.3). Los pasos 50/100/700 salen de mezclar el 500 en oklab
       —8%, 16% sobre blanco y 82% sobre negro, según §13.1— pero se escriben
       resueltos porque color-mix() devuelve un color, no canales. Si cambias un
       500, recalcula sus tres derivados. */
    --gim-danger-50: 255 241 240;
    --gim-danger-100: 255 228 226;
    --gim-danger-500: 229 72 77; /* #E5484D */
    --gim-danger-700: 176 53 57;
    --gim-warn-50: 255 248 240;
    --gim-warn-100: 255 241 225;
    --gim-warn-500: 245 165 36; /* #F5A524 */
    --gim-warn-700: 188 126 25;
    /* Rampa "current" explícita (§13.2) — valores de marca del proyecto, no cambiar.
       La alternativa por color-mix de §13.1 no es viable aquí: devolvería colores
       en vez de canales y rompería los modificadores de opacidad que usa Login. */
    --gim-current: 72 99 114; /* #486372 */
    --gim-current-50: 243 247 248; /* #f3f7f8 */
    --gim-current-100: 225 233 236; /* #e1e9ec */
    --gim-current-200: 198 214 219; /* #c6d6db */
    --gim-current-300: 158 184 194; /* #9eb8c2 */
    --gim-current-400: 111 146 161; /* #6f92a1 */
    --gim-current-500: 72 99 114; /* #486372 */
    --gim-current-600: 63 83 95; /* #3f535f */
    --gim-current-700: 57 71 81; /* #394751 */
    --gim-current-800: 51 62 70; /* #333e46 */
    --gim-current-900: 19 24 28; /* #13181c */
    --gim-current-950: 19 24 28; /* #13181c */
}

/* Modo oscuro (§2.4): solo se redefine el eje neutro. La escala "current" no cambia. */
@media (prefers-color-scheme: dark) {
    :root {
        --gim-canvas: 17 17 17; /* #111111 */
        --gim-shell: 22 22 22; /* #161616 */
        --gim-surface: 28 28 28; /* #1C1C1C */
        --gim-surface-alt: 33 33 33; /* #212121 */
        --gim-ink: 250 250 250; /* #FAFAFA */
        --gim-ink-2: 163 163 163; /* #A3A3A3 */
        --gim-muted: 110 110 110; /* #6E6E6E */
        --gim-line: 42 42 42; /* #2A2A2A */
        --gim-line-strong: 58 58 58; /* #3A3A3A */
        --gim-track: 38 38 38; /* #262626 */
        --gim-ghost: 58 58 58; /* #3A3A3A */
    }
}

@layer base {
    body {
        font-family: theme(fontFamily.sans);
    }

    @media (prefers-reduced-motion: reduce) {
        *, *::before, *::after {
            animation-duration: 0.001ms !important;
            animation-iteration-count: 1 !important;
            transition-property: opacity !important;
            transition-duration: 0.001ms !important;
            scroll-behavior: auto !important;
        }
    }
}

@layer utilities {
    .bg-ghost-ticks {
        background-image: repeating-linear-gradient(to right, rgb(var(--gim-ghost)) 0 1px, transparent 1px 3px);
    }

    .tabular-nums {
        font-variant-numeric: tabular-nums lining-nums;
    }

    /* Indicador de carga indeterminado (§10): ticks fantasma desplazándose,
       en lugar de un shimmer gris genérico. */
    .ghost-loading {
        background-image: repeating-linear-gradient(to right, rgb(var(--gim-ghost)) 0 1px, transparent 1px 3px);
        background-size: 24px 100%;
        animation: ghost-loading-scroll 1.2s linear infinite;
    }

    @media (prefers-reduced-motion: reduce) {
        .ghost-loading {
            animation: none;
        }
    }
}

@keyframes ghost-loading-scroll {
    from {
        background-position: 0 0;
    }

    to {
        background-position: 24px 0;
    }
}

.input {
    @apply appearance-none border border-line bg-surface focus:border-line-strong focus:bg-surface focus:outline-none focus:ring-1 focus:ring-current-500;
}

.textbox {
    @apply input text-body block w-full rounded-xl p-2.5 text-ink;
}

.textbox-premium {
    @apply input text-body block w-full rounded-xl p-2.5 text-ink;
}

/* Estado válido de Blazor: el acento marca "lo logrado" (§1 regla 2). */
.valid.modified:not([type=checkbox]) {
    outline: 1px solid rgb(var(--gim-current-500));
}

.invalid {
    outline: 1px solid rgb(var(--gim-danger-500));
}

/* ==========================================================================
   WP-13 · UX móvil (Blazor Hybrid / WebView táctil)
   Regla D9: en escritorio nada cambia. Todo lo de abajo o vale 0 sin notch
   (env(safe-area-inset-*)), o solo aplica a puntero táctil grueso
   (hover: none) and (pointer: coarse), o solo por debajo de 768px.
   ========================================================================== */
:root {
    /* Safe-area como variables: se consumen desde Tailwind (pt-safe-top, h-screen...).
       Requiere viewport-fit=cover en el <meta viewport> para que iOS/Android las llenen. */
    --safe-top: env(safe-area-inset-top, 0px);
    --safe-right: env(safe-area-inset-right, 0px);
    --safe-bottom: env(safe-area-inset-bottom, 0px);
    --safe-left: env(safe-area-inset-left, 0px);
}

/* Solo dispositivos táctiles (no afecta a ratón, aunque la ventana sea estrecha). */
@media (hover: none) and (pointer: coarse) {
    html,
    body {
        /* Sin pull-to-refresh ni rebote de la página: la app gestiona su propio scroll. */
        overscroll-behavior: none;
        -webkit-tap-highlight-color: transparent;
        -webkit-text-size-adjust: 100%;
        text-size-adjust: 100%;
    }

    /* Quita el retardo de doble-toque/zoom en controles. */
    a, button, [role="button"], input, select, textarea, label, summary {
        touch-action: manipulation;
    }

    /* Scroll anidado: no encadena al padre (evita que arrastrar una lista mueva la página). */
    .UIScroll {
        overscroll-behavior: contain;
    }

    /* iOS hace zoom automático al enfocar un campo con fuente < 16px. */
    input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]),
    select,
    textarea {
        font-size: 16px;
    }
}

/* Compatibilidad móvil para componentes de Components/ (sin propietario en este WP).
   Cuando cada componente adopte la clase equivalente, se puede retirar el shim.
   Ver docs/hybrid-mobile-ux.md, sección "Shims". */
@media (max-width: 767px) {
    /* Modales: si el contenido supera la pantalla (formularios largos, teclado virtual),
       el backdrop hace scroll en lugar de recortarlo; `safe center` evita que el borde
       superior quede inalcanzable y el padding respeta notch/barra de gestos. */
    .fixed.inset-0.z-50[tabindex="-1"] {
        overflow-y: auto;
        overscroll-behavior: contain;
        align-items: safe center;
        padding: max(1rem, var(--safe-top)) max(1rem, var(--safe-right)) max(1rem, var(--safe-bottom)) max(1rem, var(--safe-left));
    }

    /* BaseDrawer usa w-96 (384px): desborda pantallas de 360px. */
    .fixed.top-0.z-40[id^="drawer-"] {
        max-width: 100%;
        height: 100dvh;
        padding-top: max(0.5rem, var(--safe-top));
        padding-bottom: max(0.5rem, var(--safe-bottom));
    }

    /* ToastContainer: fixed top-6 quedaba bajo el notch. */
    .fixed.top-6.z-\[100\] {
        top: max(1.5rem, calc(var(--safe-top) + 0.75rem));
    }
}

.validation-message {
    color: rgb(var(--gim-danger-500));
}

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

    .blazor-error-boundary::after {
        content: "An error has occurred."
    }
