/* ============================================================
   DIVA Cloud — JupyterHub theme
   Atmospheric Deep Tech design system · deep-space dark + neon cyan

   Tokens are kept 1:1 with the DIVA platform site
   (diva-web/web/css/styles.css). If a token changes there,
   change it here too — they are one system across two properties.
   ============================================================ */

/* ==========================================================================
   1. Tokens
   ========================================================================== */

:root {
    color-scheme: dark;

    /* surfaces */
    --bg:          #05070d;
    --bg-1:        #080b14;
    --bg-2:        #0b101e;
    --bg-3:        #0e1626;
    --panel:       rgba(13, 20, 36, 0.55);
    --panel-solid: #0a0f1c;

    /* lines */
    --line:        rgba(126, 156, 198, 0.10);
    --line-soft:   rgba(126, 156, 198, 0.055);
    --line-strong: rgba(126, 170, 220, 0.20);

    /* accents — cyan primary, emerald/orange/rose punctual */
    --cyan:      #34d6ee;
    --cyan-2:    #22d3ee;
    --cyan-deep: #0e7d93;
    --emerald:   #34d399;
    --orange:    #fb923c;
    --violet:    #8b7cf6;
    --rose:      #fb7185;

    /* glows */
    --cyan-glow:    rgba(52, 214, 238, 0.55);
    --cyan-wash:    rgba(52, 214, 238, 0.06);
    --emerald-wash: rgba(52, 211, 153, 0.10);
    --orange-wash:  rgba(251, 146, 60, 0.10);
    --rose-wash:    rgba(251, 113, 133, 0.10);

    /* text */
    --text:  #e9eef7;
    --muted: #9aa8bf;
    --faint: #62718a;

    /* type */
    --display: 'Space Grotesk', system-ui, -apple-system, sans-serif;
    --mono:    'JetBrains Mono', ui-monospace, SFMono-Regular, monospace;

    /* the live accent (kept as an indirection so the whole UI can be
       re-accented from one place, exactly like the DIVA site's Tweaks) */
    --accent:      var(--cyan);
    --accent-glow: var(--cyan-glow);

    /* geometry */
    --maxw:   1280px;
    --radius: 3px;
    --ease:   cubic-bezier(0.4, 0, 0.2, 1);
}

/* Re-point Bootstrap 5.3's own variables at the DIVA palette. Doing it here
   means every Bootstrap component we never explicitly style (cards, dropdowns,
   pagination, form controls, the React admin table) inherits the theme instead
   of needing a per-component !important override. */
:root,
[data-bs-theme="dark"] {
    --bs-body-bg:            var(--bg);
    --bs-body-color:         var(--text);
    --bs-body-font-family:   var(--display);
    --bs-emphasis-color:     var(--text);
    --bs-secondary-color:    var(--muted);
    --bs-tertiary-color:     var(--faint);
    --bs-secondary-bg:       var(--bg-2);
    --bs-tertiary-bg:        var(--bg-1);
    --bs-border-color:       var(--line-strong);
    --bs-border-radius:      var(--radius);
    --bs-border-radius-sm:   2px;
    --bs-border-radius-lg:   4px;
    --bs-link-color:         var(--accent);
    --bs-link-hover-color:   var(--cyan-2);
    --bs-code-color:         var(--accent);
    --bs-heading-color:      var(--text);
    --bs-font-monospace:     var(--mono);
}


/* ==========================================================================
   1b. Token contract required by hub-base/static/base.css
   --------------------------------------------------------------------------
   base.css names only these semantic tokens, never a DIVA colour. This block
   is the whole of the mapping: change the palette above and the entire hub
   follows, including every Bootstrap component the theme never mentions.
   The full list and its meaning is in hub-base/BRANDING.md.
   ========================================================================== */

