/* ==========================================================================
   PocketCorp Coder — product components
   Everything here is specific to building apps: the home composer, the build
   chat, the data grid, and the device preview. The shared chrome (sidebar,
   cards, forms, modals) lives in app.css.
   ========================================================================== */

/* ---------- Full-height views (Build, Preview, Data) ----------
   Those views own the viewport: the page itself never scrolls, the panel
   inside them does. Everything else scrolls normally. */

/* The body becomes the flex column so the mobile top bar takes its share and
   .app gets exactly the rest — otherwise a 100dvh .app plus a ~57px topbar
   overflows and pushes the chat composer off the bottom of the screen. */
body.view-fixed {
  height: 100dvh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

body.view-fixed .app { flex: 1; height: auto; min-height: 0; min-width: 0; }

/* The transcript renders whatever the agent emits. Every known shape is fixed
   at the source above; this clip guarantees an unforeseen one still cannot
   push the page sideways. `clip` (not `hidden`) leaves the panel's own
   internal scrolling — the tool bodies, the data grid — working. */
.chat, .chat-scroll { overflow-x: clip; }

body.view-fixed .content {
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
  padding-bottom: 0;
}

/* The Build / Data / Preview pages fill the viewport and scroll internally.
   `min-width: 0` at every level is load-bearing: a flex item defaults to
   `min-width: auto` (its min-content width), so without it one long agent
   string widens the page instead of wrapping inside the panel. */
.page--fill {
  display: flex;
  flex-direction: column;
  min-height: 0;
  min-width: 0;
  flex: 1;
}

/* Vertical space is scarce in these views — the header gives some back. */
body.view-fixed .page-head { margin-bottom: 20px; }
body.view-fixed .page-sub { display: none; }

/* ---------- Home composer ---------- */

.hero {
  display: flex;
  flex-direction: column;
  gap: 26px;
  padding: 40px 0 12px;
  border-bottom: 1px solid var(--pc-border-muted);
  margin-bottom: 44px;
}

.hero-title {
  font-family: var(--pc-font-display);
  font-size: clamp(1.6rem, 4.4vw, 2.6rem);
  font-weight: 500;
  letter-spacing: var(--pc-track-tight);
  line-height: 1.25;
  margin: 0;
  max-width: 18ch;
}

.hero-sub {
  font-size: 0.74rem;
  line-height: 1.9;
  opacity: var(--pc-dim-2);
  max-width: 54ch;
  margin: -14px 0 0;
}

.composer {
  border: var(--pc-border-w) solid var(--pc-border);
  transition: border-color 0.3s var(--pc-ease);
  background: var(--pc-bg-subtle);
}

.composer:focus-within { border-color: var(--pc-border-strong); }

.composer-input {
  width: 100%;
  border: 0;
  background: transparent;
  color: inherit;
  font-family: var(--pc-font-body);
  font-size: 0.82rem;
  line-height: 1.8;
  padding: 18px 20px 4px;
  resize: none;
  outline: none;
  min-height: 88px;
  max-height: 40vh;
  overflow-y: auto;
}

.composer-input::placeholder { color: inherit; opacity: 0.35; }

.composer-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 10px 14px 12px 20px;
}

.composer-hint {
  font-size: 0.58rem;
  letter-spacing: var(--pc-track-tight);
  text-transform: uppercase;
  opacity: var(--pc-dim-3);
}

.composer-seeds {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.seed {
  font-family: var(--pc-font-body);
  font-size: 0.65rem;
  padding: 7px 13px;
  border: 1px solid var(--pc-border);
  background: transparent;
  color: inherit;
  cursor: pointer;
  opacity: var(--pc-dim-1);
  transition: all 0.25s var(--pc-ease);
  text-align: left;
}

.seed:hover { opacity: 1; border-color: var(--pc-border-hover); background: var(--pc-bg-hover); }

/* ---------- Theme picker (home page) ---------- */

.theme-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: -10px;
}

.theme-row-label {
  font-family: var(--pc-font-display);
  font-size: 0.55rem;
  font-weight: 500;
  letter-spacing: var(--pc-track);
  text-transform: uppercase;
  opacity: var(--pc-dim-3);
  margin-right: 4px;
}

.theme-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px 6px 7px;
  border: 1px solid var(--pc-border);
  background: transparent;
  color: inherit;
  font-family: var(--pc-font-display);
  font-size: 0.58rem;
  font-weight: 500;
  letter-spacing: var(--pc-track-tight);
  text-transform: uppercase;
  cursor: pointer;
  opacity: var(--pc-dim-1);
  transition: all 0.25s var(--pc-ease);
}

.theme-chip:hover { opacity: 1; border-color: var(--pc-border-hover); }

.theme-chip.is-active {
  opacity: 1;
  border-color: var(--pc-ink);
  border-width: var(--pc-border-w);
  background: var(--pc-bg-subtle);
}

/* A miniature of the theme itself: its surface, its ink as the frame, its
   accent as the mark inside — so the choice is seen, not imagined. */
.theme-swatch {
  width: 20px;
  height: 20px;
  border: 1px solid;
  display: grid;
  place-items: center;
  flex: none;
}

.theme-swatch > span {
  width: 9px;
  height: 9px;
  display: block;
}

/* ---------- Theme preview ----------
   A drawn phone whose screen runs a miniature of the app the scaffolder
   actually produces: splash, top bar, off-canvas sidebar, FAB, avatar list.
   Everything inside is scoped to --tp-* variables set inline on .ph-screen, so
   a previewed theme can never leak into the dashboard's own tokens. */

.phone { --ph-w: 244px; --ph-h: 468px; display: flex; justify-content: center; }
.phone--compact { --ph-w: 200px; --ph-h: 384px; }

/* The device body is the dashboard's ink, not the theme's — it reads as a
   phone holding the app rather than as part of the design. */
.ph-frame {
  position: relative;
  width: var(--ph-w);
  height: var(--ph-h);
  /* Extra top padding is the bezel the speaker slot sits in — putting it
     there rather than over the screen means it contrasts with the device
     body and stays visible whatever colour the previewed app is. */
  padding: 19px 8px 9px;
  border-radius: 30px;
  background: var(--pc-ink);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.18);
  flex: none;
  display: flex;
}

.ph-notch {
  position: absolute;
  top: 8px;
  left: 50%;
  transform: translateX(-50%);
  width: 54px;
  height: 4px;
  border-radius: 2px;
  background: var(--pc-surface);
  opacity: 0.4;
  z-index: 6;
}

