/* Teleport map (/Tables/<slug>/#teleports) — the shell around the canvas that
 * JS/pages/table-map.js paints. Loaded only by table pages that carry a
 * Teleports.json.
 *
 * The --tm-* block below is the map's palette and the ONE place it lives: the
 * canvas has no stylesheet of its own, so the module reads these properties
 * off .tm-shell and paints with what it finds. Re-theming the map is editing
 * this block, never the JavaScript. */

.tm-shell {
    --tm-bg: var(--ds-bg-inset);
    --tm-grid-minor: rgba(255, 255, 255, 0.045);
    --tm-grid-major: rgba(255, 255, 255, 0.09);
    --tm-axis: rgba(255, 255, 255, 0.2);
    --tm-ruler: var(--ds-text-3);
    --tm-hud: var(--ds-text-2);
    --tm-marker: var(--ds-link);
    --tm-marker-dim: var(--ds-text-3);
    --tm-label: var(--ds-text-1);
    --tm-label-dim: var(--ds-text-3);
    --tm-selection: var(--ds-accent);
    --tm-hover: var(--ds-link);
    --tm-badge: var(--ds-text-2);
    --tm-badge-edge: var(--ds-border-2);
    --tm-caption: var(--ds-text-2);
    --tm-ramp-space: oklab;  /* the height ramp's mix: oklab | srgb */

    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 1rem;
    align-items: start;
}

@media (min-width: 900px) {
    .tm-shell {
        grid-template-columns: minmax(0, 1fr) 21rem;
    }
}

.tm-intro {
    margin: -0.35rem 0 1.1rem;
    max-width: 62ch;
    color: var(--color-text-secondary, var(--ds-text-2));
    font-size: 0.92rem;
}

.tm-json-link {
    white-space: nowrap;
}

/* ---- the canvas column ------------------------------------------------- */

.tm-map {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    min-width: 0;
}

.tm-stage {
    position: relative;
    aspect-ratio: 16 / 10;
    min-height: 20rem;
    max-height: 60vh;
    border: 1px solid var(--color-border);
    border-radius: var(--ds-radius-3);
    background: var(--tm-bg);
    overflow: hidden;
}

.tm-canvas {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;
    /* A vertical swipe still scrolls the page: the map is a section of a long
       document, and a finger that lands on it must not trap the reader. Two
       fingers pan and pinch, and the expanded view takes the whole gesture. */
    touch-action: pan-y;
    cursor: grab;
    font-family: var(--ds-font-mono);
    outline: none;
}

.tm-canvas:focus-visible {
    box-shadow: var(--ds-focus);
}

.tm-shell.is-dragging .tm-canvas {
    cursor: grabbing;
}

.tm-shell.is-over-marker .tm-canvas {
    cursor: pointer;
}

/* ---- canvas chrome ----------------------------------------------------- */

/* One column, one corner. The canvas paints its own readouts along the top
   and left edges and in the two bottom corners; leaving the DOM chrome in a
   second corner put the layer switches on top of the height legend, and a
   control that covers the key to the picture is worse than a longer column.
   The module measures this element and keeps labels and the legend clear of
   it, so the trade is only which corner the canvas may not use. */
.tm-toolbar {
    position: absolute;
    top: 0.5rem;
    right: 0.5rem;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    z-index: 2;
}

.tm-tools {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    padding: 0.25rem;
    border: 1px solid var(--color-border);
    border-radius: var(--ds-radius-2);
    background: color-mix(in srgb, var(--ds-surface-1) 82%, transparent);
    backdrop-filter: blur(6px);
}

.tm-tool {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.9rem;
    height: 1.9rem;
    padding: 0;
    border: 0;
    border-radius: var(--ds-radius-1);
    background: transparent;
    color: var(--ds-text-2);
    font-size: 0.8rem;
    cursor: pointer;
    transition: background var(--ds-motion-1), color var(--ds-motion-1);
}

