/* Layout only. No literal colour, font, image, border width, radius or
 * shadow here: everything of that kind is a --wb-* token set by a theme in
 * static/themes/ (PLAN.md S16). */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  overflow-x: hidden;
}

body {
  min-height: 100vh;
  font-family: var(--wb-font-ui);
  font-size: var(--wb-font-size);
  color: var(--wb-ink);
  background-color: var(--wb-wallpaper-color);
  background-image: var(--wb-wallpaper-image);
  background-size: var(--wb-wallpaper-size);
}

.wb-page {
  min-height: 100vh;
}

/* a page without the logo: the tab strip stands alone, on the right, and the height the stages
   subtract for the header is the strip's */
.wb-page-bare {
  --wb-logo-height: var(--wb-tab-size);
}

.wb-page-bare .wb-header {
  justify-content: flex-end;
}

.wb-header {
  display: flex;
  flex-flow: row wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--wb-tab-gap);
  padding: var(--wb-tab-gap);
}

.wb-logo {
  display: block;
  height: var(--wb-logo-height);
  aspect-ratio: 976 / 362;
  background: var(--wb-logo-image) no-repeat left center / contain;
}

/* tabs: a wrapping row, so labels are never cut off on a phone */
.wb-tabs {
  display: flex;
  flex-flow: row wrap;
  justify-content: flex-end;
  gap: var(--wb-tab-gap);
  margin: 0;
  padding: 0;
  list-style: none;
}

.wb-tab {
  min-width: var(--wb-tab-size);
  height: var(--wb-tab-size);
  overflow: hidden;
  background: var(--wb-accent);
  color: var(--wb-accent-ink);
  border-radius: var(--wb-radius-tab);
  transition: height var(--wb-tab-time) var(--wb-tab-ease);
}

.wb-tab:hover,
.wb-tab:focus-within,
.wb-tab-active {
  height: var(--wb-tab-size-open);
}

.wb-tab > a,
.wb-tab > .wb-tab-button,
.wb-tab-lang > .wb-tab-label {
  display: block;
  padding: 0 0.25em;
  color: inherit;
  text-decoration: none;
}

.wb-tab > .wb-tab-button {
  width: 100%;
  font: inherit;
  background: none;
  border: 0;
  cursor: pointer;
}

.wb-tab-label {
  display: block;
  font-size: min(var(--wb-font-size-tab), 8vw);
  line-height: var(--wb-tab-size);
  text-align: center;
}

.wb-tab:hover .wb-tab-label,
.wb-tab-active .wb-tab-label {
  text-shadow: var(--wb-tab-glow);
}

/* the caption wraps inside the label's width instead of widening the tab */
.wb-tab-caption {
  display: block;
  width: 0;
  min-width: 100%;
  padding-bottom: 0.4em;
  font-size: var(--wb-font-size-small);
  line-height: 1.2;
}

.wb-tab:focus-within {
  outline: var(--wb-border-width) solid var(--wb-ink);
}

/* language tab: one flag per locale */
.wb-flags {
  display: flex;
  padding-top: var(--wb-tab-gap);
  flex-flow: row wrap;
  justify-content: center;
  gap: var(--wb-tab-gap);
}

.wb-flag {
  display: block;
  color: inherit;
}

.wb-flag > img {
  display: block;
  width: 24px;
  height: auto;
}

.wb-flag[aria-current] > img {
  outline: var(--wb-border-width) solid var(--wb-accent-ink);
  outline-offset: 1px;
}

.wb-content {
  padding: 0 10px;
}

/* visually hidden but focusable (the file input behind its label) */
.wb-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* upload area */
.wb-upload {
  margin-top: var(--wb-tab-gap);
}

.wb-drop {
  display: flex;
  flex-flow: column nowrap;
  align-items: center;
  justify-content: center;
  min-height: 290px;
  padding: 16px;
  text-align: center;
  border: var(--wb-frame-width) var(--wb-frame-style) var(--wb-ink);
  border-radius: var(--wb-radius-frame);
}

.wb-drop-over {
  border-style: var(--wb-frame-drag-style);
  border-color: var(--wb-accent);
  background: var(--wb-drop-fill);
}

.wb-drop-icon {
  width: 70px;
  height: 70px;
  background: var(--wb-icon-upload) center / contain no-repeat;
}

.wb-drop-text {
  margin: 12px 0 0;
  font-size: var(--wb-font-size-lead);
}

.wb-drop-or {
  margin: 8px 0;
  font-size: var(--wb-font-size-label);
}

.wb-button {
  display: block;
  max-width: 250px;
  padding: 7px 12px;
  font-size: var(--wb-font-size-button);
  text-align: center;
  color: var(--wb-accent-ink);
  background: var(--wb-accent);
  border-radius: var(--wb-radius-frame);
  cursor: pointer;
}

.wb-button:hover {
  background: var(--wb-accent-hover);
}

.wb-button:focus-within,
.wb-sr-only:focus + .wb-button {
  outline: var(--wb-border-width) solid var(--wb-ink);
  outline-offset: 2px;
}

.wb-upload-note,
.wb-upload-count {
  margin: 8px 0 0;
  text-align: left;
}

.wb-quickadd {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin: 0 0 8px;
}

.wb-editor-addbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 10px;
  margin: 0 0 8px;
}

.wb-editor-addbar .wb-quickadd {
  margin: 0;
}

.wb-quickadd-button {
  cursor: pointer;
}

.wb-quickadd-disabled {
  opacity: 0.5;
  pointer-events: none;
}

/* grid of cards */
.wb-cards {
  display: grid;
  grid-template-columns: repeat(var(--wb-card-columns), minmax(0, 1fr));
  gap: var(--wb-card-gap);
  margin: var(--wb-card-gap) 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 480px) {
  .wb-cards {
    grid-template-columns: repeat(var(--wb-card-columns-mid), minmax(0, 1fr));
  }
}

@media (min-width: 700px) {
  .wb-cards {
    grid-template-columns: repeat(var(--wb-card-columns-wide), minmax(0, 1fr));
  }
}

.wb-card {
  display: flex;
  flex-flow: column nowrap;
  min-width: 0;
  text-align: left;
}

.wb-card-box {
  position: relative;
  aspect-ratio: 1;
  border: var(--wb-border-width) solid var(--wb-ink);
  box-shadow: var(--wb-shadow-card);
  background: var(--wb-card-ground);
}

/* a picked card: a crimson and cream dashed border (it used to march; 20 picked
   cards animating at once made a phone crawl); a card a drag is over right now has it too */
.wb-card-selected > .wb-card-box,
.wb-card-ranging > .wb-card-box {
  box-shadow: var(--wb-shadow-select);
}

.wb-card-selected > .wb-card-box::after,
.wb-card-ranging > .wb-card-box::after {
  --pick-a: var(--wb-pick);
  --pick-b: var(--wb-pick-ground);
  content: '';
  position: absolute;
  inset: -4px;
  z-index: 1;
  pointer-events: none;
  background:
    repeating-linear-gradient(90deg, var(--pick-a) 0 8px, var(--pick-b) 8px 16px) 0 0 / 100% 4px no-repeat,
    repeating-linear-gradient(90deg, var(--pick-a) 0 8px, var(--pick-b) 8px 16px) 0 100% / 100% 4px no-repeat,
    repeating-linear-gradient(0deg, var(--pick-a) 0 8px, var(--pick-b) 8px 16px) 0 0 / 4px 100% no-repeat,
    repeating-linear-gradient(0deg, var(--pick-a) 0 8px, var(--pick-b) 8px 16px) 100% 0 / 4px 100% no-repeat;
}