.ph-screen {
  position: relative;
  width: 100%;
  height: 100%;
  border-radius: 21px;
  overflow: hidden;
  background: var(--tp-surface);
  color: var(--tp-ink);
  font-family: var(--tp-body);
  display: flex;
  flex-direction: column;
  /* The screen paints the previewed theme's own colours; the dashboard's dark
     mode must not invert anything inside it. */
  color-scheme: only light;
}

/* ---- splash: name over the surface, bar fills, whole thing lifts away ---- */

.ph-splash {
  position: absolute;
  inset: 0;
  z-index: 5;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  background: var(--tp-surface);
  animation: ph-splash-lift 0.5s var(--pc-ease) 0.9s both;
}

.ph-splash-name {
  font-family: var(--tp-display);
  font-size: 1.15rem;
  font-weight: var(--tp-h-weight, 700);
  letter-spacing: var(--tp-h-spacing, 0.02em);
  text-transform: var(--tp-h-transform, none);
  animation: ph-splash-in 0.4s var(--pc-ease) both;
}

.ph-splash-bar {
  width: 84px;
  height: 2px;
  background: color-mix(in srgb, var(--tp-ink) 15%, transparent);
  overflow: hidden;
}

.ph-splash-bar i {
  display: block;
  height: 100%;
  width: 100%;
  background: var(--tp-accent);
  transform-origin: left;
  animation: ph-bar 0.85s var(--pc-ease) 0.1s both;
}

@keyframes ph-splash-lift {
  to { transform: translateY(-101%); }
}

@keyframes ph-splash-in {
  from { opacity: 0; transform: translateY(6px); }
}

@keyframes ph-bar {
  from { transform: scaleX(0); }
  to { transform: scaleX(1); }
}

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

.ph-topbar {
  flex: none;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 13px;
  border-bottom: var(--tp-line) solid var(--tp-outline);
  background: var(--tp-surface);
  z-index: 3;
}

.ph-burger {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 3px;
  width: 18px;
  height: 18px;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  flex: none;
}

.ph-burger i {
  display: block;
  height: 2px;
  width: 100%;
  border-radius: 2px;
  background: var(--tp-ink);
}

.ph-topbar-title {
  flex: 1;
  font-family: var(--tp-display);
  font-size: 0.72rem;
  font-weight: var(--tp-h-weight, 700);
  letter-spacing: var(--tp-h-spacing, normal);
  text-transform: var(--tp-h-transform, none);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The Blank theme has nothing to show, so the phone carries an instruction
   rather than a mock-up. */
.ph-note {
  flex: 1;
  display: grid;
  place-items: center;
  padding: 0 26px;
  text-align: center;
}

.ph-note p {
  margin: 0;
  font-size: 0.66rem;
  line-height: 1.8;
  opacity: 0.55;
}

/* Light / dark switch, mirroring the one in the generated app's top bar. */
.ph-mode {
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  padding: 0;
  flex: none;
  cursor: pointer;
  color: inherit;
  background: transparent;
  /* Some themes drop this entirely — see each theme's toggle_border. */
  border: var(--tp-toggle-border);
  border-radius: var(--tp-radius);
}

.ph-mode .mt-moon { display: none; }
.ph-screen.is-dark .ph-mode .mt-sun,
.ph-screen.is-dark .ph-mode .mt-rays { display: none; }
.ph-screen.is-dark .ph-mode .mt-moon { display: block; }

/* ---- avatars ---- */

.ph-avatar {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  flex: none;
  display: grid;
  place-items: center;
  font-family: var(--tp-display);
  font-size: 0.55rem;
  font-weight: 700;
  /* --tp-who is set per row, so each person keeps their own colour. */
  background: var(--tp-who, var(--tp-accent));
  color: var(--tp-surface);
  border: var(--tp-line) solid var(--tp-outline);
}

.ph-avatar--me { background: var(--tp-accent); }

/* The portrait sits over the coloured circle. If it never loads the element is
   removed and the initial underneath shows instead. */
.ph-avatar { position: relative; overflow: hidden; }

.ph-avatar img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 50%;
}

/* ---- summary: KPI row + seven-day column figure ----
   Mirrors the scaffold's marks exactly: one hue, capped bar width, 2px surface
   gaps, a hairline baseline, and a reserved label slot so every bar measures
   against the same track. */

.ph-summary { flex: none; margin-bottom: 10px; }

.ph-tiles { display: grid; grid-template-columns: repeat(3, 1fr); gap: 5px; margin-bottom: 9px; }

.ph-tile {
  background: var(--tp-paper);
  border: var(--tp-line) solid var(--tp-outline);
  border-radius: var(--tp-radius);
  box-shadow: var(--tp-shadow);
  padding: 6px 7px;
}

.ph-tile-value {
  font-family: var(--tp-display);
  font-size: 0.82rem;
  font-weight: var(--tp-h-weight, 600);
  letter-spacing: var(--tp-h-spacing, normal);
  line-height: 1.1;
}

.ph-tile-label { font-size: 0.46rem; opacity: 0.6; margin-top: 1px; }

.ph-bars {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  align-items: end;
  gap: 2px;
  height: 60px;
  border-bottom: 1px solid var(--tp-outline);
}

.ph-bar { display: flex; flex-direction: column; align-items: center; height: 100%; }

.ph-bar-track {
  flex: 1;
  min-height: 0;
  width: 100%;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}

.ph-bar i {
  display: block;
  width: 100%;
  max-width: 10px;
  background: var(--tp-accent);
  border-radius: var(--tp-radius) var(--tp-radius) 0 0;
  min-height: 2px;
  flex: none;
}

.ph-bar-value { flex: none; height: 0.6rem; line-height: 0.6rem; font-size: 0.45rem; opacity: 0.75; }
.ph-bar-day { flex: none; font-size: 0.45rem; opacity: 0.5; margin-top: 3px; }

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

.ph-body {
  flex: 1;
  min-height: 0;
  overflow: hidden;
  padding: 10px 11px;
  display: flex;
  flex-direction: column;
  gap: 7px;
}

.ph-row {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 9px;
  background: var(--tp-paper);
  border: var(--tp-line) solid var(--tp-outline);
  border-radius: var(--tp-radius);
  /* The theme supplies a complete box-shadow: a hard offset for the sticker
     look, soft blur for Material/Fluent/Apple, or `none`. */
  box-shadow: var(--tp-shadow);
  flex: none;
}

.ph-row-text { min-width: 0; }
.ph-row-name {
  font-family: var(--tp-display);
  font-size: 0.6rem;
  font-weight: var(--tp-h-weight, 600);
  letter-spacing: var(--tp-h-spacing, normal);
  text-transform: var(--tp-h-transform, none);
}