.tm-tool:hover,
.tm-tool:focus-visible {
    background: var(--ds-interactive);
    color: var(--ds-text-1);
}

.tm-tool[aria-pressed="true"] {
    background: var(--ds-interactive);
    color: var(--ds-text-1);
}

.tm-tool[aria-pressed="false"] {
    color: var(--ds-text-3);
}

.tm-tool[disabled] {
    opacity: 0.4;
    cursor: default;
}

/* The hover card: what the pointer is on, and what else is stacked under it.
   Positioned by the module in stage coordinates. */
.tm-card {
    position: absolute;
    z-index: 3;
    max-width: 17rem;
    padding: 0.5rem 0.65rem;
    border: 1px solid var(--color-border);
    border-radius: var(--ds-radius-2);
    background: color-mix(in srgb, var(--ds-surface-2) 94%, transparent);
    box-shadow: var(--ds-shadow-pop);
    color: var(--ds-text-1);
    font-size: 0.8rem;
    line-height: 1.35;
    pointer-events: none;
    display: flex;
    flex-direction: column;
}

.tm-card b {
    display: block;
    font-weight: 600;
}

.tm-card .tm-card-meta {
    color: var(--ds-text-3);
    font-size: 0.74rem;
}

.tm-card .tm-card-coords {
    margin-top: 0.2rem;
    color: var(--ds-text-2);
    font-family: var(--ds-font-mono);
    font-size: 0.72rem;
}

.tm-card ul {
    margin: 0.35rem 0 0;
    padding-left: 0.9rem;
    color: var(--ds-text-2);
    font-size: 0.74rem;
}

.tm-hint {
    position: absolute;
    inset: auto 0 0.75rem;
    z-index: 4;
    margin: 0 auto;
    width: max-content;
    max-width: calc(100% - 1.5rem);
    padding: 0.35rem 0.7rem;
    border-radius: 999px;
    background: color-mix(in srgb, var(--ds-surface-3) 92%, transparent);
    color: var(--ds-text-1);
    font-size: 0.78rem;
    pointer-events: none;
    animation: tmHint var(--ds-motion-2) ease both;
}

.tm-hint kbd {
    padding: 0.05rem 0.3rem;
    border: 1px solid var(--ds-border-2);
    border-radius: var(--ds-radius-1);
    background: var(--ds-bg-code);
    font-family: var(--ds-font-mono);
    font-size: 0.72rem;
    color: var(--color-accent);
}

@keyframes tmHint {
    from {
        opacity: 0;
        transform: translateY(0.4rem);
    }

    to {
        opacity: 1;
        transform: none;
    }
}

.tm-status {
    margin: 0;
    min-height: 1.2em;
    color: var(--ds-text-3);
    font-size: 0.8rem;
}

.tm-status.is-error {
    color: var(--ds-danger);
}

/* The locations could not be loaded: an empty grid and an empty list are a map
   of nothing. What stays is the one sentence saying so — and the download link
   above it, which is the same file the map failed to read. */
.tm-shell.is-failed .tm-stage,
.tm-shell.is-failed .tm-side {
    display: none;
}

/* ---- the list column --------------------------------------------------- */

.tm-side {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    min-width: 0;
}

