:root {
  --primary: hsl(200, 100%, 50%);
  --bg-color: hsl(222, 47%, 11%);
  --surface-color: rgba(255, 255, 255, 0.04);
  --surface-hover: rgba(255, 255, 255, 0.08);
  --border-color: rgba(255, 255, 255, 0.1);
  --text-main: hsl(210, 20%, 98%);
  --text-dim: hsl(210, 10%, 70%);
  --ink: #008080;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  background: var(--bg-color);
  color: var(--text-main);
  font-family: 'Inter', sans-serif;
  height: 100vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

header {
  user-select: none;
}

/* ---------- Toolbar ---------- */

.toolbar {
  padding: 0.9rem 1.5rem;
  border-bottom: 1px solid var(--border-color);
  display: flex;
  align-items: center;
  gap: 1rem;
}

.toolbar h1 {
  font-family: 'Outfit', sans-serif;
  font-size: 1.1rem;
  margin: 0;
  white-space: nowrap;
}

.toolbar .spacer {
  flex: 1;
}

/* ---------- Back buttons (toolbar + row-editor panel) ---------- */

.back-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  color: var(--text-main);
  border-radius: 7px;
  padding: 0.4rem 0.7rem 0.4rem 0.55rem;
  font-family: inherit;
  font-size: 0.85rem;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  -webkit-tap-highlight-color: transparent;
}

.back-btn:hover {
  background: var(--surface-hover);
  border-color: var(--primary);
}

.back-btn .chev {
  width: 14px;
  height: 14px;
  flex: none;
}

.back-btn--panel {
  color: var(--text-dim);
  max-width: calc(100% - 40px);
  /* leave room for the close button */
  padding: 0.25rem 0.6rem 0.25rem 0.5rem;
  height: 28px;
  box-sizing: border-box;
  margin-bottom: 0.8rem;
}

.back-btn--panel span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.btn,
.back-btn {
  -webkit-tap-highlight-color: transparent;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  color: var(--text-main);
  padding: 0.45rem 0.85rem;
  border-radius: 7px;
  font-family: inherit;
  font-size: 0.85rem;
  cursor: pointer;
  white-space: nowrap;
}

.btn:hover {
  background: var(--surface-hover);
  border-color: var(--primary);
}

.btn:active {
  background: var(--surface-hover);
}

.btn:focus-visible,
.back-btn:focus-visible,
.dd summary:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 1px;
}

.btn-primary {
  background: var(--primary);
  border-color: var(--primary);
  color: #04121e;
  font-weight: 600;
}

.btn-primary:hover,
.btn-primary:active {
  background: var(--primary);
  filter: brightness(1.1);
}

.btn-small {
  padding: 0.3rem 0.6rem;
  font-size: 0.78rem;
}

.btn-danger:hover {
  border-color: #ef4444;
  color: #fca5a5;
}

.icon-btn {
  width: 34px;
  height: 34px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1.2rem;
  line-height: 1;
}

/* Themed native checkbox — simpler and more robust than a hand-rolled
   custom checkbox, and matches the accent color everywhere else. */
.cb input[type="checkbox"] {
  width: 16px;
  height: 16px;
  accent-color: var(--primary);
  cursor: pointer;
}

input[type="range"] {
  width: 120px;
  accent-color: var(--primary);
  cursor: pointer;
}

input[type="color"] {
  width: 30px;
  height: 26px;
  padding: 2px;
  border: 1px solid var(--border-color);
  border-radius: 6px;
  background: var(--surface-color);
  cursor: pointer;
}

input[type="color"]::-webkit-color-swatch-wrapper {
  padding: 0;
}

input[type="color"]::-webkit-color-swatch {
  border: none;
  border-radius: 3px;
}

/* Settings fields (page size, orientation, color, padding) live inside the
   toolbar overflow menu now rather than a separate settings bar. */
.dd-menu--wide {
  min-width: 220px;
}

.dd-field {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  padding: 0.4rem 0.5rem;
}

.dd-field-label {
  color: var(--text-dim);
  font-size: 0.78rem;
  white-space: nowrap;
}

.dd-field-val {
  margin-left: 0.35rem;
  opacity: 0.65;
  font-size: 0.73rem;
  font-family: monospace;
}

.dd-field select {
  width: auto;
  max-width: 120px;
  padding: 0.3rem 1.5rem 0.3rem 0.5rem;
  font-size: 0.82rem;
  border-radius: 6px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M5.5 8l4.5 4.5L14.5 8' stroke='%2399a6b8' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.35rem center;
  background-size: 13px;
  appearance: none;
  -webkit-appearance: none;
}

.dd-field input[type="range"] {
  width: 100px;
}

/* ---------- Floating zoom control ---------- */

.zoom-float {
  position: fixed;
  right: 1rem;
  bottom: 1rem;
  z-index: 40;
  display: flex;
  align-items: center;
  gap: 0.25rem;
  background: hsl(222, 44%, 15%);
  border: 1px solid var(--border-color);
  border-radius: 999px;
  padding: 0.3rem 0.4rem;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
}