.ph-row-note {
  font-size: 0.53rem;
  opacity: 0.6;
  margin-top: 1px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Each row lifts into place; the delay is set inline so the list assembles. */
.ph-in { animation: ph-row-in 0.42s var(--pc-ease) both; }

@keyframes ph-row-in {
  from { opacity: 0; transform: translateY(11px); }
}

/* ---- floating action button ---- */

.ph-fab {
  position: absolute;
  right: 13px;
  bottom: 13px;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--tp-accent);
  color: var(--tp-surface);
  border: var(--tp-line) solid transparent;
  display: grid;
  place-items: center;
  font-family: var(--tp-display);
  font-size: 1.15rem;
  font-weight: 700;
  line-height: 1;
  z-index: 4;
  box-shadow: var(--tp-shadow);
}

.ph-fab-in { animation: ph-fab-in 0.42s var(--pc-ease) both; }

@keyframes ph-fab-in {
  from { opacity: 0; transform: scale(0.4); }
}

/* ---- off-canvas sidebar ---- */

.ph-side {
  position: absolute;
  inset: 0 auto 0 0;
  width: 64%;
  z-index: 8;
  padding: 13px 0;
  background: var(--tp-surface);
  border-right: var(--tp-line) solid var(--tp-outline);
  transform: translateX(-100%);
  transition: transform 0.3s var(--pc-ease);
}

.ph-screen.is-open .ph-side { transform: translateX(0); }

/* ---- layout variants ----
   The drawer comes over the content from whichever side was picked, exactly as
   the generated app does. The burger in the top bar drives it, and both the
   drawer and its scrim start below that bar so the burger stays reachable
   while the drawer is open. */
.ph-screen.has-bar .ph-side,
.ph-screen.has-bar .ph-scrim { top: 41px; }
/* Longhand, not `inset`: the shorthand would reset the `top` above and put the
   drawer back over the top bar. */
.ph-screen.lay-side-right .ph-side {
  right: 0;
  left: auto;
  border-right: 0;
  border-left: var(--tp-line) solid var(--tp-outline);
  transform: translateX(100%);
}

.ph-screen.lay-side-right.is-open .ph-side { transform: translateX(0); }

/* The floating mode toggle, for layouts with no top bar to hold it. */
.ph-float {
  position: absolute;
  top: 9px;
  right: 9px;
  z-index: 4;
}

.ph-float .ph-mode {
  background: var(--tp-paper);
  border: var(--tp-line) solid var(--tp-outline);
}

/* Same reason as the generated app: the docked sidebar is on that side. */
.ph-screen.lay-side-right .ph-float { right: auto; left: 9px; }

/* Nothing above the content to hold the toggle, so the content makes room for
   it rather than being sat on. */
.ph-screen:not(.has-bar) .ph-float ~ .ph-body { padding-top: 30px; }



/* ---- footer navigation ---- */

.ph-foot {
  flex: none;
  display: flex;
  z-index: 3;
  background: var(--tp-surface);
  border-top: var(--tp-line) solid var(--tp-outline);
}

.ph-foot-link {
  flex: 1;
  padding: 7px 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0.5;
  border-top: 2px solid transparent;
  margin-top: -1px;
}

.ph-foot-link.is-active {
  opacity: 1;
  border-top-color: var(--tp-accent);
  color: var(--tp-accent);
}

/* ---- layout picker ----
   Toggle chips. Unselected is a hairline outline with the tick collapsed to
   nothing; selecting fills the border, brings the tick in, and shifts the
   label along — so the row reads as a set of switches rather than as buttons
   that might navigate somewhere. */

.chips { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 4px; }

.chip-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0;
  padding: 9px 15px;
  border: 1px solid var(--pc-border);
  border-radius: var(--pc-radius);
  background: transparent;
  color: var(--pc-ink);
  font-family: var(--pc-font-body);
  font-size: 0.62rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  cursor: pointer;
  opacity: var(--pc-dim-1);
  transition: border-color 0.18s var(--pc-ease), opacity 0.18s var(--pc-ease),
              background 0.18s var(--pc-ease);
}

.chip-toggle:hover { border-color: var(--pc-border-hover); opacity: 1; }

.chip-tick {
  width: 0;
  opacity: 0;
  margin-right: 0;
  transition: width 0.18s var(--pc-ease), opacity 0.18s var(--pc-ease),
              margin-right 0.18s var(--pc-ease);
}

.chip-toggle.is-on {
  border-color: var(--pc-ink);
  background: var(--pc-bg-hover);
  opacity: 1;
}

.chip-toggle.is-on .chip-tick { width: 13px; opacity: 1; margin-right: 7px; }

/* Selected because a sidebar needs it, not because it was pressed. Still
   pressable — pressing it releases the sidebar too. */
.chip-toggle.is-required { border-style: dashed; }

@media (prefers-reduced-motion: reduce) {
  .chip-toggle, .chip-tick { transition: none; }
}

.ph-side-head {
  font-family: var(--tp-display);
  font-size: 0.68rem;
  font-weight: var(--tp-h-weight, 700);
  letter-spacing: var(--tp-h-spacing, normal);
  text-transform: var(--tp-h-transform, none);
  padding: 0 14px 11px;
  border-bottom: var(--tp-line) solid var(--tp-outline);
  margin-bottom: 8px;
}

.ph-side-link {
  padding: 8px 14px;
  font-family: var(--tp-display);
  font-size: 0.58rem;
  font-weight: var(--tp-l-weight, 400);
  letter-spacing: var(--tp-l-spacing, normal);
  text-transform: var(--tp-l-transform, none);
  opacity: 0.65;
  border-left: 2px solid transparent;
}

.ph-side-link.is-active {
  opacity: 1;
  border-left-color: var(--tp-accent);
  background: color-mix(in srgb, var(--tp-accent) 10%, transparent);
}

/* Dimmed and blurred, the same treatment the generated app uses: it reads as
   the drawer being on top of the page rather than beside it. */
