/* ═══════════════════════════════════════════════════════════════
   XODE — WEBSITE EDITOR

   Everything here is loaded by pages/website-editor.html and by
   nothing else, so none of it can reach the portfolio or the resume
   editor. It rides on the variables the main stylesheet already
   defines rather than restating any colour.
   ═══════════════════════════════════════════════════════════════ */

/* ─────────────────────────────────────────────────────────────
   1. THE BOARD

   Five pages across, as many rows as the project has. The stage
   already scrolls in both directions and already carries the dotted
   backdrop; the grid simply sits in it and grows.
   ───────────────────────────────────────────────────────────── */

/* A positioned box, not a grid. Every page carries its own board
   coordinates and is placed from them, which is what lets one be
   dragged anywhere instead of only into the slot its index gives it.
   The size is set inline from the furthest page, so the stage has
   something to scroll. */
.board-grid {
  position: relative;
  z-index: 1;
}

.board-cell {
  position: absolute;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/* Lifted while it is being dragged, so it passes over its neighbours
   rather than under them. */
.board-cell.is-dragging {
  z-index: 30;
  opacity: 0.92;
  cursor: grabbing;
}

.board-cell.is-dragging .board-frame {
  outline-color: #7C5CFF;
  box-shadow: 0 14px 40px rgba(0, 0, 0, 0.5);
}

/* Lined up with a neighbour. One green edge is enough to say so. */
.board-cell.is-snapped .board-frame {
  outline-color: #3DDC84;
}

/* The name strip is the grab handle for the whole page. */
.board-name { cursor: grab; }
.board-cell.is-dragging .board-name { cursor: grabbing; }

body.moving-page,
body.moving-page * { user-select: none !important; }

/* The name strip. Kept outside the page and at a fixed size, so it
   stays readable when the board is zoomed out far enough to see
   twenty pages at once — which is the whole point of the board. */
.board-name {
  display: flex;
  align-items: center;
  gap: 7px;
  height: 22px;
  padding: 0 2px;
  width: 100%;
  min-width: 0;
  overflow: hidden;
  font-size: 11.5px;
  color: var(--text-dim, #8B8D98);
  user-select: none;
}

.board-index {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 5px;
  background: rgba(124, 92, 255, 0.14);
  color: #9E86FF;
  font-size: 10px;
  font-weight: 700;
  flex-shrink: 0;
}

.board-name-input {
  flex: 1 1 auto;
  /* Zero, not 40px. A flex item will not shrink below its content
     width unless min-width says it may, and that refusal is what made
     each board column wider than the page above it. */
  min-width: 0;
  max-width: 190px;
  padding: 2px 5px;
  border: 1px solid transparent;
  border-radius: 5px;
  background: transparent;
  color: var(--text, #E7E7EA);
  font: inherit;
  font-weight: 600;
  text-overflow: ellipsis;
}

.board-name-input:hover {
  border-color: rgba(255, 255, 255, 0.12);
  background: rgba(255, 255, 255, 0.04);
}

.board-name-input:focus {
  outline: none;
  border-color: #7C5CFF;
  background: rgba(124, 92, 255, 0.1);
  color: #fff;
}

/* Zoomed out, the name is all there is room for. */
.board-grid.tight .board-dims { display: none; }

/* THE HANDLE NEVER GOES AWAY.
   The number is the grab handle for moving a page, and this used to be
   `display: none` below 0.18 zoom — hiding the only way to rearrange
   the board at exactly the zoom where you can see enough of it to want
   to. It shrinks now instead. */
.board-grid.tighter .board-index {
  min-width: 16px;
  padding: 0 3px;
  font-size: 9.5px;
}
.board-grid.tighter .board-name { gap: 4px; }

/* It has to look like something you can pick up. A bare number reads as
   a label, so it gets a chip, a grab cursor and a hover state. */
.board-index {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 17px;
  padding: 0 5px;
  border-radius: 5px;
  border: 1px solid var(--border-1, #2A2A34);
  background: var(--bg-3, #22242C);
  color: var(--text-dim, #8B8D98);
  font-size: 10.5px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  cursor: grab;
  flex-shrink: 0;
  transition: background .15s, color .15s, border-color .15s;
}
.board-index:hover {
  background: var(--violet, #7C5CFF);
  border-color: var(--violet, #7C5CFF);
  color: #fff;
}
.board-index:active,
.board-cell.is-dragging .board-index { cursor: grabbing; }
.board-index:focus-visible {
  outline: 2px solid var(--violet, #7C5CFF);
  outline-offset: 1px;
}

.board-dims {
  flex-shrink: 0;
  font-size: 10.5px;
  font-variant-numeric: tabular-nums;
  opacity: 0.6;
}

/* The handle you drag a prototype link from. Hidden until the cell is
   hovered, so twenty of them do not sit on the board shouting.

   grab, not crosshair: it is dragged to a target, and the cursor is
   the only thing that says so before you try. */
.board-proto-dot {
  flex-shrink: 0;
  display: inline-block;
  width: 14px;
  height: 14px;
  padding: 0;
  border: 1.5px solid rgba(255, 255, 255, 0.35);
  border-radius: 50%;
  background: transparent;
  cursor: grab;
  opacity: 0;
  touch-action: none;
  transition: opacity 0.14s, border-color 0.14s, background 0.14s, transform 0.14s;
}

.board-proto-dot:active { cursor: grabbing; }

.board-proto-dot::after {
  /* A dot in the middle, so it reads as a connector rather than an
     empty circle waiting to be ticked. */
  content: "";
  display: block;
  width: 4px;
  height: 4px;
  margin: 3.5px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.5);
}

.board-proto-dot:hover::after { background: #fff; }

/* The page number is the grab handle for moving the page. */
.board-index {
  cursor: grab;
}

.board-index:active { cursor: grabbing; }

.board-index:hover {
  background: rgba(124, 92, 255, 0.3);
  color: #C9BCFF;
}

/* The page the pointer is over while a link is being dragged out. */
.board-cell.proto-target .board-frame {
  outline-color: #3DDC84;
  box-shadow: 0 4px 26px rgba(61, 220, 132, 0.34);
}

/* While a link is being dragged, nothing on the board should be
   selecting text or showing an I-beam. */
body.linking,
body.linking * {
  cursor: crosshair !important;
  user-select: none !important;
}

body.linking .board-proto-dot { opacity: 1; }

/* The existing arrows must not catch the drop.
   .bl-hit takes pointer events on its stroke and .bl-tag takes them
   outright — that is what makes a drawn link clickable. Mid-drag it
   also meant elementFromPoint returned an SVG node sitting over the
   target page, .closest('.board-cell') found nothing, and the link
   was silently dropped on the floor. */
body.linking .board-links,
body.linking .board-links * {
  pointer-events: none !important;
}

.board-links .bl-ghost {
  fill: none;
  stroke: #3DDC84;
  stroke-width: 2.2;
  stroke-dasharray: 6 5;
  stroke-linecap: round;
  pointer-events: none;
}

.board-cell:hover .board-proto-dot,
.board-grid.proto-on .board-proto-dot { opacity: 1; }

.board-proto-dot:hover {
  border-color: #7C5CFF;
  background: rgba(124, 92, 255, 0.4);
}

/* The frame is what occupies layout space: the page inside it is
   transformed, and a transform is drawn rather than laid out, so
   without this the grid would think every page was full size however
   far you zoomed out. */
.board-frame {
  position: relative;
  border-radius: 2px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
  transition: box-shadow 0.16s, outline-color 0.16s;
  outline: 2px solid transparent;
  outline-offset: 2px;
}

.board-frame > .artboard,
.board-frame > .board-page {
  position: absolute;
  left: 0;
  top: 0;
  margin: 0 !important;
}

.board-cell.is-active .board-frame {
  outline-color: #7C5CFF;
  box-shadow: 0 4px 22px rgba(124, 92, 255, 0.26);
}

.board-cell:not(.is-active) .board-frame:hover {
  outline-color: rgba(255, 255, 255, 0.28);
  cursor: pointer;
}

/* A page you are not editing takes no clicks of its own — the click
   belongs to the board, which switches to that page. Without this,
   a link or a text node on an inactive page would swallow it. */
.board-page,
.board-page * {
  pointer-events: none !important;
  user-select: none;
}

.board-page {
  overflow: hidden;
  background: #fff;
}

.board-cell.proto-source .board-frame {
  outline-color: #FFB454;
  box-shadow: 0 4px 22px rgba(255, 180, 84, 0.3);
}

.board-grid.proto-on .board-frame { cursor: crosshair; }

/* ─────────────────────────────────────────────────────────────
   2. PROTOTYPE LINKS
   ───────────────────────────────────────────────────────────── */

.board-links {
  position: absolute;
  pointer-events: none;
  overflow: visible;
  z-index: 3;
  color: #7C5CFF;
}

.board-links .bl-line {
  fill: none;
  stroke: #7C5CFF;
  stroke-width: 2;
  stroke-linecap: round;
  opacity: 0.85;
}

/* An invisible fat stroke under the visible one. A 2px line is nearly
   impossible to click; this gives it a 16px target without drawing a
   16px line. */
.board-links .bl-hit {
  fill: none;
  stroke: transparent;
  stroke-width: 16;
  pointer-events: stroke;
  cursor: pointer;
}

.board-links .bl-dot {
  fill: #7C5CFF;
  stroke: #14141A;
  stroke-width: 2;
  pointer-events: auto;
  cursor: pointer;
}

.board-links .bl-tag {
  pointer-events: auto;
  cursor: pointer;
}

.board-links .bl-tag rect {
  fill: #1C1C24;
  stroke: rgba(124, 92, 255, 0.55);
  stroke-width: 1;
}

.board-links .bl-tag text {
  fill: #E7E7EA;
  font-family: inherit;
  font-size: 11px;
  font-weight: 600;
  text-anchor: middle;
  pointer-events: none;
}

.board-links .bl:hover .bl-line { opacity: 1; stroke-width: 2.6; }
.board-links .bl:hover .bl-tag rect { stroke: #7C5CFF; fill: #262632; }

/* ── naming a link ─────────────────────────────────────────── */

.proto-pop {
  position: fixed;
  z-index: 900;
  width: 272px;
  padding: 14px;
  border: 1px solid var(--border, #2A2A34);
  border-radius: 12px;
  background: var(--surface-2, #1C1C24);
  box-shadow: 0 18px 48px rgba(0, 0, 0, 0.5);
  font-size: 13px;
}

.proto-pop-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
}

.proto-pop-x {
  border: 0;
  background: none;
  color: var(--text-dim, #8B8D98);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  padding: 2px 4px;
}

.proto-pop-x:hover { color: var(--text, #E7E7EA); }

.proto-pop-route {
  margin: 0 0 12px;
  font-size: 12px;
  color: var(--text-dim, #8B8D98);
}

.proto-pop-route span { color: #7C5CFF; }

.proto-pop-label {
  display: block;
  margin-bottom: 5px;
  font-size: 11px;
  font-weight: 600;
  color: var(--text-dim, #8B8D98);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.proto-pop-input {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid var(--border, #2A2A34);
  border-radius: 8px;
  background: var(--surface, #14141A);
  color: var(--text, #E7E7EA);
  font: inherit;
}

.proto-pop-input:focus { outline: none; border-color: #7C5CFF; }

.proto-pop-actions {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  margin-top: 12px;
}

/* While prototyping, the drawing tools are not what the pointer is
   for. Saying so beats letting someone draw a rectangle by accident. */
body.proto-mode .tool-dock { opacity: 0.4; pointer-events: none; }

.tool-btn.active#btn-prototype,
#btn-prototype.active {
  background: rgba(255, 180, 84, 0.16);
  color: #FFB454;
}

/* ── Link straight out of a selected element ────────────────────
   Sits clear of the eight resize handles, on the right, so it can
   never be mistaken for one of them. Inside the artboard, so it
   scales with the page the way every other handle does. */
.el-link-handle {
  position: absolute;
  width: 15px;
  height: 15px;
  margin: -7.5px 0 0 -7.5px;
  border-radius: 50%;
  border: 2px solid #fff;
  background: #7C5CFF;
  box-shadow: 0 1px 5px rgba(0, 0, 0, 0.5);
  cursor: grab;
  touch-action: none;
  z-index: 40;
}

.el-link-handle:hover { background: #9E86FF; transform: scale(1.18); }
.el-link-handle:active { cursor: grabbing; }

/* ── The interaction panel ─────────────────────────────────────
   Injected into the inspector when exactly one element is selected.
   This is where "this button goes to that page" is said. */
.interaction-panel {
  border-top: 1px solid var(--border, #2A2A34);
  padding: 12px;
}

.ip-what {
  margin: 0 0 10px;
  font-size: 12px;
  line-height: 1.5;
  color: var(--text-dim, #8B8D98);
}

.ip-what b {
  color: var(--text, #E7E7EA);
  font-weight: 600;
}

.ip-select {
  width: 100%;
  padding: 7px 9px;
  border: 1px solid var(--border, #2A2A34);
  border-radius: 7px;
  background: var(--surface, #14141A);
  color: var(--text, #E7E7EA);
  font-size: 12.5px;
}

.ip-select:focus { outline: none; border-color: #7C5CFF; }

.ip-links { margin-top: 10px; }

.ip-link {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 7px 9px;
  margin-bottom: 5px;
  border-radius: 7px;
  background: rgba(124, 92, 255, 0.1);
  font-size: 12px;
}

.ip-arrow { color: #9E86FF; font-weight: 700; }

.ip-to {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text, #E7E7EA);
  font-weight: 600;
}

.ip-edit,
.ip-del {
  flex-shrink: 0;
  border: 0;
  background: none;
  color: var(--text-dim, #8B8D98);
  font-size: 11px;
  cursor: pointer;
  padding: 3px 5px;
  border-radius: 5px;
}

.ip-edit:hover { color: #C9BCFF; background: rgba(255, 255, 255, 0.06); }
.ip-del:hover  { color: #F0678C; background: rgba(240, 103, 140, 0.16); }

.ip-hint {
  margin: 9px 0 0;
  font-size: 11px;
  line-height: 1.55;
  color: var(--text-dim, #8B8D98);
}

/* ── The zoom tool's marquee, and the hand ─────────────────────── */
.zoom-marquee {
  position: absolute;
  z-index: 90;
  border: 1.5px solid #7C5CFF;
  background: rgba(124, 92, 255, 0.14);
  border-radius: 2px;
  pointer-events: none;
}

/* A held space bar pans whatever tool you have. The cursor has to say
   so, and it has to say so over the artboard too — which sets its own
   cursor per element. */
body.space-pan .canvas-viewport,
body.space-pan .canvas-viewport *,
body.panning .canvas-viewport,
body.panning .canvas-viewport * {
  cursor: grab !important;
}

body.panning .canvas-viewport,
body.panning .canvas-viewport * {
  cursor: grabbing !important;
  user-select: none !important;
}

/* ─────────────────────────────────────────────────────────────
   3. THE CODE PANEL
   ───────────────────────────────────────────────────────────── */

.code-panel {
  position: fixed;
  inset: 0;
  z-index: 880;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 4vh 3vw;
  background: rgba(0, 0, 0, 0.55);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
  animation: cp-fade 0.16s ease;
}

@keyframes cp-fade { from { opacity: 0; } to { opacity: 1; } }

.code-panel-inner {
  display: flex;
  flex-direction: column;
  width: min(1180px, 94vw);
  height: min(76vh, 800px);
  /* Never the full height: the padding on .code-panel guarantees a
     margin, and min-height keeps it usable on a short laptop screen
     where 76vh is not much. */
  min-height: 320px;
  border: 1px solid var(--border, #2A2A34);
  border-radius: 16px;
  background: var(--surface-2, #1C1C24);
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.55);
  overflow: hidden;
  animation: cp-rise 0.22s cubic-bezier(0.2, 0.8, 0.3, 1);
}

@keyframes cp-rise {
  from { transform: translateY(18px) scale(0.985); opacity: 0; }
  to   { transform: none; opacity: 1; }
}

.code-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--border, #2A2A34);
  flex-shrink: 0;
}

.code-head-title { display: flex; align-items: center; gap: 11px; min-width: 0; }

.code-glyph {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 9px;
  background: rgba(124, 92, 255, 0.16);
  color: #9E86FF;
  font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: 13px;
  font-weight: 700;
  flex-shrink: 0;
}

.code-head-title strong { display: block; font-size: 14px; }

.code-head-title span {
  display: block;
  font-size: 11.5px;
  color: var(--text-dim, #8B8D98);
}

.code-head-actions { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }

.code-x {
  border: 0;
  background: none;
  color: var(--text-dim, #8B8D98);
  font-size: 15px;
  cursor: pointer;
  padding: 5px 7px;
  border-radius: 7px;
}

.code-x:hover { background: rgba(255, 255, 255, 0.06); color: var(--text, #E7E7EA); }

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

.code-files {
  width: 216px;
  flex-shrink: 0;
  padding: 10px;
  border-right: 1px solid var(--border, #2A2A34);
  overflow-y: auto;
}

.code-file {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  padding: 8px 10px;
  margin-bottom: 3px;
  border: 0;
  border-radius: 7px;
  background: none;
  color: var(--text-dim, #8B8D98);
  font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: 12px;
  text-align: left;
  cursor: pointer;
}

.code-file:hover { background: rgba(255, 255, 255, 0.05); color: var(--text, #E7E7EA); }

.code-file.active {
  background: rgba(124, 92, 255, 0.16);
  color: #C9BCFF;
}

.code-file-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.code-file-size { flex-shrink: 0; opacity: 0.55; font-size: 10.5px; }

.code-files-note {
  margin-top: 12px;
  padding: 9px 10px;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.03);
  font-size: 11px;
  line-height: 1.5;
  color: var(--text-dim, #8B8D98);
}

.code-view { flex: 1; display: flex; flex-direction: column; min-width: 0; }

.code-view-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 9px 14px;
  border-bottom: 1px solid var(--border, #2A2A34);
  font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: 12px;
  color: var(--text-dim, #8B8D98);
  flex-shrink: 0;
}

.code-pre {
  flex: 1;
  margin: 0;
  padding: 14px 16px;
  overflow: auto;
  background: #101016;
  font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: 12px;
  line-height: 1.62;
  tab-size: 2;
}

.code-pre code { color: #C9CBD4; white-space: pre; }

.cd-tag  { color: #7CC4FF; }
.cd-attr { color: #FFB454; }
.cd-str  { color: #8FE3A8; }
.cd-com  { color: #6A6B78; font-style: italic; }

@media (max-width: 1000px) {
  .code-panel { padding: 2vh 2vw; }
  .code-panel-inner { width: 96vw; height: 90vh; border-radius: 14px; }
  .code-body { flex-direction: column; }
  .code-files {
    width: 100%;
    max-height: 132px;
    border-right: 0;
    border-bottom: 1px solid var(--border, #2A2A34);
  }
  .code-files-note { display: none; }
  .code-head-actions .btn-ghost { display: none; }
}

/* ─────────────────────────────────────────────────────────────
   4. CO-WORK
   ───────────────────────────────────────────────────────────── */

/* The HTML hidden attribute is display:none from the user agent
   sheet, and ANY author display rule outranks it. Both of these start
   life hidden and are shown only once a project is actually shared,
   so without these two lines an empty pen button and an empty avatar
   row sit in the toolbar of every project that is not shared. */
.cowork-faces[hidden],
.cowork-pen[hidden] { display: none !important; }

.cowork-faces {
  display: flex;
  align-items: center;
  gap: -4px;
  margin-right: 6px;
}

.cw-face {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  margin-left: -6px;
  border-radius: 50%;
  border: 2px solid var(--surface-2, #1C1C24);
  background: var(--cw, #7C5CFF);
  color: #101014;
  font-size: 11px;
  font-weight: 800;
  cursor: default;
}

.cw-face:first-child { margin-left: 0; }

.cw-face.holding { box-shadow: 0 0 0 2px var(--cw, #7C5CFF); }

/* The blinking light. Only ever on someone who has sent a heartbeat
   in the last half minute, so it means "here now" rather than
   "has an account". */
.cw-live {
  position: absolute;
  right: -1px;
  bottom: -1px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #3DDC84;
  border: 1.5px solid var(--surface-2, #1C1C24);
  animation: cw-blink 1.7s ease-in-out infinite;
}

@keyframes cw-blink {
  0%, 100% { opacity: 1;   transform: scale(1); }
  50%      { opacity: 0.35; transform: scale(0.82); }
}

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

.cowork-pen {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 13px;
  border: 1px solid rgba(124, 92, 255, 0.4);
  border-radius: 100px;
  background: rgba(124, 92, 255, 0.12);
  color: #C9BCFF;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
}

.cowork-pen:hover:not(:disabled) { background: rgba(124, 92, 255, 0.2); }
.cowork-pen.holding { border-color: #3DDC84; background: rgba(61, 220, 132, 0.14); color: #7BE8AE; }
.cowork-pen.busy,
.cowork-pen.muted {
  border-color: var(--border, #2A2A34);
  background: rgba(255, 255, 255, 0.04);
  color: var(--text-dim, #8B8D98);
  cursor: not-allowed;
}

/* Watching, not editing. The canvas still scrolls and zooms — only
   the things that would change the project are shut off, and the
   module refuses the mutation itself as well, so this is the sign
   rather than the lock. */
body.cowork-readonly .tool-dock,
body.cowork-readonly .sidebar-right,
body.cowork-readonly .bottom-pagenav-wrap,
body.cowork-readonly #btn-pagenav-add,
body.cowork-readonly .board-name-input {
  opacity: 0.45;
  pointer-events: none;
}

body.cowork-readonly .artboard { cursor: default; }

body.cowork-readonly .canvas-viewport::after {
  content: "View only — someone else has the pen";
  position: absolute;
  left: 50%;
  bottom: 14px;
  transform: translateX(-50%);
  z-index: 60;
  padding: 7px 14px;
  border-radius: 100px;
  background: rgba(17, 17, 20, 0.9);
  border: 1px solid rgba(255, 255, 255, 0.14);
  color: #C9CBD4;
  font-size: 12px;
  font-weight: 600;
  pointer-events: none;
}

.cowork-panel {
  position: fixed;
  top: 62px;
  right: 16px;
  z-index: 890;
  width: 340px;
  max-height: calc(100vh - 96px);
  overflow-y: auto;
  padding: 15px;
  border: 1px solid var(--border, #2A2A34);
  border-radius: 14px;
  background: var(--surface-2, #1C1C24);
  box-shadow: 0 20px 56px rgba(0, 0, 0, 0.5);
  font-size: 13px;
}

.cw-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
}

.cw-x {
  border: 0;
  background: none;
  color: var(--text-dim, #8B8D98);
  font-size: 15px;
  cursor: pointer;
  padding: 2px 5px;
}

.cw-state {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 10px 12px;
  margin-bottom: 13px;
  border-radius: 9px;
  font-size: 12.5px;
  line-height: 1.45;
}

.cw-state-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
.cw-state.is-mine { background: rgba(61, 220, 132, 0.12); color: #7BE8AE; }
.cw-state.is-mine .cw-state-dot { background: #3DDC84; }
.cw-state.is-free { background: rgba(255, 255, 255, 0.04); color: var(--text-dim, #8B8D98); }
.cw-state.is-free .cw-state-dot { background: #8B8D98; }
.cw-state.is-busy { background: rgba(255, 180, 84, 0.12); color: #FFCE8A; }
.cw-state.is-busy .cw-state-dot { background: #FFB454; }

.cw-list { list-style: none; margin: 0 0 13px; padding: 0; }

.cw-row {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 7px 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}

.cw-row:last-child { border-bottom: 0; }

.cw-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--cw, #7C5CFF);
  opacity: 0.32;
  flex-shrink: 0;
}

.cw-dot.live { opacity: 1; animation: cw-blink 1.7s ease-in-out infinite; }

.cw-who { flex: 1; min-width: 0; }
.cw-who b { display: block; font-size: 12.5px; }

.cw-who span {
  display: block;
  font-size: 11px;
  color: var(--text-dim, #8B8D98);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cw-role,
.cw-invite-row select {
  padding: 4px 6px;
  border: 1px solid var(--border, #2A2A34);
  border-radius: 6px;
  background: var(--surface, #14141A);
  color: var(--text, #E7E7EA);
  font-size: 11px;
}

.cw-role-flat {
  font-size: 11px;
  color: var(--text-dim, #8B8D98);
  text-transform: lowercase;
}

.cw-kick {
  border: 0;
  background: none;
  color: var(--text-dim, #8B8D98);
  cursor: pointer;
  padding: 3px 5px;
  border-radius: 5px;
  font-size: 12px;
}

.cw-kick:hover { background: rgba(240, 103, 140, 0.16); color: #F0678C; }

.cw-invite label {
  display: block;
  margin-bottom: 6px;
  font-size: 11px;
  font-weight: 600;
  color: var(--text-dim, #8B8D98);
}

.cw-invite-row { display: flex; gap: 6px; }

.cw-invite-row input {
  flex: 1;
  min-width: 0;
  padding: 7px 9px;
  border: 1px solid var(--border, #2A2A34);
  border-radius: 7px;
  background: var(--surface, #14141A);
  color: var(--text, #E7E7EA);
  font-size: 12px;
}

.cw-invite-row input:focus { outline: none; border-color: #7C5CFF; }

.cw-legend {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 3px 9px;
  margin: 13px 0 0;
  padding-top: 12px;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
  font-size: 11px;
}

.cw-legend dt { color: #9E86FF; font-weight: 700; }
.cw-legend dd { margin: 0; color: var(--text-dim, #8B8D98); }

.cw-note,
.cw-fine {
  margin: 10px 0 0;
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--text-dim, #8B8D98);
}

@media (max-width: 600px) {
  .cowork-panel { right: 8px; left: 8px; width: auto; }
}

/* ─────────────────────────────────────────────────────────────
   5. MOBILE VIEW — a column in the canvas, not a thing floating over it
   ───────────────────────────────────────────────────────────── */

/* The canvas area becomes a row: the board on the left, the device
   preview docked on the right. Opening it narrows the board rather
   than covering it, which is the difference between a preview you
   work alongside and one you keep dismissing.

   Scoped by file, not by selector: this stylesheet is linked from
   pages/website-editor.html and from nowhere else, so .canvas-area
   here cannot reach the portfolio or resume editor. */
.canvas-area {
  display: flex;
  align-items: stretch;
  /* The closed panel is positioned against this box rather than the
     page, so it has to be the containing block. It already was —
     styles.css sets position:relative on .canvas-area — but relying on
     that from another file is how a layout breaks silently later. */
  position: relative;
}

.canvas-viewport {
  flex: 1 1 auto;
  min-width: 0;
  width: auto;
}

/* CLOSED, IT IS NOT IN THE LAYOUT AT ALL.

   It used to keep a 34px column whether you were using it or not —
   a permanent tax on the board for a panel you had shut. Closed it is
   now absolutely positioned against the right edge, so it occupies no
   width and the board gets the whole canvas; the tab floats over the
   corner as the way back in.

   Open, it returns to the flow and the two sit side by side, which is
   what makes it a preview you work alongside rather than one you keep
   dismissing. */
/* Closed, the preview is not on the canvas at all — not as a column,
   not as a floating handle, not as a strip of anything. It used to
   leave a tab parked on the right edge, which is a small permanent
   tax on the thing the editor is actually for.

   The way back in is the toolbar button, which is where a toggle for
   a panel belongs and which can also show whether it is on. */
.mobile-view { display: none; }

.mobile-view.open {
  position: relative;
  display: flex;
  align-items: stretch;
  flex: 0 0 auto;
  z-index: 20;
  border-left: 1px solid var(--border, #2A2A34);
  background: var(--surface-2, #1C1C24);
}

/* Closed, it is the tab and nothing else — 34px of the canvas given
   up, against the 300px it used to cover. */
/* The vertical "Mobile" strip that used to live on the panel edge is
   gone. It was a third way to do what the toolbar button and the
   header chevron already do, and it charged 34px of the panel width
   for the privilege — on a 220px column that is a seventh of the
   preview. The header says "Mobile preview" instead, which costs
   nothing because that row was already there. */

.mv-body {
  width: 320px;
  padding: 12px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
}

.mv-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 11px;
  flex-shrink: 0;
}

.mv-devices {
  display: flex;
  gap: 2px;
  padding: 2px;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.05);
}

.mv-device {
  padding: 5px 9px;
  border: 0;
  border-radius: 6px;
  background: none;
  color: var(--text-dim, #8B8D98);
  font-size: 11px;
  font-weight: 600;
  cursor: pointer;
}

.mv-device.active { background: rgba(124, 92, 255, 0.2); color: #C9BCFF; }

.mv-dims {
  font-size: 10.5px;
  font-variant-numeric: tabular-nums;
  color: var(--text-dim, #8B8D98);
  flex-shrink: 0;
}

.mv-stage {
  display: flex;
  justify-content: center;
  align-items: flex-start;
  padding: 10px 0;
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
}

.mv-frame {
  position: relative;
  overflow: hidden;
  border: 7px solid #26262F;
  border-radius: 18px;
  background: #f4f4f5;
  box-shadow: 0 8px 26px rgba(0, 0, 0, 0.42);
  flex-shrink: 0;
}

.mv-screen { position: relative; overflow: hidden; }

/* The preview is a picture of the page, not a second copy to click. */
.mv-screen * { pointer-events: none !important; }

/* ── RESPONSIVE CONTROLS ─────────────────────────────────────────
   A row under the device tabs, and a strip that appears when an
   element in the frame is tapped. Both are narrow by necessity — the
   panel is 320px by default — so the buttons are short words rather
   than icons nobody would recognise at 11px. */
.mv-tools {
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px;
  padding: 8px 12px 0;
  flex-shrink: 0;
}
.mv-tool {
  padding: 5px 9px;
  border-radius: 7px;
  border: 1px solid rgba(255,255,255,.14);
  background: rgba(255,255,255,.05);
  color: var(--text-1, #C7C9D3);
  font-size: 11px; font-weight: 600;
  cursor: pointer; line-height: 1;
  transition: background .15s, border-color .15s, color .15s;
}
.mv-tool:hover { background: rgba(255,255,255,.1); color: #fff; }
.mv-tool.primary {
  background: rgba(124,92,255,.22);
  border-color: rgba(124,92,255,.5);
  color: #C9BCFF;
}
.mv-tool.primary:hover { background: rgba(124,92,255,.32); color: #fff; }
/* "on" is a state, not a hover — the element IS hidden, or IS half
   width, and the button has to say so when nothing is pointing at it. */
.mv-tool.on {
  background: rgba(255,180,84,.2);
  border-color: rgba(255,180,84,.45);
  color: #FFD79A;
}
.mv-tools-note {
  font-size: 10.5px; line-height: 1.4;
  color: var(--text-dim, #8B8D98);
}

.mv-sel {
  display: flex; align-items: center; gap: 5px; flex-wrap: wrap;
  margin: 8px 12px 0;
  padding: 7px 8px;
  border-radius: 9px;
  border: 1px solid rgba(124,92,255,.3);
  background: rgba(124,92,255,.1);
  flex-shrink: 0;
}
.mv-sel[hidden] { display: none; }
.mv-sel-name {
  flex: 1 1 100%;
  font-size: 10.5px; font-weight: 700;
  color: #C9BCFF;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* The frame is a scroll box once a stacked column is taller than the
   device — which it usually is, that being the point of stacking. */
.mv-frame { overflow: auto; -webkit-overflow-scrolling: touch; }
/* shapeContent() writes the font size and alignment onto a div INSIDE
   each element, as inline styles. The preview cannot rewrite that
   markup without reimplementing it, so it sets a custom property on
   the wrapper and these two rules carry it down — the same child the
   exported stylesheet targets, so the panel and the download agree. */
.mv-screen [data-mv-fs] > div { font-size: var(--mv-fs) !important; }
.mv-screen [data-mv-align] > div { text-align: var(--mv-align) !important; }

.mv-screen [data-mv-el] { cursor: pointer; }
.mv-screen .mv-picked {
  outline: 2px solid #7C5CFF;
  outline-offset: 1px;
}

.mv-note {
  margin: 4px 0 0;
  font-size: 11px;
  line-height: 1.5;
  color: var(--text-dim, #8B8D98);
  flex-shrink: 0;
}

/* Below this there is not enough width left for a board and a phone
   side by side, so the panel keeps its tab and drops to a narrower
   body rather than squeezing the canvas to nothing. */
@media (max-width: 1200px) {
  .mv-body { width: 250px; }
}

@media (max-width: 1024px) {
  .mobile-view { display: none; }
}

/* ─────────────────────────────────────────────────────────────
   6. THE TWO NEW BUTTONS IN THE CHROME
   ───────────────────────────────────────────────────────────── */

.web-tools {
  display: flex;
  align-items: center;
  gap: 7px;
}

.btn-code {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  width: 100%;
  justify-content: center;
  padding: 10px 14px;
  border: 1px solid rgba(124, 92, 255, 0.35);
  border-radius: 9px;
  background: rgba(124, 92, 255, 0.1);
  color: #C9BCFF;
  font-size: 12.5px;
  font-weight: 700;
  cursor: pointer;
  transition: background 0.14s, border-color 0.14s;
}

.btn-code:hover { background: rgba(124, 92, 255, 0.2); border-color: #7C5CFF; }

.btn-code code {
  font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: 12px;
}

/* The code button lives at the bottom of the right-hand column, under
   whatever the inspector is showing, and stays there when the panel
   above it scrolls. */
.inspector-code-dock {
  margin-top: auto;
  padding: 12px;
  border-top: 1px solid var(--border, #2A2A34);
  background: var(--surface-2, #1C1C24);
  position: sticky;
  bottom: 0;
}

.inspector-code-dock .dock-hint {
  margin: 8px 0 0;
  font-size: 11px;
  line-height: 1.5;
  color: var(--text-dim, #8B8D98);
  text-align: center;
}

.sidebar-right { display: flex; flex-direction: column; }

/* ─────────────────────────────────────────────────────────────
   7. LIMITS

   The screen gate and the one dialog that asks for money. Both live
   in this stylesheet, so neither can appear in the portfolio or
   resume editors — both of which work fine on a phone and neither of
   which has a page you have to buy.
   ───────────────────────────────────────────────────────────── */

.screen-gate {
  position: fixed;
  inset: 0;
  z-index: 2147483000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: var(--bg-0, #0B0C0F);
  overflow-y: auto;
}

/* The editor underneath keeps running — it just must not be reachable.
   Hiding it outright would throw away an unsaved project if someone
   rotated a tablet into portrait for a moment. */
body.screen-gated .editor-body,
body.screen-gated .editor-topbar,
body.screen-gated .welcome-screen {
  pointer-events: none;
}

.sg-inner {
  max-width: 460px;
  text-align: center;
  color: var(--text-1, #E7E7EA);
}

.sg-inner svg {
  color: #7C5CFF;
  margin-bottom: 18px;
}

.sg-inner h1 {
  margin: 0 0 14px;
  font-size: clamp(22px, 6vw, 30px);
  font-weight: 800;
  line-height: 1.2;
}

.sg-inner p {
  margin: 0 0 14px;
  font-size: 15px;
  line-height: 1.65;
  color: var(--text-3, #8B8D98);
}

.sg-inner b { color: var(--text-1, #E7E7EA); font-weight: 700; }

.sg-now {
  display: inline-block;
  padding: 6px 14px;
  border-radius: 100px;
  background: rgba(255, 255, 255, 0.05);
  font-size: 13px !important;
}

.sg-alt a { color: #9E86FF; }

.sg-inner .btn-primary { margin-top: 10px; }

/* ── Asking for money ────────────────────────────────────────── */

.gate-ask {
  position: fixed;
  inset: 0;
  z-index: 950;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(0, 0, 0, 0.6);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
}

.ga-box {
  position: relative;
  width: min(430px, 100%);
  padding: 26px;
  border: 1px solid var(--border, #2A2A34);
  border-radius: 16px;
  background: var(--surface-2, #1C1C24);
  box-shadow: 0 28px 70px rgba(0, 0, 0, 0.55);
}

.ga-x {
  position: absolute;
  top: 12px;
  right: 12px;
  border: 0;
  background: none;
  color: var(--text-dim, #8B8D98);
  font-size: 15px;
  cursor: pointer;
  padding: 5px 7px;
  border-radius: 7px;
}

.ga-x:hover { background: rgba(255, 255, 255, 0.06); color: var(--text, #E7E7EA); }

.ga-box h2 {
  margin: 0 0 12px;
  font-size: 19px;
  font-weight: 700;
  color: var(--text, #E7E7EA);
  padding-right: 24px;
}

.ga-box p {
  margin: 0 0 12px;
  font-size: 14px;
  line-height: 1.65;
  color: var(--text-dim, #8B8D98);
}

.ga-box p b { color: var(--text, #E7E7EA); font-weight: 700; }

.ga-note {
  padding: 10px 12px;
  border-radius: 9px;
  background: rgba(124, 92, 255, 0.1);
  font-size: 12.5px !important;
  color: #C9BCFF !important;
}

.ga-actions {
  display: flex;
  justify-content: flex-end;
  gap: 9px;
  margin-top: 18px;
}

/* ── The page size inputs ────────────────────────────────────── */

.prop-num {
  width: 78px;
  padding: 5px 8px;
  border: 1px solid var(--border, #2A2A34);
  border-radius: 6px;
  background: var(--surface, #14141A);
  color: var(--text, #E7E7EA);
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.prop-num:focus { outline: none; border-color: #7C5CFF; }

/* Spinners in a 78px box leave no room for four digits. */
.prop-num::-webkit-outer-spin-button,
.prop-num::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.prop-num { -moz-appearance: textfield; appearance: textfield; }

.tool-divider {
  width: 1px;
  height: 20px;
  margin: 0 3px;
  background: var(--border, #2A2A34);
  flex-shrink: 0;
}

/* ─────────────────────────────────────────────────────────────
   8. THE PROTOTYPE PLAYER

   Full screen, over everything, because a prototype you view inside a
   panel is a prototype nobody trusts. The chrome is a thin bar that
   gets out of the way; the page below it is the product.
   ───────────────────────────────────────────────────────────── */

.pv {
  position: fixed;
  inset: 0;
  z-index: 2000;
  display: flex;
  flex-direction: column;
  background: #0B0C0F;
}

body.pv-open { overflow: hidden; }

.pv-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
  padding: 9px 14px;
  border-bottom: 1px solid var(--border, #2A2A34);
  background: var(--surface-2, #1C1C24);
}

.pv-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 11px;
  border: 1px solid var(--border, #2A2A34);
  border-radius: 8px;
  background: transparent;
  color: var(--text-dim, #8B8D98);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: color 0.14s, background 0.14s, border-color 0.14s;
}

.pv-btn:hover:not(:disabled) {
  color: var(--text, #E7E7EA);
  background: rgba(255, 255, 255, 0.06);
  border-color: rgba(255, 255, 255, 0.2);
}

.pv-btn:disabled { opacity: 0.35; cursor: default; }

.pv-x { border-color: transparent; font-size: 14px; }
.pv-x:hover { background: rgba(240, 103, 140, 0.16) !important; color: #F0678C !important; }

.pv-where {
  margin-left: 6px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text, #E7E7EA);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.pv-spacer { flex: 1; }

.pv-devices {
  display: flex;
  gap: 2px;
  padding: 2px;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.05);
}

.pv-device {
  padding: 5px 10px;
  border: 0;
  border-radius: 6px;
  background: none;
  color: var(--text-dim, #8B8D98);
  font-size: 11.5px;
  font-weight: 600;
  cursor: pointer;
}

.pv-device.active { background: rgba(124, 92, 255, 0.22); color: #C9BCFF; }

.pv-body {
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  overflow: auto;
  /* The same dotted workspace the board uses, so it is obviously the
     same product and obviously not the page itself. */
  background:
    radial-gradient(circle at 1px 1px, rgba(255, 255, 255, 0.05) 1px, transparent 0) 0 0 / 24px 24px,
    #0B0C0F;
}

.pv-frame {
  position: relative;
  overflow: hidden;
  flex-shrink: 0;
  background: #fff;
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.6);
  border-radius: 4px;
}

/* A named device gets a bezel; "Fit" is just the page. */
.pv-frame.is-device {
  border: 8px solid #26262F;
  border-radius: 22px;
}

.pv-stage {
  position: absolute;
  left: 0;
  top: 0;
  transform-origin: 0 0;
  will-change: transform, opacity;
}

.pv-ghost { pointer-events: none; }

.pv-el { position: absolute; box-sizing: border-box; }

/* Anything with a link is a control, and has to look like one. */
.pv-link { cursor: pointer; }

.pv-link:focus-visible {
  outline: 3px solid #7C5CFF;
  outline-offset: 3px;
}

/* H, or the button. On a finished design nothing tells you what is
   clickable until you find it — every prototype tool has this. */
@keyframes pv-flash {
  0%, 100% { box-shadow: 0 0 0 0 rgba(124, 92, 255, 0); }
  40%      { box-shadow: 0 0 0 4px rgba(124, 92, 255, 0.75), 0 0 26px rgba(124, 92, 255, 0.5); }
}

.pv-flash .pv-link { animation: pv-flash 0.9s ease-in-out; }

.pv-hint {
  position: absolute;
  left: 50%;
  bottom: 16px;
  transform: translateX(-50%);
  margin: 0;
  padding: 7px 15px;
  border-radius: 100px;
  background: rgba(17, 17, 20, 0.88);
  border: 1px solid rgba(255, 255, 255, 0.12);
  color: var(--text-dim, #8B8D98);
  font-size: 12px;
  pointer-events: none;
  white-space: nowrap;
  max-width: calc(100vw - 40px);
  overflow: hidden;
  text-overflow: ellipsis;
}

.btn-play svg { flex-shrink: 0; }

.btn-play:hover {
  color: #7BE8AE !important;
  border-color: rgba(61, 220, 132, 0.45) !important;
}

/* ── The link editor's new fields ─────────────────────────────── */

.proto-pop-trigger {
  margin: 0 0 12px;
  padding: 8px 10px;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.04);
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--text-dim, #8B8D98);
}

.proto-pop select.proto-pop-input { cursor: pointer; }

.proto-pop-label:not(:first-of-type) { margin-top: 12px; }

.proto-pop-pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}

.proto-pop-units {
  margin: 5px 0 0;
  font-size: 10.5px;
  color: var(--text-dim, #8B8D98);
  opacity: 0.8;
}

.proto-pop-actions { flex-wrap: wrap; }

/* ── The interaction panel's hover half ───────────────────────── */

.ip-sep {
  height: 1px;
  margin: 14px 0 12px;
  background: var(--border, #2A2A34);
}

.ip-stack { flex-direction: column; align-items: stretch; gap: 5px; }

.ip-num { max-width: 90px; }

.ip-to em {
  display: block;
  font-style: normal;
  font-size: 10.5px;
  font-weight: 500;
  color: var(--text-dim, #8B8D98);
}

.ip-hint code {
  padding: 1px 4px;
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.07);
  font-size: 10.5px;
}

/* ── The mobile panel's resize grip ───────────────────────────── */

.mv-grip {
  flex: 0 0 5px;
  width: 5px;
  cursor: col-resize;
  background: transparent;
  transition: background 0.14s;
  touch-action: none;
}

.mv-grip:hover,
.mv-grip:focus-visible,
body.mv-resizing .mv-grip { background: #7C5CFF; outline: none; }

body.mv-resizing,
body.mv-resizing * { cursor: col-resize !important; user-select: none !important; }

/* Set inline by the script and remembered per browser; this is only
   the starting point before anyone has dragged it. */
.mv-body { width: 320px; }

/* The nav a page-level link becomes — the same bar the exported
   styles.css builds, so the preview and the download agree. */
.pv-nav {
  position: absolute;
  left: 50%;
  bottom: 16px;
  transform: translateX(-50%);
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 7px;
  border-radius: 100px;
  background: rgba(17, 17, 20, 0.86);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow: 0 10px 32px rgba(0, 0, 0, 0.35);
  z-index: 5;
  max-width: calc(100% - 24px);
}

.pv-nav a {
  padding: 7px 14px;
  border-radius: 100px;
  color: #fff;
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background 0.15s;
}

.pv-nav a:hover { background: rgba(255, 255, 255, 0.15); }

/* In a phone or tablet frame the page scrolls, and a bar positioned
   absolutely scrolled away with it. Sticky keeps it on screen. */
.pv-frame.is-flow .pv-nav {
  position: sticky;
  left: auto;
  bottom: 16px;
  transform: none;
  width: max-content;
  margin: 0 auto 16px;
}

/* A menu word that names a page is a link, and says so when you reach
   for it. !important because every element carries its opacity inline. */
.pv-menu:hover,
.pv-menu:focus-visible { opacity: 0.72 !important; }

/* ─────────────────────────────────────────────────────────────
   9. CLOSING THE PREVIEW

   The vertical tab always toggled the panel, but a tab does not say
   "close" — the only way out was one you had to find by accident.
   This is the title row with the chevron at the end of it, which is
   where every docked panel in every editor puts the same control.
   ───────────────────────────────────────────────────────────── */

.mv-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: -4px -4px 10px;
  padding: 0 0 9px;
  border-bottom: 1px solid var(--border, #2A2A34);
  flex-shrink: 0;
}

.mv-bar-title {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex: 1;
  min-width: 0;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--text-dim, #8B8D98);
}

.mv-bar-title svg { flex-shrink: 0; opacity: 0.8; }

.mv-close {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 7px;
  background: transparent;
  color: var(--text-dim, #8B8D98);
  cursor: pointer;
  transition: color 0.14s, background 0.14s, border-color 0.14s;
}

.mv-close:hover {
  color: #C9BCFF;
  background: rgba(124, 92, 255, 0.14);
  border-color: rgba(124, 92, 255, 0.4);
}

.mv-close:focus-visible {
  outline: 2px solid #7C5CFF;
  outline-offset: 1px;
}

/* The dimensions move up into the title row, so the device tabs get
   the whole of the row below them. At 220px they were fighting. */
.mv-bar .mv-dims { flex-shrink: 0; }

.mv-head { margin-bottom: 9px; }
.mv-head .mv-devices { width: 100%; }
.mv-head .mv-device { flex: 1; text-align: center; }


/* The ms suffix beside a number field in the Interaction panel. */
.interaction-panel .ip-unit {
  font-size: 10.5px;
  color: var(--text-dim, #8B8D98);
  margin-left: 6px;
  flex-shrink: 0;
}

/* ── Play, at a device that reflows ─────────────────────────────
   The phone and tablet tabs no longer show the desktop drawing at 23%
   — they show the real single-column layout at its real width, in a
   frame that scrolls. So the stage stops being an absolutely
   positioned canvas and becomes ordinary flow, and the frame becomes
   a viewport. */
.pv-frame.is-flow { overflow-y: auto; overflow-x: hidden; }

.pv-frame.is-flow .pv-stage {
  position: relative;
  transform: none;
  width: 100%;
}

/* A box in the flow is in flow — the absolute positioning that carries
   the desktop drawing would put every one of them at the top left. */
.pv-frame.is-flow .pv-el,
.pv-frame.is-flow .canvas-el { position: relative; }

/* Nothing to grab in a preview; the scrollbar is the frame's job. */
.pv-frame.is-flow::-webkit-scrollbar { width: 0; height: 0; }

/* ═══════════════════════════════════════════════════════════════
   TOP BAR ICONS, IN COLOUR

   Each icon is stroked with a gradient of its own. The gradients are
   SVG paint servers defined once, in website-tools.js (#xg-…); a
   stroke set in CSS outranks the stroke="currentColor" attribute on
   the icon, so the markup itself is untouched. Hover and the active
   state get a soft tile in the same spirit.
   ═══════════════════════════════════════════════════════════════ */
.editor-topbar #btn-back-home svg   { stroke: url(#xg-slate); }
.editor-topbar #btn-undo svg,
.editor-topbar #btn-redo svg        { stroke: url(#xg-sky); }
.editor-topbar #btn-prototype svg   { stroke: url(#xg-violet); }
.editor-topbar #btn-fit-board svg   { stroke: url(#xg-teal); }
.editor-topbar #btn-tidy svg        { stroke: url(#xg-amber); }
.editor-topbar #btn-toggle-grid svg { stroke: url(#xg-pink); }
.editor-topbar #btn-mobile-view svg { stroke: url(#xg-lime); }
.editor-topbar #btn-login svg       { stroke: url(#xg-sunset); }
.editor-topbar .ai-chip-btn svg     { stroke: url(#xg-aurora); }
.editor-topbar [data-xode-play] svg { stroke: url(#xg-green); }
.editor-topbar [data-xode-play] svg path { fill: url(#xg-green); }
.editor-topbar #btn-present svg     { stroke: url(#xg-sky); }
.editor-topbar #btn-cowork svg      { stroke: url(#xg-teal); }
.editor-topbar #btn-share svg       { stroke: url(#xg-violet); }

.editor-topbar .icon-btn svg,
.editor-topbar .btn-ghost svg { transition: transform .18s ease, filter .18s ease; }

.editor-topbar .icon-btn:hover:not(:disabled) {
  background: linear-gradient(135deg, rgba(124, 92, 255, .18), rgba(255, 106, 26, .12));
}
.editor-topbar .icon-btn:hover:not(:disabled) svg,
.editor-topbar .btn-ghost:hover svg {
  transform: translateY(-1px);
  filter: drop-shadow(0 2px 6px rgba(124, 92, 255, .38));
}
.editor-topbar .icon-btn.active,
.editor-topbar .icon-btn[aria-pressed="true"] {
  background: linear-gradient(135deg, rgba(124, 92, 255, .28), rgba(43, 181, 160, .18));
  box-shadow: inset 0 0 0 1px rgba(124, 92, 255, .38);
}

/* The (i) is a letter in a ring rather than a stroked icon, so it takes
   the warm gradient as a tint and a matching ring. */
.editor-topbar .ht-i {
  color: #FFC766;
  border-color: rgba(255, 199, 102, .42);
  background: linear-gradient(135deg, rgba(255, 199, 102, .10), rgba(255, 94, 138, .10));
}
.editor-topbar .ht-i:hover {
  color: #fff;
  border-color: #FF8A6B;
  background: linear-gradient(135deg, rgba(255, 199, 102, .28), rgba(255, 94, 138, .24));
}