.zf-btn {
  background: none;
  border: none;
  color: var(--text-main);
  width: 28px;
  height: 28px;
  border-radius: 50%;
  cursor: pointer;
  font-size: 1.05rem;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  -webkit-tap-highlight-color: transparent;
}

.zf-btn:hover {
  background: var(--surface-hover);
}

.zf-pct {
  font-size: 0.76rem;
  color: var(--text-dim);
  min-width: 2.6rem;
  text-align: center;
}

.zf-divider {
  width: 1px;
  height: 16px;
  background: var(--border-color);
}

.zf-fit {
  width: auto;
  border-radius: 999px;
  padding: 0 0.65rem;
  font-size: 0.76rem;
  font-weight: 600;
}

@media (max-width: 820px) {
  body.panel-open .zoom-float {
    display: none;
  }
}

/* ---------- Layout ---------- */

.layout {
  position: relative;
  flex: 1;
  min-height: 0;
}

/* display:none until a viewport-specific rule below (mobile or desktop)
   opts it into the appropriate always-rendered-but-transform-hidden setup —
   an animated slide needs the element present throughout, so unlike a plain
   show/hide toggle this can't just be `body.panel-open #sidebar`. */
#sidebar {
  display: none;
  padding: 0.85rem 1.25rem 1.25rem;
  overflow-y: auto;
}

/* ---------- Desktop: sidebar slides in as a fixed-width panel ----------
   #sidebar keeps a constant 320px box at all times and only ever slides via
   transform — animating a grid/flex track's *size* instead forces the
   sidebar's own content to reflow/squish down to near-zero width mid-
   transition (see the mobile bottom sheet below for the same technique).
   .canvas's margin-left animates in lockstep (same duration + easing) so its
   left edge always meets the sidebar's trailing edge with no gap or overlap. */
@media (min-width: 821px) {
  .layout {
    overflow: hidden;
  }

  #sidebar {
    display: block;
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    width: 320px;
    border-right: 1px solid var(--border-color);
    background: hsl(222, 44%, 13%);
    transform: translateX(-100%);
    z-index: 5;
  }

  /* Transitions are opt-in via body.anim-ready (added by script.js a couple
     frames after first paint) so the sidebar/canvas establish their initial
     open/closed state instantly on page load instead of visibly sliding
     into place — which was also throwing off the initial fit-to-width zoom
     calculation, since it measured the canvas mid-slide instead of at its
     final width. Real user-triggered toggles still animate normally once
     this class is present. */
  body.anim-ready #sidebar {
    transition: transform 0.25s ease;
  }

  body.panel-open #sidebar {
    transform: translateX(0);
  }
}

.panel-top-actions {
  position: absolute;
  top: 0.85rem;
  right: 0.8rem;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.4rem;
  z-index: 10;
}

.panel-top-row {
  display: flex;
  gap: 0.4rem;
}

.panel-close,
.panel-action-btn {
  width: 28px;
  height: 28px;
  border-radius: 6px;
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  color: var(--text-dim);
  font-size: 1.15rem;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
}

.panel-close:hover,
.panel-action-btn:hover {
  color: var(--text-main);
  border-color: var(--primary);
}

.panel-action-btn--danger:hover {
  color: #ef4444 !important;
  border-color: #ef4444 !important;
  background: rgba(239, 68, 68, 0.05);
}

.sheet-handle {
  display: none;
}

/* ---------- Responsive Toolbar (intermediate screens) ---------- */

/* Step 1: Collapse sync status text to icon only */
@media (max-width: 1200px) {

  .sync-status-text,
  .sync-save-now {
    display: none;
  }
}

/* Step 2: Collapse toolbar buttons to icon-only squares */
@media (max-width: 1000px) {

  #add-switch .btn-text,
  #print-btn .btn-text {
    display: none;
  }

  #add-switch,
  #print-btn {
    width: 34px;
    height: 34px;
    padding: 0;
  }
}

@media (max-width: 820px) {

  #sidebar {
    display: block;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    max-height: 74vh;
    overflow-y: auto;
    background: hsl(222, 44%, 13%);
    border: none;
    border-top: 1px solid var(--border-color);
    border-radius: 16px 16px 0 0;
    box-shadow: 0 -12px 34px rgba(0, 0, 0, 0.55);
    transform: translateY(100%);
    transition: transform 0.25s ease;
    z-index: 60;
    padding-top: 1.15rem;
    padding-bottom: 2rem;
  }

  body.panel-open #sidebar {
    transform: translateY(0);
  }

  .sheet-handle {
    display: block;
    position: absolute;
    top: 0.55rem;
    left: 50%;
    transform: translateX(-50%);
    width: 42px;
    height: 4px;
    border-radius: 2px;
    background: var(--border-color);
    cursor: pointer;
  }

  .panel-top-actions {
    top: 1.15rem;
    right: 1.25rem;
    flex-direction: row;
  }

  .toolbar {
    flex-wrap: wrap;
    padding: 0.7rem 1rem;
    gap: 0.5rem 0.55rem;
  }

  /* One compact row: hide the title (back button + icons are enough
     context) and collapse every button's text label down to just its icon,
     rather than wrapping into a second/third row. */
  .toolbar {
    flex-wrap: nowrap;
    gap: 0.4rem;
  }

  .toolbar h1 {
    display: none;
  }

  /* With the title hidden, the sync status icon would otherwise sit right
     up against the sidebar toggle button with only the toolbar's regular
     inter-button gap between them. */
  #sync-warning {
    margin-left: 0.5rem;
  }

  .btn-text {
    display: none;
  }

  .sync-status-text,
  .sync-save-now {
    display: none;
  }

  #add-switch {
    display: none;
  }

  .btn {
    padding: 0.45rem 0.6rem;
    font-size: 0.8rem;
  }

  .back-btn {
    padding: 0.45rem 0.55rem;
  }

  #pages-scroll {
    padding: 0;
  }

  #pages {
    padding: 1rem;
  }
}

