/* webimage: the look of macroscope_v2's navigator and viewer.
 *
 * One CSS pixel is one Qt logical pixel of the macroscope (which runs at
 * QT_SCALE_FACTOR=1 on a 1920x1080 screen). The values come from
 * macroscope_v2/files/style.css, the layout code and the libgui widgets; see
 * the design document, section "Look and feel". Only the middle area scales
 * with the window; sidebars and everything in them are fixed.
 */

@font-face { font-family: "WI Ubuntu"; src: url(fonts/Ubuntu-R.ttf); font-weight: 400; font-style: normal; }
@font-face { font-family: "WI Ubuntu"; src: url(fonts/Ubuntu-B.ttf); font-weight: 700; font-style: normal; }
@font-face { font-family: "WI Ubuntu"; src: url(fonts/Ubuntu-RI.ttf); font-weight: 400; font-style: italic; }
@font-face { font-family: "WI Ubuntu"; src: url(fonts/Ubuntu-BI.ttf); font-weight: 700; font-style: italic; }
@font-face { font-family: "WI DejaVu Sans"; src: url(fonts/DejaVuSans.ttf); font-weight: 400; }
@font-face { font-family: "WI DejaVu Sans"; src: url(fonts/DejaVuSans-Bold.ttf); font-weight: 600 700; }
@font-face { font-family: "WI DejaVu Sans Mono"; src: url(fonts/DejaVuSansMono.ttf); }
/* Stand-in for Arial, which is proprietary: metric-compatible. */
@font-face { font-family: "WI Arial"; src: url(fonts/LiberationSans-Regular.ttf); font-weight: 400; }
@font-face { font-family: "WI Arial"; src: url(fonts/LiberationSans-Bold.ttf); font-weight: 700; }

:root {
  --sidebar-w: 120px;
  --sidebar-bg: #2315a2;
  --nav-bg: #1b117c;
  --view-bg: #130c58;
  --fg: #e0e0e0;
  --checked: #2196f3;
  --checked-viewer: var(--crumb-bg);     /* the macroscope has #ffcc00; light purple here */

  --font-ubuntu: "WI Ubuntu", sans-serif;
  --font-dejavu: "WI DejaVu Sans", sans-serif;
  --font-mono: "WI DejaVu Sans Mono", monospace;
  --font-arial: "WI Arial", Arial, sans-serif;

  --crumb-bg: #938af7;
  --crumb-fg: #3d34a5;
  --crumb-last: #150e63;

  --header-h: 63px;
  --row-h: 50px;
  --col-date: 320px;
  --col-size: 180px;

  --overlay-bg: rgba(0, 0, 0, 0.2);
}

html, body {
  margin: 0;
  height: 100%;
  overflow: hidden;
  background: var(--view-bg);
  color: var(--fg);
  font-family: var(--font-ubuntu);
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  overscroll-behavior: none;               /* no pull-to-refresh, which brings the URL bar back */
}

button { font: inherit; color: inherit; }

/* ---- screens and sidebars ---------------------------------------------- */

.screen {
  position: fixed;
  inset: 0;
  display: flex;
}
.screen[hidden] { display: none; }

.sidebar {
  width: var(--sidebar-w);
  flex: none;
  box-sizing: border-box;
  padding: 9px 0;                 /* QVBoxLayout margins */
  background: var(--sidebar-bg);
  display: flex;
  flex-direction: column;
  align-items: center;
  overflow-x: hidden;
  overflow-y: auto;               /* only when the window is too short */
  scrollbar-width: none;
}
.sidebar::-webkit-scrollbar { display: none; }
.sidebar > .stretch { flex: 1 0 0; }

.center {
  flex: 1;
  min-width: 0;
  position: relative;
  overflow: hidden;
}

/* GlowingSvgButton: icon tinted in the icon colour, bold label 10 below it,
 * padding 8. The icon box is the requested square; the SVG is scaled into it
 * keeping its aspect ratio and centred. No hover effect. */
.sbtn {
  appearance: none;
  border: 0;
  margin: 0;
  padding: 8px;
  background: none;
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  color: var(--fg);
  font: 700 16px/18px var(--font-arial);
  cursor: pointer;
}
.sbtn:focus { outline: none; }
.sbtn .ico {
  width: var(--isz);
  height: var(--isz);
  background-color: currentColor;
  -webkit-mask: var(--icon) center / contain no-repeat;
  mask: var(--icon) center / contain no-repeat;
}
.sbtn .lbl { margin-top: 10px; white-space: nowrap; }
.sbtn.checked { color: var(--checked); }
.viewer .sbtn.checked { color: var(--checked-viewer); }
.sbtn.inert { cursor: default; }

