/* MRI wrist viewer — visual system.
 *
 * Dark by necessity: greyscale MRI is read against black, and light chrome
 * would wash the images out. There is no light theme and there should not be.
 *
 * The accent is amber, not blue. Reading consoles have put their overlay text
 * in yellow-amber on black for decades, it is the one hue that never appears
 * in a greyscale acquisition, and it holds ~10:1 against the chrome — so a
 * gold marker in this UI always means "this one, here, now".
 */

:root {
  /* surfaces — near-black, a whisper of cool chroma so the amber has a room */
  --void:      #000000;   /* the image well; nothing else is this dark */
  --bg:        #0d0e11;   /* stage bed */
  --chrome:    #15171a;   /* rail, bars, dock */
  --raise:     #202327;   /* controls at rest */
  --raise-2:   #2b2e32;   /* controls, hovered */
  --line:      #2e3237;   /* hairline */
  --line-soft: #222428;   /* hairline, quieter */

  /* ink */
  --ink:   #eff0f2;   /* 15.8:1 on chrome */
  --ink-2: #bbbec2;   /*  9.6:1 */
  --ink-3: #93979c;   /*  6.1:1 — the floor for real text */
  --ink-4: #7e8288;   /*  4.7:1 — labels, glyphs, dividers */

  /* accent */
  --acc:      #f3b743;
  --acc-hi:   #fdd37d;
  --acc-dim:  #aa7d2d;
  --acc-ink:  #201000;   /* text on an accent fill, 10.3:1 */
  --acc-wash: rgba(243, 183, 67, .10);
  --acc-edge: rgba(243, 183, 67, .38);

  --danger: #f47b74;

  --r-sm: 5px;
  --r:    7px;
  --r-lg: 12px;

  --ease: cubic-bezier(.2, .7, .3, 1);
  --fast: 120ms var(--ease);
  --med:  180ms var(--ease);

  --z-sticky: 10;
  --z-overlay: 20;

  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial,
          "Helvetica Neue", sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", "Cascadia Mono", "Segoe UI Mono",
          Menlo, Consolas, monospace;
}

* { box-sizing: border-box; }

html { height: 100%; }

body {
  height: 100%;
  min-height: 100dvh;
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 400 14px/1.5 var(--sans);
  -webkit-font-smoothing: antialiased;
  -webkit-text-size-adjust: 100%;
}

button, input, select { font: inherit; color: inherit; }
h1, h2, h3, p, dl, dd, figure { margin: 0; }
[hidden] { display: none !important; }

:where(a, button, input, [tabindex]):focus-visible {
  outline: 2px solid var(--acc);
  outline-offset: 2px;
  border-radius: 3px;
}

/* Scrollbars: present, because a scroll region should say so, but drawn as a
   dark rail rather than as the browser's bright default furniture. */
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb {
  background: var(--raise-2);
  border: 3px solid transparent;
  background-clip: content-box;
  border-radius: 99px;
}
*::-webkit-scrollbar-thumb:hover { background: #3d4147; background-clip: content-box; }

/* Firefox has no ::-webkit-scrollbar; give it the standard properties instead
   (in Chrome these would win over the rules above, so they are scoped). */
@supports (scrollbar-width: thin) and (not selector(::-webkit-scrollbar)) {
  * { scrollbar-width: thin; scrollbar-color: var(--raise-2) transparent; }
}

/* ==================================================================== gate */

.is-login {
  display: grid;
  place-items: center;
  padding: 32px 20px;
  background:
    radial-gradient(120% 90% at 50% 0%, #16181d 0%, #0d0e11 55%, #08090b 100%);
}

.gate { width: min(410px, 100%); }

.gate__card {
  background: #121417;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: 0 1px 0 rgba(255, 255, 255, .04) inset,
              0 24px 60px -24px rgba(0, 0, 0, .9);
  overflow: hidden;
}

.gate__head {
  display: flex;
  gap: 13px;
  align-items: center;
  padding: 22px 24px 20px;
  border-bottom: 1px solid var(--line-soft);
}

.gate__mark { display: block; flex: none; color: var(--acc); }

.gate__title {
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -.008em;
  line-height: 1.25;
}

.gate__org { margin-top: 3px; font-size: 12.5px; color: var(--ink-3); }

/* The study identifies itself before you are let in — non-identifying facts
   only, laid out like a record rather than like marketing. */
.gate__facts {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  border-bottom: 1px solid var(--line-soft);
}

.gate__facts > div {
  padding: 12px 14px;
  border-left: 1px solid var(--line-soft);
}
.gate__facts > div:first-child { border-left: 0; padding-left: 24px; }

.gate__facts dt {
  font-size: 10.5px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink-4);
}
.gate__facts dd {
  margin-top: 4px;
  font: 500 13px/1.3 var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink-2);
  white-space: nowrap;
}