:root {
    /* semantic roles -> DIVA palette */
    --accent-hover: var(--cyan-2);
    --accent-wash:  var(--cyan-wash);
    --ok:           var(--emerald);
    --ok-wash:      var(--emerald-wash);
    --warn:         var(--orange);
    --warn-wash:    var(--orange-wash);
    --danger:       var(--rose);
    --danger-wash:  var(--rose-wash);

    /* text drawn on top of an accent-filled surface */
    --on-accent:      #04121a;
    /* text drawn on the white plate a partner logo sits on */
    --on-logo-plate:  #1b2a4a;

    /* hairlines: the same hue as the role, at list/badge weight */
    --accent-line:         rgba(52, 214, 238, 0.18);
    --accent-ring:         rgba(52, 214, 238, 0.25);
    --accent-drop:         rgba(52, 214, 238, 0.12);
    --ok-line:             rgba(52, 211, 153, 0.25);
    --warn-line:           rgba(251, 146, 60, 0.25);
    --warn-line-strong:    rgba(251, 146, 60, 0.3);
    --danger-line:         rgba(251, 113, 133, 0.3);
    --danger-line-strong:  rgba(251, 113, 133, 0.45);

    /* neutral fills */
    --row-hover:        rgba(126, 156, 198, 0.035);
    --neutral-wash:     rgba(255, 255, 255, 0.04);
    --logo-plate:       #fff;
    --logo-plate-line:  rgba(255, 255, 255, 0.06);

    /* depth. A light-theme tenant would soften every one of these. */
    --shadow-drop:        rgba(0, 0, 0, 0.5);
    --shadow-panel:       rgba(0, 0, 0, 0.45);
    --shadow-modal:       rgba(0, 0, 0, 0.6);
    --shadow-tile:        rgba(0, 0, 0, 0.9);
    --shadow-tile-hover:  rgba(0, 0, 0, 1);


    /* --- idioma tipográfico y ornamento (contrato de base.css) ------------ */
    /* DIVA pone las micro-etiquetas en mono y versalitas */
    --data-family:     var(--mono);
    --label-family:    var(--mono);
    --label-transform: uppercase;
    --panel-blur:      blur(14px);
    --logo-hover-filter: drop-shadow(0 0 10px var(--accent-glow));
    /* Deep space: aspa invertida y realce por aclarado. */
    --close-filter:  invert(1) grayscale(1);
    --hover-filter:  brightness(1.1);
    --card-logo-filter:  drop-shadow(0 0 12px var(--accent-drop));

    /* the atmospheric vignette behind every page: cyan aloft, emerald at the
       surface. A tenant with no vignette sets this to `none`. */
    --vignette:
        radial-gradient(120% 80% at 50% -10%, rgba(34, 211, 238, 0.06), transparent 55%),
        radial-gradient(90% 60% at 100% 100%, rgba(52, 211, 153, 0.04), transparent 60%);
}

/* ==========================================================================
   Marcadores de identidad de DIVA
   --------------------------------------------------------------------------
   Estaban en base.css. Son la firma visual de DIVA —el filete corto delante de
   cada eyebrow, el subrayado que crece bajo la nav, el filamento encendido en
   el borde superior de los paneles—, no estructura. Viven aquí para que otro
   tenant pueda tener los suyos en vez de heredar estos.
   ========================================================================== */

/* el filete corto que precede a toda micro-etiqueta */
.eyebrow::before {
    content: "";
    width: 22px;
    height: 1px;
    background: var(--accent);
    opacity: 0.7;
}

/* el subrayado es la señal de hover de la nav */
.navbar .nav-link::after {
    content: "";
    position: absolute;
    left: 0.9rem;
    right: 0.9rem;
    bottom: 0.15rem;
    height: 1px;
    background: var(--accent);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform 0.25s var(--ease);
}

.navbar .nav-link:hover::after,
.navbar .nav-link:focus-visible::after {
    transform: scaleX(1);
}

/* un solo filamento encendido en el borde superior — el único ornamento */
.login-box::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 1px;
    background: linear-gradient(90deg, transparent, var(--accent), transparent);
    opacity: 0.6;
}