.canvas {
  height: 100%;
  background:
    repeating-linear-gradient(45deg, rgba(255, 255, 255, 0.015) 0 10px, transparent 10px 20px),
    hsl(222, 47%, 9%);
  overflow: auto;
  /* Allow native 1-finger panning but hand 2-finger pinch to our own JS
     zoom (script.js) instead of the browser's whole-page pinch-zoom. */
  touch-action: pan-x pan-y;
  user-select: none;
  -webkit-user-select: none;
}

/* Only desktop's fixed-position sidebar needs the canvas to make room for
   it — mobile's bottom sheet overlays on top instead. */
@media (min-width: 821px) {
  .canvas {
    margin-left: 0;
  }

  body.anim-ready .canvas {
    transition: margin-left 0.25s ease;
  }

  body.panel-open .canvas {
    margin-left: 320px;
  }
}

.toolbar,
#sidebar {
  touch-action: manipulation;
}

#pages-scroll {
  padding: 0;
}

#pages {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2rem;
  width: max-content;
  padding: 2rem;
  margin: 0 auto;
}

/* ---------- Paper pages ---------- */

.page {
  position: relative;
  background: #fff;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.5);
  overflow: hidden;
  flex: none;
}

.switch-block {
  position: absolute;
  cursor: pointer;
}

.switch-block .plate {
  display: block;
}

.switch-block .switch-name {
  text-align: center;
  font-size: 2.6mm;
  line-height: 1.1;
  color: #444;
  font-family: 'Inter', sans-serif;
  margin-top: 0.5mm;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Selected switch: no outline/background here, drawn inside the SVG now */
.switch-block.selected {}

.switch-hl,
.row-hl {
  fill: rgba(0, 160, 255, 0.14);
  stroke: var(--primary);
  stroke-width: 0.3;
}

.cal {
  position: absolute;
  color: #666;
}

.page-title,
.page-footer,
.page-url {
  position: absolute;
  font-size: 2.4mm;
  line-height: 1;
  color: #666;
  font-family: 'Inter', sans-serif;
  white-space: nowrap;
}

.page-title {
  left: 5mm;
  top: 5mm;
}

.page-title strong {
  /* The loaded Inter weights are 400/500/600 (see index.html's font link) —
     700 would be synthesized/faked by the browser rather than using an
     actual bold face. */
  font-weight: 600;
}

.page-footer {
  right: 5mm;
  bottom: 5mm;
}

.page-url {
  right: 5mm;
  top: 5mm;
}

/* ---------- Sidebar panel ---------- */

.empty {
  color: var(--text-dim);
  font-size: 0.9rem;
  line-height: 1.6;
  padding-top: 1rem;
}

.panel-title {
  font-family: 'Outfit', sans-serif;
  font-weight: 600;
  font-size: 1rem;
  margin-bottom: 1rem;
}

.panel-head {
  margin-bottom: 1rem;
}

.field {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  margin-bottom: 0.9rem;
}

.field>label {
  font-size: 0.72rem;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.row2 {
  display: flex;
  gap: 0.6rem;
}

.row2 .field {
  flex: 1;
  min-width: 0;
}

.swap-lr-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  margin-top: 0.6rem;
  width: 100%;
}

select,
input[type="text"],
input[type="number"],
textarea {
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  color: var(--text-main);
  padding: 0.5rem 0.6rem;
  border-radius: 6px;
  font-family: inherit;
  font-size: 0.9rem;
  width: 100%;
}

.label-input {
  resize: none;
  line-height: 1.3;
}

/* The native options list is drawn by the OS on a white background, so it
   needs dark-on-light colors — otherwise near-white text is invisible. */
select option {
  color: #111;
  background: #fff;
}

select:focus,
input:focus,
textarea:focus {
  outline: none;
  border-color: var(--primary);
}

.cb {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.9rem;
  cursor: pointer;
  margin-bottom: 0.9rem;
}

.cb input {
  width: auto;
}

.field-label {
  display: block;
  font-size: 0.72rem;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin: 0 0 0.4rem;
}

/* ---------- Window pane composer ---------- */

.segments {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-bottom: 0.6rem;
}

.segment {
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  border-radius: 8px;
  padding: 0.6rem 0.7rem;
}

.seg-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 0.5rem;
}