/* Channel toggles (libgui/toggle.py): 80x48 widget, label 3 below. */
.channels {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;                       /* grid spacing */
}
.channel {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.channel[hidden] { display: none; }
.channel.combined { margin-top: 32px; }
.toggle { display: block; cursor: pointer; }
.toggle.on { cursor: default; }
.toggle .track, .toggle .knob {
  transition: fill 200ms cubic-bezier(0.455, 0.03, 0.515, 0.955),
              stroke 200ms cubic-bezier(0.455, 0.03, 0.515, 0.955);
}
.toggle .handle { transition: transform 200ms cubic-bezier(0.455, 0.03, 0.515, 0.955); }
.toggle.on .handle { transform: translateX(var(--travel)); }
.channel .label {
  margin-top: 3px;
  font: 700 15px/17px var(--font-arial);
  color: #fff;
  white-space: nowrap;
}

/* ---- navigator --------------------------------------------------------- */

.nav-center {
  background: var(--nav-bg);
  box-sizing: border-box;
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.crumbrow { display: flex; align-items: flex-start; gap: 20px; flex: none; }
.crumbs {
  display: flex;
  align-items: center;
  min-width: 0;
  background: var(--crumb-bg);
  border-radius: 8px;
  padding: 4px 6px;
}
.crumb {
  appearance: none;
  border: 0;
  background: none;
  margin: 0;
  padding: 6px 10px;
  font: 400 36px/41px var(--font-ubuntu);
  color: var(--crumb-fg);
  white-space: nowrap;
  cursor: pointer;
}
.crumb:last-child { color: var(--crumb-last); }
.crumb:focus { outline: none; }
.crumb-sep { width: 2px; height: 34px; background: var(--crumb-fg); flex: none; }

/* Addition (design doc): a filter box, shown with Ctrl+F or "/". */
.filter {
  margin-left: auto;
  width: 360px;
  box-sizing: border-box;
  border: 0;
  border-radius: 8px;
  padding: 10px 16px;
  background: var(--crumb-bg);
  color: var(--crumb-last);
  font: 400 30px/41px var(--font-ubuntu);
  outline: none;
}
.filter::placeholder { color: var(--crumb-fg); opacity: 0.7; }
.filter[hidden] { display: none; }

.table {
  flex: 1;
  min-height: 0;
  position: relative;
}
.scroller {
  position: absolute;
  inset: 0;
  overflow-x: hidden;
  overflow-y: auto;
  scrollbar-color: var(--fg) transparent;
}
.scroller::-webkit-scrollbar { width: 24px; }
.scroller::-webkit-scrollbar-track { background: transparent; }
.scroller::-webkit-scrollbar-button { display: none; height: 0; }
.scroller::-webkit-scrollbar-thumb {
  border: 4px solid transparent;
  border-radius: 12px;
  box-shadow: inset 0 0 0 3px var(--fg);
  background: transparent;
  min-height: 40px;
}
.scroller:focus { outline: none; }

.cols {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--col-date) var(--col-size);
}
.thead {
  position: sticky;
  top: 0;
  z-index: 1;
  height: var(--header-h);
  box-sizing: border-box;
  border-bottom: 1px solid rgba(255, 255, 255, 0.3);
  background: var(--nav-bg);
}
.th {
  position: relative;
  padding: 16px 10px;
  font: 600 27px/31px var(--font-dejavu);
  letter-spacing: 1px;
  color: var(--fg);
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
}
.th .arrow {
  position: absolute;
  right: 12px;
  top: 25px;
  width: 18px;
  height: 12px;
}

.rows { position: relative; }
.row {
  position: absolute;
  left: 0;
  right: 0;
  height: var(--row-h);
  font: 400 30px/var(--row-h) var(--font-ubuntu);
  color: var(--fg);
  cursor: pointer;
}
.row.odd { background: rgba(0, 0, 0, 0.1); }
.row.selected::after {             /* addition: keyboard / last viewed */
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(255, 255, 255, 0.08);
  pointer-events: none;
}
.row.dim { color: rgba(224, 224, 224, 0.45); cursor: default; }
.cell { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cell.name { padding-left: 12px; display: flex; align-items: center; }
.cell.name .txt { margin-left: 3px; overflow: hidden; text-overflow: ellipsis; }
.cell.name .folder {
  width: 32px;
  height: 32px;
  flex: none;
  background-color: currentColor;
  -webkit-mask: url(icons/folder.svg) center / contain no-repeat;
  mask: url(icons/folder.svg) center / contain no-repeat;
}
.cell.date { padding-left: 15px; }
.cell.size { padding-right: 15px; text-align: right; }
.row.writing .cell.size { font-style: italic; }

.message {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  font: 400 30px/36px var(--font-ubuntu);
  color: var(--fg);
  pointer-events: none;
}
.message[hidden] { display: none; }
.message .title { font-weight: 700; }
.message .dots { display: inline-block; width: 1.2em; text-align: left; }
.nav-center .message { top: var(--header-h); }

/* ---- viewer -------------------------------------------------------------- */

.view-center { background: var(--view-bg); }
.view-center > canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  touch-action: none;
  display: block;
}
.view-center .message { background: var(--view-bg); }
.view-center .message .sub { font-weight: 400; }

/* InfoWidget: top left of the image area. */
.infoline {
  position: absolute;
  left: 0;
  top: 0;
  height: 54px;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  gap: 5px;
  /* left margin 15 + spacer 4; on the right the (empty) icon bar's spacing,
     then the 15 spacer */
  padding: 0 27px 0 19px;
  background: var(--overlay-bg);
  border-bottom-right-radius: 6px;
  font: 400 21px/24px var(--font-ubuntu);
  color: #fff;
  white-space: pre;
  pointer-events: none;
}
.infoline[hidden] { display: none; }
.infoline b { font-weight: 700; }
.infoline .text { margin-left: 5px; }   /* Qt's QLabel insets its text */
.infoline .icon {
  width: var(--isz);
  height: var(--isz);
  flex: none;
  background-color: #fff;
  -webkit-mask: var(--icon) center / contain no-repeat;
  mask: var(--icon) center / contain no-repeat;
}
.infoline .icon[hidden] { display: none; }

/* Scale bar and zoom percentage (libgui/scale_widget.py): bottom right. */
.scalebar {
  position: absolute;
  right: 0;
  bottom: 0;
  box-sizing: border-box;
  height: 56px;
  display: flex;
  align-items: flex-start;
  padding: 10px 16px 16px 20px;
  background: var(--overlay-bg);
  border-top-left-radius: 6px;
  color: #fff;
  pointer-events: none;
}
.scalebar[hidden] { display: none; }
.scalebar .ruler { display: flex; flex-direction: column; align-items: center; }
.scalebar .ruler[hidden] { display: none; }
.scalebar .label { font: 400 12px/14px var(--font-dejavu); white-space: nowrap; }
.scalebar .bar {
  position: relative;
  height: 11px;
  margin-top: 3px;
  box-sizing: border-box;
  border-left: 3px solid #fff;
  border-right: 3px solid #fff;
}
.scalebar .bar::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 4px;
  height: 3px;
  background: #fff;
}
.scalebar .pct {
  margin-left: 16px;
  position: relative;
  top: 4px;
  font: 400 21px/24px var(--font-dejavu);
  color: #c8c8c8;
  white-space: nowrap;
}