/* Narrow phones: the record row keeps its three columns rather than wrapping a
   date across two lines, which would make it look like a broken table. */
@media (max-width: 430px) {
  .gate__head { padding: 20px 18px 18px; }
  .gate__body { padding: 20px 18px 22px; }
  .gate__facts > div { padding: 11px 9px; }
  .gate__facts > div:first-child { padding-left: 18px; }
  .gate__facts dt { font-size: 10px; }
  .gate__facts dd { font-size: 12px; }
}

.gate__body { padding: 22px 24px 24px; }

.gate__sub {
  margin-bottom: 18px;
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--ink-3);
  text-wrap: pretty;
}

.field { display: grid; gap: 7px; }

.field > label {
  font-size: 12px;
  font-weight: 500;
  letter-spacing: .01em;
  color: var(--ink-2);
}

.gate__input {
  width: 100%;
  padding: 11px 13px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--r);
  color: var(--ink);
  letter-spacing: .04em;
  transition: border-color var(--fast), box-shadow var(--fast);
}
.gate__input::placeholder { color: var(--ink-4); }
.gate__input:hover { border-color: #3a3e44; }
.gate__input:focus {
  outline: none;
  border-color: var(--acc-edge);
  box-shadow: 0 0 0 3px rgba(243, 183, 67, .14);
}

.gate__error {
  display: flex;
  gap: 8px;
  align-items: flex-start;
  margin-top: 14px;
  padding: 10px 12px;
  background: rgba(244, 123, 116, .09);
  border: 1px solid rgba(244, 123, 116, .3);
  border-radius: var(--r);
  font-size: 13px;
  line-height: 1.45;
  color: #ffb3ad;
}
.gate__error svg { flex: none; margin-top: 1px; color: var(--danger); }
.gate__error span { min-width: 0; }

.gate__btn {
  width: 100%;
  margin-top: 18px;
  padding: 12px;
  background: var(--acc);
  color: var(--acc-ink);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: .01em;
  border: 0;
  border-radius: var(--r);
  cursor: pointer;
  transition: background var(--fast), transform var(--fast);
}
.gate__btn:hover { background: var(--acc-hi); }
.gate__btn:active { transform: translateY(1px); }

.gate__foot {
  margin-top: 16px;
  padding: 0 4px;
  font-size: 11.5px;
  line-height: 1.6;
  color: var(--ink-4);
  text-align: center;
  text-wrap: balance;
}

/* ================================================================== viewer */

.is-viewer {
  display: flex;
  flex-direction: column;
  height: 100dvh;
  overflow: hidden;
}

/* --- top bar --- */

.top {
  display: flex;
  gap: 16px;
  align-items: center;
  justify-content: space-between;
  flex: none;
  padding: 9px 16px;
  padding-top: max(9px, env(safe-area-inset-top));
  background: var(--chrome);
  border-bottom: 1px solid var(--line);
  z-index: var(--z-sticky);
}

.top__id { display: flex; gap: 11px; align-items: center; min-width: 0; }
.top__idtext { min-width: 0; }
.top__mark { flex: none; color: var(--acc); opacity: .9; }

.top__title {
  font-size: 13.5px;
  font-weight: 600;
  letter-spacing: -.005em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.top__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 2px 10px;
  margin-top: 2px;
  font-size: 11.5px;
  line-height: 1.35;
  color: var(--ink-3);
}
.top__meta span { display: inline-flex; gap: 10px; align-items: center; }
.top__meta span + span::before {
  content: "";
  width: 1px;
  height: 9px;
  background: var(--line);
}
.top__meta b {
  font: 400 11.5px/1 var(--mono);
  font-variant-numeric: tabular-nums;
}

.top__actions { display: flex; gap: 6px; flex: none; }

/* --- buttons --- */

/* One button vocabulary across the whole tool: a quiet outlined chip that
   fills on hover. Chrome should be legible, not eye-catching. */
.btn, .tool {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 11px;
  background: transparent;
  border: 1px solid var(--line);
  border-radius: var(--r);
  color: var(--ink-2);
  font-size: 12.5px;
  font-weight: 500;
  line-height: 1.15;
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--fast), color var(--fast), border-color var(--fast);
}