.seg-head-left {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

.seg-n {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--text-dim);
  white-space: nowrap;
}

.seg-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.4rem 0.6rem;
}

.seg-field {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  font-size: 0.72rem;
  color: var(--text-dim);
}

.seg-field select,
.seg-field input[type="number"] {
  font-size: 0.85rem;
  padding: 0.35rem 0.5rem;
}

.seg-field input[type="range"] {
  width: 100%;
}

.toggle-group {
  display: inline-flex;
  border: 1px solid var(--border-color);
  border-radius: 6px;
  overflow: hidden;
  align-self: start;
}

.toggle-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 28px;
  background: var(--surface-color);
  border: none;
  border-right: 1px solid var(--border-color);
  color: var(--text-dim);
  cursor: pointer;
}

.toggle-btn:last-child {
  border-right: none;
}

.toggle-btn:hover {
  color: var(--text-main);
}

.toggle-btn.active {
  background: var(--primary);
  color: #fff;
}

.seg-field.cb,
.seg-field .cb {
  margin-bottom: 0;
  font-size: 0.82rem;
  color: var(--text-main);
  justify-self: start;
  align-self: end;
}

.seg-field--full {
  grid-column: 1 / -1;
}

.seg-field--full .cb {
  margin-bottom: 0;
  font-size: 0.82rem;
  color: var(--text-main);
}

/* A separator is a small spacer between pane groups, not a pane itself —
   visually lighter and more compact so it doesn't compete with real panes. */
.segment-sep {
  background: transparent;
  border-style: dashed;
  padding: 0.4rem 0.7rem;
}

.segment-sep .seg-field {
  max-width: 140px;
}

.seg-actions {
  display: flex;
  gap: 0.5rem;
  margin-bottom: 0.9rem;
}

.seg-remove {
  background: none;
  border: none;
  color: var(--text-dim);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  padding: 0.2rem 0.4rem;
}

.seg-remove:hover {
  color: #fca5a5;
}

/* ---------- Rows list ---------- */

.rows-list-label {
  font-size: 0.72rem;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin: 0.4rem 0 0.5rem;
}

.rows-list {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin-bottom: 1.2rem;
}

.row-item {
  display: flex;
  align-items: stretch;
  gap: 0.4rem;
}

.row-item-btn {
  flex: 1;
  min-width: 0;
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-areas: "n mode" "n sum";
  gap: 0 0.6rem;
  align-items: center;
  text-align: left;
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  border-radius: 8px;
  padding: 0.55rem 0.7rem;
  color: var(--text-main);
  font-family: inherit;
  cursor: pointer;
}

.row-item-btn:hover {
  background: var(--surface-hover);
  border-color: var(--primary);
}

.ri-n {
  grid-area: n;
  font-weight: 600;
  font-size: 0.85rem;
  color: var(--text-dim);
}

.ri-mode {
  grid-area: mode;
  font-size: 0.8rem;
}

.ri-sum {
  grid-area: sum;
  font-size: 0.78rem;
  color: var(--text-dim);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---------- Switches list (browse/reorder all switches) ---------- */

.switches-list {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin-bottom: 1rem;
}

/* One bordered card per row — the name button and its action icons
   (share/overflow) all live inside it, rather than the icons floating
   outside as a disconnected cluster. Shared by both the switches list and
   the projects list (only the latter uses .active-project / has action
   icons at all). */
.switch-item {
  display: flex;
  align-items: stretch;
  gap: 0.1rem;
  padding-right: 0.35rem;
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  border-radius: 8px;
  transition: border-color 0.15s ease, background 0.15s ease;
}

.switch-item:hover {
  background: var(--surface-hover);
  border-color: var(--primary);
}

.switch-item.active-project {
  border-color: var(--primary);
  background: rgba(0, 160, 255, 0.06);
}

.switch-item-btn {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  text-align: left;
  background: none;
  border: none;
  padding: 0.55rem 0.7rem;
  color: var(--text-main);
  font-family: inherit;
  cursor: pointer;
}

.si-title {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  min-width: 0;
  flex: 1;
}

.si-name {
  font-size: 0.88rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

.si-cloud {
  flex: none;
  display: inline-flex;
  color: var(--text-dim);
}

.si-meta {
  font-size: 0.76rem;
  color: var(--text-dim);
  flex: none;
}

.si-check {
  display: inline-flex;
  flex: none;
  color: var(--primary);
}

.panel-actions {
  display: flex;
  gap: 0.6rem;
}

.panel-actions .btn {
  flex: 1;
}

/* ---------- Custom lamp dropdown ---------- */

.dd {
  position: relative;
}

.dd summary {
  list-style: none;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  border-radius: 6px;
  padding: 0.4rem 0.6rem;
  cursor: pointer;
  font-size: 0.9rem;
}

.dd summary::-webkit-details-marker {
  display: none;
}

.dd summary.icon-btn {
  padding: 0;
}

.dd[open] summary {
  border-color: var(--primary);
}

/* Default: a compact, right-aligned menu (the toolbar overflow menu). Inside
   a sidebar .field (the lamp pickers), it stretches to the field's full
   width instead — see the .field .dd-menu override below. Single-column so
   option labels ("Chandelier", "Wall light") never get cramped into a
   half-width cell and truncate or spill over their neighbour. */
.dd-menu {
  position: absolute;
  z-index: 30;
  top: calc(100% + 4px);
  right: 0;
  min-width: 160px;
  max-width: min(280px, 90vw);
  background: hsl(222, 44%, 15%);
  border: 1px solid var(--border-color);
  border-radius: 8px;
  padding: 0.3rem;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.5);
  max-height: 60vh;
  overflow-y: auto;
}

.field .dd-menu {
  min-width: 200px;
  width: max-content;
  max-width: 260px;
}

.row2>.field:first-child .dd-menu {
  left: 0;
  right: auto;
}

.row2>.field:last-child .dd-menu {
  right: 0;
  left: auto;
}

/* Lamp-picker dropdowns live inside the scrolling bottom sheet; anchoring
   the option list under the trigger (as on desktop) means a long list
   scrolls independently right next to the sheet's own scroll, which on a
   small screen fights the user's touch. Pin it as a fixed overlay instead
   — #sidebar's own transform makes it a containing block for `fixed`
   descendants, so this centers over the sheet itself rather than the whole
   viewport, with its own single scroll region and no nested scroll. This
   must come after the .row2 first/last-child rules above (same specificity,
   source order decides) so centering wins over their left:0/right:0. */
@media (max-width: 820px) {

  .field .dd-menu,
  .row2>.field:first-child .dd-menu,
  .row2>.field:last-child .dd-menu {
    position: fixed;
    top: 50%;
    left: 50%;
    right: auto;
    transform: translate(-50%, -50%);
    min-width: 0;
    width: min(320px, 86vw);
    max-width: none;
    max-height: 70vh;
  }

  .dd-backdrop {
    display: none;
  }

  .field .dd[open] .dd-backdrop {
    display: block;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.45);
    z-index: 29;
  }
}