/* Addition: the z-slider for z-stacks (there is no rotary knob on the web).
 * Black and white only, so it does not compete with the image. It spans the
 * middle part of the height between the info line and the scale bar, and the
 * track runs down its middle. */
.zslider {
  --zspace: calc(100% - 130px);            /* below the info line, above the scale bar */
  --zinset: 40px;                          /* room above and below the track */
  position: absolute;
  right: 0;
  top: calc(64px + 0.1 * var(--zspace));
  height: calc(0.8 * var(--zspace));
  width: 96px;
  background: var(--overlay-bg);           /* like the info line and scale bar */
  border-radius: 6px 0 0 6px;
  opacity: 0;
  transition: opacity 200ms;
  touch-action: none;
  cursor: pointer;
}
.zslider.visible { opacity: 1; }
.zslider[hidden] { display: none; }
.zslider .ztrack {
  position: absolute;
  left: 46px;                              /* centred in the box */
  width: 4px;
  top: var(--zinset);
  bottom: var(--zinset);
  background: rgba(255, 255, 255, 0.175);  /* the part above the handle */
  border-radius: 2px;
}
.zslider .zfill {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  background: #fff;
  border-radius: 2px;
}
.zslider .zhandle {
  position: absolute;
  left: 47.8px;                            /* its tip just right of the track */
  width: 22.4px;
  height: 28.8px;
  margin-top: -14.4px;
  pointer-events: none;
}