.btn:hover, .tool:hover { background: var(--raise); border-color: #3d4147; color: var(--ink); }
.btn:active, .tool:active { background: var(--raise-2); }

.btn svg, .tool svg { flex: none; opacity: .85; }

.btn--quiet { border-color: transparent; color: var(--ink-4); }
.btn--quiet:hover { border-color: transparent; color: var(--ink-2); }

.btn__note {
  font: 400 11px/1 var(--mono);
  color: var(--ink-4);
  font-variant-numeric: tabular-nums;
}

.tool { padding: 6px 10px; font-size: 12px; }

/* One selection language across the whole tool: amber wash, amber edge, amber
   label. It reads the same on a live toolbar mode as on the current series in
   the rail, so "on" and "selected" never have to be learned twice. */
.tool.is-on {
  background: var(--acc-wash);
  border-color: var(--acc-edge);
  color: var(--acc);
  font-weight: 600;
}
.tool.is-on:hover {
  background: rgba(243, 183, 67, .17);
  border-color: var(--acc);
  color: var(--acc-hi);
}
.tool.is-on svg { opacity: 1; }

/* --- shell --- */

.shell { flex: 1; display: flex; min-height: 0; }

/* --- rail --- */

.rail {
  width: 258px;
  flex: none;
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--chrome);
  border-right: 1px solid var(--line);
}

.rail__tabs {
  display: flex;
  gap: 2px;
  flex: none;
  padding: 8px;
  background: var(--chrome);
  border-bottom: 1px solid var(--line-soft);
}

.rail__tab {
  flex: 1;
  padding: 7px 8px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  color: var(--ink-3);
  font-size: 12.5px;
  font-weight: 500;
  cursor: pointer;
  transition: background var(--fast), color var(--fast);
}
.rail__tab:hover { background: var(--raise); color: var(--ink-2); }

.rail__tab[aria-selected="true"] {
  background: var(--raise-2);
  color: var(--ink);
  font-weight: 600;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .06);
}

.rail__list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 6px 8px 16px;
  /* Both edges fade, so a list that continues past them says so. The bottom
     fade lands on the 16px of trailing padding when the list already fits, so
     it costs nothing when there is nothing to scroll. Native scrollbar is off:
     its colour cannot be relied on across browsers, and a bright system bar
     down the side of the chrome would be the loudest thing on the screen. */
  mask-image: linear-gradient(to bottom, transparent 0, #000 9px,
                              #000 calc(100% - 15px), transparent 100%);
  scrollbar-width: none;
}
.rail__list::-webkit-scrollbar { display: none; }

.rail__group {
  display: flex;
  gap: 8px;
  align-items: center;
  padding: 14px 4px 6px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--ink-4);
}
.rail__group::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--line-soft);
}
.rail__group:first-child { padding-top: 6px; }

.series {
  display: flex;
  gap: 10px;
  align-items: center;
  width: 100%;
  padding: 5px;
  margin-bottom: 1px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--r);
  text-align: left;
  cursor: pointer;
  transition: background var(--fast), border-color var(--fast);
}

.series:hover { background: var(--raise); }