.dd-opt {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  background: none;
  border: 1px solid transparent;
  border-radius: 6px;
  padding: 0.45rem 0.5rem;
  color: var(--text-main);
  font-family: inherit;
  font-size: 0.85rem;
  cursor: pointer;
  text-align: left;
  width: 100%;
}

.dd-opt:hover {
  background: var(--surface-hover);
}

.dd-opt.active {
  border-color: var(--primary);
}

.dd-check {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.45rem 0.5rem;
  color: var(--text-main);
  font-size: 0.85rem;
  cursor: pointer;
  border-radius: 6px;
}

.dd-check:hover {
  background: var(--surface-hover);
}

.dd-check input[type="checkbox"] {
  width: 15px;
  height: 15px;
  accent-color: var(--primary);
  cursor: pointer;
}

.dd-sep {
  height: 1px;
  background: var(--border-color);
  margin: 0.3rem 0.2rem;
}

.lamp-preview {
  width: 24px;
  height: 22px;
  flex: none;
  background: transparent;
  border-radius: 3px;
}

/* Used inside the grid option tiles (dd-opt--tile) — bigger than the trigger
   preview since these are what's "hard to see" when scanning the list. */
.lamp-preview--lg {
  width: 34px;
  height: 32px;
}

/* Tighter vertical padding than the default .dd summary so the taller
   .lamp-preview above doesn't grow the trigger's overall height. */
.dd--lamp summary {
  padding: 0.3rem 0.6rem;
}

.dd--lamp summary span {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.dd-menu--tiles {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(64px, 1fr));
  gap: 0.3rem;
}

.field .dd-menu--tiles {
  width: max-content;
  max-width: 320px;
}

/* Number-of-lamps stepper shown under the lamp picker for pendant shapes
   (see lampDropdown in script.js) — a shape's tile is always its 1-lamp
   variant, so this is how 2/3/4 get chosen without needing a tile each. */
.lamp-count {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: 0.4rem;
}