.wb-card-face {
  position: absolute;
  inset: 0;
  display: block;
  margin: 0;
  padding: 0;
  overflow: hidden;
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  cursor: grab;
  touch-action: pan-y; /* a sideways swipe over cards chooses a run (cardrange.js); up and down scrolls */
}

.wb-card-image {
  display: block;
  width: 100%;
  height: 100%;
  pointer-events: none;
  transition: transform 0.2s;
}

/* the photo always fills the square; its crop slides along the long edge (EDITOR.md S2.5) */
.wb-card-image {
  object-fit: cover;
}

.wb-card-pan-x .wb-card-face {
  cursor: ew-resize;
  touch-action: pan-y;
}

.wb-card-pan-y .wb-card-face {
  cursor: ns-resize;
  touch-action: pan-x;
}

.wb-card-used .wb-card-face {
  cursor: default;
}

.wb-card-nopreview {
  display: block;
  padding: 4px;
  font-size: var(--wb-font-size-small);
}

/* the icons scale with the card: a quarter of its width, 18-26px */
.wb-card-box {
  container-type: inline-size;
  --wb-card-icon: clamp(18px, 24cqw, 26px);
}

/* round icon buttons down the right edge: remove, rotate, add */
.wb-round,
.wb-card-add {
  position: absolute;
  right: 2px;
  width: var(--wb-card-icon);
  height: var(--wb-card-icon);
  padding: 0;
  cursor: pointer;
}

.wb-round {
  border: var(--wb-border-width) outset var(--wb-button-round-border);
  border-radius: var(--wb-radius-round);
}

.wb-card-remove {
  top: 2px;
  background: var(--wb-icon-delete) center / 80% no-repeat, var(--wb-button-round-bg);
}

.wb-card-rotate {
  top: calc(var(--wb-card-icon) + 4px);
  background: var(--wb-icon-rotate) center / 80% no-repeat, var(--wb-button-round-bg);
}

.wb-round:hover {
  background-color: var(--wb-button-round-hover);
}

.wb-round:active {
  border-style: inset;
}

/* "add to node": a bold green plus, as big as the rotate arrow */
.wb-card-add {
  top: calc(2 * var(--wb-card-icon) + 6px);
  font-size: 0;
  background: linear-gradient(var(--wb-add-ink), var(--wb-add-ink)) center / 80% 26% no-repeat, linear-gradient(var(--wb-add-ink), var(--wb-add-ink)) center / 26% 80% no-repeat;
  border: 0;
  filter: drop-shadow(0 0 1px var(--wb-button-round-border)) drop-shadow(0 0 1px var(--wb-button-round-border));
}

.wb-card-add:hover {
  filter: drop-shadow(0 0 2px var(--wb-button-round-hover)) drop-shadow(0 0 1px var(--wb-ink));
}

/* a double arrow in the lower left corner says which way the crop can be moved;
   shown where there is no mouse cursor to say it (touch), see the media query */
.wb-card-pan {
  display: none;
  position: absolute;
  bottom: 3px;
  left: 3px;
  width: calc(var(--wb-card-icon) * 1.3);
  height: calc(var(--wb-card-icon) * 0.7);
  pointer-events: none;
  background: var(--wb-pan-ink);
  filter: drop-shadow(0 0 1px var(--wb-ink)) drop-shadow(0 0 1px var(--wb-ink));
}

.wb-card-pan-icon-x {
  clip-path: polygon(0 50%, 28% 0, 28% 30%, 72% 30%, 72% 0, 100% 50%, 72% 100%, 72% 70%, 28% 70%, 28% 100%);
}

.wb-card-pan-icon-y {
  width: calc(var(--wb-card-icon) * 0.7);
  height: calc(var(--wb-card-icon) * 1.3);
  clip-path: polygon(50% 0, 100% 28%, 70% 28%, 70% 72%, 100% 72%, 50% 100%, 0 72%, 30% 72%, 30% 28%, 0 28%);
}

@media (pointer: coarse) {
  .wb-card-pan {
    display: block;
  }
}

[draggable='true'] {
  cursor: grab;
}