.series.is-current {
  background: var(--acc-wash);
  border-color: var(--acc-edge);
}
.series.is-current .series__name { color: var(--acc); font-weight: 600; }
.series.is-current .series__thumb { box-shadow: 0 0 0 1px var(--acc); }

.series--scout { opacity: .72; }
.series--scout:hover, .series--scout.is-current { opacity: 1; }

/* 46px is load-bearing: CELL_RAIL in app.js drives the sprite-sheet maths. */
.series__thumb {
  width: 46px;
  height: 46px;
  flex: none;
  border-radius: var(--r-sm);
  background-color: var(--void);
  background-position: 0 0;
  background-repeat: no-repeat;
  box-shadow: 0 0 0 1px var(--line-soft);
  transition: box-shadow var(--fast);
}

.series__text { display: grid; gap: 2px; min-width: 0; }

.series__name {
  font-size: 13px;
  font-weight: 500;
  color: var(--ink);
  letter-spacing: -.003em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: color var(--fast);
}

.series__sub {
  display: flex;
  gap: 6px;
  align-items: center;
  font-size: 11px;
  color: var(--ink-4);
  white-space: nowrap;
}
.series__sub b {
  font: 400 11px/1 var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink-3);
}
.series__sub i { font-style: normal; opacity: .55; }

/* --- stage --- */

.stage {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  background: var(--bg);
}

.stage__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex: none;
  padding: 7px 12px 7px 14px;
  background: var(--bg);
  border-bottom: 1px solid var(--line-soft);
}