/* The info line's IconBar: 10 between icons, after the text. */
.infoline .iconbar { display: flex; align-items: center; gap: 10px; margin-left: 5px; }
.infoline .iconbar[hidden] { display: none; }

/* ---- drawers (mazu/wm.py Drawer): centred, glued to the bottom ------------ */

.drawer {
  position: absolute;
  left: calc(50% - 530px);        /* where the macroscope puts the 1051-wide card */
  bottom: 0;
  z-index: 2;
  transform: translateY(100%);
  visibility: hidden;
  transition: transform 260ms cubic-bezier(0.215, 0.61, 0.355, 1), visibility 0s 260ms;
}
.drawer.open {
  transform: none;
  visibility: visible;
  transition: transform 260ms cubic-bezier(0.215, 0.61, 0.355, 1);
}
.drawer-card {
  display: flex;
  align-items: flex-start;
  box-sizing: border-box;
  padding: 20px;
  background: var(--sidebar-bg);
  border-radius: 8px 8px 0 0;
  box-shadow: 0 0 12px rgba(0, 0, 0, 0.35);
}

/* Histogram drawer: button, slider (700 wide), RESET, overexposure toggle,
 * 10 apart as in its QHBoxLayout (18 before the toggle box, which follows
 * two spacers). */
.histogram-drawer .drawer-card { width: 1051px; }
.histogram-drawer .drawer-button { width: 96px; margin-right: 10px; cursor: pointer; }
.histogram-drawer .hslider { display: block; flex: none; margin-right: 10px; touch-action: none; }
.histogram-drawer .reset {
  appearance: none;
  flex: none;
  align-self: center;
  width: 80px;
  height: 80px;
  margin: 0 18px 0 0;
  padding: 0;
  border: 0;
  border-radius: 5px;
  background: transparent;
  color: #e0e0e0;
  font: 700 18px/21px var(--font-dejavu);
  cursor: pointer;
}
.histogram-drawer .reset:focus { outline: none; }
.overexposure-box {
  flex: none;
  align-self: center;
  width: 86px;
  margin-right: 11px;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.overexposure-box .label {
  margin-top: 6px;
  font: 400 12px/14px var(--font-dejavu);
  color: #e0e0e0;
  text-align: center;
  white-space: pre;
}
.toggle.two-way, .toggle.two-way.on { cursor: pointer; }

/* ---- popups (macroscope_v2/make_popup.py) --------------------------------- */

.popup-backdrop {
  position: fixed;
  inset: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: center;
}
.popup-backdrop[hidden] { display: none; }
.popup {
  position: relative;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  background: var(--sidebar-bg);           /* the macroscope's popups are #333 */
  border-radius: 10px;
  box-shadow: 0 0 24px rgba(0, 0, 0, 0.6);
  padding: 15px 20px 20px;
}
.popup::before {                  /* the 2 px inset line */
  content: "";
  position: absolute;
  inset: 4px;
  border: 2px solid #999;
  border-radius: 8px;
  pointer-events: none;
}
.popup .header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 8px 0 0;                         /* the icon in line with the text below */
  font: 700 24px/30px var(--font-arial);
  color: #fff;
}
.popup .header .icon {
  width: 30px;
  height: 30px;
  background-color: #fff;
  -webkit-mask: var(--icon) center / contain no-repeat;
  mask: var(--icon) center / contain no-repeat;
}
.popup .buttons { display: flex; justify-content: flex-end; gap: 20px; margin-top: auto; }
.popup .large-button {
  appearance: none;
  height: 80px;
  padding: 0 20px;
  border: 0;
  border-radius: 5px;
  background: #444;
  color: #333;
  font: 400 36px/1 var(--font-arial);
  cursor: pointer;
}
.popup .large-button.active { background: var(--crumb-bg); }   /* the macroscope has #568dfd */
.popup .large-button:focus { outline: none; }
.info-popup { width: 800px; height: 640px; }
.info-popup .body .line { padding-left: var(--hang); text-indent: calc(-1 * var(--hang)); }
.info-popup .body .key { white-space: pre; }
.info-popup .body {
  flex: 1;
  min-height: 0;
  margin: 25px 0 4px;
  overflow-x: hidden;                       /* long lines wrap instead */
  overflow-y: auto;
  font: 400 16px/19px var(--font-mono);
  color: #eee;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  -webkit-user-select: text;
  user-select: text;
  scrollbar-color: #999 transparent;
}