.lamp-count-label {
  font-size: 0.72rem;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.lamp-count-btn {
  flex: 1;
  background: none;
  border: 1px solid var(--border-color);
  border-radius: 6px;
  padding: 0.3rem 0;
  color: var(--text-dim);
  font-family: inherit;
  font-size: 0.8rem;
  cursor: pointer;
}

.lamp-count-btn:hover {
  background: var(--surface-hover);
  color: var(--text-main);
}

.lamp-count-btn.active {
  border-color: var(--primary);
  color: var(--text-main);
}

.dd-opt--tile {
  position: relative;
  flex-direction: column;
  justify-content: flex-start;
  gap: 0.35rem;
  padding: 0.55rem 0.3rem;
  text-align: center;
}

.dd-opt--tile span {
  font-size: 0.68rem;
  line-height: 1.15;
  color: var(--text-dim);
}

.dd-opt--tile.active span {
  color: var(--text-main);
}

/* Hints, before a shape is even picked, that the lamp count for it can be
   adjusted (via the .lamp-count stepper shown once it's selected — see
   lampDropdown in script.js). */
.tile-count-badge {
  position: absolute;
  top: 3px;
  right: 5px;
  font-size: 0.52rem;
  line-height: 1;
  color: var(--text-dim);
  background: var(--surface-hover);
  border: 1px solid var(--border-color);
  border-radius: 999px;
  padding: 1px 4px;
}

.dd-opt--tile.active .tile-count-badge {
  border-color: var(--primary);
  color: var(--text-main);
}

.dd-backdrop {
  display: none;
}

/* The tile grid (26+ lamp icons) is too tall to anchor under its trigger
   and fit inside #sidebar's own scroll area without clipping/scrolling
   oddly — pin it as a page-centered fixed overlay with a backdrop instead,
   same treatment the mobile bottom sheet already uses below. Needs
   body.dd-tiles-open (see syncLampTilesOpenClass() in script.js) to briefly
   drop #sidebar's transform, since that transform would otherwise make
   #sidebar — not the viewport — the containing block for this `fixed`
   element, trapping it inside the sidebar's own box. */
/* transition: none is essential here — #sidebar normally transitions `transform`
   over 0.25s (its own slide animation). Without disabling that, this rule's
   transform:none would itself animate in, and since the overlay's containing
   block only flips from #sidebar to the viewport once the transform value
   actually reaches "none", the overlay stays trapped in the sidebar's box for
   the whole 0.25s and only snaps to its correct centered position at the very
   end — read by the user as the menu appearing in the wrong place, then
   visibly jumping. */
body.dd-tiles-open #sidebar {
  transform: none;
  transition: none;
}

@media (min-width: 821px) {

  /* Matches .row2>.field:first-child/:last-child .dd-menu's own specificity
     (they anchor the default popup style's left/right edge to each side-by-
     side field) so this centering wins over them instead of losing silently
     to a same-specificity rule declared earlier in the file. */
  .field .dd-menu--tiles,
  .row2>.field:first-child .dd-menu--tiles,
  .row2>.field:last-child .dd-menu--tiles {
    position: fixed;
    z-index: 61;
    top: 50%;
    left: 50%;
    right: auto;
    transform: translate(-50%, -50%);
    /* Scales with the viewport instead of a fixed 360px — on a large
       monitor the grid can spread into many more columns and needs far
       fewer scroll-past rows to show all ~30 lamp options at once. */
    width: min(78vw, 900px);
    max-width: none;
    min-width: 0;
    max-height: 82vh;
  }

  .dd-menu--tiles {
    grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
    gap: 0.5rem;
  }

  /* Scale with the viewport (like the modal's own width above) rather than
     staying pinned to the same small size the cramped 360px popup needed —
     on a large monitor the labels read as noticeably undersized otherwise. */
  .dd-opt--tile span {
    font-size: clamp(0.68rem, 0.45vw + 0.55rem, 0.95rem);
  }

  .dd-opt--tile .lamp-preview--lg {
    width: clamp(34px, 2vw + 20px, 46px);
    height: clamp(32px, 2vw + 18px, 44px);
  }

  .dd--lamp[open] .dd-backdrop {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 60;
    background: rgba(0, 0, 0, 0.45);
  }
}

@media (max-width: 820px) {
  .field .dd-menu--tiles {
    width: min(340px, 86vw);
    max-width: none;
  }
}

#sidebar .lamp-preview * {
  stroke: #fff !important;
}

#sidebar .lamp-preview *[fill]:not([fill="none"]) {
  fill: #fff !important;
}

/* ---------- Drag to reorder ---------- */

.drag-handle,
.proj-action-btn {
  flex: none;
  align-self: center;
  background: none;
  border: none;
  color: var(--text-dim);
  padding: 0.3rem;
  display: flex;
  align-items: center;
  justify-content: center;
  -webkit-tap-highlight-color: transparent;
}

/* .proj-overflow (a <details>) is the flex child, not the .proj-action-btn
   <summary> inside it — <details> and <button> stretch differently under
   .switch-item's align-items:stretch, so this needs the same centering
   applied at the wrapper level too, or the kebab ends up a different
   height than its sibling action buttons. */
.proj-overflow {
  align-self: center;
}

.drag-handle {
  cursor: grab;
  touch-action: none;
}

.proj-action-btn {
  cursor: pointer;
}

.drag-handle:hover,
.proj-action-btn:hover {
  color: var(--text-main);
}

.proj-action-btn.panel-action-btn--danger:hover {
  color: #ef4444 !important;
}

/* Higher specificity than the generic `.dd summary` rule (class + type
   beats a single class — same trap as the auth avatar fix above), which
   otherwise wins and wraps this in its own padded/backgrounded/6px-rounded
   box instead of matching the plain icon-button look of its siblings. An
   SVG icon (not a text glyph) so it sizes/aligns identically to the other
   14x14 action icons instead of depending on font metrics. */