.ph-scrim {
  position: absolute;
  inset: 0;
  z-index: 7;
  background: rgba(0, 0, 0, 0.42);
  backdrop-filter: blur(5px);
  -webkit-backdrop-filter: blur(5px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s var(--pc-ease);
}

.ph-screen.is-open .ph-scrim { opacity: 1; pointer-events: auto; }

/* Soft confetti behind the content, matching the generated app's body. */
.ph-dots {
  background:
    radial-gradient(circle at 14% 12%, color-mix(in srgb, var(--tp-c2) 22%, transparent) 0 9px, transparent 10px),
    radial-gradient(circle at 86% 26%, color-mix(in srgb, var(--tp-c4) 20%, transparent) 0 7px, transparent 8px),
    radial-gradient(circle at 74% 76%, color-mix(in srgb, var(--tp-c3) 20%, transparent) 0 11px, transparent 12px),
    var(--tp-surface);
}

@media (prefers-reduced-motion: reduce) {
  .ph-side, .ph-scrim { transition: none; }
}

/* The picker: chips stacked in a column, the live preview beside them. A
   single wrapping row of chips left a tall void next to the preview; stacking
   makes the two columns roughly equal height and reads like a menu. */
.theme-pick {
  display: grid;
  grid-template-columns: 210px minmax(0, 1fr);
  gap: 24px;
  align-items: start;
}

/* The left column stacks the two choices — layout, then style — against the
   shared preview on the right. */
.pick-col { display: flex; flex-direction: column; gap: 18px; }

.pick-group { display: flex; flex-direction: column; gap: 7px; }

.pick-label {
  font-family: var(--pc-font-display);
  font-size: 0.52rem;
  font-weight: 600;
  letter-spacing: var(--pc-track);
  text-transform: uppercase;
  opacity: var(--pc-dim-2);
}

.pick-group .chips { margin-bottom: 0; }

/* Narrower chips here than in the modal: the column is 210px, so two per row
   rather than one long line that wraps awkwardly. */
.pick-group .chip-toggle {
  padding: 7px 11px;
  font-size: 0.56rem;
  letter-spacing: 0.09em;
}

.pick-group .help { margin: 0; }

.theme-pick .theme-row {
  flex-direction: column;
  align-items: stretch;
  gap: 5px;
  margin-top: 0;
}

.theme-pick .theme-chip { justify-content: flex-start; }

.theme-pick-preview {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 9px;
}

.theme-pick-caption {
  font-family: var(--pc-font-display);
  font-size: 0.52rem;
  letter-spacing: var(--pc-track);
  text-transform: uppercase;
  opacity: var(--pc-dim-3);
}

@media (max-width: 760px) {
  /* Too narrow for two columns: chips go back to a wrapping row above the
     preview, which keeps the hero from becoming a tall scroll. */
  .theme-pick { grid-template-columns: 1fr; gap: 16px; }
  .theme-pick .theme-row { flex-direction: row; flex-wrap: wrap; align-items: center; gap: 8px; }
  .theme-pick .theme-chip { justify-content: center; }
  .theme-pick-preview { align-items: center; }
}

/* ---------- Create wizard ---------- */

.preset-grid--2 { grid-template-columns: repeat(2, 1fr); }

/* The DNS choices carry a sentence, not a logo, so they read left-aligned. */
.preset--wide {
  align-items: flex-start;
  text-align: left;
  gap: 6px;
  padding: 16px 16px 15px;
  cursor: pointer;
}

.preset--wide small {
  font-family: var(--pc-font-body);
  font-size: 0.6rem;
  line-height: 1.7;
  letter-spacing: 0;
  text-transform: none;
  opacity: var(--pc-dim-2);
}

.domain-preview {
  font-size: 0.68rem;
  padding: 11px 14px;
  border: 1px dashed var(--pc-border);
  opacity: var(--pc-dim-2);
  word-break: break-all;
}

/* ---------- Server folder browser (import) ---------- */

.browse-list {
  display: flex;
  flex-direction: column;
  max-height: 220px;
  overflow-y: auto;
  border: 1px solid var(--pc-border-muted);
}

.browse-row {
  text-align: left;
  padding: 9px 13px;
  border: 0;
  border-bottom: 1px solid var(--pc-border-muted);
  background: transparent;
  color: inherit;
  font-family: var(--pc-font-body);
  font-size: 0.68rem;
  cursor: pointer;
}

.browse-row:last-child { border-bottom: 0; }
.browse-row:hover { background: var(--pc-bg-hover); }

/* ---------- App cards ---------- */

.app-card {
  display: flex;
  flex-direction: column;
  gap: 14px;
  text-decoration: none;
  color: inherit;
}

.app-card-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}

.app-card-name {
  font-family: var(--pc-font-display);
  font-size: 0.95rem;
  font-weight: 500;
  letter-spacing: var(--pc-track-tight);
  margin: 0;
}

.app-card-domain {
  font-size: 0.62rem;
  opacity: var(--pc-dim-3);
  word-break: break-all;
  margin: 4px 0 0;
}

.app-card-desc {
  font-size: 0.7rem;
  line-height: 1.8;
  opacity: var(--pc-dim-2);
  margin: 0;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.app-card-foot {
  display: flex;
  align-items: center;
  gap: 14px;
  font-size: 0.58rem;
  letter-spacing: var(--pc-track-tight);
  text-transform: uppercase;
  opacity: var(--pc-dim-3);
  margin-top: auto;
  padding-top: 4px;
}

/* Status is line-work, not color — one live dot is the only exception. */
.dot {
  width: 6px;
  height: 6px;
  border: 1px solid currentColor;
  border-radius: 50%;
  flex: none;
}

.dot--live { background: var(--pc-ok); border-color: var(--pc-ok); animation: dot-pulse 1.6s infinite; }
.dot--on { background: currentColor; }

@keyframes dot-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.25; }
}

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

/* ---------- App sidebar header ---------- */

/* Sits inside .sidebar-nav, which has no horizontal padding of its own. */
.side-app {
  padding: 0 24px 18px;
  border-bottom: 1px solid var(--pc-border-muted);
  margin-bottom: 14px;
}

.side-back {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: var(--pc-font-display);
  font-size: 0.55rem;
  letter-spacing: var(--pc-track);
  text-transform: uppercase;
  opacity: var(--pc-dim-3);
  text-decoration: none;
  color: inherit;
  margin-bottom: 14px;
  transition: opacity 0.25s;
}

.side-back:hover { opacity: 1; }

.side-app-name {
  font-family: var(--pc-font-display);
  font-size: 0.86rem;
  font-weight: 500;
  letter-spacing: var(--pc-track-tight);
  margin: 0;
  word-break: break-word;
}

.side-app-meta {
  font-size: 0.58rem;
  opacity: var(--pc-dim-3);
  margin: 6px 0 0;
  display: flex;
  align-items: center;
  gap: 7px;
}

/* ---------- Build chat ---------- */

.chat {
  display: flex;
  flex-direction: column;
  min-height: 0;
  min-width: 0;
  flex: 1;
  gap: 0;
}