.screen > .sidebar[hidden] { display: none; }

/* Tools drawer (run.py ToolsDrawer): Contrast and Measure, 20 apart, bottom
 * aligned, 10 in from the card's padding. Contrast is highlighted while on,
 * icon and label, like the sidebar buttons (the macroscope colours the icon only). */
.tools-drawer { left: calc(50% - 126px); }
.tools-drawer .drawer-card { width: 244px; align-items: flex-end; gap: 20px; padding: 20px 30px; }
.tools-drawer .tool.on { color: var(--checked-viewer); }

/* The ruler (libgui/ruler_overlay.py) takes all input over the image. */
.ruler-overlay { position: absolute; inset: 0; touch-action: none; }
.ruler-overlay[hidden] { display: none; }
.ruler-overlay svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }

/* ruler.py RulerOutput, in the left sidebar while measuring. */
.ruler-sidebar { align-items: stretch; padding-left: 9px; padding-right: 9px; }
.ruler-output { display: flex; flex-direction: column; gap: 4px; color: #e0e0e0; font: 400 15px/17px var(--font-arial); }
.ruler-output .distance-header { font-weight: 700; }
.ruler-output .distance { white-space: nowrap; }

/* The page: sized and transformed by ui.js, applyLayout() (turned for
 * portrait windows, scaled down for small ones). The screens and popups are
 * position: fixed, and a transformed ancestor contains fixed elements, so
 * they fill #app. */
#app {
  position: fixed;
  top: 0;
  left: 0;
  transform-origin: top left;
}

/* Phones and tablets: the opening screen with "Show fullscreen" (ui.js,
 * fullScreenGate). Outside #app, so it is never turned or scaled. */
.fullscreen-gate {
  position: fixed;
  inset: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--sidebar-bg);
}
.fullscreen-gate[hidden] { display: none; }
.fullscreen-gate button {               /* like the Image info popup's Ok button, rounder */
  appearance: none;
  height: 80px;
  padding: 0 30px;
  border: 0;
  border-radius: 10px;
  background: var(--crumb-bg);
  color: #333;
  font: 400 36px/1 var(--font-arial);
  cursor: pointer;
}
.fullscreen-gate button:focus { outline: none; }

/* iPhone Safari (ui.js, softFullScreen): the document can scroll, so that a
 * swipe up shrinks Safari's bars; the page itself (#app) is position: fixed. */
html.soft-fullscreen, html.soft-fullscreen body { height: auto; overflow: visible; }
.treadmill { height: calc(100vh + 200px); visibility: hidden; }
.fullscreen-gate.swipe { flex-direction: column; gap: 12px; color: #e0e0e0; text-align: center; }
.fullscreen-gate .arrow { font: 400 64px/1 var(--font-arial); }
.fullscreen-gate .hint { font: 400 30px/1.2 var(--font-arial); padding: 0 20px; }

/* ?layout-debug: what the browser reports (ui.js, layoutDebug). */
.layout-debug {
  position: fixed;
  left: 4px;
  top: 4px;
  z-index: 30;
  max-width: calc(100vw - 8px);
  padding: 6px 8px;
  background: rgba(0, 0, 0, 0.75);
  color: #ffe;
  font: 11px/1.35 var(--font-mono);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  pointer-events: none;
}

/* The viewer's loading indicator (busy.js): a turning ring in the middle of
 * the image area, on the translucent backing of the info line. */
.busy {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 72px;
  height: 72px;
  margin: -36px 0 0 -36px;
  border-radius: 50%;
  background: var(--overlay-bg);
  pointer-events: none;
}
.busy[hidden] { display: none; }
.busy::after {
  content: "";
  position: absolute;
  inset: 14px;
  border-radius: 50%;
  border: 5px solid rgba(224, 224, 224, 0.25);
  border-top-color: var(--fg);
  animation: busy-turn 0.9s linear infinite;
}
@keyframes busy-turn { to { transform: rotate(360deg); } }
