/* The sign-in scene. Global, not component-scoped: js/login-map.js positions the cards and the slab layers
   are plain <svg> copies. Everything light-dependent reads --daylight (1 = full day, 0 = night). */

@property --daylight { syntax: '<number>'; inherits: true; initial-value: 1; }
/* Animated in place of opacity and transform, which would make every ring a compositor layer of its
   own; this simply repaints with the layer the rings are already on. */
@property --ring     { syntax: '<number>'; inherits: true; initial-value: 0.6; }

.scene {
    position: absolute;
    inset: 0;
    overflow: hidden;
    overflow: clip;
    font-family: 'DM Sans', sans-serif;
    color: #fff;
    user-select: none;

    --daylight: 1;
    --night: calc(1 - var(--daylight));
    /* The night pictures lie under the day ones and are gone by full day: left in, their shadows show
       through the day pictures' own and double them, but only if the night set happens to be loaded. */
    --night-under: clamp(0, calc(var(--night) * 10), 1);
    --night-pc: calc(var(--night) * 100%);
    /* The step keeps text legible by flipping light/dark instead of fading through grey. */
    --night-step: clamp(0, calc((var(--night) - 0.5) * 8 + 0.5), 1);
    --night-step-pc: calc(var(--night-step) * 100%);

    /* Sea plane the slab stands in */
    --sea-a:     color-mix(in oklab, #0b2250 var(--night-pc), #2f6ab0);
    --sea-b:     color-mix(in oklab, #061737 var(--night-pc), #1f4f8f);
    --land-side: color-mix(in oklab, #0a1b2e var(--night-pc), #1f3a55);
    --land-side-top: color-mix(in oklab, #1a3650 var(--night-pc), #3a5878);

    /* Grid */
    --wire:      color-mix(in oklab, rgba(140,190,255,0.45) var(--night-pc), rgba(37,99,235,0.6));
    --wire-glow: color-mix(in oklab, rgba(90,160,255,0.22) var(--night-pc), rgba(255,255,255,0.45));
    --flow:      color-mix(in oklab, #bfe0ff var(--night-pc), #2f7bff);
    --spark:     #ffffff;
    --hub:       #ffcf6e;
    --hub-glow:  calc(0.55 + 0.35 * var(--night));
    --label:        rgba(255,255,255,0.92);
    --label-halo:   rgba(5,20,30,0.7);
    --label-far:    rgba(255,255,255,0.75);
    --label-far-halo: rgba(5,20,40,0.6);
    --foreign-dot:  rgba(255,255,255,0.7);
    --glow:      calc(0.3 + 0.7 * var(--night));

    /* Overlays */
    --caption:   #f8fafc;
    --caption-muted: rgba(248, 250, 252, 0.74);
    --text-shadow: 0 1px 2px rgba(5, 12, 40, 0.35), 0 0 24px rgba(5, 12, 40, 0.25);

    transition: --daylight 2s ease;
}

/* ── Map stage (3D) ──────────────────────────────────────────────────── */
/* The stage spans the whole scene so the sea and the neighbouring countries
   run under the sign-in column; the UK sits centred in the space left of it. */
.scene {
    /* The column's width and its distance from the right edge are shared tokens (css/auth.css). */
    --panel-reserve: calc(var(--column-width) + var(--column-right));
    --avail: calc(100% - var(--panel-reserve));
    --map-y: 0.405; /* share of the stage height; above the visual centre, as perspective pushes the near edge down */

    /* --u is one map unit on screen. The tilted map (0.76 of its own height) takes --fill of the stage, or
       less where the column leaves less room: what is drawn reaches 480 units right of centre, 228 left. */
    --fill: 0.8265;
    --edge: 24px;
    --stage-h: 100vh;
    --u: clamp(0.285px,
               min(calc(var(--stage-h) * var(--fill) / (var(--map-h) * 0.76)),
                   calc((100vw - var(--panel-reserve) - 2 * var(--edge)) / 708)),
               2.28px);

    /* Just right of the middle of the space left of the column, moving left only as far as it must to
       keep its right-hand reach clear of the column. */
    --map-x: min(calc(var(--avail) * 0.51), calc(var(--avail) - var(--edge) - 480 * var(--u)));

    /* Room for the key and the credit: the space left of the column, less a margin each side. In lengths,
       as the key's list is sized from it inside a track being animated, where a percentage would be circular. */
    --foot-max: calc(100vw - var(--panel-reserve) - 5.2rem);
    --key-button: 6rem; /* the Close button beside the list: 5.6rem, and a little over for a fallback font */
    --key-max: calc(var(--foot-max) - var(--key-button));
}

/* Sea-coloured itself, so a screen wider than the sea plane was drawn for still shows water at its edge. */
.map-stage {
    position: absolute;
    inset: 0;
    overflow: hidden;
    overflow: clip;
    background: var(--sea-b);
}

/* Each layer carries the whole tilt itself rather than sharing one preserve-3d scene: Chrome draws every
   member of such a scene through its own offscreen pass on every frame. Vanishing point 38% down. */
.map-tilt {
    position: absolute;
    left: var(--map-x);
    top: calc(var(--map-y) * 100%);
    width: calc(var(--map-w) * var(--u));
    height: calc(var(--map-h) * var(--u));
    transform: translate(-50%, -50%);
    /* In map units like everything else, so the tilt looks the same at every size. */
    perspective: calc(1600 * var(--u));
    perspective-origin: 50% calc(50% + (0.38 - var(--map-y)) * var(--stage-h));
    /* backwards, not both: a finished fill-forwards animation would keep owning transform. */
    animation: settle 1s cubic-bezier(0.22, 1, 0.36, 1) backwards;
}

@keyframes settle {
    from { opacity: 0.5; transform: translate(-50%, -48%) scale(0.97); }
    to   { opacity: 1; }
}

/* All in map units: --z is the layer's height above the land, --px/--py the map's centre in the
   layer's own box (the point every layer tilts about). */
.map-layer {
    --z: 0;
    --px: calc(var(--map-w) / 2);
    --py: calc(var(--map-h) / 2);
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    transform-origin: calc(var(--px) * var(--u)) calc(var(--py) * var(--u));
    transform: rotateX(52deg) rotateZ(-9deg) translateZ(calc(var(--z) * var(--u)));
}

/* Sea: open water out to the furthest point any screen shape can see (a 32:9 monitor reaches about
   1,600 map units west and 2,900 east), and no further. A tiled grain keeps it from reading as flat. */
.sea {
    inset: -135% -410% -75% -300%;
    width: auto;
    height: auto;
    --z: -18;
    --px: calc(var(--map-w) * 3.5);
    --py: calc(var(--map-h) * 1.85);
    background:
        url('/img/map/sea-noise.png') repeat,
        radial-gradient(ellipse 22.23% 41.3% at 44.44% 35.81%, var(--sea-a) 0%, var(--sea-b) 100%);
    background-size: calc(128 * var(--u)) calc(128 * var(--u)), 100% 100%;
}

/* Layers that cover a wider frame than the map are placed by PowerMap, in map units. */
.floor, .ghost-layer {
    inset: auto;
    left: calc(var(--fx) * var(--u));
    top: calc(var(--fy) * var(--u));
    width: calc(var(--fw) * var(--u));
    height: calc(var(--fh) * var(--u));
    overflow: hidden;
}

/* Two floors of imagery: the far one (coarse) under the near one (detailed, with the shelf glow). */
.floor-far { --z: -17.9; }
.floor-near { --z: -17.8; }
.floor img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    max-width: none;
    pointer-events: none;
}
.floor-shelf { opacity: calc(0.35 + 0.5 * var(--daylight)); }
.floor-night { opacity: calc(0.95 * var(--night-under)); }
.floor-day { opacity: var(--daylight); }

/* <use> clones live in a shadow tree: colour the <svg> and let fill inherit. */
.ghost-layer { --z: -17.5; }

.borders {
    fill: none;
    stroke: rgba(255, 255, 255, 0.28);
    stroke-width: 0.9;
    stroke-linejoin: round;
    stroke-dasharray: 3 2;
}

.foreign-city { fill: var(--foreign-dot); }

.foreign-label {
    font-family: 'DM Sans', sans-serif;
    font-size: 9px;
    font-weight: 600;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    fill: var(--label-far);
    paint-order: stroke;
    stroke: var(--label-far-halo);
    stroke-width: 2px;
    stroke-linejoin: round;
}

/* Stacked copies of the coastline fake the slab's vertical faces. */
.slab-side {
    --z: calc(var(--i) * -2.8);
    fill: var(--land-side);
    stroke: var(--land-side);
    stroke-width: 0.6;
}
.slab-side[style="--i:1"] { fill: var(--land-side-top); }

/* The land top is a pre-rendered picture per time of day, with a 60px bleed for its shadow and coast glow. */
.slab { --z: 0.5; }
/* 792x1108 over the 672x988 map: the picture's bleed, as shares of the map's box. */
.slab img {
    position: absolute;
    left: -8.9286%;
    top: -6.0729%;
    width: 117.8571%;
    height: 112.1457%;
    max-width: none;
    pointer-events: none;
}
.top-night { opacity: var(--night-under); }
.top-day { opacity: var(--daylight); }

/* A picture the hour does not need has no src yet (see PowerMap.razor): kept out of the drawing
   altogether, as some browsers outline or mark an image that has nothing to show. */
.floor img:not([src]), .slab img:not([src]) { visibility: hidden; }

.map-top { --z: 0.8; }
.map-flow { --z: 1; }
.map-stations { --z: 1.2; }

/* The entrance: the grid lights up over the land once it has settled. */
.map-top, .map-flow, .map-stations { animation: layerIn 0.9s ease 0.45s backwards; }

@keyframes layerIn {
    from { opacity: 0; }
}

/* ── Focus ───────────────────────────────────────────────────────────── */
/* The UK is the subject: a fine line of light picks out its coast and the scene darkens away from
   it. Its neighbours' soft focus is baked into their pictures (docs/sign-in-map). */
.coast {
    stroke: color-mix(in oklab, #cfe6ff var(--night-pc), #ffffff);
    stroke-width: 0.75;
    stroke-linejoin: round;
    opacity: calc(0.55 + 0.25 * var(--night));
}

.map-focus {
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: radial-gradient(ellipse 56% 76% at var(--map-x) 50%,
        transparent 40%,
        rgba(3, 8, 28, calc(0.14 + 0.1 * var(--night))) 70%,
        rgba(3, 8, 28, calc(0.4 + 0.16 * var(--night))) 100%);
}

/* ── Grid lines ──────────────────────────────────────────────────────── */
.wire-glow {
    fill: none;
    stroke: var(--wire-glow);
    stroke-width: 4;
    stroke-linecap: round;
}

.wire {
    fill: none;
    stroke: var(--wire);
    stroke-width: 1.2;
    stroke-linecap: round;
}

/* Everything that moves on the map steps on one 30 Hz grid (PowerMap snaps the delays to it), so the
   layer is repainted 30 times a second however fast the screen refreshes. At these speeds it reads the same. */
.flow {
    fill: none;
    stroke: var(--flow);
    stroke-width: 1.7;
    stroke-linecap: round;
    stroke-dasharray: 4 18;
    animation: flow 1.1s steps(33) infinite;
    opacity: calc(0.8 + 0.2 * var(--night));
}

.spark {
    fill: none;
    stroke: var(--spark);
    stroke-width: 2.6;
    stroke-linecap: round;
    stroke-dasharray: 2 160;
    animation: spark 4.5s steps(135) infinite;
    opacity: calc(0.5 + 0.5 * var(--night));
}

@keyframes flow  { to { stroke-dashoffset: -22;  } }
@keyframes spark { to { stroke-dashoffset: -162; } }

/* ── City hubs ───────────────────────────────────────────────────────── */
.hub-glow {
    fill: #ffb347;
    opacity: calc(var(--hub-glow) * 0.45);
    filter: blur(3px);
}
.hub { fill: var(--hub); opacity: 0.85; stroke: rgba(255,255,255,0.5); stroke-width: 0.5; }
.hub-label {
    font-family: 'DM Sans', sans-serif;
    font-size: 8.5px;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    fill: var(--label);
    paint-order: stroke;
    stroke: var(--label-halo);
    stroke-width: 2px;
    stroke-linejoin: round;
    pointer-events: none;
}

/* ── Stations ────────────────────────────────────────────────────────── */
.station { cursor: pointer; outline: none; }
.station circle, .ring { transform-box: fill-box; transform-origin: center; }
/* Only the core and the hit disc take the pointer, so neighbouring halos don't steal the hover. */
.station .halo, .station .dot { pointer-events: none; }

/* The glow is for the marker being pointed at or focused; at rest it is not drawn. */
.station .halo { opacity: 0; }
/* One animation per set of rings in step with each other; the rings follow its progress. Keyframes
   sit on quarters of the cycle so every stretch is a whole number of grid steps. */
.ring-set { animation: ring 3.2s steps(24) infinite; }

.ring {
    fill: none;
    stroke: var(--c);
    stroke-width: 1;
    stroke-opacity: calc(0.9 * (1 - var(--ring, 0.6)));
    transform: scale(calc(0.35 + 1.55 * var(--ring, 0.6)));
}
.station .core { fill: #fff; stroke: var(--c); stroke-width: 1.8; }
.station .dot  { fill: var(--c); }
.station .hit  { fill: transparent; }

@keyframes ring {
    0%   { --ring: 0; }
    25%  { --ring: 0.55; }
    50%  { --ring: 0.8; }
    100% { --ring: 1; }
}

.station:hover .halo, .station:focus-visible .halo, .station.active .halo { opacity: 0.95; }
.station:hover .core, .station:focus-visible .core, .station.active .core { stroke-width: 2.6; }
.station:hover .dot,  .station.active .dot  { transform: scale(1.5); }
.station:focus-visible .core { stroke: #fff; stroke-width: 3; }

/* A fingertip needs more than the few pixels a marker measures on a tablet. */
@media (pointer: coarse) {
    .station .hit { transform: scale(1.7); }
}

.t-wind-offshore, .t-wind-onshore { --c: #38bdf8; }
.t-solar   { --c: #fbbf24; }
.t-hydro   { --c: #60a5fa; }
.t-nuclear { --c: #c084fc; }
.t-gas     { --c: #fb923c; }
.t-biomass { --c: #4ade80; }
.t-tidal   { --c: #2dd4bf; }

/* Solar farms idle at night: the marker dims with the daylight (the key's own entry does not). */
.station.t-solar, .ring.t-solar { opacity: calc(0.35 + 0.65 * var(--daylight)); }

/* ── Overlays ────────────────────────────────────────────────────────── */
/* The key sits over the credit, bottom-left, in one column: the credit wraps on a narrow window and the
   key has to rise with it. */
.scene-foot {
    position: absolute;
    left: 2.6rem;
    bottom: 0.75rem;
    max-width: var(--foot-max);
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.6rem;
    z-index: 2;
}

/* The key to the map: a chip that opens sideways into the list of sources. The first column holds
   the list and is closed to nothing until then. */
.scene-info {
    max-width: 100%;
    display: inline-grid;
    grid-template-columns: 0fr auto;
    align-items: center;
    border-radius: 1.3rem;
    background: rgba(6, 12, 34, 0.42);
    border: 1px solid rgba(255, 255, 255, 0.16);
    box-shadow: 0 12px 40px -16px rgba(0, 0, 0, 0.6), 0 1px 0 rgba(255,255,255,0.08) inset;
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    transition: grid-template-columns 0.45s cubic-bezier(0.22, 1, 0.36, 1);
    animation: fadeSlide 0.9s cubic-bezier(0.16, 1, 0.3, 1) 0.5s backwards;
    z-index: 2;
}

.scene.info-open .scene-info { grid-template-columns: 1fr auto; }

/* The window the list is uncovered through: one row tall until opened, then as tall as the list. */
.info-legend {
    min-width: 0;
    overflow: hidden;
    display: grid;
    grid-template-rows: 0fr;
    padding-block: 0.35rem;
    opacity: 0;
    visibility: hidden;
    transition: grid-template-rows 0.45s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.25s ease, visibility 0s linear 0.45s;
}

.scene.info-open .info-legend {
    grid-template-rows: 1fr;
    opacity: 1;
    visibility: visible;
    transition: grid-template-rows 0.45s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.35s ease 0.15s, visibility 0s;
}

/* Laid out at its finished width and wrapping from the start, whatever the window's size. Sized by
   the window instead, it re-wrapped on every frame of the opening: seven rows tall, then back to one. */
.info-legend-list {
    align-self: start;
    /* The inset is a margin, not padding: Firefox adds padding on top of a max-width when it sizes the
       chip, leaving a gap before the button. */
    margin-left: 1.1rem;
    width: max-content;
    max-width: calc(var(--key-max) - 1.1rem);
    min-height: 1.4rem; /* one row (.legend-item), which the closed window keeps to */
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem 1.15rem;
}

.info-toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    height: 2.5rem;
    padding: 0 1rem 0 0.8rem;
    border: none;
    border-radius: 1.3rem;
    background: none;
    color: rgba(255, 255, 255, 0.9);
    font: 600 0.62rem/1 'DM Sans', sans-serif;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    white-space: nowrap;
    cursor: pointer;
    transition: color 0.2s, background 0.2s;
}

.info-toggle:hover { color: #fff; background: rgba(255, 255, 255, 0.1); }
.info-toggle svg { width: 15px; height: 15px; flex: none; }
.info-toggle span { padding-top: 0.07em; }

.legend-item {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    height: 1.4rem;
    font-size: 0.6rem;
    font-weight: 600;
    line-height: 1;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.86);
    white-space: nowrap;
    padding-top: 0.07em; /* uppercase glyphs sit high; nudge them onto the dot's centre line */
}

.legend-item i {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--c);
    box-shadow: 0 0 10px var(--c), 0 0 0 1px rgba(255,255,255,0.25);
}

.scene-credit {
    margin: 0;
    font-size: 0.62rem;
    line-height: 1.5;
    letter-spacing: 0.04em;
    color: rgba(255, 255, 255, 0.72);
    text-shadow: 0 1px 2px rgba(5, 12, 40, 0.5);
    animation: fadeSlide 0.9s cubic-bezier(0.16, 1, 0.3, 1) 0.7s backwards;
}

.scene-credit a {
    color: inherit;
    text-decoration: underline;
    text-decoration-color: rgba(255, 255, 255, 0.3);
    text-underline-offset: 2px;
    transition: color 0.2s;
}

.scene-credit a:hover,
.scene-credit a:focus-visible { color: #fff; }

.scene-tools {
    position: absolute;
    left: 2.6rem;
    top: 2.4rem;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.7rem;
    color: var(--caption);
    text-shadow: var(--text-shadow);
    animation: fadeSlide 0.9s cubic-bezier(0.16, 1, 0.3, 1) 0.6s backwards;
    z-index: 2;
}

.scene-clock {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.4rem;
    padding: 0;
    border: none;
    background: none;
    color: inherit;
    text-shadow: inherit;
    text-align: left;
    cursor: pointer;
}

.scene-clock .time {
    font-family: 'Outfit', sans-serif;
    font-size: 1.6rem;
    font-weight: 300;
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.02em;
    line-height: 1;
}

.scene-clock .phase {
    font-size: 0.62rem;
    font-weight: 600;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--caption-muted);
    transition: color 0.2s;
}

.scene-clock:hover .phase { color: var(--caption); }

/* Time-of-day preview, opened by clicking the clock. */
.time-test {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.5rem 0.7rem 0.5rem 0.9rem;
    border-radius: 100px;
    background: rgba(6, 12, 34, 0.42);
    border: 1px solid rgba(255, 255, 255, 0.16);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
}
.time-test[hidden] { display: none; }
.time-test:not([hidden]) { animation: fadeSlide 0.4s cubic-bezier(0.16, 1, 0.3, 1) backwards; }

.time-slider {
    width: 200px;
    accent-color: #ffcf6e;
    cursor: pointer;
}

.time-live {
    padding: 0.3rem 0.7rem;
    border-radius: 100px;
    border: 1px solid rgba(255, 255, 255, 0.22);
    background: rgba(255, 255, 255, 0.1);
    color: rgba(255, 255, 255, 0.85);
    font: 600 0.6rem/1 'DM Sans', sans-serif;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    cursor: pointer;
}
.time-live:hover { background: rgba(255, 255, 255, 0.22); color: #fff; }

.scene-clock:focus-visible,
.time-live:focus-visible,
.info-toggle:focus-visible {
    outline: 2px solid rgba(255, 255, 255, 0.85);
    outline-offset: 3px;
    border-radius: 100px;
}

/* ── Station cards ───────────────────────────────────────────────────── */
.station-cards {
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 3;
}

.station-card {
    position: absolute;
    left: 0;
    top: 0;
    width: 450px;
    height: 200px;
    display: flex;
    border-radius: 18px;
    overflow: hidden;
    background: rgba(255, 255, 255, 0.94);
    color: #131926;
    box-shadow: 0 24px 60px -16px rgba(2, 8, 30, 0.55), 0 0 0 1px rgba(255,255,255,0.35) inset;
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);
    opacity: 0;
    visibility: hidden;
    transform: translateY(8px) scale(0.97);
    transition: opacity 0.22s ease, transform 0.32s cubic-bezier(0.16, 1, 0.3, 1), visibility 0s linear 0.22s;
    pointer-events: none;
}

.station-card.show {
    opacity: 1;
    visibility: visible;
    transform: none;
    transition-delay: 0s;
}

.card-photo {
    flex: 0 0 60%;
    position: relative;
    overflow: hidden;
    background: #1b2546;
}

.card-photo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transform: scale(1.07);
    transition: transform 1.4s cubic-bezier(0.16, 1, 0.3, 1);
}

.station-card.show .card-photo img { transform: none; }

.card-credit {
    position: absolute;
    top: 0.5rem;
    right: 0.6rem;
    max-width: 85%;
    font-size: 0.5rem;
    letter-spacing: 0.04em;
    color: rgba(255, 255, 255, 0.78);
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.card-name {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    padding: 2.2rem 1rem 0.9rem;
    background: linear-gradient(180deg, transparent 0%, rgba(5, 10, 30, 0.82) 100%);
    color: #fff;
}

.card-name .card-type {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.58rem;
    font-weight: 600;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    opacity: 0.9;
    margin-bottom: 0.3rem;
}

.card-name .card-type i {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--c);
    box-shadow: 0 0 6px var(--c);
}

.card-name h3 {
    font-family: 'Outfit', sans-serif;
    font-size: 1.15rem;
    font-weight: 600;
    letter-spacing: -0.01em;
    line-height: 1.1;
    margin: 0;
}

.card-name p {
    font-size: 0.68rem;
    opacity: 0.8;
    margin: 0.2rem 0 0;
}

.card-info {
    flex: 1;
    padding: 0.95rem 1rem 0.9rem;
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.card-info dl {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 0.28rem 0.6rem;
    margin: 0;
    font-size: 0.68rem;
}

.card-info dt {
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    font-size: 0.56rem;
    color: #8f96a6;
    align-self: baseline;
    padding-top: 0.1em;
}

.card-info dd {
    margin: 0;
    color: #131926;
    font-weight: 500;
    line-height: 1.3;
}

.card-info dd.capacity {
    font-family: 'Outfit', sans-serif;
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--c);
    filter: saturate(0.9) brightness(0.85);
}

.card-fact {
    margin: 0.6rem 0 0;
    padding-top: 0.6rem;
    border-top: 1px solid rgba(19, 25, 38, 0.08);
    font-size: 0.68rem;
    line-height: 1.45;
    color: #5b6478;
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 4;
    -webkit-box-orient: vertical;
}

html[data-theme="dark"] .station-card {
    background: rgba(15, 23, 42, 0.92);
    color: #f1f5f9;
    box-shadow: 0 24px 60px -16px rgba(0, 0, 0, 0.8), 0 0 0 1px rgba(255,255,255,0.08) inset;
}
html[data-theme="dark"] .card-info dd { color: #f1f5f9; }
html[data-theme="dark"] .card-info dd.capacity { filter: none; }
html[data-theme="dark"] .card-fact { color: #94a3b8; border-top-color: rgba(255,255,255,0.08); }

@keyframes fadeSlide {
    from { opacity: 0; transform: translateY(12px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* ── Fallbacks ───────────────────────────────────────────────────────── */
/* No color-mix(): a fixed night palette instead of invalid (black/transparent) colours. */
@supports not (color: color-mix(in oklab, red, blue)) {
    .scene {
        --sea-a: #0b2250; --sea-b: #061737;
        --land-side: #0a1b2e; --land-side-top: #1a3650;
        --wire: rgba(140,190,255,0.45); --wire-glow: rgba(90,160,255,0.22); --flow: #bfe0ff;
        --glow: 1; --hub-glow: 0.8;
    }
    .top-day { display: none; }
}

/* No frosted glass: solid-enough surfaces instead of see-through ones. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .scene-info { background: rgba(8, 14, 36, 0.85); }
    .station-card { background: rgba(255, 255, 255, 0.98); }
    html[data-theme="dark"] .station-card { background: rgb(20, 28, 50); }
}

/* ── Lite mode ───────────────────────────────────────────────────────── */
/* Set on <html> by js/login-map.js when the first second renders slowly: nothing moving on the map
   and no blurs anywhere, the sign-in column's included. */
html[data-scene-lite] .flow, html[data-scene-lite] .spark, html[data-scene-lite] .ring-set { animation: none; }
html[data-scene-lite] .flow { stroke-dasharray: none; opacity: 0.35; }
html[data-scene-lite] .spark { display: none; }
html[data-scene-lite] .hub-glow { filter: none; opacity: 0.25; }
html[data-scene-lite] .scene-info, html[data-scene-lite] .station-card, html[data-scene-lite] .auth-surface { backdrop-filter: none; -webkit-backdrop-filter: none; }
html[data-scene-lite] .scene-info { background: rgba(8, 14, 36, 0.8); }
html[data-scene-lite] .auth-surface { background: rgba(255, 255, 255, 0.97); }
html[data-scene-lite][data-theme="dark"] .auth-surface { background: rgb(28, 38, 64); }

/* ── Before the script ───────────────────────────────────────────────── */
/* The key is the script's and the circuit's to run, so it is not offered until they can. The clock is
   disabled in the markup until then (PowerMap.razor) and must not look greyed out for it. */
.scene:not([data-ready]) .scene-info { display: none; }
.scene-clock:disabled { cursor: default; }

/* ── Nobody watching ─────────────────────────────────────────────────── */
/* js/login-map.js sets this after a minute without input: the loops cost about a third of a core. */
html[data-scene-idle] .flow, html[data-scene-idle] .spark, html[data-scene-idle] .ring-set { animation-play-state: paused; }

@media (prefers-reduced-motion: reduce) {
    .flow, .spark, .ring-set { animation: none; }
    .map-tilt, .map-top, .map-flow, .map-stations { animation: none; }
    .scene-tools, .scene-info, .scene-credit { animation: none; }
    .card-photo img { transform: none; transition: none; }
    .scene-info, .info-legend, .scene.info-open .info-legend { transition: none; }
}

/* Phones, and any screen too narrow, short or upright for the map beside the column, show the sign-in
   panel alone. The scene is not drawn at all there, and PowerMap.razor keeps its pictures unfetched. */
@media (max-width: 959px), (max-height: 599px), (orientation: portrait) {
    .scene { display: none; }
}