.tm-side-controls {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.tm-selects {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 0.5rem;
}

.tm-select select {
    width: 100%;
    padding: 0.4rem 0.55rem;
    border: 1px solid var(--color-border);
    border-radius: var(--ds-radius-2);
    background: var(--ds-surface-1);
    color: var(--ds-text-1);
    font-size: 0.82rem;
}

.tm-select select:disabled {
    opacity: 0.5;
}

.tm-list {
    max-height: 22rem;
    overflow-y: auto;
    padding-right: 0.25rem;
    border-radius: var(--ds-radius-2);
    scrollbar-width: thin;
}

.tm-list:focus-visible {
    box-shadow: var(--ds-focus);
}

.tm-list-group {
    position: sticky;
    top: 0;
    z-index: 1;
    padding: 0.4rem 0.1rem 0.25rem;
    background: var(--color-bg-primary);
    color: var(--ds-text-3);
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

.tm-entry {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    width: 100%;
    padding: 0.3rem 0.45rem;
    border: 0;
    border-radius: var(--ds-radius-1);
    background: transparent;
    color: var(--ds-text-2);
    font-size: 0.85rem;
    text-align: left;
    cursor: pointer;
    transition: background var(--ds-motion-1), color var(--ds-motion-1);
}

.tm-entry:hover,
.tm-entry:focus-visible {
    background: var(--ds-interactive);
    color: var(--ds-text-1);
}

.tm-entry.is-selected {
    background: var(--ds-hover);
    color: var(--ds-text-1);
}

.tm-entry-name {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.tm-entry-height {
    flex: 0 0 auto;
    color: var(--ds-text-3);
    font-family: var(--ds-font-mono);
    font-size: 0.72rem;
}

.tm-list-more,
.tm-list-empty {
    padding: 0.6rem 0.45rem;
    color: var(--ds-text-3);
    font-size: 0.8rem;
}

/* ---- the selected location --------------------------------------------- */

.tm-details {
    padding: 0.7rem 0.8rem;
    border: 1px solid var(--color-border);
    border-radius: var(--ds-radius-2);
    background: var(--ds-surface-1);
}

.tm-details h3 {
    margin: 0 0 0.15rem;
    font-size: 0.98rem;
    font-weight: 600;
}

.tm-details-meta {
    margin: 0 0 0.5rem;
    color: var(--ds-text-3);
    font-size: 0.76rem;
}

.tm-details-note {
    margin: 0 0 0.5rem;
    color: var(--ds-text-2);
    font-size: 0.82rem;
}

.tm-coords {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
    margin: 0 0 0.55rem;
}

.tm-coord {
    padding: 0.2rem 0.45rem;
    border: 1px solid var(--color-border);
    border-radius: var(--ds-radius-1);
    background: var(--ds-bg-code);
    color: var(--ds-text-1);
    font-family: var(--ds-font-mono);
    font-size: 0.76rem;
}

.tm-coord span {
    color: var(--ds-text-3);
}

.tm-details-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
}

/* ---- expanded ---------------------------------------------------------- */

/* Expanded: the shell leaves the document and takes the viewport. Every box
   in the chain has to be allowed to stretch AND to shrink — the resting
   layout aligns its columns to the start and caps the list, and either one
   left in place gives a full-screen map 20rem tall. */
.tm-shell.is-expanded {
    position: fixed;
    inset: 0;
    z-index: 1090;
    margin: 0;
    padding: 0.75rem;
    background: var(--color-bg-primary);
    grid-template-rows: minmax(0, 1fr);
    align-items: stretch;
}

.tm-shell.is-expanded .tm-map,
.tm-shell.is-expanded .tm-side {
    min-height: 0;
    max-height: 100%;
}

.tm-shell.is-expanded .tm-stage {
    flex: 1 1 auto;
    aspect-ratio: auto;
    min-height: 0;
    max-height: none;
}

.tm-shell.is-expanded .tm-canvas {
    /* Nothing behind it to scroll: the whole gesture belongs to the map. */
    touch-action: none;
}

.tm-shell.is-expanded .tm-list {
    flex: 1 1 auto;
    min-height: 0;
    max-height: none;
}

@media (max-width: 899px) {
    .tm-shell.is-expanded {
        grid-template-rows: minmax(0, 3fr) minmax(0, 2fr);
    }
}

body.tm-locked {
    overflow: hidden;
}

.tm-noscript {
    margin-top: 1rem;
}

@media (prefers-reduced-motion: reduce) {
    .tm-hint {
        animation: none;
    }
}