.chat-scroll {
  flex: 1;
  min-height: 0;
  min-width: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 4px 4px 24px;
  display: flex;
  flex-direction: column;
  gap: 22px;
  scrollbar-width: thin;
}

.msg { display: flex; flex-direction: column; gap: 7px; max-width: 760px; min-width: 0; }

.msg-who {
  font-family: var(--pc-font-display);
  font-size: 0.55rem;
  font-weight: 500;
  letter-spacing: var(--pc-track);
  text-transform: uppercase;
  opacity: var(--pc-dim-3);
}

.msg-body {
  font-size: 0.76rem;
  line-height: 1.9;
  min-width: 0;
  /* `anywhere`, not `break-word`: only this value lowers the element's
     min-content width, and that floor is what max-width cannot clamp. A single
     long path or URL from the agent would otherwise widen the whole page. */
  overflow-wrap: anywhere;
}

/* Code keeps its line structure — it scrolls in place instead of breaking. */
.msg-body pre,
.msg-body code {
  overflow-x: auto;
  overflow-wrap: normal;
  max-width: 100%;
}

.msg-body > :first-child { margin-top: 0; }
.msg-body > :last-child { margin-bottom: 0; }

.msg--user {
  align-self: flex-end;
  align-items: flex-end;
  max-width: min(620px, 88%);
}

.msg--user .msg-body {
  border: var(--pc-border-w) solid var(--pc-border);
  background: var(--pc-bg-subtle);
  padding: 12px 16px;
  white-space: pre-wrap;
  text-align: left;
}

.msg--error .msg-body {
  border-left: var(--pc-border-w) solid var(--pc-danger);
  padding-left: 14px;
  color: var(--pc-danger);
  white-space: pre-wrap;
}

/* A tool call and its result collapse into one line until you open it. */
.tool {
  border: 1px solid var(--pc-border-muted);
  max-width: 760px;
  min-width: 0;
  background: var(--pc-bg-subtle);
}

.tool-head {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-width: 0;
  padding: 9px 13px;
  background: transparent;
  border: 0;
  color: inherit;
  font-family: var(--pc-font-body);
  font-size: 0.65rem;
  cursor: pointer;
  text-align: left;
}

.tool-head:hover { background: var(--pc-bg-hover); }

.tool-name {
  font-family: var(--pc-font-display);
  font-size: 0.55rem;
  font-weight: 500;
  letter-spacing: var(--pc-track);
  text-transform: uppercase;
  flex: none;
}

.tool-arg {
  opacity: var(--pc-dim-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
  flex: 1;
}

.tool-caret { flex: none; opacity: var(--pc-dim-3); transition: transform 0.25s var(--pc-ease); }
.tool.is-open .tool-caret { transform: rotate(90deg); }

.tool-body {
  border-top: 1px solid var(--pc-border-muted);
  padding: 12px 13px;
  font-size: 0.66rem;
  line-height: 1.8;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  overflow-x: auto;
  max-height: 380px;
  overflow-y: auto;
  opacity: var(--pc-dim-1);
}

.tool--error { border-color: var(--pc-danger); }
.tool--error .tool-name { color: var(--pc-danger); }

/* ---------- Chat attachments ---------- */

/* Sent with a message. */
.msg-files {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: flex-end;
}

.att {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  text-decoration: none;
  color: inherit;
  border: 1px solid var(--pc-border);
  transition: border-color 0.25s var(--pc-ease);
}

.att:hover { border-color: var(--pc-border-hover); }

.att--image { padding: 0; overflow: hidden; line-height: 0; }

.att--image img {
  display: block;
  max-width: 220px;
  max-height: 180px;
  width: auto;
  height: auto;
  object-fit: cover;
}

.att--file {
  padding: 9px 13px;
  font-size: 0.66rem;
  background: var(--pc-bg-subtle);
  max-width: 260px;
}

.att--file span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Staged in the composer, not yet sent. */
.tray {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 0 20px 4px;
}

.tray[hidden] { display: none; }

.tray-item {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 5px 6px 5px 8px;
  border: 1px solid var(--pc-border);
  background: var(--pc-surface);
  font-size: 0.63rem;
  max-width: 220px;
}

.tray-item.is-error { border-color: var(--pc-danger); color: var(--pc-danger); }

.tray-item img {
  width: 26px;
  height: 26px;
  object-fit: cover;
  display: block;
  flex: none;
}

.tray-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  opacity: var(--pc-dim-1);
}

.tray-x {
  border: 0;
  background: transparent;
  color: inherit;
  cursor: pointer;
  opacity: var(--pc-dim-3);
  font-size: 0.7rem;
  line-height: 1;
  padding: 4px;
  flex: none;
}

.tray-x:hover { opacity: 1; color: var(--pc-danger); }

/* Drag-and-drop target: the whole chat, so a dropped file lands wherever the
   user aims. The outline is drawn on a pseudo-element to avoid reflow. */
.chat.is-dropping { position: relative; }

.chat.is-dropping::after {
  content: 'Drop to attach';
  position: absolute;
  inset: 0;
  z-index: 5;
  display: grid;
  place-items: center;
  pointer-events: none;
  border: var(--pc-border-w) dashed var(--pc-border-strong);
  background: color-mix(in srgb, var(--pc-surface) 88%, transparent);
  font-family: var(--pc-font-display);
  font-size: 0.6rem;
  letter-spacing: var(--pc-track);
  text-transform: uppercase;
}

/* Platform notices (import progress) — quieter than the agent's own voice. */
.msg--system .msg-body {
  font-size: 0.68rem;
  opacity: var(--pc-dim-2);
  border-left: var(--pc-border-w) solid var(--pc-border);
  padding-left: 12px;
}

/* Live token stream — replaced by the settled message when the block closes. */
.chat-live { max-width: 760px; min-width: 0; }

/* On a wide display the transcript can take a little more measure without
   becoming hard to read, which stops the chat looking like a narrow ribbon
   down the middle of a 4K screen. Deliberately a small step: past roughly
   90 characters a line gets harder to track, not easier. */
@media (min-width: 1920px) {
  .msg, .chat-live { max-width: 880px; }
}

@media (min-width: 2400px) {
  .msg, .chat-live { max-width: 960px; }
}
.chat-live:empty { display: none; }

.chat-thinking {
  font-size: 0.7rem;
  line-height: 1.9;
  opacity: var(--pc-dim-3);
  font-style: italic;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.chat-status {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--pc-font-display);
  font-size: 0.55rem;
  letter-spacing: var(--pc-track);
  text-transform: uppercase;
  opacity: var(--pc-dim-2);
  padding: 2px 0 4px;
}

.chat-status[hidden] { display: none; }