.stage__where {
  display: flex;
  gap: 10px;
  align-items: center;
  min-width: 0;
  overflow: hidden;
}
.stage__where strong {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
}
.stage__where > span {
  flex: 0 1 auto;
  min-width: 0;
  font-size: 12.5px;
  color: var(--ink-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.stage__where strong + span::before {
  content: "";
  display: inline-block;
  width: 3px;
  height: 3px;
  margin-right: 10px;
  border-radius: 50%;
  background: var(--ink-4);
  vertical-align: middle;
}
/* Acquisition parameters read as an instrument print-out: mono chips, one fact
   each, quiet enough to ignore and precise enough to check. */
.stage__where em {
  display: flex;
  gap: 4px;
  flex: none;
  font-style: normal;
  overflow: hidden;
}
.stage__where em span {
  padding: 2px 6px;
  background: var(--raise);
  border-radius: 4px;
  font: 400 10.5px/1.35 var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink-3);
  white-space: nowrap;
}

.stage__tools { display: flex; gap: 4px; flex: none; }
.tool--wide { min-width: 66px; justify-content: center; }

/* --- panes --- */

.panes {
  flex: 1;
  display: grid;
  gap: 2px;
  padding: 2px;
  min-height: 0;
  background: var(--line-soft);
}
.panes--two { grid-template-columns: 1fr 1fr; }

.pane {
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: 0;
  min-width: 0;
  overflow: hidden;
  background: var(--void);
}

.pane__head {
  display: flex;
  gap: 9px;
  align-items: center;
  flex: none;
  padding: 6px 10px;
  background: rgba(13, 14, 17, .82);
  border-bottom: 1px solid var(--line-soft);
  font-size: 11.5px;
}

.pane__wrist {
  display: inline-flex;
  align-items: center;
  font-weight: 600;
  color: var(--ink-2);
  letter-spacing: .01em;
}
.pane__series {
  color: var(--ink-4);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.pane__slice {
  margin-left: auto;
  padding-left: 10px;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink-3);
}

.pane__view {
  position: relative;
  flex: 1;
  min-height: 0;
  overflow: hidden;
  touch-action: none;
  cursor: grab;
}
.pane__view.is-dragging { cursor: grabbing; }

.pane__img {
  /* Fill the viewport the way a reading workstation does. These are 288-640px
     acquisitions; shown at native size they are postage stamps.
     Pinned to the box rather than laid out in it: a percentage height inside an
     auto-sized track is circular, and the image ends up sized by its own aspect
     ratio and cropped by the pane whenever the pane is wider than it is tall. */
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
  image-rendering: auto;
  transform-origin: center;
  user-select: none;
  -webkit-user-drag: none;
}

.pane__load {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 2px;
  background: rgba(255, 255, 255, .06);
}
.pane__load i {
  display: block;
  height: 100%;
  width: 0;
  background: var(--acc);
  transition: width 140ms linear;
}
.pane__load.is-done { opacity: 0; transition: opacity .4s .2s; }

/* Compare: the active side is ringed in amber and the idle side recedes, so
   two stacks never read as one wide picture. */
.panes--two .pane { outline: 1px solid transparent; outline-offset: -1px; }
.panes--two .pane__head { background: var(--chrome); }
.panes--two .pane:not(.is-active) .pane__wrist { color: var(--ink-4); }
.panes--two .pane.is-active { outline-color: var(--acc-edge); }
.panes--two .pane.is-active .pane__head {
  background: var(--acc-wash);
  border-bottom-color: var(--acc-edge);
}
.panes--two .pane.is-active .pane__wrist { color: var(--acc); }

/* The link between the two stacks, drawn on the seam. It exists only while the
   stacks actually move together; the head bars open a gap to make room. */
.panes--two.panes--linked { position: relative; }
.panes--two.panes--linked .pane:first-child .pane__head { padding-right: 20px; }
.panes--two.panes--linked .pane:last-child .pane__head { padding-left: 20px; }
.panes--two.panes--linked::after {
  content: "";
  position: absolute;
  /* on the seam between the two head bars, never over anatomy */
  top: 4px;
  left: 50%;
  width: 22px;
  height: 22px;
  margin: 0 0 0 -11px;
  border-radius: 50%;
  background: var(--chrome) center / 13px 13px no-repeat
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23f3b743' stroke-width='1.5' stroke-linecap='round'%3E%3Cpath d='M6.4 9.6 9.6 6.4'/%3E%3Cpath d='M9.1 4.6 10.3 3.4a2.4 2.4 0 0 1 3.3 3.3L12.4 7.9'/%3E%3Cpath d='M6.9 11.4 5.7 12.6a2.4 2.4 0 0 1-3.3-3.3L3.6 8.1'/%3E%3C/svg%3E");
  box-shadow: 0 0 0 1px var(--acc-edge);
  pointer-events: none;
  z-index: var(--z-overlay);
}

/* --- dock: scrub, filmstrip, display --- */

.dock {
  flex: none;
  background: var(--chrome);
  border-top: 1px solid var(--line);
  padding-bottom: env(safe-area-inset-bottom);
}

.scrub {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 6px 16px 4px;
}
.scrub__range { flex: 1; min-width: 0; }

.scrub__count {
  flex: none;
  font-family: var(--mono);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--ink-3);
  letter-spacing: .02em;
}
.scrub__count #sliceNow { color: var(--acc); font-weight: 600; }
.scrub__count i { font-style: normal; color: var(--ink-4); padding: 0 2px; }

/* --- range inputs --- */

input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 20px;
  margin: 0;
  background: transparent;
  cursor: pointer;
  --fill: var(--ink-4);
  --thumb: var(--ink);
  --pct: 50;
}

/* Position in the stack is a point, not a quantity, so the slice control marks
   it with an amber handle and leaves the track neutral. The same amber marks
   the current thumbnail in the rail and the filmstrip: one colour, one meaning. */
input[type="range"].scrub__range { --thumb: var(--acc); }

input[type="range"]::-webkit-slider-runnable-track {
  height: 4px;
  border-radius: 99px;
  background:
    linear-gradient(to right, var(--fill) 0 calc(var(--pct) * 1%),
                              var(--raise-2) calc(var(--pct) * 1%) 100%);
}
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 13px;
  height: 13px;
  margin-top: -4.5px;
  border-radius: 50%;
  background: var(--thumb);
  border: 0;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .75), 0 1px 3px rgba(0, 0, 0, .6);
  transition: transform var(--fast), box-shadow var(--fast);
}
input[type="range"]:hover::-webkit-slider-thumb { transform: scale(1.15); }
input[type="range"]:active::-webkit-slider-thumb {
  transform: scale(1.15);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .75), 0 0 0 5px rgba(243, 183, 67, .2);
}
input[type="range"]:focus-visible { outline: none; }
input[type="range"]:focus-visible::-webkit-slider-thumb {
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .75), 0 0 0 4px var(--acc);
}