.proj-overflow summary.proj-action-btn {
  list-style: none;
  padding: 0.3rem;
  border: none;
  background: none;
  border-radius: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.proj-overflow summary::-webkit-details-marker {
  display: none;
}

.proj-overflow[open] summary.proj-action-btn {
  color: var(--text-main);
  background: var(--surface-hover);
}

.drag-handle:active {
  cursor: grabbing;
}

/* Applied to the real item while it's floating (temporarily moved to
   <body> — see initDragReorder in script.js) so it visually lifts above
   the list it's being reordered within. */
.dragging {
  opacity: 0.95;
  box-shadow: 0 12px 28px rgba(0, 0, 0, 0.55);
  z-index: 1000;
  pointer-events: none;
}

.drag-placeholder {
  border: 1px dashed var(--border-color);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.02);
}

/* ---------- Print ---------- */

@media print {

  /* The general-purpose utility class used throughout index.html/JS (toasts,
     sync/invite banners, the collab-status icon, the auth slot, etc.) — the
     rule for it was missing entirely, so only .toolbar/#sidebar/.zoom-float
     (hidden below by their own selectors, redundantly now) were ever
     actually kept out of print; everything else carrying this class,
     including a toast that happened to be showing at print time, printed
     right along with the page. */
  .no-print {
    display: none !important;
  }

  .toolbar,
  #sidebar,
  .zoom-float {
    display: none !important;
  }

  body {
    background: #fff;
  }

  .layout {
    display: block;
    min-height: 0;
  }

  .canvas {
    background: none;
    overflow: visible;
  }

  #pages-scroll {
    padding: 0;
  }

  #pages {
    zoom: 1 !important;
    gap: 0;
    width: auto;
    display: block;
    padding: 0;
    margin: 0;
  }

  .page {
    box-shadow: none;
    page-break-after: always;
    break-after: page;
  }

  .page:last-child {
    page-break-after: auto;
    break-after: auto;
  }

  .switch-block.selected {
    outline: none;
  }

  .row-hl {
    display: none;
  }
}

/* ---------------------------------------------------------------------------
   Invite links (Phase 4) — top banner shown when the page was opened via a
   ?invite=<token> link (see share.js)
   --------------------------------------------------------------------------- */

.invite-banner:empty {
  display: none;
}

.invite-banner {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  padding: 0.6rem 1rem;
  background: var(--primary);
  color: #04121e;
  font-size: 0.88rem;
  font-weight: 500;
}

.invite-banner .btn-primary {
  background: #04121e;
  border-color: #04121e;
  color: var(--primary);
}

.invite-dismiss {
  background: none;
  border: none;
  color: inherit;
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  padding: 0.2rem 0.4rem;
  opacity: 0.7;
}

.invite-dismiss:hover {
  opacity: 1;
}

/* ---------------------------------------------------------------------------
   Cloud sync status — toolbar indicator (own DOM node, see cloud-sync.js —
   deliberately never touches #sidebar so it can't steal focus out of a
   field mid-edit). Cycles between a busy spinner (auth/sync resolving, or a
   write in flight), a saved cloud icon, and a warning triangle.
   --------------------------------------------------------------------------- */

/* #sync-warning holds the .sync-status span and, when shown, the "save now"
   button as separate inline siblings — without this, the button falls back
   to default inline baseline alignment and sits visibly lower than the icon
   and text inside .sync-status's own inline-flex row. */
#sync-warning {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}

.sync-status {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.8rem;
  white-space: nowrap;
  cursor: pointer;
}

.sync-status svg {
  flex: none;
}

.sync-status--warning {
  color: hsl(43, 96%, 62%);
}

.sync-save-now {
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  font: inherit;
  font-size: 0.8rem;
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
  opacity: 0.75;
  cursor: pointer;
}

.sync-save-now:hover {
  opacity: 1;
}

.sync-status--saved,
.sync-status--busy {
  color: var(--text-dim);
}

.sync-spinner {
  flex: none;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  border: 2px solid currentColor;
  border-top-color: transparent;
  opacity: 0.85;
  animation: sync-spin 0.7s linear infinite;
}

@keyframes sync-spin {
  to {
    transform: rotate(360deg);
  }
}

/* ---------------------------------------------------------------------------
   Real-time collaboration badge — top-left of the toolbar, shown only while
   cloud-sync.js has an active onSnapshot listener open (i.e. only for a
   shared project the user currently has open; see syncActiveListener()).
   --------------------------------------------------------------------------- */

#collab-status {
  display: none;
}

#collab-status:not(:empty) {
  display: flex;
  align-items: center;
}

.collab-status {
  display: inline-flex;
  align-items: center;
  color: var(--primary);
}

.collab-status svg {
  flex: none;
}

@keyframes collab-pulse {

  0%,
  100% {
    opacity: 1;
  }

  50% {
    opacity: 0.55;
  }
}

/* ---------------------------------------------------------------------------
   Auth (Google sign-in) — toolbar slot, avatar, dropdown, toast
   --------------------------------------------------------------------------- */

.auth-slot {
  display: flex;
  align-items: center;
}

.auth-signin {
  transition: opacity 0.3s ease, width 0.3s ease, padding-left 0.3s ease, padding-right 0.3s ease;
  width: 102px;
  overflow: hidden;
  white-space: nowrap;
}