.spinner {
  width: 9px;
  height: 9px;
  border: 1.5px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: spin 0.9s linear infinite;
  flex: none;
}

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

@media (prefers-reduced-motion: reduce) {
  .spinner { animation-duration: 3s; }
}

.chat-foot {
  flex: none;
  min-width: 0;
  padding: 14px 0 18px;
  background: var(--pc-surface);
  border-top: 1px solid var(--pc-border-muted);
}

/* ---------- Data tab ---------- */

.data-layout {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: 230px minmax(0, 1fr);
  gap: 28px;
}

/* With no tables there is nothing to pick, so the panel takes the full width. */
.data-layout.is-empty { grid-template-columns: 1fr; }

.table-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
  overflow-y: auto;
  min-height: 0;
  padding-bottom: 24px;
}

.table-link {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  padding: 9px 12px;
  border: 0;
  background: transparent;
  color: inherit;
  font-family: var(--pc-font-body);
  font-size: 0.7rem;
  cursor: pointer;
  text-align: left;
  border-left: 2px solid transparent;
  transition: all 0.2s var(--pc-ease);
}

.table-link:hover { background: var(--pc-bg-hover); }

.table-link.is-active {
  border-left-color: var(--pc-ink);
  background: var(--pc-bg-hover);
}

.table-link small { opacity: var(--pc-dim-3); font-size: 0.58rem; flex: none; }

.table-link--sql { margin-top: 12px; opacity: var(--pc-dim-2); }
.table-link--sql:hover { opacity: 1; }

.data-panel {
  display: flex;
  flex-direction: column;
  min-height: 0;
  min-width: 0;
  gap: 14px;
  padding-bottom: 24px;
}

.data-bar {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  flex: none;
}

.data-bar .grow { flex: 1; }

.table-wrap {
  flex: 1;
  min-height: 0;
  overflow: auto;
  border: 1px solid var(--pc-border-muted);
}

.dtable {
  border-collapse: collapse;
  width: 100%;
  font-size: 0.68rem;
}

.dtable th, .dtable td {
  border-bottom: 1px solid var(--pc-border-muted);
  border-right: 1px solid var(--pc-border-muted);
  padding: 0;
  text-align: left;
  vertical-align: top;
}

.dtable th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--pc-surface);
  font-family: var(--pc-font-display);
  font-size: 0.55rem;
  font-weight: 500;
  letter-spacing: var(--pc-track-tight);
  text-transform: uppercase;
  padding: 10px 12px;
  white-space: nowrap;
  border-bottom-width: var(--pc-border-w);
}

.dtable th .pk { opacity: var(--pc-dim-3); margin-left: 5px; }

.dtable td.actions { padding: 0 4px; white-space: nowrap; text-align: right; }

.cell {
  width: 100%;
  min-width: 90px;
  border: 0;
  background: transparent;
  color: inherit;
  font-family: var(--pc-font-body);
  font-size: 0.68rem;
  padding: 9px 12px;
  outline: none;
  resize: none;
  line-height: 1.6;
}

.cell:focus { background: var(--pc-bg-hover); box-shadow: inset 0 0 0 1.5px var(--pc-border-strong); }
.cell.is-dirty { background: var(--pc-bg-hover); box-shadow: inset 2px 0 0 var(--pc-ink); }
.cell.is-null::placeholder { opacity: 0.3; font-style: italic; }

.row-btn {
  border: 0;
  background: transparent;
  color: inherit;
  cursor: pointer;
  opacity: var(--pc-dim-3);
  padding: 6px 8px;
  font-size: 0.7rem;
  line-height: 1;
}

.row-btn:hover { opacity: 1; }
.row-btn--danger:hover { color: var(--pc-danger); }

.pager {
  display: flex;
  align-items: center;
  gap: 14px;
  font-size: 0.6rem;
  letter-spacing: var(--pc-track-tight);
  text-transform: uppercase;
  opacity: var(--pc-dim-2);
  flex: none;
}

.pager .grow { flex: 1; }

.sql-row { display: flex; gap: 10px; align-items: stretch; flex: none; }
.sql-row .input { font-size: 0.68rem; }

/* ---------- Preview tab ---------- */

.preview-bar {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  flex: none;
  padding-bottom: 16px;
}

.preview-bar .grow { flex: 1; }

.seg {
  display: inline-flex;
  border: 1px solid var(--pc-border);
}

.seg button {
  font-family: var(--pc-font-display);
  font-size: 0.55rem;
  letter-spacing: var(--pc-track);
  text-transform: uppercase;
  padding: 9px 16px;
  border: 0;
  background: transparent;
  color: inherit;
  cursor: pointer;
  opacity: var(--pc-dim-2);
  transition: all 0.25s var(--pc-ease);
}

.seg button + button { border-left: 1px solid var(--pc-border); }
.seg button:hover { opacity: 1; }
.seg button.is-active { background: var(--pc-ink); color: var(--pc-surface); opacity: 1; }

.preview-stage {
  flex: 1;
  min-height: 0;
  min-width: 0;
  display: flex;
  align-items: stretch;
  justify-content: center;
  padding-bottom: 24px;
  background:
    repeating-linear-gradient(45deg,
      var(--pc-bg-subtle) 0 8px, transparent 8px 16px);
}