input[type="range"]::-moz-range-track {
  height: 4px;
  border-radius: 99px;
  background: var(--raise-2);
}
input[type="range"]::-moz-range-progress {
  height: 4px;
  border-radius: 99px;
  background: var(--fill);
}
input[type="range"]::-moz-range-thumb {
  width: 13px;
  height: 13px;
  border: 0;
  border-radius: 50%;
  background: var(--thumb);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .75), 0 1px 3px rgba(0, 0, 0, .6);
}
input[type="range"]:focus-visible::-moz-range-thumb {
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .75), 0 0 0 4px var(--acc);
}

/* Display controls are deliberately grey: amber is reserved for "where you
   are", so it never competes with "how it looks". */
.range--display { width: 104px; flex: none; }

/* --- filmstrip --- */

.strip {
  display: flex;
  gap: 2px;
  overflow-x: auto;
  overflow-y: hidden;
  padding: 4px 16px 6px;
  scroll-padding-inline: 16px;
  overscroll-behavior-x: contain;
  /* the ends fade, so a long stack visibly continues past the edge */
  mask-image: linear-gradient(to right, transparent 0, #000 22px,
                              #000 calc(100% - 22px), transparent 100%);
  /* No scrollbar here: the slider directly above is the same control with a
     handle, the strip re-centres itself on the current slice, and the faded
     ends already say "there is more". A 10px bar of browser furniture across
     the dock would only compete with the images. Wheel over the strip pans it
     (see app.js), so a mouse alone still gets there. */
  scrollbar-width: none;
}
.strip::-webkit-scrollbar { display: none; }

/* 52px is load-bearing: CELL_STRIP in app.js drives the sprite maths. */
.strip__t {
  width: 52px;
  height: 52px;
  flex: none;
  padding: 0;
  border: 0;
  border-radius: 3px;
  background-color: var(--void);
  background-repeat: no-repeat;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .05);
  opacity: .68;
  cursor: pointer;
  transition: opacity var(--fast), box-shadow var(--fast);
}
.strip__t:hover { opacity: .92; box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .3); }

.strip__t.is-current {
  opacity: 1;
  box-shadow: inset 0 0 0 2px var(--acc);
}

/* --- display adjustment --- */

.adjust {
  display: flex;
  gap: 8px 20px;
  align-items: center;
  flex-wrap: wrap;
  padding: 7px 16px 9px;
  border-top: 1px solid var(--line-soft);
  font-size: 12px;
  color: var(--ink-3);
}

.adjust label {
  display: flex;
  align-items: center;
  gap: 9px;
  font-weight: 500;
  color: var(--ink-3);
}

.adjust__group { display: flex; gap: 18px; align-items: center; flex: none; }

/* The honest caveat. It sits beside the two sliders it is about, at readable
   contrast, at every screen size. It is never hidden. */
.adjust__note {
  display: flex;
  gap: 7px;
  align-items: flex-start;
  flex: 1;
  min-width: 260px;
  font-size: 11.5px;
  line-height: 1.45;
  color: var(--ink-4);
  text-wrap: pretty;
}
.adjust__note svg { flex: none; margin-top: 1px; color: var(--acc-dim); }
.adjust__note b { font-weight: 600; color: var(--ink-3); }

/* --- dialogs --- */

.sheet {
  width: min(520px, calc(100vw - 32px));
  max-width: none;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--ink);
}
.sheet::backdrop { background: rgba(4, 5, 7, .74); }

.sheet__inner {
  background: var(--chrome);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: 0 30px 80px -30px rgba(0, 0, 0, .95);
  overflow: hidden;
}

.sheet__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 14px 14px 18px;
  border-bottom: 1px solid var(--line-soft);
}
.sheet__head h2 { font-size: 14px; font-weight: 600; letter-spacing: -.003em; }