.auth-slot--logged-in .auth-signin {
  opacity: 0;
  width: 0;
  padding-left: 0 !important;
  padding-right: 0 !important;
  border-left: 0 solid transparent !important;
  border-right: 0 solid transparent !important;
  pointer-events: none;
}

.auth-dd {
  transition: opacity 0.3s ease, width 0.3s ease, transform 0.3s ease;
  width: 34px;
  overflow: hidden;
  flex: none;
}

.auth-dd[open] {
  overflow: visible;
}

.auth-slot:not(.auth-slot--logged-in) .auth-dd {
  opacity: 0;
  width: 0;
  pointer-events: none;
  transform: scale(0.85);
}

.auth-signin svg {
  flex: none;
}

/* Config not filled in yet: still clickable (shows an explanatory toast), but
   visually muted so it doesn't imply a working feature. */
.auth-signin--pending {
  opacity: 0.6;
}

/* Higher specificity than the generic `.dd summary` rule (class + type beats
   a single class), which otherwise wins and wraps the circular avatar in
   that rule's padded, backgrounded, 6px-rounded box — the "rounded square"
   halo. Sized to match .icon-btn (34x34) so the toolbar stays a consistent
   height next to the other icon-only buttons (kebab menu, switches list). */
.auth-dd summary.auth-summary {
  list-style: none;
  width: 34px;
  height: 34px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: none;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.auth-summary::-webkit-details-marker {
  display: none;
}

.auth-avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  object-fit: cover;
  border: 1px solid var(--border-color);
  box-sizing: border-box;
  flex: none;
}

.auth-dd[open] .auth-avatar {
  border-color: var(--primary);
}

.auth-avatar--letter {
  background: var(--primary);
  color: #04121e;
  font-weight: 600;
  font-size: 0.9rem;
}

.auth-menu {
  min-width: 200px;
}

.auth-id {
  padding: 0.35rem 0.5rem 0.2rem;
}

.auth-name {
  font-weight: 600;
  font-size: 0.9rem;
  color: var(--text-main);
}

.auth-email {
  font-size: 0.8rem;
  color: var(--text-dim);
  overflow: hidden;
  text-overflow: ellipsis;
}

.auth-toast {
  position: fixed;
  left: 50%;
  bottom: 1.25rem;
  transform: translateX(-50%) translateY(0.75rem);
  z-index: 100;
  max-width: min(360px, 90vw);
  padding: 0.6rem 0.9rem;
  background: hsl(222, 44%, 15%);
  border: 1px solid var(--border-color);
  border-radius: 8px;
  color: var(--text-main);
  font-size: 0.85rem;
  line-height: 1.4;
  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.5);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease, transform 0.2s ease;
}

.auth-toast.show {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}
/* Classes that set `display` (like .btn) would otherwise override the hidden attribute. */
[hidden] {
  display: none !important;
}

/* ---------- Sharing a project (dialog from the project bar) ---------- */

/* The bar's dialog takes its colors from these, so it matches the page. */
:root {
  --surface: hsl(222, 44%, 13%);
  --ink: var(--text-main);
  --line: var(--border-color);
}

.si-shared {
  display: block;
  font-size: 0.75rem;
  color: var(--text-dim);
}

.share-panel {
  color: var(--ink);
}

.share-lede {
  margin: 0 0 12px;
  color: var(--text-dim);
}

.share-members {
  list-style: none;
  margin: 0 0 16px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 10px;
}

.share-members li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 12px;
}

.share-members li + li {
  border-top: 1px solid var(--line);
}

.share-role {
  font-size: 0.8rem;
  color: var(--text-dim);
}

.share-form label {
  display: block;
  margin-bottom: 6px;
  font-size: 0.85rem;
  color: var(--text-dim);
}

.share-row {
  display: flex;
  gap: 8px;
}

.share-row input {
  flex: 1;
  min-width: 0;
  padding: 8px 10px;
  font: inherit;
  color: var(--ink);
  background: var(--surface-color);
  border: 1px solid var(--line);
  border-radius: 8px;
}

.share-error {
  margin: 8px 0 0;
  color: #ff8a80;
  font-size: 0.85rem;
}

.share-link {
  margin: 0 0 16px;
}

.share-link label {
  display: block;
  margin-bottom: 4px;
  font-size: 0.85rem;
  color: var(--text-dim);
}

.share-hint {
  margin: 0 0 8px;
  font-size: 0.85rem;
  color: var(--text-dim);
}

.share-link .share-row + .share-row {
  margin-top: 8px;
}

.invite-banner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
  padding: 10px 16px;
  background: hsl(43, 96%, 90%);
  color: #422006;
  font-size: 0.9rem;
}

.invite-banner span {
  flex: 1 1 240px;
}

/* ---------- Floating button to reopen the sidebar ---------- */

.sidebar-open {
  position: absolute;
  top: 0.75rem;
  left: 0.75rem;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  padding: 0;
  color: var(--text-main);
  background: hsl(222, 44%, 15%);
  border: 1px solid var(--border-color);
  border-radius: 12px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
  cursor: pointer;
}

.sidebar-open:hover {
  background: hsl(222, 44%, 19%);
  border-color: var(--primary);
}

.sidebar-open:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}
