/* XelRay — dark, minimal, no framework.
   Radiology reading is done on black, and every band of chrome is a band
   taken away from the image, so all of it lives in one narrow left rail
   that folds away entirely. */

:root {
    /* Palette borrowed from xelth.com: its deep teal "felt", cream text and
       gold accent, so the two read as one product. Two deliberate
       departures, both because this is a radiology viewer:

       - The stage stays pure black. Any tint behind a greyscale image
         shifts how bright the image itself looks, and a doctor reading
         from it should not have to correct for the furniture.
       - Everything is pulled a stop or two dimmer than on the main site.
         Chrome sitting beside black at full contrast is what makes eyes
         ache over a long session. Cream is used at reading weight; gold
         appears only where something is actually selected. */

    --stage:    #000000;  /* the image surround — never tinted */
    --bg:       #001611;  /* app ground, a darkened xelth felt */
    --panel:    #00241c;  /* xelth.com's house background, as the rail */
    --panel-2:  #033126;  /* hover / selected surface */
    --line:     #0d3b2f;  /* dividers, dim enough to read as separation */

    --text:     #cdbfa6;  /* xelth.com body cream */
    --bright:   #ead8c1;  /* xelth.com heading cream — emphasis only */
    /* Both checked against --panel: 5.6:1 and 5.0:1. The dimmer greys this
       replaced measured 4.3:1, which is under the readable floor and was
       exactly the "too thin to read" complaint. */
    --muted:    #a09580;
    --faint:    #998d75;

    --accent:       #d9b36a;  /* xelth.com gold */
    --accent-hi:    #f5c451;  /* its brighter sibling, for hover */
    --warn:         #e0836f;  /* xelth.com's soft terracotta */

    /* --- functional hues -------------------------------------------------
       One hue per family of controls, so position is not the only thing
       telling them apart. Used on dots, borders and hover states only —
       never as a filled surface, which would turn the rail into a toybox
       and compete with the image. Red is deliberately absent: beside a
       medical image it reads as a finding, not a button. */
    --nav:      #d9b36a;  /* moving through the stack — the house gold */
    --zoom:     #7fb3c8;  /* size: a cool sky, opposite the warm base */
    --zoom-in:  #9ccbdd;  /* larger — lighter of the same hue */
    --zoom-out: #6a95a8;  /* smaller — darker of the same hue */

    /* Window presets, each tinted the way its tissue reads. */
    --w-soft:  #e2cdae;  /* soft tissue — cream */
    --w-lung:  #9fb6c4;  /* lung — cool blue-grey, like air */
    --w-bone:  #f0e6d2;  /* bone — warm ivory */
    --w-brain: #b6a6cc;  /* brain — muted violet */

    /* Wide enough for two 14px labels side by side without clipping. */
    --rail:     228px;
    --radius:   7px;
    /* Cascadia Mono is xelth.com's signature face. Used here for the
       wordmark, labels and readouts; prose stays in the system UI face,
       which is easier to read in bulk for someone who is a patient rather
       than a developer. */
    --mono: "Cascadia Mono", "Lucida Console", Consolas, ui-monospace, monospace;
    --sans: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

* { box-sizing: border-box; }

html, body {
    margin: 0;
    height: 100%;
    /* The viewer owns the viewport; nothing outside it ever scrolls. */
    overflow: hidden;
    background: var(--bg);
    color: var(--text);
    /* 15px base. The previous 13px was a developer's habit; this is read
       at arm's length, sometimes by someone who needs reading glasses. */
    font: 15px/1.55 var(--sans);
    font-weight: 450;
    -webkit-font-smoothing: antialiased;
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

.app { height: 100vh; display: flex; flex-direction: column; }

/* Files may be dropped anywhere on the window, not into a target. */
.app.dropping::after {
    content: "";
    position: fixed;
    inset: 6px;
    border: 2px dashed var(--accent);
    border-radius: 12px;
    pointer-events: none;
    z-index: 50;
}

.logo {
    font-family: var(--mono);
    font-size: 15px;
    font-weight: 600;
    letter-spacing: -0.2px;
    color: var(--bright);
}
.logo::first-letter { color: var(--accent); }
.logo.big { font-size: 30px; }
.tag { color: var(--muted); font-size: 15px; }

/* ---------- landing ---------- */

.landing {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 20px;
    padding: 40px 20px;
    overflow-y: auto;
    /* A faint echo of xelth.com's lamp-lit felt. Confined to the landing
       screen, which has no image on it — nothing like this is allowed
       anywhere near the stage. */
    background:
        radial-gradient(ellipse 70% 45% at 50% 18%, rgba(26, 118, 88, 0.16), rgba(26, 118, 88, 0) 70%),
        radial-gradient(ellipse 120% 120% at 50% 45%, rgba(0, 18, 13, 0) 45%, rgba(0, 10, 7, 0.6) 100%);
}

.landing-brand { display: flex; align-items: baseline; gap: 10px; }

.dropzone {
    width: min(620px, 100%);
    padding: 42px 32px;
    text-align: center;
    border: 2px dashed var(--line);
    border-radius: 14px;
    background: var(--panel);
}

.dz-icon { font-size: 42px; color: var(--accent); line-height: 1; }
.dropzone h1 {
    margin: 16px 0 8px;
    font-size: 27px;
    font-weight: 600;
    letter-spacing: -0.2px;
    color: var(--bright);
}
.dz-sub { margin: 0; font-size: 16px; color: var(--text); }
.dz-sub code {
    font-family: var(--mono);
    background: var(--panel-2);
    padding: 1px 5px;
    border-radius: 4px;
}

.dz-buttons { display: flex; gap: 12px; justify-content: center; margin-top: 22px; }

/* Shared by the folder button and the file-input labels, which have to be
   indistinguishable — `font` and `line-height` are reset because a real
   <button> otherwise takes the OS font while a <label> inherits the page's. */
.btn {
    display: inline-block;
    padding: 12px 26px;
    border-radius: var(--radius);
    background: var(--accent);
    color: #0b1a14;
    /* `font: inherit` first — it is shorthand, so it would otherwise wipe
       out the size and weight set beside it. */
    font: inherit;
    font-size: 16px;
    font-weight: 600;
    line-height: 1.5;
    cursor: pointer;
    border: 1px solid transparent;
}
.btn:hover { background: var(--accent-hi); }
.btn.ghost { background: transparent; color: var(--text); border-color: var(--line); }
.btn.ghost:hover { background: var(--panel-2); filter: none; }
/* The real input stays in the DOM (labels need it) but never shows. */
.btn input[type="file"] { display: none; }

.privacy {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 0;
    padding: 10px 18px 10px 14px;
    border-left: 3px solid var(--accent);
    border-radius: 3px;
    background: rgba(217, 179, 106, 0.07);
    color: var(--bright);
    font-size: 15px;
    font-weight: 500;
}
.lock { font-size: 17px; line-height: 1; }
.landing-links { margin: 0; color: var(--muted); font-size: 14px; }

.progress { margin-top: 22px; color: var(--text); font-size: 14px; }
.bar {
    height: 5px;
    border-radius: 3px;
    background: var(--panel-2);
    overflow: hidden;
    margin-bottom: 7px;
}
.fill { height: 100%; background: var(--accent); transition: width 0.1s linear; }

.notice { margin: 16px 0 0; color: var(--warn); font-size: 14px; font-weight: 500; }

/* ---------- viewer: rail + stage ---------- */

.viewer { flex: 1; display: flex; min-height: 0; position: relative; }

.rail {
    font-size: 14px;
    width: var(--rail);
    flex: none;
    display: flex;
    flex-direction: column;
    border-right: 1px solid var(--line);
    background: var(--panel);
    overflow: hidden;
    user-select: none;
}

.rail-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 7px 8px 7px 12px;
    border-bottom: 1px solid var(--line);
}

.icon {
    width: 24px;
    height: 24px;
    display: grid;
    place-items: center;
    border: 1px solid transparent;
    border-radius: 5px;
    background: transparent;
    color: var(--muted);
    font-size: 15px;
    line-height: 1;
    cursor: pointer;
}
.icon:hover { background: var(--panel-2); color: var(--text); }

/* The strip that brings the rail back. Sits over the image, top-left, the
   same place the rail's own chevron was. */
.rail-tab {
    position: absolute;
    top: 8px;
    left: 8px;
    z-index: 20;
    width: 30px;
    height: 30px;
    display: grid;
    place-items: center;
    border: 1px solid var(--line);
    border-radius: 6px;
    background: rgba(0, 36, 28, 0.82);
    backdrop-filter: blur(3px);
    color: var(--muted);
    font-size: 14px;
    cursor: pointer;
    opacity: 0.55;
    transition: opacity 0.12s;
}
.rail-tab:hover { opacity: 1; color: var(--text); }

.rail-body {
    flex: 1;
    overflow-y: auto;
    padding: 4px 8px 8px;
    scrollbar-width: thin;
    scrollbar-color: rgba(234, 216, 193, 0.15) transparent;
}

.rail-sec { padding: 6px 0; border-bottom: 1px solid var(--line); }
.rail-sec:last-child { border-bottom: none; }

.rail-head {
    font-family: var(--mono);
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    padding: 0 3px 5px;
    color: var(--muted);
    font-size: 11.5px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

/* Inline reminder of the key that drives each section. */
.kbd-hint {
    font-family: var(--mono);
    font-size: 11.5px;
    letter-spacing: 0;
    text-transform: none;
    color: var(--faint);
}

.series {
    display: block;
    width: 100%;
    text-align: left;
    padding: 6px 9px;
    margin-bottom: 3px;
    border: 1px solid transparent;
    border-radius: var(--radius);
    background: transparent;
    color: var(--text);
    font: inherit;
    cursor: pointer;
}
.series:hover { background: var(--panel-2); }
.series.active {
    background: var(--panel-2);
    border-color: var(--accent);
    color: var(--bright);
}
.s-label {
    display: block;
    font-size: 14px;
    font-weight: 500;
    line-height: 1.4;
    overflow-wrap: anywhere;
}
.s-meta { display: block; color: var(--muted); font-size: 12.5px; margin-top: 3px; }
.s-warn {
    display: block;
    color: var(--warn);
    font-size: 12.5px;
    font-weight: 500;
    margin-top: 4px;
}

.grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 3px; }

.tool {
    /* Labels are words, not data: the system face reads better at this size
       than the mono one, which is kept here for numbers and keys only. */
    padding: 6px 8px;
    border: 1px solid var(--line);
    border-radius: 6px;
    background: transparent;
    color: var(--text);
    font: inherit;
    font-size: 14px;
    font-weight: 500;
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.tool:hover { background: var(--panel-2); }
.tool:hover { border-color: var(--line); }
.tool.active { border-color: var(--accent); color: var(--accent); }
.tool.wide {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 6px;
    width: 100%;
    margin-top: 3px;
}

.readout {
    margin-top: 5px;
    padding: 0 3px;
    color: var(--text);
    font-family: var(--mono);
    font-size: 13px;
}

.scrub { width: 100%; margin-top: 6px; accent-color: var(--nav); }

/* ---------- functional colour ----------
   Each family of controls carries its own hue, so a glance tells brightness
   from size without reading. The dose is deliberately small: a dot, a
   border, a hover — never a filled button. The rail has to stay quieter
   than the image next to it. */

/* A dot before each section heading, coloured by what the section does. */
.rail-head::before {
    content: "";
    width: 7px;
    height: 7px;
    margin-right: 7px;
    border-radius: 50%;
    background: var(--dot, var(--muted));
    flex: none;
    align-self: center;
}
.rail-head { align-items: center; }
.rail-head.nav    { --dot: var(--nav); }
.rail-head.window { --dot: var(--w-soft); }
.rail-head.view   { --dot: var(--zoom); }

/* A coloured chip on the leading edge, worn as a label rather than a fill.
   Every control that belongs to a family carries one, so the family is
   legible at rest and not only under the cursor. */
.chip {
    position: relative;
    padding-left: 18px;
    text-align: left;
}
.chip::before {
    content: "";
    position: absolute;
    left: 7px;
    top: 50%;
    width: 6px;
    height: 6px;
    margin-top: -3px;
    border-radius: 50%;
    background: var(--chip);
}
.chip:hover { border-color: var(--chip); }

/* Window presets, tinted the way each tissue reads. */
.preset-soft  { --chip: var(--w-soft); }
.preset-lung  { --chip: var(--w-lung); }
.preset-bone  { --chip: var(--w-bone); }
.preset-brain { --chip: var(--w-brain); }
/* Selected still reads as gold, so "which one is on" never changes meaning
   between sections. */
.preset.active { border-color: var(--accent); color: var(--accent); }

/* Size controls take the cool hue: lighter for bigger, darker for smaller,
   so the direction is carried by the colour as well as the word. */
.zoom-in  { --chip: var(--zoom-in); }
.zoom-out { --chip: var(--zoom-out); }
.fit      { --chip: var(--zoom); }
.zoom-in:hover, .zoom-out:hover, .fit:hover { color: var(--chip); }

/* Playback is navigation, so it wears the navigation gold. */
.cine { --chip: var(--nav); }
.cine.active { border-color: var(--accent); color: var(--accent); }

/* The same hues label the help sheet, so the cheat sheet teaches the
   colour system as well as the keys. */
.hk-group.images, .hk-group.series { color: var(--nav); }
.hk-group.window { color: var(--w-soft); }
.hk-group.view { color: var(--zoom); }

.rail-foot { padding: 7px 8px; border-top: 1px solid var(--line); }
.rail-links {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 4px;
    margin-top: 7px;
    color: var(--muted);
    font-size: 12.5px;
}

/* The language picker sits in the link row and is dressed as one of the
   links: present when looked for, silent otherwise. */
.lang {
    appearance: none;
    padding: 1px 3px;
    border: none;
    background: transparent;
    color: var(--muted);
    font-family: var(--mono);
    font-size: 12.5px;
    cursor: pointer;
}
.lang:hover { color: var(--accent); }
.lang:focus-visible { outline: 1px solid var(--accent); border-radius: 3px; }
/* The popup itself is drawn by the OS, so it needs real colours. */
.lang option { background: var(--panel); color: var(--text); }

/* ---------- stage ---------- */

.stage {
    position: relative;
    flex: 1;
    min-width: 0;
    min-height: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    background: var(--stage);
    cursor: crosshair;
    /* Every gesture here is custom: never let a drag select the overlay
       text, and never let a swipe scroll or bounce the page. */
    user-select: none;
    -webkit-user-select: none;
    touch-action: none;
}
/* Zoomed in, a drag moves the image — so say so with the cursor. */
.stage.zoomed { cursor: grab; }
.stage.zoomed:active { cursor: grabbing; }

.stage-message {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    max-width: min(420px, 80%);
    padding: 16px 20px;
    border: 1px solid var(--line);
    border-radius: 10px;
    background: rgba(0, 36, 28, 0.94);
    text-align: center;
    pointer-events: none;
}
.stage-message.error { border-color: rgba(224, 131, 111, 0.45); }
.sm-title { color: var(--warn); font-size: 16px; font-weight: 600; margin-bottom: 8px; }
.sm-body {
    color: var(--text);
    font-size: 13.5px;
    overflow-wrap: anywhere;
    margin-top: 3px;
}

.stage-busy {
    position: absolute;
    left: 50%;
    bottom: 22px;
    transform: translateX(-50%);
    padding: 4px 12px;
    border-radius: 999px;
    background: rgba(0, 36, 28, 0.82);
    color: var(--text);
    font-size: 13px;
    pointer-events: none;
}

.stage canvas {
    /* Fitted to the pane by CSS, so a window resize needs no JavaScript;
       zoom and pan then ride on top as a transform, with no repaint. */
    max-width: 100%;
    max-height: 100%;
    image-rendering: pixelated;
    transform-origin: center center;
}

.overlay {
    position: absolute;
    padding: 8px 12px;
    max-width: 45%;
    color: rgba(234, 216, 193, 0.62);
    font-family: var(--mono);
    font-size: 12.5px;
    pointer-events: none;
    text-shadow: 0 1px 3px #000;
    overflow-wrap: anywhere;
}
/* Clear of the floating rail button when the panel is folded away. */
.tl { top: 0; left: 44px; }
.tr { top: 0; right: 0; text-align: right; }
.bl { bottom: 0; left: 0; }
.br { bottom: 0; right: 0; text-align: right; }

.warnbar {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    padding: 7px 14px;
    font-size: 13px;
    font-weight: 500;
    background: rgba(224, 131, 111, 0.13);
    border-bottom: 1px solid rgba(224, 131, 111, 0.3);
    color: var(--warn);
    font-size: 12px;
    text-align: center;
    pointer-events: none;
}

/* ---------- help ---------- */

.help-backdrop {
    position: fixed;
    inset: 0;
    z-index: 100;
    display: grid;
    place-items: center;
    padding: 24px;
    background: rgba(0, 12, 9, 0.66);
    backdrop-filter: blur(2px);
}

.help-card {
    width: min(460px, 100%);
    max-height: 100%;
    overflow-y: auto;
    border: 1px solid var(--line);
    border-radius: 12px;
    background: var(--panel);
    box-shadow: 0 18px 50px rgba(0, 0, 0, 0.6);
}

.help-title {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 12px 14px 18px;
    border-bottom: 1px solid var(--line);
    font-size: 16px;
    font-weight: 600;
    color: var(--bright);
}

.help-grid {
    display: grid;
    grid-template-columns: auto minmax(120px, auto) 1fr;
    gap: 5px 12px;
    align-items: baseline;
    padding: 16px 18px;
}

.hk-group {
    color: var(--muted);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    /* Empty cells continue the group above; they still hold the column. */
    min-width: 48px;
}
.hk-keys { display: flex; flex-wrap: wrap; gap: 4px; }
.hk-what { color: var(--text); font-size: 14px; }

kbd {
    display: inline-block;
    padding: 1px 6px;
    border: 1px solid var(--line);
    border-bottom-width: 2px;
    border-radius: 5px;
    background: var(--panel-2);
    color: var(--text);
    font-family: var(--mono);
    font-size: 12.5px;
    font-weight: 600;
    line-height: 1.5;
    white-space: nowrap;
}

.help-foot {
    padding: 14px 18px 18px;
    border-top: 1px solid var(--line);
    color: var(--muted);
    font-size: 13px;
    line-height: 1.5;
}
.help-foot p { margin: 0 0 6px; }
.help-foot p:last-child { margin-bottom: 0; }
.help-note { color: var(--faint); }

@media (max-width: 640px) {
    :root { --rail: 160px; }
    .overlay { font-size: 10.5px; padding: 6px 8px; }
}