.profile-card::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 1px;
    background: linear-gradient(90deg, transparent, var(--accent), transparent);
    opacity: 0;
    transition: opacity 0.25s var(--ease);
}

.profile-card:hover::before {
    opacity: 0.7;
}

/* ==========================================================================
   14. Spawn pending — satellite overpass / ground collocation
   --------------------------------------------------------------------------
   This is the one screen a DIVA user actually waits on, sometimes minutes
   while a multi-gigabyte image is pulled. What it shows is the platform's
   whole reason to exist: DIVA validates atmospheric *missions* by collocating
   a satellite overpass with what a ground station measured at the same time
   and place. So the wait renders that moment — the orbit tracks, the station
   beam reaches up, and the two meet at the apex.

   Pure CSS and inline SVG: no library, and no motion-path dependency (the
   arc is two nested transforms, X linear and Y alternating, which every
   browser honours). Under prefers-reduced-motion the pass parks at the
   coincidence instead of looping.
   ========================================================================== */

.overpass {
    position: relative;
    width: 300px;
    height: 140px;
    margin: 0 auto;
}

.overpass svg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    overflow: visible;
}

/* --- static scene --- */
.op-horizon  { stroke: var(--line-strong); stroke-width: 1; }
.op-ring     { fill: none; stroke: var(--line); stroke-width: 1; }
.op-orbit    { fill: none; stroke: var(--line-strong); stroke-width: 1; stroke-dasharray: 3 5; }
.op-station  { fill: var(--faint); }

/* --- the ground beam, brightest as the satellite crosses --- */
.op-beam {
    fill: url(#op-beam-grad);
    opacity: 0.25;
    animation: op-beam 4.6s ease-in-out infinite;
}

/* --- the coincidence: one ring, expanding once per pass --- */
.op-hit {
    fill: none;
    stroke: var(--accent);
    stroke-width: 1.5;
    transform-box: fill-box;
    transform-origin: center;
    opacity: 0;
    animation: op-hit 4.6s ease-out infinite;
}

/* --- the satellite: X linear, Y alternating, so the pair trace an arc --- */
.op-sat-x {
    position: absolute;
    left: 150px;
    top: 30px;
    width: 0;
    height: 0;
    animation: op-x 4.6s linear infinite;
}

.op-sat-y {
    position: absolute;
    /* exact quadratic ease-out — this is what makes the satellite ride the
       drawn parabola instead of drifting off it. See the orbit path's Q. */
    animation: op-y 2.3s cubic-bezier(0.3333, 0.6667, 0.6667, 1) infinite alternate;
}

.op-sat {
    display: block;
    transform: translate(-50%, -50%);
    color: var(--accent);
    filter: drop-shadow(0 0 6px var(--accent-glow));
}

@keyframes op-x {
    from { transform: translateX(-126px); }
    to   { transform: translateX(126px); }
}

@keyframes op-y {
    from { transform: translateY(74px); }
    to   { transform: translateY(0); }
}

@keyframes op-beam {
    0%, 32%   { opacity: 0.16; }
    50%       { opacity: 0.85; }
    68%, 100% { opacity: 0.16; }
}

@keyframes op-hit {
    0%, 44%  { opacity: 0;    transform: scale(0.35); }
    52%      { opacity: 0.95; transform: scale(0.6); }
    76%,100% { opacity: 0;    transform: scale(2.6); }
}

/* Under prefers-reduced-motion the pass parks at the coincidence instead of
   looping. base.css already neutralises durations globally; these rules pin
   the scene to its meaningful frame rather than to frame zero. */
@media (prefers-reduced-motion: reduce) {
    .op-sat-x { animation: none; transform: translateX(0); }
    .op-sat-y { animation: none; transform: translateY(0); }
    .op-beam  { animation: none; opacity: 0.85; }
    .op-hit   { animation: none; opacity: 0.9; transform: scale(0.6); }
}