.sheet__x {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  padding: 0;
  background: transparent;
  border: 0;
  border-radius: var(--r-sm);
  color: var(--ink-4);
  cursor: pointer;
  transition: background var(--fast), color var(--fast);
}
.sheet__x:hover { background: var(--raise); color: var(--ink); }

.sheet__body { padding: 4px 18px 18px; }

.sheet__sub {
  padding: 16px 0 7px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--ink-4);
}

.kv { display: grid; grid-template-columns: minmax(104px, auto) 1fr; font-size: 13px; }
.kv dt {
  padding: 7px 18px 7px 0;
  color: var(--ink-4);
  border-top: 1px solid var(--line-soft);
}
.kv dd {
  padding: 7px 0;
  color: var(--ink);
  border-top: 1px solid var(--line-soft);
}
.kv dt:first-of-type, .kv dd:first-of-type { border-top: 0; }
.kv--keys { grid-template-columns: minmax(128px, auto) 1fr; }
.kv--keys dt {
  display: flex;
  gap: 3px;
  align-items: center;
  flex-wrap: wrap;
  padding-right: 24px;
}
.kv--keys dd { color: var(--ink-2); }

kbd {
  display: inline-block;
  min-width: 22px;
  padding: 2px 6px;
  background: var(--raise);
  border: 1px solid var(--line);
  border-bottom-width: 2px;
  border-radius: 4px;
  font: 500 11px/1.55 var(--mono);
  text-align: center;
  color: var(--ink);
}
.kv--keys dt span { color: var(--ink-4); padding: 0 1px; }

.sheet__note {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--line-soft);
  font-size: 12px;
  line-height: 1.55;
  color: var(--ink-4);
  text-wrap: pretty;
}

/* --- motion --- */

.sheet[open] { animation: sheet-in 200ms var(--ease); }
.sheet[open]::backdrop { animation: fade-in 200ms var(--ease); }

@keyframes sheet-in {
  from { opacity: 0; transform: translateY(8px) scale(.99); }
  to   { opacity: 1; transform: none; }
}
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  .sheet[open] { animation: fade-in 1ms linear; }
}

/* ============================================================== responsive */

/* Laptop: give the stage back some pixels. */
@media (max-width: 1180px) {
  .rail { width: 224px; }
  .top__title { font-size: 13px; }
}

/* Small laptop / tablet landscape: the rail loses its metadata before it
   loses its thumbnails — the thumbnail is the fastest way to know a series. */
@media (max-width: 1024px) {
  .rail { width: 200px; }
  .series__sub i, .series__sub em { display: none; }
}

/* Drop acquisition chips from the right rather than clipping one mid-value —
   a half-printed matrix is worse than no matrix. */
@media (max-width: 1120px) {
  .stage__where em span:nth-child(n + 4) { display: none; }
}
@media (max-width: 980px) {
  .stage__where em span:nth-child(n + 3) { display: none; }
}

/* Tablet portrait and phone: the rail stops being a column and becomes a
   horizontal shelf, because vertical space is the scarce resource once the
   image has to share a screen with a stack of controls. */