.wb-card-name,
.wb-card-size {
  overflow: hidden;
  font-size: var(--wb-font-size-small);
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* upload progress and state */
.wb-card-progress {
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  height: 6px;
  background: var(--wb-ink-soft);
}

.wb-card-progress-bar {
  height: 100%;
  background: var(--wb-accent);
  transition: width 0.15s linear;
}

.wb-card-failed > .wb-card-box {
  outline: var(--wb-select-width) solid var(--wb-error-frame);
}

.wb-card-queued .wb-card-image,
.wb-card-uploading .wb-card-image,
.wb-card-processing .wb-card-image {
  opacity: 0.6;
}

.wb-card-status {
  font-size: var(--wb-font-size-small);
  overflow-wrap: anywhere;
}

.wb-card-retry {
  align-self: flex-start;
  margin-top: 2px;
  padding: 1px 6px;
  font: inherit;
  font-size: var(--wb-font-size-small);
  color: var(--wb-accent-ink);
  background: var(--wb-accent);
  border: 0;
  cursor: pointer;
}

.wb-card-retry:hover {
  background: var(--wb-accent-hover);
}

/* "New node" tile: the last cell of the upload grid */
.wb-new-node {
  display: flex;
  flex-flow: column nowrap;
  align-items: center;
  justify-content: center;
  gap: 4px;
  width: 100%;
  margin: 0;
  padding: 8px;
  font: inherit;
  color: inherit;
  cursor: pointer;
  border: var(--wb-frame-width) var(--wb-frame-drag-style) var(--wb-ink);
  border-radius: var(--wb-radius-frame);
}

.wb-new-node:hover,
.wb-new-node-open {
  color: var(--wb-accent-ink);
  background: var(--wb-accent);
  border-style: var(--wb-frame-style);
}

.wb-new-node:focus-visible {
  outline: var(--wb-select-width) solid var(--wb-select);
  outline-offset: 2px;
}

.wb-new-node-plus {
  font-size: clamp(24px, 40cqw, 48px);
  line-height: 1;
}

.wb-new-node-label {
  font-size: clamp(10px, 12cqw, var(--wb-font-size-button));
  line-height: 1.1;
  text-align: center;
}

/* never taller than the photo cards beside it: the tile keeps the square box
   and its contents shrink with the card width */
.wb-card-new > .wb-card-box {
  height: auto;
  min-height: 0;
  padding: 4px;
  overflow: hidden;
}

/* node editor frame (EDITOR.md S2.2); colours and sizes are tokens (E44) */
.wb-editor {
  margin: 0;
  padding: 8px;
  text-align: left;
}

.wb-editor-head {
  display: flex;
  gap: 8px;
  margin-bottom: 8px;
}

.wb-editor-title {
  flex: 1;
  min-width: 0;
}

.wb-editor-title input {
  box-sizing: border-box;
  width: 100%;
  padding: 6px 8px;
  font: inherit;
  color: inherit;
  background: var(--wb-card-ground);
  border: var(--wb-border-width) solid var(--wb-ink);
  border-radius: var(--wb-radius-frame);
}

.wb-editor-close,
.wb-editor-button {
  font: inherit;
  color: var(--wb-accent-ink);
  background: var(--wb-accent);
  border: 0;
  border-radius: var(--wb-radius-frame);
  cursor: pointer;
}

.wb-editor-close {
  padding: 6px 12px;
}

.wb-editor-close:hover {
  background: var(--wb-accent-hover);
}

.wb-editor-button {
  min-width: var(--wb-editor-tool-size);
  min-height: var(--wb-editor-tool-size);
  padding: 4px;
}

.wb-editor-tool {
  position: relative;
}

.wb-editor-tool-icon {
  display: block;
  width: 24px;
  height: 24px;
  margin: 0 auto;
  background: currentcolor;
  -webkit-mask: var(--wb-icon-tool) center / contain no-repeat;
  mask: var(--wb-icon-tool) center / contain no-repeat;
}

.wb-editor-tool-select { --wb-icon-tool: var(--wb-icon-tool-select); }
.wb-editor-tool-pen { --wb-icon-tool: var(--wb-icon-tool-pen); }
.wb-editor-tool-shape { --wb-icon-tool: var(--wb-icon-tool-shape); }
.wb-editor-tool-clip { --wb-icon-tool: var(--wb-icon-tool-clip); }
.wb-editor-undo { --wb-icon-tool: var(--wb-icon-tool-undo); }
.wb-editor-redo { --wb-icon-tool: var(--wb-icon-tool-redo); }
.wb-editor-add-page { --wb-icon-tool: var(--wb-icon-tool-page); }
.wb-editor-delete { --wb-icon-tool: var(--wb-icon-tool-delete); }
.wb-editor-save { --wb-icon-tool: var(--wb-icon-tool-save); }
.wb-editor-tool-wand { --wb-icon-tool: var(--wb-icon-tool-wand); }
.wb-editor-tool-unclip { --wb-icon-tool: var(--wb-icon-tool-unclip); }
.wb-editor-tool-text { --wb-icon-tool: var(--wb-icon-tool-text); }
.wb-editor-dropper { --wb-icon-tool: var(--wb-icon-tool-dropper); }

.wb-editor-dropper > .wb-editor-tool-icon {
  width: 20px;
  height: 20px;
}

.wb-editor-tool-key {
  position: absolute;
  right: 3px;
  bottom: 1px;
  font-size: var(--wb-font-size-small);
  opacity: 0.7;
}

/* the active tool */
.wb-editor-button[aria-pressed='true'] {
  outline: var(--wb-select-width) solid var(--wb-select);
  background: var(--wb-select-fill);
}

/* the cursor of the active tool, shown over the stage */
.wb-editor-cursor-select { cursor: default; }
.wb-editor-cursor-pen,
.wb-editor-cursor-wand,
.wb-editor-cursor-shape { cursor: crosshair; }
.wb-editor-cursor-clip,
.wb-editor-cursor-unclip { cursor: pointer; }
.wb-editor-cursor-text { cursor: text; }

.wb-editor-button:disabled {
  opacity: 0.5;
  cursor: default;
}

.wb-editor-body {
  display: flex;
  flex-flow: column nowrap;
  gap: var(--wb-editor-gap);
}

/* the tools are rows above and below the stage, wrapping; in landscape they
   become the columns beside it (see the landscape block) */
.wb-editor-tools,
.wb-editor-actions {
  display: flex;
  flex-flow: row wrap;
  gap: 4px;
}

.wb-editor-stage {
  display: flex;
  width: 100%;
  align-items: center;
  justify-content: center;
  aspect-ratio: 1;
  background: var(--wb-card-ground);
  border: var(--wb-border-width) solid var(--wb-ink);
  box-shadow: var(--wb-shadow-card);
}

.wb-editor-stage {
  position: relative;
  overflow: hidden;
  touch-action: none;
}

.wb-node {
  width: 100%;
  height: 100%;
}

.wb-editor-stage svg {
  display: block;
  width: 100%;
  height: 100%;
}

.wb-editor-stage-over {
  outline: var(--wb-select-width) solid var(--wb-select);
}

.wb-editor-overlay {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* the overlay only takes pointer events while a tool is active */
.wb-editor-interactive {
  pointer-events: auto;
}

.wb-editor-stage-hint {
  position: absolute;
  pointer-events: none;
  opacity: 0.6;
}

.wb-editor-pen-options {
  display: flex;
  gap: 12px;
  align-items: center;
  margin-top: 8px;
}

.wb-editor-context {
  margin: 8px 0 0;
  min-height: 1.4em;
}

.wb-editor-pages {
  display: flex;
  gap: 4px;
  margin-top: 8px;
}

/* film-strip (E53): a row under the stage, a column beside it when wide */
.wb-editor-strip {
  display: flex;
  flex-flow: row nowrap;
  gap: var(--wb-editor-gap);
  margin: var(--wb-editor-gap) 0 0;
  padding: 0;
  overflow-x: auto;
  list-style: none;
}

.wb-editor-strip-item {
  flex: 0 0 auto;
  display: flex;
  flex-flow: column nowrap;
  gap: 4px;
  width: 88px;
}

.wb-editor-strip-pick {
  padding: 0;
  border: var(--wb-frame-width) var(--wb-frame-style) var(--wb-ink);
  background: none;
  cursor: grab;
}

.wb-editor-strip-selected .wb-editor-strip-pick {
  outline: 3px solid var(--wb-select);
}

.wb-editor-strip-drag {
  opacity: 0.4;
}

.wb-editor-strip-pick img {
  display: block;
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
}

.wb-editor-strip-tools {
  display: flex;
  justify-content: space-between;
}

.wb-editor-strip-tools .wb-editor-chip {
  min-width: 0;
  padding: 2px 6px;
}

/* palette (E54): the target chip and two rows of four swatches */
.wb-editor-palette {
  display: flex;
  flex-flow: row wrap;
  gap: var(--wb-editor-gap);
  align-items: center;
  margin-top: var(--wb-editor-gap);
}

.wb-editor-swatches {
  display: grid;
  grid-template-columns: repeat(4, 36px);
  gap: 4px;
}

.wb-editor-swatch {
  width: 36px;
  height: 36px;
  padding: 0;
  border: var(--wb-swatch-border);
  cursor: pointer;
}

.wb-editor-swatch[aria-pressed='true'] {
  outline: 3px solid var(--wb-select);
}

.wb-editor-popover-left {
  right: auto;
  left: 0;
}

/* the title row: the title, and right of it the gallery's icon buttons */
.wb-node-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--wb-tab-gap);
}

.wb-node-head .wb-node-title {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.wb-gallery-tools,
.wb-gallery-nav {
  display: flex;
  flex: none;
  align-items: center;
  gap: var(--wb-tab-gap);
}

/* the row under the stage: the edit button, and right of it the previous / next picture */
.wb-node-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--wb-tab-gap);
  margin: 1em 0;
}

.wb-node-foot .wb-gallery-nav {
  flex: 1;
  justify-content: flex-end;
  min-width: 0;
}

.wb-node-foot .wb-gallery-count {
  flex: 0 1 auto;
  max-width: none;
}

.wb-icon-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  padding: 0;
}