.device {
  background: var(--pc-surface);
  border: var(--pc-border-w) solid var(--pc-border);
  width: 100%;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.device--mobile {
  width: 390px;
  max-width: 100%;
  align-self: center;
  height: min(844px, 100%);
}

.preview-frame {
  flex: 1;
  width: 100%;
  border: 0;
  background: var(--pc-surface);
  min-height: 0;
}

.preview-log {
  font-size: 0.62rem;
  line-height: 1.7;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  max-height: 190px;
  overflow: auto;
  border: 1px solid var(--pc-border-muted);
  padding: 12px 14px;
  opacity: var(--pc-dim-2);
  margin: 0;
}

/* ---------- Overview bits ---------- */

.kv {
  display: grid;
  grid-template-columns: minmax(110px, auto) minmax(0, 1fr);
  gap: 10px 20px;
  font-size: 0.7rem;
  align-items: baseline;
}

.kv dt {
  font-family: var(--pc-font-display);
  font-size: 0.55rem;
  font-weight: 500;
  letter-spacing: var(--pc-track);
  text-transform: uppercase;
  opacity: var(--pc-dim-3);
}

.kv dd { margin: 0; word-break: break-word; }

.file-list {
  display: flex;
  flex-direction: column;
  max-height: 340px;
  overflow-y: auto;
  font-size: 0.66rem;
}

.file-row {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding: 6px 0;
  border-bottom: 1px solid var(--pc-border-muted);
}

.file-row:last-child { border-bottom: 0; }
.file-row span:last-child { opacity: var(--pc-dim-3); flex: none; }

/* ---------- Responsive ---------- */

@media (max-width: 980px) {
  /* The table picker becomes a scrolling tab strip above the grid. `auto` for
     its row keeps it at content height; the grid takes whatever is left. */
  .data-layout {
    grid-template-columns: 1fr;
    grid-template-rows: auto minmax(0, 1fr);
    gap: 14px;
  }

  .table-list {
    flex-direction: row;
    align-items: center;
    overflow-x: auto;
    overflow-y: hidden;
    padding-bottom: 6px;
    flex: none;
  }

  .table-link {
    border-left: 0;
    border-bottom: 2px solid transparent;
    white-space: nowrap;
    flex: none;
  }

  .table-link.is-active { border-left-color: transparent; border-bottom-color: var(--pc-ink); }
  .table-link--sql { margin-top: 0; margin-left: 8px; }
}

@media (max-width: 860px) {
  .hero { padding-top: 16px; margin-bottom: 32px; }
  /* 16px, not smaller: this used to shrink further on mobile than it already
     was on desktop, which is backwards — it made the iOS zoom-on-focus bug
     (any text input under 16px triggers it) worse on the one surface where
     it matters most. */
  .composer-input { min-height: 76px; font-size: 16px; }
  .composer-bar { flex-wrap: wrap; gap: 10px; }
  .composer-hint { display: none; }
  .msg--user { max-width: 92%; }
  /* A little more legible on a phone than the desktop density this was
     tuned for — the transcript is the thing being read here. */
  .msg-body { font-size: 0.82rem; }
  .tool-head { padding: 11px 13px; }
  .device--mobile { width: 100%; height: 100%; }
  .preview-stage { background: none; padding-bottom: 16px; }
  body.view-fixed .content { padding-bottom: 0; }
  .chat-foot { padding-bottom: 14px; }

  /* These carry their own class alongside `.input`/`.textarea` (`.input
     color-hex`, `.input palette-text`) so app.css's bare `.input` rule
     can't reach them, and `.sql-row .input` outranks it on specificity
     regardless — each needs the same 16px, explicitly. `.color-hex` and
     `.palette-text` are defined later in this same file at plain-class
     specificity, which would otherwise win the tie by source order — the
     element-qualified form here outranks them so this doesn't depend on
     staying below both in the file. */
  input.color-hex, input.palette-text, .sql-row .input { font-size: 16px; }
}

/* ==========================================================================
   Theme designer — list page + full-page wizard.
   Uses only --pc-* dashboard tokens (the preview's own colours live inside its
   shadow root, isolated from all of this).
   ========================================================================== */

/* ---- list ---- */
.themes-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 16px;
  margin: 0 0 32px;
}
.theme-card {
  border: var(--pc-border-w) solid var(--pc-border);
  background: var(--pc-surface);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.theme-card-top { height: 76px; display: flex; align-items: flex-end; padding: 10px; }
.theme-swatches { display: flex; gap: 4px; }
.theme-swatch {
  width: 22px; height: 22px; border-radius: 4px;
  box-shadow: 0 0 0 1px rgba(128, 128, 128, 0.25);
}
.theme-card-body { padding: 12px 14px 14px; display: flex; flex-direction: column; gap: 8px; }
.theme-card-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.theme-card-head h3 { margin: 0; font-size: 0.9rem; }
.theme-badge {
  font-size: 0.55rem; letter-spacing: 0.12em; text-transform: uppercase;
  padding: 2px 7px; border: 1px solid var(--pc-border); opacity: 0.7;
}
.theme-card-hint { margin: 0; font-size: 0.72rem; opacity: 0.6; line-height: 1.5; }
.theme-card-actions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 2px; }
.theme-del:hover { color: var(--pc-danger); border-color: var(--pc-danger); }
.themes-empty {
  border: 1px dashed var(--pc-border); padding: 28px; text-align: center;
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  margin-bottom: 32px;
}
.themes-empty p { margin: 0; opacity: 0.6; }

/* ---- editor: floating dark rail + full-space preview ----
   The reference's layout (ui.shadcn.com/create), matched deliberately: the
   preview takes the whole page, and the controls are a dark floating panel —
   a rail down the left on desktop, a bottom bar on mobile — whose rows are
   individually rounded pills. The rail is always inverse (ink-on-ink panel,
   surface-coloured text) via tokens, so it flips correctly with the
   dashboard's own light/dark mode. */
.theme-editor {
  flex: 1;
  min-height: 0;
  display: flex;
  width: 100%;
  background: var(--pc-bg-subtle);
}

.editor-rail {
  flex: none;
  order: 0;
  width: 236px;
  margin: 14px 0 14px 14px;
  /* Sharp, like everything else in the brand — the floating-inverse-panel
     STRUCTURE is the reference's; the skin is PocketCorp's. */
  border-radius: 0;
  background: var(--pc-ink);
  color: var(--pc-surface);
  overflow-y: auto;
  padding: 10px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  scrollbar-width: none;
}
.editor-rail::-webkit-scrollbar { display: none; }

.rail-group { display: flex; flex-direction: column; gap: 8px; }
.rail-group--save { margin-top: auto; }

/* Every row is its own pill on the dark panel — the reference's chip
   treatment. color-mix against the surface token keeps the "slightly lighter
   than the panel" fill correct in both dashboard modes. */
.rail-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  width: 100%;
  padding: 9px 13px;
  border: 1px solid color-mix(in srgb, var(--pc-surface) 18%, transparent);
  border-radius: 0;
  background: color-mix(in srgb, var(--pc-surface) 6%, transparent);
  color: inherit;
  text-align: left;
  cursor: pointer;
  font-family: var(--pc-font-body);
  transition: background 0.15s, border-color 0.15s;
}
.rail-row:hover {
  background: color-mix(in srgb, var(--pc-surface) 13%, transparent);
  border-color: color-mix(in srgb, var(--pc-surface) 32%, transparent);
}

.rail-row-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.rail-row-label {
  font-family: var(--pc-font-display);
  font-size: 0.54rem;
  letter-spacing: var(--pc-track);
  text-transform: uppercase;
  opacity: 0.55;
}
.rail-row-value {
  font-family: var(--pc-font-body);
  font-size: 0.74rem;
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 15ch;
}