@media (max-width: 900px) {
  .shell { flex-direction: column; }

  .rail {
    width: auto;
    flex: none;
    border-right: 0;
    border-bottom: 1px solid var(--line);
  }

  .rail__tabs { padding: 6px 10px; gap: 4px; border-bottom: 0; }
  .rail__tab { flex: 0 1 136px; }

  .rail__list {
    display: flex;
    gap: 6px;
    flex: none;
    padding: 0 10px 8px;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x proximity;
    scrollbar-width: none;
    mask-image: linear-gradient(to right, transparent 0, #000 14px,
                                #000 calc(100% - 14px), transparent 100%);
  }
  .rail__list::-webkit-scrollbar { display: none; }

  .rail__group { display: none; }

  .series {
    flex: none;
    width: 172px;
    margin-bottom: 0;
    background: var(--raise);
    scroll-snap-align: start;
  }
  .series:hover { background: var(--raise-2); }
  .series.is-current { background: var(--acc-wash); }

  .top { padding: 8px 12px; padding-top: max(8px, env(safe-area-inset-top)); }
  .top__meta span:nth-child(n + 3) { display: none; }

  .stage__bar { padding: 6px 10px; }
  .stage__where { flex: 1; }
  .stage__where em { display: none; }
  .stage__tools { overflow-x: auto; }

  .scrub { padding: 8px 12px 4px; }
  .strip { padding: 4px 12px 6px; }

  .adjust { padding: 8px 12px 10px; gap: 8px 16px; }
  .adjust__group { flex: 1; gap: 16px; }
  .range--display { flex: 1; width: auto; max-width: 180px; }
  .adjust__note { flex: 1 0 100%; min-width: 0; }
}

/* Phone. */
@media (max-width: 620px) {
  .top { flex-wrap: wrap; gap: 8px; }
  .top__id { flex: 1 1 100%; }
  .top__actions { flex: 1 1 100%; }
  .top__actions .btn { flex: 1; justify-content: center; }
  .top__meta span:nth-child(n + 2) { display: none; }

  .series { width: 152px; }

  /* The pane header directly below already names the wrist, and in compare mode
     the live side is the amber one — so the stage bar keeps only the series. */
  .stage__where strong { display: none; }
  .stage__where strong + span::before { display: none; }
  .adjust__group { flex: 1 0 100%; }
  .range--display { max-width: none; }
}

/* Touch: every control clears a 40px target. */
@media (pointer: coarse) {
  .btn, .tool { padding: 10px 13px; min-height: 40px; }
  .rail__tab { min-height: 40px; }
  input[type="range"] { height: 34px; }
  input[type="range"]::-webkit-slider-thumb { width: 18px; height: 18px; margin-top: -7px; }
  input[type="range"]::-moz-range-thumb { width: 18px; height: 18px; }
  .sheet__x { width: 40px; height: 40px; }
}

/* Short viewports — a phone held in landscape, or a tablet with the keyboard
   drawer open. Here the image is losing to the furniture, so the furniture is
   cut back hard: no filmstrip (the slider and counter still place you in the
   stack), no thumbnails in the rail, no duplicated pane header. The one thing
   that never goes is the display-adjustment caveat. */
@media (max-height: 620px) and (max-width: 900px) {
  .strip { display: none; }
  .top__meta { display: none; }

  .rail { flex-direction: row; align-items: stretch; }
  .rail__tabs {
    flex-direction: column;
    justify-content: center;
    gap: 3px;
    padding: 5px 8px;
    border-right: 1px solid var(--line-soft);
  }
  .rail__tab { flex: none; min-height: 0; padding: 4px 10px; font-size: 11.5px; }

  .rail__list { align-items: center; padding: 5px 8px; }
  .series { width: auto; max-width: 190px; padding: 6px 10px; }
  .series__thumb, .series__sub { display: none; }

  .panes:not(.panes--two) .pane__head { display: none; }
  .adjust { padding: 5px 12px 7px; }
}

/* Host-throttle notice. The shared host answers HTTP 468 to a client it thinks
   is fetching too fast; the loader backs off, and this says so rather than
   leaving a reader staring at an empty image well. */
.netnote {
  position: fixed;
  left: 50%;
  bottom: 18px;
  transform: translate(-50%, 12px);
  max-width: min(520px, calc(100vw - 32px));
  padding: 10px 16px;
  border: 1px solid var(--acc-edge);
  border-radius: var(--r);
  background: var(--chrome);
  color: var(--ink-2);
  font-size: 12.5px;
  line-height: 1.45;
  text-align: center;
  box-shadow: 0 8px 28px rgba(0, 0, 0, .55);
  opacity: 0;
  pointer-events: none;
  z-index: var(--z-overlay);
  transition: opacity var(--med), transform var(--med);
}

.netnote.is-on { opacity: 1; transform: translate(-50%, 0); }

/* The image well while its slice is still in flight. */
.pane.is-waiting .pane__img { opacity: .35; transition: opacity var(--fast); }