.wb-icon-button svg {
  width: 24px;
  height: 24px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.wb-node-title {
  margin: 8px 0;
  font-size: var(--wb-font-size-lead);
}

.wb-link {
  cursor: pointer;
}

.wb-link:hover,
.wb-link:focus-visible {
  text-decoration: underline;
}

.wb-node-view {
  aspect-ratio: 1;
  /* header and title stay in view with the stage: only the edit button is below the fold */
  width: min(100%, max(240px, calc(100vh - var(--wb-logo-height) - 3 * var(--wb-tab-gap) - 4.5em)));
  width: min(100%, max(240px, calc(100dvh - var(--wb-logo-height) - 3 * var(--wb-tab-gap) - 4.5em)));
  margin: 0 auto;
  overflow: hidden;
  background: var(--wb-card-ground);
  border: var(--wb-border-width) solid var(--wb-ink);
  box-shadow: var(--wb-shadow-card);
}

/* the 3D gallery in the node's square (GALLERY.md, 13.6); .wb-gallery-fill is the page-filling fallback */
.wb-gallery {
  position: relative;
  aspect-ratio: 1;
  --wb-fit: calc(100vh - var(--wb-logo-height) - 3 * var(--wb-tab-gap) - 4.5em); /* until GalleryView.js has measured it */
  width: min(100%, max(240px, var(--wb-fit)));
  margin: 0 auto;
  overflow: hidden;
  color: var(--wb-gallery-ink);
  background: var(--wb-gallery-ground);
  border: var(--wb-border-width) solid var(--wb-ink);
  box-shadow: var(--wb-shadow-card);

  /* a long press is a control here (the flight stick, the chips), never a text selection or a callout */
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
}

.wb-gallery {
  transition: width 0.7s ease, aspect-ratio 0.7s ease;
}

/* a gallery node once the visitor walks: the stage grows to the left and right and is no longer square.
   Its height is the one the square has, so the menu bar, the node title and the stage fit the screen */
.wb-gallery-wide {
  --wb-stage-h: max(240px, var(--wb-fit));
  --wb-wide: min(96vw, 1500px, calc(var(--wb-stage-h) * 16 / 9));

  width: var(--wb-wide);
  margin-left: calc(50% - var(--wb-wide) / 2);
  aspect-ratio: 16 / 9;
}

@supports (height: 100dvh) {
  .wb-gallery {
    --wb-fit: calc(100dvh - var(--wb-logo-height) - 3 * var(--wb-tab-gap) - 4.5em);
  }
}

/* a phone held upright: the stage fills the height between the title and the edit button
   (GalleryView.js measures it into --wb-fit), so the page needs no scrolling */
@media (orientation: portrait) and (max-width: 900px) {
  .wb-gallery:not(.wb-gallery-fill):not(:fullscreen) {
    width: 100%;
    height: var(--wb-fit);
    min-height: 240px;
    margin-left: 0;
    aspect-ratio: auto;
  }
}

.wb-gallery-poster {
  position: relative;
  width: min(100%, max(240px, calc(100vh - var(--wb-logo-height) - 3 * var(--wb-tab-gap) - 4.5em)));
  width: min(100%, max(240px, calc(100dvh - var(--wb-logo-height) - 3 * var(--wb-tab-gap) - 4.5em)));
  margin: 0 auto;
}

.wb-gallery-poster .wb-node-view {
  width: 100%;
}

.wb-gallery-enter {
  position: absolute;
  bottom: 12px;
  left: 50%;
  transform: translateX(-50%);
}

.wb-gallery-enter.wb-gallery-enter-inline {
  position: static;
  transform: none;
}

.wb-gallery-hud {
  position: absolute;
  right: 8px;
  bottom: 8px;
  left: 8px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 6px;
}

.wb-gallery-count {
  max-width: 60%;
  padding: 4px 10px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--wb-gallery-label-ink);
  background: var(--wb-gallery-label-ground);
  border: 1px solid var(--wb-gallery-label-ink);
}

.wb-gallery-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: var(--wb-tab-gap);
  margin: 0;
  padding: 0;
  list-style: none;
}

.wb-gallery-grid img {
  display: block;
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border: var(--wb-border-width) solid var(--wb-ink);
  box-shadow: var(--wb-shadow-card);
}

.wb-gallery:fullscreen,
.wb-gallery-fill {
  position: fixed;
  inset: 0;
  z-index: 100;
  width: 100%;
  height: 100vh;
  height: 100dvh;
  aspect-ratio: auto;
  margin: 0;
  border: 0;
}

.wb-gallery-canvas {
  display: block;
  width: 100%;
  height: 100%;
  outline: none;
  touch-action: none;
  user-select: none;
}

/* the lens: a vignette and a soft blur toward the edges while the camera glides from picture to picture */
.wb-gallery-lens {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(ellipse at center, transparent 48%, var(--wb-gallery-note) 100%);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
  -webkit-mask-image: radial-gradient(ellipse at center, transparent 38%, var(--wb-ink) 100%);
  mask-image: radial-gradient(ellipse at center, transparent 38%, var(--wb-ink) 100%);
}