.rail-row--menu { justify-content: space-between; }
.rail-row--menu .rail-row-value { font-size: 0.8rem; }
.rail-row-icon--burger { position: relative; width: 16px; height: 10px; }
.rail-row-icon--burger::before, .rail-row-icon--burger::after {
  content: ''; position: absolute; left: 0; right: 0; height: 2px;
  border-radius: 2px; background: currentColor;
}
.rail-row-icon--burger::before { top: 0; }
.rail-row-icon--burger::after { bottom: 0; }

.rail-row-icon {
  flex: none;
  width: 18px;
  height: 18px;
  display: grid;
  place-items: center;
  opacity: 0.75;
}
.rail-row-icon--text { font-family: var(--pc-font-display); font-size: 0.68rem; font-weight: 600; }
.rail-row-icon--radius::before {
  content: '';
  display: block;
  width: 11px; height: 11px;
  border-top: 1.6px solid currentColor;
  border-left: 1.6px solid currentColor;
  border-top-left-radius: 6px;
}

.rail-row-swatch {
  flex: none;
  width: 16px; height: 16px;
  border: 1px solid color-mix(in srgb, var(--pc-surface) 35%, transparent);
}

/* The one light pill on the dark panel — the reference's Get Code. */
.rail-save {
  width: 100%;
  padding: 12px 14px;
  border: 0;
  border-radius: 0;
  background: var(--pc-surface);
  color: var(--pc-ink);
  cursor: pointer;
  font-family: var(--pc-font-display);
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: var(--pc-track);
  text-transform: uppercase;
  transition: opacity 0.15s;
}
.rail-save:hover { opacity: 0.88; }

/* ---- the shared flyout: a popover on desktop, a bottom sheet on mobile --- */
.picker-scrim {
  position: fixed; inset: 0; z-index: 500;
  background: rgba(0, 0, 0, 0.25);
}
.picker-flyout {
  position: fixed;
  z-index: 501;
  width: 250px;
  max-height: min(440px, 70vh);
  overflow-y: auto;
  border-radius: 0;
  background: var(--pc-ink);
  color: var(--pc-surface);
  border: 1px solid color-mix(in srgb, var(--pc-surface) 20%, transparent);
  box-shadow: 0 14px 40px rgba(0, 0, 0, 0.35);
  padding: 6px;
}
.picker-list { display: flex; flex-direction: column; gap: 1px; }
.picker-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 9px 11px;
  border: 0;
  background: transparent;
  color: inherit;
  text-align: left;
  cursor: pointer;
  font-family: var(--pc-font-body);
  font-size: 0.76rem;
  border-radius: 0;
}
.picker-item:hover { background: color-mix(in srgb, var(--pc-surface) 10%, transparent); }
.picker-item.is-active { background: color-mix(in srgb, var(--pc-surface) 10%, transparent); font-weight: 600; }
.picker-item svg { flex: none; margin-left: auto; }
.picker-item-swatch-wrap { flex: none; display: flex; }
.picker-item-swatch {
  width: 16px; height: 16px;
  border: 1px solid color-mix(in srgb, var(--pc-surface) 35%, transparent);
}
.picker-item-font {
  flex: none; width: 26px; text-align: center;
  font-size: 0.9rem; opacity: 0.85;
}
.picker-item-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---- stage: the preview takes all remaining space ---- */
.editor-stage {
  flex: 1;
  order: 1;
  min-width: 0;
  min-height: 0;
  position: relative;
  display: flex;
  padding: 14px;
}

.kit-canvas { display: block; }
/* The scenes reflow by column count inside; the canvas itself only ever
   scrolls vertically, like the reference's preview iframe. container-type
   makes the host the @container the shadow CSS breakpoints resolve against,
   so the rail's width never skews them. */
.preview-canvas {
  flex: 1;
  min-width: 0;
  border: var(--pc-border-w) solid var(--pc-border);
  border-radius: 0;
  overflow-y: auto;
  overflow-x: hidden;
  /* No background of its own: the scene inside the shadow root paints the
     PREVIEWED theme's surface edge to edge, so the dashboard's surface (and
     its dark mode) can never show through the preview. */
  container-type: inline-size;
}

.preview-pager {
  position: absolute;
  right: 30px;
  bottom: 28px;
  display: inline-flex;
  gap: 4px;
  padding: 4px;
  background: var(--pc-ink);
  color: var(--pc-surface);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.3);
}
.pager-dot {
  padding: 5px 11px;
  border: 0;
  background: transparent;
  color: inherit;
  opacity: 0.55;
  cursor: pointer;
  font-family: var(--pc-font-body);
  font-size: 0.66rem;
}
.pager-dot.is-active { opacity: 1; background: var(--pc-surface); color: var(--pc-ink); }

.ai-panel-bar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.ai-status { font-size: 0.68rem; opacity: 0.6; }

/* ---- responsive: rail becomes the reference's floating bottom panel ---- */
@media (max-width: 760px) {
  .theme-editor { flex-direction: column; }

  .editor-stage { order: 0; padding: 0; }
  .preview-canvas { border: 0; }
  .preview-pager { right: 12px; bottom: 12px; }

  /* Two rows, like the reference: picker chips scrolling sideways on top,
     Menu + Save beneath. */
  .editor-rail {
    order: 1;
    width: auto;
    margin: 0;
    padding: 8px;
    max-height: none;
    overflow: visible;
    display: grid;
    grid-template-columns: auto 1fr;
    grid-template-areas: "pickers pickers" "menu save";
    gap: 8px;
  }
  .rail-group--pickers {
    grid-area: pickers;
    flex-direction: row;
    overflow-x: auto;
    scrollbar-width: none;
    padding-bottom: 2px;
  }
  .rail-group--pickers::-webkit-scrollbar { display: none; }
  .rail-group--menu { grid-area: menu; }
  .rail-group--save { grid-area: save; margin-top: 0; }

  /* Chips stay row-shaped (label over value beside the swatch) and size to
     their own content — a fixed width with stacked lines is what turned
     these into blobs before: border-radius clamps to the shorter side, and
     a box taller than wide clamps to width. */
  .rail-row { width: auto; padding: 7px 11px; gap: 8px; flex: none; }
  .rail-row-label { font-size: 0.5rem; }
  .rail-row-value { font-size: 0.68rem; }
  .rail-row-swatch, .rail-row-icon { width: 15px; height: 15px; }
  .rail-row--menu { width: auto; }
  .rail-save { padding: 10px 14px; }

  .picker-flyout {
    left: 0 !important; right: 0; bottom: 0; top: auto !important;
    width: 100%;
    max-height: 60vh;
    border-left: 0; border-right: 0; border-bottom: 0;
  }
}