/* the thumb stick on a touch screen: a ring where the thumb landed, a knob under it */
.wb-gallery-stick {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.wb-gallery-stick[hidden] {
  display: none;
}

.wb-gallery-stick span {
  position: absolute;
  border-radius: 50%;
}

.wb-gallery-stick span:first-child {
  border: 2px solid var(--wb-accent);
  opacity: 0.55;
}

.wb-gallery-stick span:last-child {
  background: var(--wb-accent);
  opacity: 0.75;
}

.wb-gallery-lens[hidden] {
  display: none;
}

.wb-gallery-bar {
  position: absolute;
  top: 8px;
  right: 8px;
  display: flex;
  gap: 6px;
}

.wb-gallery-aids {
  position: absolute;
  top: 8px;
  left: 8px;
  z-index: 4;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 4px 8px;
  font-family: monospace;
  font-size: 0.85em;
  color: var(--wb-gallery-ink);
  background: var(--wb-gallery-note);
  pointer-events: none;
}

.wb-gallery-aids[hidden] {
  display: none;
}

.wb-gallery-aids[data-warn='sink'] {
  color: var(--wb-ink);
  background: var(--wb-accent);
}

.wb-gallery-medal {
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 5;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  max-width: 80%;
  transform: translate(-50%, -50%);
  animation: wb-medal-in 0.9s cubic-bezier(0.2, 1.4, 0.4, 1) both;
  cursor: pointer;
}

.wb-gallery-medal p {
  margin: 0;
  padding: 4px 12px;
  text-align: center;
  color: var(--wb-gallery-ink);
  background: var(--wb-gallery-note);
}

.wb-medal-graphic {
  width: min(42vw, 150px);
  height: auto;
  filter: drop-shadow(0 6px 12px var(--wb-gallery-note));
}

.wb-medal-shine {
  animation: wb-medal-shine 2.2s 0.9s ease-in-out infinite;
}

@keyframes wb-medal-in {
  from {
    opacity: 0;
    transform: translate(-50%, -160%) rotate(-14deg) scale(0.6);
  }

  to {
    opacity: 1;
    transform: translate(-50%, -50%) rotate(0) scale(1);
  }
}

@keyframes wb-medal-shine {
  from {
    transform: translateX(0) skewX(-20deg);
  }

  60%,
  to {
    transform: translateX(150px) skewX(-20deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  .wb-gallery-medal,
  .wb-medal-shine {
    animation: none;
  }
}

.wb-gallery-note {
  position: absolute;
  right: 8px;
  bottom: 56px;
  left: 8px;
  margin: 0;
  padding: 6px 10px;
  text-align: center;
  background: var(--wb-gallery-note);
  pointer-events: none;
}

/* selection overlay on the stage (E39) */
.wb-editor-outline {
  fill: none;
  stroke: var(--wb-editor-outline);
  stroke-width: var(--wb-editor-outline-width);
  vector-effect: non-scaling-stroke;
  pointer-events: none;
}

.wb-editor-marquee {
  fill: var(--wb-select-fill);
  stroke: var(--wb-select);
  stroke-width: var(--wb-editor-outline-width);
  vector-effect: non-scaling-stroke;
  pointer-events: none;
}

.wb-editor-handle {
  fill: var(--wb-editor-handle-fill);
  stroke: var(--wb-editor-handle-stroke);
  stroke-width: var(--wb-editor-outline-width);
  vector-effect: non-scaling-stroke;
  pointer-events: none;
}

/* context bar and its controls (E42) */
.wb-editor-context-bar {
  display: flex;
  flex-flow: row wrap;
  gap: var(--wb-editor-gap);
  align-items: center;
  padding: 4px var(--wb-editor-gap);
  background: var(--wb-editor-context-bg);
  border-radius: var(--wb-radius-frame);
}

.wb-editor-group {
  display: inline-flex;
  gap: 2px;
}

.wb-editor-field {
  display: inline-flex;
  gap: 4px;
  align-items: center;
}

.wb-editor-chip {
  min-height: 32px;
  padding: 2px 8px;
  font: inherit;
  color: var(--wb-accent-ink);
  background: var(--wb-accent);
  border: 0;
  border-radius: var(--wb-radius-button);
  cursor: pointer;
}

.wb-editor-chip[aria-pressed='true'],
.wb-editor-dropping .wb-editor-dropper {
  outline: var(--wb-select-width) solid var(--wb-select);
}

.wb-editor-chip:disabled {
  opacity: 0.5;
  cursor: default;
}

/* properties popover (E41) */
.wb-editor-props {
  position: relative;
}

.wb-editor-popover {
  position: absolute;
  z-index: 2;
  top: 100%;
  right: 0;
  display: flex;
  flex-flow: column nowrap;
  gap: var(--wb-editor-gap);
  min-width: 14em;
  padding: var(--wb-editor-gap);
  background: var(--wb-editor-popover-bg);
  border: var(--wb-popover-border);
  border-radius: var(--wb-radius-frame);
  box-shadow: var(--wb-popover-shadow);
}

/* a stored draft was found (E43) */
.wb-editor-banner {
  display: flex;
  flex-flow: row wrap;
  gap: var(--wb-editor-gap);
  align-items: center;
  margin: 0 0 var(--wb-editor-gap);
  padding: 4px var(--wb-editor-gap);
  background: var(--wb-editor-banner-bg);
  border-radius: var(--wb-radius-frame);
}

/* the picture that follows a finger while a card is dragged by touch (E46) */
.wb-ghost {
  position: fixed;
  z-index: 10;
  top: 0;
  left: 0;
  width: 96px;
  height: 96px;
  object-fit: cover;
  opacity: 0.85;
  pointer-events: none;
  border: var(--wb-border-width) solid var(--wb-ink);
  box-shadow: var(--wb-shadow-pop);
}

.wb-editor:focus {
  outline: none;
}

/* page strip (E55): thumbnails of the pages, the current one ringed */
.wb-editor-pages {
  align-items: flex-start;
  overflow-x: auto;
}

.wb-editor-page-list {
  display: flex;
  gap: var(--wb-editor-gap);
  margin: 0;
  padding: 0;
  list-style: none;
}

.wb-editor-page {
  flex: 0 0 auto;
  display: flex;
  flex-flow: column nowrap;
  gap: 4px;
  width: 80px;
}

.wb-editor-page-pick {
  position: relative;
  padding: 0;
  border: var(--wb-frame-width) var(--wb-frame-style) var(--wb-ink);
  background: var(--wb-card-ground);
  cursor: grab;
}

.wb-editor-page-current .wb-editor-page-pick {
  outline: 3px solid var(--wb-select);
}

.wb-editor-page-thumb {
  display: block;
  aspect-ratio: 1;
  pointer-events: none;
}

.wb-editor-page-thumb svg {
  display: block;
  width: 100%;
  height: 100%;
}

.wb-editor-page-number {
  position: absolute;
  right: 2px;
  bottom: 2px;
  padding: 0 4px;
  background: var(--wb-editor-popover-bg);
  color: var(--wb-ink);
  font-size: 0.8em;
}

/* step scrubber (E56): play button, slider, count */
.wb-editor-scrubber {
  display: flex;
  gap: var(--wb-editor-gap);
  align-items: center;
  margin-top: var(--wb-editor-gap);
}

.wb-editor-scrubber input[type='range'] {
  flex: 1 1 auto;
  min-width: 0;
}

.wb-editor-scrub-count {
  min-width: 4em;
  text-align: right;
}

/* mode switch (E57) */
.wb-editor-modes {
  display: flex;
  gap: 4px;
  margin-top: var(--wb-editor-gap);
}

/* shape tool (E60): the first vertex is where a click closes the shape */
.wb-editor-handle-first {
  stroke-width: 3px;
}

.wb-editor-hint {
  font-size: var(--wb-font-size-small);
  opacity: 0.7;
}

/* vertex editing (E61): the selected corner */
.wb-editor-handle-selected {
  fill: var(--wb-select);
}

/* a failed save: the banner in the danger colour */
.wb-editor-banner-error {
  border-color: var(--wb-danger);
}

/* open a saved node by number (E66) */
.wb-open-node {
  display: flex;
  gap: var(--wb-editor-gap);
  align-items: center;
  margin: var(--wb-editor-gap) 0;
}

.wb-open-node input {
  width: 6em;
}

/* a read-only editor (E67): the locked parts do not react */
.wb-editor-frame[inert],
.wb-editor-title[inert],
.wb-editor-head-fields[inert] {
  opacity: 0.6;
}

.wb-editor-head-fields {
  display: contents;
}

/* saved nodes (E68): the same grid as the upload cards, read-only tiles */
.wb-saved-title {
  margin: 16px 0 0;
  font-size: var(--wb-font-size-lead);
}

.wb-saved-box {
  overflow: hidden;
}

.wb-saved-thumb {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: inherit;
  text-decoration: none;
  font-size: var(--wb-font-size-small);
}

.wb-saved-thumb img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.wb-saved-name {
  margin-top: 2px;
  overflow: hidden;
  font-size: var(--wb-font-size-small);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.wb-saved-edit {
  align-self: flex-start;
}

/* texture role (E71): chosen in the editor, shown as a dimmed film-strip entry */
.wb-editor-strip-texture .wb-editor-strip-pick {
  opacity: 0.45;
}

/* keyboard use (E73): a visible focus everywhere in the editor, the cursor, the help list */
.wb-editor :focus-visible,
.wb-open-node :focus-visible,
.wb-saved :focus-visible {
  outline: 3px solid var(--wb-select);
  outline-offset: 2px;
}

.wb-editor-stage:focus-visible {
  outline-offset: -3px;
}

.wb-editor-candidate {
  stroke-dasharray: 8 6;
}

.wb-editor-keylist {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 4px 12px;
  margin: 0;
  max-width: 26em;
}

.wb-editor-keylist dt {
  margin: 0;
}

.wb-editor-keylist dd {
  margin: 0;
}

.wb-editor-keylist kbd {
  padding: 0 4px;
  font: inherit;
  border: 1px solid var(--wb-ink);
  border-radius: 3px;
}

/* selection order: a solid disc as big as the round card buttons, upper left */
.wb-card-order {
  position: absolute;
  top: 2px;
  left: 2px;
  z-index: 2;
  display: grid;
  place-items: center;
  width: var(--wb-card-icon);
  height: var(--wb-card-icon);
  font-size: calc(var(--wb-card-icon) * 0.6);
  font-weight: bold;
  line-height: 1;
  color: var(--wb-pick-ink);
  background: var(--wb-pick);
  border: 2px solid var(--wb-pick-ground);
  border-radius: var(--wb-radius-round);
  box-sizing: border-box;
  pointer-events: none;
}

/* "add N selected" replaces the close tile while photos are selected */
.wb-new-node-add,
.wb-new-node-add:hover {
  color: var(--wb-add-text);
  background: var(--wb-add-ink);
  border-style: var(--wb-frame-style);
}

.wb-new-node-arrow {
  width: clamp(24px, 36cqw, 48px);
  height: clamp(24px, 36cqw, 48px);
  background: currentColor;
  clip-path: polygon(35% 0, 65% 0, 65% 50%, 90% 50%, 50% 100%, 10% 50%, 35% 50%);
}

/* a photo the open node already uses: dimmed and shaded, nothing to do with it
   until it is taken out of the node again */
.wb-card-used .wb-card-image {
  filter: grayscale(0.7) brightness(0.8);
}

.wb-card-used .wb-card-face {
  cursor: default;
}

.wb-card-used .wb-card-add {
  visibility: hidden;
}

/* portrait: the stage is as wide as the screen. The editor frame gives up
   its side border and padding and the page's side padding, and the head row
   keeps its own. The tools are rows above and below the stage. */
@media (orientation: portrait) {
  .wb-editor {
    margin-right: -10px;
    margin-left: -10px;
    padding: 4px 0;
  }

  .wb-editor-head,
  .wb-editor-banner,
  .wb-editor-strip,
  .wb-editor-side {
    padding-right: 8px;
    padding-left: 8px;
  }

  /* the title takes a line of its own, the buttons wrap below it */
  .wb-editor-head {
    flex-wrap: wrap;
  }

  .wb-editor-title {
    flex: 1 1 100%;
  }

  .wb-editor-stage {
    border-right-width: 0;
    border-left-width: 0;
    box-shadow: none;
  }
}

/* the panel sections: all shown in portrait; the tab row is for landscape */
.wb-editor-sec {
  display: contents;
}

.wb-editor-tabs {
  display: none;
}

/* landscape: the editor is a surface exactly one window high that does not
   scroll (so the browser's address bar stays away). From the left: the
   drawing tools, the square stage (as tall as the window), the actions, and
   a panel that shows one section at a time (select, photos, sequence) and
   scrolls inside itself. */
@media (orientation: landscape) {
  .wb-editor {
    --wb-stage: min(calc(100dvh - 8px), calc(100vw - 420px));
    --wb-strip: 52px;
    display: grid;
    grid-template-columns: var(--wb-strip) var(--wb-stage) var(--wb-strip) minmax(0, 1fr);
    grid-template-rows: auto auto auto minmax(0, 1fr);
    column-gap: var(--wb-editor-gap);
    row-gap: 4px;
    align-content: start;
    height: 100dvh;
    margin-right: -10px;
    margin-left: -10px;
    padding: 4px var(--wb-editor-gap);
    overflow: hidden;
  }

  .wb-editor-frame,
  .wb-editor-work,
  .wb-editor-body {
    display: contents;
  }

  /* the locked frame has no box here (display: contents), so its dimming goes to what it holds (E109) */
  .wb-editor-frame[inert] {
    opacity: 1;
  }

  .wb-editor-frame[inert] button,
  .wb-editor-frame[inert] input,
  .wb-editor-frame[inert] select,
  .wb-editor-frame[inert] .wb-editor-stage,
  .wb-editor-frame[inert] .wb-editor-pages,
  .wb-editor-frame[inert] .wb-editor-context {
    opacity: 0.6;
  }

  .wb-editor-head,
  .wb-editor-tabs,
  .wb-editor-banners,
  .wb-editor-side {
    grid-column: 4;
    margin: 0;
  }

  .wb-editor-head {
    grid-row: 1;
    flex-wrap: wrap;
  }

  .wb-editor-tabs {
    display: flex;
    grid-row: 2;
    gap: 4px;
  }

  .wb-editor-tabs .wb-editor-chip {
    flex: 1 1 0;
    min-width: 0;
    padding-right: 4px;
    padding-left: 4px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .wb-editor-tabs [aria-selected='true'] {
    outline: var(--wb-select-width) solid var(--wb-select);
  }

  .wb-editor-banners {
    grid-row: 3;
  }

  .wb-editor-side {
    grid-row: 4;
    min-height: 0;
    overflow: auto;
    overscroll-behavior: contain;
  }

  .wb-editor-tools,
  .wb-editor-actions {
    flex-flow: column nowrap;
    grid-row: 1 / span 4;
    align-self: start;
    height: var(--wb-stage);
  }

  .wb-editor-tools {
    grid-column: 1;
  }

  .wb-editor-actions {
    grid-column: 3;
  }

  .wb-editor-tools > *,
  .wb-editor-actions > * {
    flex: 1 1 0;
    min-width: 0;
    min-height: 32px;
  }

  .wb-editor-stage {
    grid-column: 2;
    grid-row: 1 / span 4;
    align-self: start;
    width: var(--wb-stage);
    height: var(--wb-stage);
  }

  /* the title stands on its own line, the buttons wrap below it */
  .wb-editor-title {
    flex: 1 1 100%;
  }

  .wb-editor-banner {
    font-size: 0.85em;
  }

  .wb-editor-banner .wb-editor-chip {
    min-height: 28px;
    padding: 2px 8px;
  }

  /* one section at a time */
  .wb-editor[data-tab='select'] .wb-editor-sec:not([data-sec='select']),
  .wb-editor[data-tab='photos'] .wb-editor-sec:not([data-sec='photos']),
  .wb-editor[data-tab='sequence'] .wb-editor-sec:not([data-sec='sequence']),
  .wb-editor[data-tab='gallery'] .wb-editor-sec:not([data-sec='gallery']) {
    display: none;
  }

  .wb-editor-sec {
    display: block;
  }
}

/* the key list is of no use without a keyboard */
@media (pointer: coarse) {
  .wb-editor-keys {
    display: none;
  }
}

/* the key list opens under its button towards the left (the button sits at the
   right edge) and scrolls instead of leaving the window */
.wb-editor-keys .wb-editor-popover {
  right: 0;
  left: auto;
  width: min(26em, calc(100vw - 32px));
  max-height: calc(100dvh - 140px);
  overflow: auto;
}

@media (max-width: 700px) {
  .wb-editor-keys .wb-editor-popover {
    position: fixed;
    top: 16px;
    right: 16px;
    left: 16px;
    width: auto;
    max-height: calc(100dvh - 32px);
  }
}

/* larger / smaller / turn buttons of the context bar (E113): a finger-sized target */
.wb-editor-nudge {
  display: inline-flex;
  gap: 4px;
}

.wb-editor-nudge-btn {
  min-width: 36px;
  min-height: 36px;
  font-size: 1.2em;
  line-height: 1;
}

@media (pointer: coarse) {
  .wb-editor-nudge-btn {
    min-width: 44px;
    min-height: 44px;
  }
}

/* where the server is working: a ring over the stage (magic wand, background removal) */
.wb-busy-track,
.wb-busy-arc {
  fill: none;
  stroke-width: 5px;
  vector-effect: non-scaling-stroke;
}

.wb-busy-track {
  stroke: var(--wb-card-ground);
  stroke-opacity: 0.85;
}

.wb-busy-arc {
  stroke: var(--wb-select);
  stroke-linecap: round;
}

.wb-busy-text,
.wb-busy-label {
  fill: var(--wb-ink);
  paint-order: stroke;
  stroke: var(--wb-card-ground);
  stroke-width: 3px;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
  font-family: inherit;
  pointer-events: none;
}

.wb-fresh {
  animation: wb-fresh 0.5s ease-out;
}

@keyframes wb-fresh {
  from { opacity: 0.45; }
  to { opacity: 1; }
}

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

.wb-busy-spin {
  transform-box: fill-box;
  transform-origin: center;
  animation: wb-busy-spin 0.9s linear infinite;
}

@keyframes wb-busy-spin {
  to { transform: rotate(270deg); }
}

@media (prefers-reduced-motion: reduce) {
  .wb-busy-spin { animation: none; }
}

/* the text box being typed in: a transparent textarea over the drawn box */
.wb-text-edit {
  position: absolute;
  top: 0;
  left: 0;
  box-sizing: border-box;
  margin: 0;
  overflow: hidden;
  color: transparent;
  resize: none;
  background: transparent;
  border: 0;
  outline: 0; /* the selection outline and its handles frame the box */
  transform-origin: 0 0;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.wb-text-edit::selection {
  color: transparent;
  background: var(--wb-select-fill);
}

/* the dropper: a colour field's button, and the stage while it waits for a tap */
.wb-editor-colour {
  display: inline-flex;
  gap: var(--wb-editor-gap);
  align-items: center;
}

.wb-editor-dropping .wb-editor-stage,
.wb-editor-dropping .wb-editor-stage * {
  cursor: crosshair;
}

/* what is kept and for how long (E111): the retention note, expiry badges, the sweep tile */
.wb-upload-retention {
  max-width: 60ch;
}

.wb-upload-details {
  margin: 0 0 8px;
  font-size: var(--wb-font-size-small, 0.9em);
}

.wb-upload-details ul {
  margin: 4px 0 0;
  padding-left: 1.2em;
}

.wb-card-expiry {
  display: block;
  font-size: var(--wb-font-size-small, 0.85em);
  color: var(--wb-accent);
}

.wb-sweep {
  display: flex;
  flex-flow: column;
  gap: 4px;
  align-items: center;
  justify-content: center;
  padding: 8px;
  text-align: center;
  background: transparent;
  border: var(--wb-border-width) dashed var(--wb-ink);
  color: var(--wb-ink);
  font: inherit;
}

.wb-sweep-title {
  font-weight: bold;
}

.wb-sweep-hint {
  font-size: var(--wb-font-size-small, 0.85em);
}

.wb-sweep-buttons {
  display: flex;
  gap: var(--wb-editor-gap, 4px);
}

/* graph view (GRAPH.md S2.7): a full-width drawing under a row of tools */
.wb-graph-bar {
  display: flex;
  flex-flow: row wrap;
  gap: var(--wb-editor-gap);
  align-items: center;
  margin-bottom: var(--wb-editor-gap);
}

.wb-graph-hint {
  min-width: 0;
  margin-inline-start: auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.wb-graph {
  display: block;
  width: 100%;
  height: calc(100vh - var(--wb-logo-height) - 4 * var(--wb-tab-gap) - 3em);
  height: calc(100dvh - var(--wb-logo-height) - 4 * var(--wb-tab-gap) - 3em);
  min-height: 280px;
  touch-action: none;
  user-select: none;
}

.wb-content-bleed {
  padding: 0;
}

.wb-content-bleed .wb-graph-bar {
  padding: 0 10px;
}

.wb-graph-edge line {
  stroke: var(--wb-ink);
  stroke-width: 2;
}

.wb-graph-edge .wb-graph-hit {
  stroke: transparent;
  stroke-width: 22;
  cursor: pointer;
}

.wb-graph-edge.wb-selected line:not(.wb-graph-hit) {
  stroke: var(--wb-accent);
  stroke-width: 4;
}

.wb-graph-node {
  cursor: grab;
}

/* the selection is drawn by the frame, not by the browser's focus ring */
.wb-graph-node:focus,
.wb-graph-node:focus-visible {
  outline: none;
}

.wb-graph-frame {
  fill: none;
  stroke: none;
  stroke-width: 1.5;
}

/* the active node: one thin stippled line, ink and transparent */
.wb-graph-node.wb-selected .wb-graph-frame,
.wb-graph-node.wb-linking .wb-graph-frame {
  stroke: var(--wb-ink);
  stroke-dasharray: 3 3;
}

.wb-graph-title {
  font-size: 15px;
  font-weight: bold;
  fill: var(--wb-ink);
  pointer-events: none;
}

.wb-disabled {
  opacity: 0.4;
  pointer-events: none;
}

/* the shared colour selector (palette strip, properties, text popovers) */
.wb-colour-pick {
  display: flex;
  flex-flow: row wrap;
  gap: 6px;
  align-items: center;
  max-width: 100%;
}

.wb-colour-pick .wb-editor-swatches {
  display: flex;
  flex-flow: row wrap;
  gap: 4px;
}

.wb-colour-pick .wb-editor-swatch {
  width: 28px;
  height: 28px;
}

.wb-colour-free {
  display: inline-flex;
  gap: 4px;
  align-items: center;
}

/* opacity slider and hex field of the colour selector */
.wb-colour-alpha {
  display: flex;
  flex-flow: row wrap;
  gap: 4px 8px;
  align-items: center;
}

.wb-colour-hex {
  width: 9ch;
  font-family: monospace;
}

/* the tiny button for any colour: a colour wheel, the system picker behind it */
.wb-colour-other {
  display: inline-block;
  width: 20px;
  height: 20px;
  overflow: hidden;
  cursor: pointer;
  border: var(--wb-frame-width) var(--wb-frame-style) var(--wb-ink);
  border-radius: 50%;
}

.wb-colour-other input {
  width: 100%;
  height: 100%;
  padding: 0;
  cursor: pointer;
  opacity: 0;
}

/* several nodes at once: the group, its target, the drop preview */
.wb-graph-node.wb-private .wb-graph-ground,
.wb-graph-node.wb-private image {
  opacity: 0.55;
}

.wb-graph-node.wb-private .wb-graph-frame {
  stroke-dasharray: 6 4;
}

.wb-graph-node.wb-multi .wb-graph-frame {
  stroke: var(--wb-accent);
  stroke-width: 2;
  stroke-dasharray: none;
}

.wb-graph-node.wb-target .wb-graph-frame {
  stroke: var(--wb-select);
  stroke-width: 3;
  stroke-dasharray: none;
}

.wb-graph-preview {
  stroke: var(--wb-select);
  stroke-width: 3;
  stroke-dasharray: 6 5;
  pointer-events: none;
}

.wb-graph-bubble rect {
  fill: var(--wb-ink);
}

.wb-graph-bubble text {
  font-size: 13px;
  fill: var(--wb-card-ground);
}

.wb-graph-count {
  fill: var(--wb-select);
}

.wb-graph-bubble .wb-graph-count-text {
  font-size: 13px;
  font-weight: bold;
  fill: var(--wb-ink);
}

.wb-graph-marquee {
  fill: none;
  stroke: var(--wb-select);
  stroke-width: 2;
  stroke-dasharray: 6 4;
  pointer-events: none;
}

.wb-graph-hint-live {
  font-weight: bold;
}

/* a group node: member tiles over a strip with its title and size */
.wb-graph-slot {
  fill: var(--wb-ink);
  opacity: 0.12;
}

.wb-graph-strip {
  fill: var(--wb-ink);
}

.wb-graph-strip-text {
  font-size: 12px;
  font-weight: bold;
  fill: var(--wb-card-ground);
  pointer-events: none;
}

/* the viewer's flow (EDITOR.md E135): a track of stages that pages or scrolls */
.wb-flow-track {
  display: flex;
  width: 100%;
  height: 100%;
  overflow: auto;
  scrollbar-width: thin;
}

.wb-flow-h .wb-flow-track {
  flex-flow: row nowrap;
  overflow-y: hidden;
}

.wb-flow-v .wb-flow-track {
  flex-flow: column nowrap;
  overflow-x: hidden;
}

.wb-flow-page.wb-flow-h .wb-flow-track {
  scroll-snap-type: x mandatory;
}

.wb-flow-page.wb-flow-v .wb-flow-track {
  scroll-snap-type: y mandatory;
}

.wb-flow-item {
  flex: none;
  scroll-snap-align: start;
  scroll-snap-stop: always;
}

.wb-flow-item .wb-node,
.wb-flow-item svg {
  display: block;
}

.wb-flow-page .wb-flow-item,
.wb-flow-page .wb-flow-item .wb-node {
  width: 100%;
  height: 100%;
}

.wb-flow-page .wb-flow-item svg {
  width: 100%;
  height: 100%;
}

/* scrolling: the stages keep their shape and run on along the axis */
.wb-flow-scroll.wb-flow-v .wb-flow-item,
.wb-flow-scroll.wb-flow-v .wb-flow-item .wb-node,
.wb-flow-scroll.wb-flow-v .wb-flow-item svg {
  width: 100%;
  height: auto;
}

.wb-flow-scroll.wb-flow-h .wb-flow-item,
.wb-flow-scroll.wb-flow-h .wb-flow-item .wb-node,
.wb-flow-scroll.wb-flow-h .wb-flow-item svg {
  width: auto;
  height: 100%;
}

.wb-flow-nav {
  display: flex;
  gap: var(--wb-editor-gap);
  align-items: center;
  justify-content: center;
  margin: var(--wb-editor-gap) auto 0;
}

/* the loupe above a finger while it places a point (E124) */
.wb-loupe {
  position: absolute;
  z-index: 4;
  overflow: hidden;
  pointer-events: none;
  background: var(--wb-card-ground);
  border: var(--wb-border-width) solid var(--wb-ink);
  border-radius: 50%;
}

.wb-loupe-inner {
  position: absolute;
  top: 0;
  left: 0;
  transform-origin: 0 0;
}

.wb-loupe-inner > * {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.wb-loupe-dot {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 6px;
  height: 6px;
  margin: -3px 0 0 -3px;
  border: 1px solid var(--wb-select);
  border-radius: 50%;
}

/* ground control after a landing: a written transmission over the stage */
.wb-gallery-atc {
  text-align: left;
}

/* login: the overlay (gradient set inline) tumbles as a whole; start pose in
 * from the top right (the Login tab), end pose out to the bottom left */
.wb-login-overlay {
  position: fixed;
  inset: 0;
  z-index: 12;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform var(--wb-login-time) linear;
  transform: perspective(1000px) translate3d(50vw, -50vh, 50px) rotateX(-45deg) rotateY(-45deg) rotateZ(90deg) scale3d(0.02, 0.02, 1);
}

.wb-login-open {
  transform: perspective(1000px) translate3d(0, 0, 50px) rotate3d(0, 0, 1, 0deg) scale3d(1, 1, 1);
}

.wb-login-leave {
  transform: perspective(1000px) translate3d(-50vw, 50vh, 50px) rotateX(45deg) rotateY(45deg) rotateZ(-90deg) scale3d(0.02, 0.02, 1);
}

.wb-login {
  display: flex;
  flex-direction: column;
  width: min(75vmin, 275px);
  min-height: 275px;
  background: var(--wb-login-card);
  color: var(--wb-ink);
  box-shadow: var(--wb-login-shadow);
}

.wb-login-title {
  padding: 6px 16px 4px;
  background: var(--wb-accent);
  color: var(--wb-accent-ink);
  font-size: var(--wb-font-size-lead);
  text-align: center;
}

.wb-login-field {
  display: flex;
  flex-direction: column;
  padding: 2px 10px;
  font-size: var(--wb-font-size-label);
}

.wb-login-field > input {
  width: 100%;
  padding: 2px;
  font: inherit;
  font-size: var(--wb-font-size-lead);
  color: var(--wb-ink);
  border: var(--wb-border-width) solid var(--wb-login-ring);
  border-radius: var(--wb-radius-button);
}

.wb-login-button {
  align-self: center;
  margin: 10px 0;
  padding: 4px 10px 2px;
  font: inherit;
  font-size: var(--wb-font-size-lead);
  background: var(--wb-accent);
  color: var(--wb-accent-ink);
  border: var(--wb-border-width) solid var(--wb-pick);
  border-radius: var(--wb-radius-button);
  box-shadow: var(--wb-login-shadow);
}

.wb-login-switch {
  align-self: center;
  padding: 0;
  font: inherit;
  font-size: var(--wb-font-size-small);
  color: inherit;
  background: none;
  border: 0;
  text-decoration: underline;
  cursor: pointer;
}

.wb-login-button:active {
  transform: translate(1px, 1px);
}

.wb-login-status {
  align-self: center;
  margin: 0 0 10px;
  padding: 0 4px;
  font-size: var(--wb-font-size-lead);
  background: var(--wb-login-status-ground);
  color: var(--wb-login-status-ink);
}

.wb-login-error {
  color: var(--wb-danger);
}

@media (prefers-reduced-motion: reduce) {
  .wb-login-overlay,
  .wb-login-open,
  .wb-login-leave {
    transform: none;
    transition: opacity var(--wb-login-time) linear;
  }

  .wb-login-overlay:not(.wb-login-open) {
    opacity: 0;
  }
}

/* button rows inside a popover wrap with a gap, so a long row (align, fonts) never overlaps */
.wb-editor-popover [role='group'] {
  display: flex;
  flex-flow: row wrap;
  gap: var(--wb-editor-gap);
}

/* the gallery context pane of the editor (client/components/GalleryPane.js) */
.wb-gal-pane {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: var(--wb-font-size-small);
}

.wb-gal-title,
.wb-gal-sub {
  margin: 8px 0 0;
  font-size: var(--wb-font-size-button);
}

.wb-gal-steps {
  margin: 0;
  padding: 0;
  list-style: none;
}

.wb-gal-step {
  display: flex;
  gap: 6px;
  opacity: 0.7;
}

.wb-gal-done {
  opacity: 1;
}

.wb-gal-mark {
  flex: none;
  width: 1.2em;
  text-align: center;
}

.wb-gal-help summary {
  cursor: pointer;
}

.wb-gal-help ul {
  margin: 4px 0;
  padding-left: 1.2em;
}

.wb-gal-warn {
  margin: 0;
  padding: 4px 6px;
  border: var(--wb-border-width) solid var(--wb-danger);
}

.wb-gal-note,
.wb-gal-empty {
  margin: 0;
  opacity: 0.75;
}

.wb-gal-plan {
  width: 100%;
  max-height: 240px;
  border: var(--wb-border-width) solid var(--wb-ink-soft);
  background: var(--wb-card-ground);
}

.wb-gal-room {
  fill: var(--wb-ink-soft);
}

.wb-gal-corridor {
  fill: none;
  stroke: var(--wb-ink-soft);
}

.wb-gal-wall {
  fill: none;
  stroke: var(--wb-ink);
  stroke-width: 2px;
  vector-effect: non-scaling-stroke;
}

.wb-gal-start {
  fill: var(--wb-accent);
}

.wb-gal-children {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.wb-gal-children a {
  display: flex;
  align-items: center;
  gap: 4px;
  color: inherit;
}

.wb-gal-children img,
.wb-gal-blank {
  width: 28px;
  height: 28px;
  object-fit: cover;
  border: var(--wb-border-width) solid var(--wb-ink-soft);
}

.wb-gal-looks {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.wb-gal-look {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 3px;
  font: inherit;
  color: inherit;
  background: var(--wb-card-ground);
  border: var(--wb-border-width) solid var(--wb-ink-soft);
}

.wb-gal-look[aria-pressed='true'],
.wb-gal-pick[aria-pressed='true'] {
  border: var(--wb-select-width) solid var(--wb-select);
}

/* a swatch: the wall of the look over its floor */
.wb-gal-swatch {
  display: flex;
  flex-direction: column;
  width: 56px;
  height: 36px;
}

.wb-gal-swatch-wall,
.wb-gal-swatch-floor {
  flex: 1;
  background-position: center;
  background-size: cover;
}

.wb-gal-slot {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.wb-gal-slot-name {
  font-weight: bold;
}

.wb-gal-slot-hint {
  opacity: 0.75;
}

.wb-gal-slot-picks {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
}

.wb-gal-pick {
  padding: 0;
  background: none;
  border: var(--wb-border-width) solid var(--wb-ink-soft);
}

.wb-gal-pick img {
  display: block;
  width: 36px;
  height: 36px;
  object-fit: cover;
}
