/*
 * The frame: boot gate, sidebar, topbar, overlays, toasts.
 *
 * The sidebar is the only permanently visible surface, so it carries the
 * identity: the mark, the river, and nothing else that moves.
 */

/* ------------------------------------------------------------- boot gate -- */

.boot {
  position: fixed;
  inset: 0;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: var(--sp-4);
  background: var(--bg);
  color: var(--text);
  z-index: 100;
}

/* The same plate the sign-in card wears, so the wait and the screen it hands
   over to are visibly one thing rather than two loading states. */
.boot__mark {
  display: grid;
  place-items: center;
  width: 60px; height: 60px;
  border-radius: var(--r-md);
  background: var(--accent-soft);
  border: 1px solid var(--accent-line);
  color: var(--accent);
}
.boot__text { letter-spacing: 0.22em; }

/* A thread of river under the mark, filling and draining. It measures nothing —
   and a progress bar that measures nothing is a lie, so this one is plainly a
   pulse rather than a percentage. */
.boot__thread {
  width: 96px;
  height: 2px;
  border-radius: var(--r-pill);
  background: var(--surface-3);
  overflow: hidden;
}
.boot__thread::after {
  content: '';
  display: block;
  width: 40%;
  height: 100%;
  border-radius: var(--r-pill);
  background: var(--accent);
  animation: boot-flow 1.5s var(--ease-settle) infinite;
}

@keyframes boot-flow {
  0% { transform: translateX(-110%); }
  100% { transform: translateX(360%); }
}
@media (prefers-reduced-motion: reduce) {
  .boot__thread::after { animation: none; width: 100%; opacity: 0.5; }
}

/* ------------------------------------------------------------- screens -- */
/* Gate and onboarding: full-bleed, no chrome, exactly one visible at a time. */

.screen-host {
  position: fixed;
  inset: 0;
  z-index: 90;
  overflow-y: auto;
  background: var(--bg);
}
.screen-host.hidden { display: none; }

/* ---------------------------------------------------------- sidebar usage -- */

.sidebar-usage { display: grid; gap: 5px; padding: 0 var(--sp-2) var(--sp-1); }
.sidebar-usage__row { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: var(--sp-2); }
/* A two-character hint rather than a heading. The bar is the information; the
   label only says which window it counts. */
.sidebar-usage__label {
  font-family: var(--font-mono);
  font-size: 0.54rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-faint);
  white-space: nowrap;
}
.sidebar-usage__track { display: block; height: 3px; border-radius: var(--r-pill); background: var(--surface-3); overflow: hidden; }
.sidebar-usage__fill {
  display: block;
  height: 100%;
  background: var(--accent);
  transition: width var(--t-slow) var(--ease-settle);
}
.sidebar-usage__row[data-level='mid'] .sidebar-usage__fill { background: var(--sand); }
.sidebar-usage__row[data-level='high'] .sidebar-usage__fill { background: var(--warn); }

.app[data-sidebar='collapsed'] .sidebar-usage { display: none; }

/* ----------------------------------------------------------------- layout -- */

.app {
  display: grid;
  grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
  height: 100dvh;
  transition: grid-template-columns var(--t-base) var(--ease-settle);
}
.app[data-sidebar='collapsed'] { grid-template-columns: var(--sidebar-w-collapsed) minmax(0, 1fr); }

.main {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  min-width: 0;
  /* min-height: 0 is load-bearing, not defensive. A grid item defaults to
     min-height: auto, so .main refuses to shrink below its content and grows
     straight past .app's 100dvh — measured at 3056px inside a 1004px shell.
     .view then inherits that full height, has nothing left to overflow, and the
     page simply ends where the viewport does with no way to scroll. It only
     shows up on views taller than the window, which is why Image Studio hit it
     and Chat did not. The min-width: 0 beside it is the same fix on the other
     axis, already present. */
  min-height: 0;
  background: var(--bg);
}

.view-host { position: relative; min-height: 0; overflow: hidden; }
.view { height: 100%; overflow-y: auto; overscroll-behavior: contain; }
.view[hidden] { display: none; }

/* ---------------------------------------------------------------- sidebar -- */

.sidebar {
  display: grid;
  /* One row per child, in order: brand, search, new conversation, nav, footer.
     The nav is the only one that takes the slack. Adding the search button
     without adding its row pushed every later child up a slot, which put "new
     conversation" into the 1fr and stretched it to 227px. */
  grid-template-rows: auto auto auto minmax(0, 1fr) auto;
  gap: var(--sp-2);
  min-width: 0;
  padding: var(--sp-3) var(--sp-3) var(--sp-4);
  background: var(--surface);
  border-right: 1px solid var(--line);
  z-index: var(--z-sidebar);
}

.sidebar__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
  min-height: 44px;
  padding-left: var(--sp-2);
}

.brand {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-width: 0;
  width: 100%;
  padding: var(--sp-2);
  border-radius: var(--r-md);
  color: var(--text);
  text-decoration: none;
  text-align: left;
  transition: background var(--t-fast) var(--ease-out);
}
.brand:hover { background: var(--surface-2); }
.brand__mark {
  color: var(--accent);
  flex: none;
  display: grid;
  place-items: center;
  transition: transform var(--t-base) var(--ease-settle);
}
.brand:hover .brand__mark { transform: translateX(-2px) scaleX(-1); }
.app[data-sidebar='collapsed'] .brand:hover .brand__mark { transform: translateX(2px); }
@media (prefers-reduced-motion: reduce) {
  .brand__mark, .brand:hover .brand__mark { transition: none; transform: none; }
}
.brand__word {
  flex: 1;
  min-width: 0;
  font-family: var(--font-display);
  font-size: var(--step-1);
  font-weight: 600;
  letter-spacing: var(--track-title);
  white-space: nowrap;
}
.brand__word-dim { color: var(--text-muted); font-weight: 400; }

.new-chat {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  width: 100%;
  min-height: 44px;
  padding: 0 var(--sp-3);
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--text);
  font-weight: 500;
  transition: background var(--t-fast) var(--ease-out), transform var(--t-fast) var(--ease-out);
}
.new-chat:hover { background: var(--surface-3); }
.new-chat:active { transform: scale(0.98); }
.new-chat svg { flex: none; margin-left: 2px; }

.nav { overflow-y: auto; overflow-x: hidden; margin-top: var(--sp-2); }
.nav__gap { height: 1px; margin: var(--sp-3) var(--sp-2); background: var(--line); }

.nav__item {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-height: 42px;
  padding: 0 var(--sp-3);
  border-radius: var(--r-md);
  color: var(--text-muted);
  text-decoration: none;
  white-space: nowrap;
  transition: background var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out);
}
.nav__item:hover { background: var(--surface-2); color: var(--text); }
.nav__item.is-active { background: var(--accent-soft); color: var(--text); }

/* The active marker is a slice of river, not a generic bar. */
.nav__item.is-active::before {
  content: '';
  position: absolute;
  left: calc(var(--sp-3) * -1 + 3px);
  top: 50%;
  width: 3px;
  height: 18px;
  margin-top: -9px;
  border-radius: var(--r-pill);
  background: var(--accent);
}

.nav__icon { flex: none; width: 20px; height: 20px; }
.nav__label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }

.nav__tier {
  flex: none;
  font-family: var(--font-body);
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  padding: 3px 7px;
  border-radius: var(--r-pill);
  background: var(--surface-2);
  color: var(--text-faint);
  border: 1px solid var(--line);
}
.nav__tier[data-tier='lin'] { color: var(--sitowie); border-color: color-mix(in srgb, var(--sitowie) 40%, transparent); }
.nav__tier[data-tier='sum'] { color: var(--bursztyn); border-color: color-mix(in srgb, var(--bursztyn) 45%, transparent); }

.nav__go { flex: none; width: 15px; height: 15px; color: var(--text-faint); }
.nav__item.is-locked .nav__label { opacity: 0.72; }

/* --------------------------------------------------------- sidebar footer -- */

.sidebar__foot { display: grid; gap: var(--sp-2); }

/*
 * The bridge state — the signature element.
 *
 * A dot would say the same thing, but this app is named after a river and its
 * one strange, honest fact is that the machine answering you is a laptop in a
 * house that sometimes has its lid shut. So the state of that link is drawn as
 * water: moving when it is open, flat when it is not.
 */
.bridge {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: 44px;
  padding: 0 var(--sp-3);
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--text-muted);
  text-decoration: none;
  overflow: hidden;
}



.bridge[data-state='online'] { color: var(--text); }


/*
 * Four bars, driven by how fresh the Mac's last heartbeat is — a real reading of
 * whether the link is keeping up, not a light that is either on or off. They sit
 * on their own row under the label, because the wave they replaced ran behind
 * the text and was unreadable wherever it mattered.
 */
.bridge__bars { display: flex; align-items: flex-end; gap: 3px; height: 12px; }
.bridge__bars i {
  width: 3px;
  border-radius: 1px;
  background: var(--line-strong);
  transition: background var(--t-base) var(--ease-out);
}
.bridge__bars i:nth-child(1) { height: 35%; }
.bridge__bars i:nth-child(2) { height: 57%; }
.bridge__bars i:nth-child(3) { height: 79%; }
.bridge__bars i:nth-child(4) { height: 100%; }

.bridge[data-level='1'] .bridge__bars i:nth-child(-n + 1),
.bridge[data-level='2'] .bridge__bars i:nth-child(-n + 2),
.bridge[data-level='3'] .bridge__bars i:nth-child(-n + 3),
.bridge[data-level='4'] .bridge__bars i:nth-child(-n + 4) { background: var(--ok); }
.bridge[data-level='1'] .bridge__bars i:nth-child(1) { background: var(--warn); }
.bridge[data-level='2'] .bridge__bars i:nth-child(-n + 2) { background: var(--sand); }

.bridge__dot {
  flex: none;
  width: 8px; height: 8px;
  border-radius: var(--r-pill);
  background: var(--text-faint);
  box-shadow: 0 0 0 0 transparent;
}
.bridge[data-state='online'] .bridge__dot {
  background: var(--ok);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--ok) 20%, transparent);
}
.bridge[data-state='offline'] .bridge__dot { background: var(--text-faint); }

.bridge__text {
  position: relative;
  font-size: var(--step--1);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.user-chip {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-height: 48px;
  padding: 0 var(--sp-3);
  border-radius: var(--r-md);
  color: var(--text);
  text-decoration: none;
  transition: background var(--t-fast) var(--ease-out);
}
.user-chip:hover { background: var(--surface-2); }

.user-chip__avatar {
  flex: none;
  display: grid;
  place-items: center;
  width: 30px; height: 30px;
  border-radius: var(--r-pill);
  background: var(--accent-soft);
  color: var(--accent);
  border: 1px solid var(--accent-line);
  font-size: 0.8rem;
  font-weight: 600;
  background-size: cover;
  background-position: center;
}
.user-chip__avatar.has-photo { color: transparent; border-color: var(--line); }

.user-chip__portrait { position: relative; flex: none; display: grid; }
.user-chip__edit {
  position: absolute;
  right: -5px; bottom: -5px;
  display: grid;
  place-items: center;
  width: 18px; height: 18px;
  border-radius: var(--r-pill);
  background: var(--surface-3);
  border: 1px solid var(--line-strong);
  color: var(--text-muted);
  opacity: 0;
  transition: opacity var(--t-fast) var(--ease-out);
}
.user-chip__edit svg { width: 10px; height: 10px; }
.user-chip:hover .user-chip__edit,
.user-chip__edit:focus-visible { opacity: 1; }

.user-chip__body { display: grid; min-width: 0; line-height: 1.25; }
.user-chip__name { font-size: var(--step--1); font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.user-chip__mail { font-size: 0.72rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* -------------------------------------------------------------- collapsed -- */

.app[data-sidebar='collapsed'] .sidebar { padding-left: var(--sp-2); padding-right: var(--sp-2); }
.app[data-sidebar='collapsed'] .brand__word,
.app[data-sidebar='collapsed'] .new-chat__label,
.app[data-sidebar='collapsed'] .nav__label,
.app[data-sidebar='collapsed'] .nav__tier,
.app[data-sidebar='collapsed'] .nav__go,
.app[data-sidebar='collapsed'] .bridge__text,
.app[data-sidebar='collapsed'] .user-chip__body { display: none; }

/* The head stacks instead of hiding the toggle: a control that collapses the
   sidebar has to still exist afterwards, or the only way back is clearing
   localStorage. The topbar button expands it too — see main.js. */
.app[data-sidebar='collapsed'] .sidebar__head {
  flex-direction: column;
  justify-content: center;
  gap: var(--sp-1);
  padding-left: 0;
}
.app[data-sidebar='collapsed'] .brand { justify-content: center; }
.app[data-sidebar='collapsed'] .new-chat,
.app[data-sidebar='collapsed'] .nav__item,
.app[data-sidebar='collapsed'] .bridge,
.app[data-sidebar='collapsed'] .user-chip { justify-content: center; padding: 0; }

/* The toggle moves into the topbar when there is no room for it in the head. */


/* ----------------------------------------------------------------- topbar -- */

.topbar {
  position: sticky;
  top: 0;
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-height: 56px;
  padding: 0 var(--sp-4);
  background: var(--bg);
  z-index: 10;
}
.topbar__title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.topbar__right { display: flex; align-items: center; gap: var(--sp-1); }
.topbar__menu { display: none; }

:root[data-theme='dark'] .theme-sun { display: none; }
:root[data-theme='light'] .theme-moon { display: none; }

/* ----------------------------------------------------------------- scrim -- */

.scrim {
  position: fixed;
  inset: 0;
  background: var(--scrim);
  z-index: calc(var(--z-sidebar) - 1);
}
.scrim[hidden] { display: none; }

/* --------------------------------------------------------------- overlay -- */

.overlay-host { position: fixed; inset: 0; z-index: var(--z-sheet); }
/* The plans sheet is three columns wide; every other overlay stays a dialog. */
/* (The plans sheet used to have a width override here. It mounts in the drawer,
   which is already full width, and the rule targeted .overlay__panel - a
   combination that has never existed. Removed rather than re-pointed.) */
.overlay-host[hidden] { display: none; }

.overlay { position: absolute; inset: 0; display: grid; place-items: center; padding: var(--sp-4); }
.overlay__scrim { position: absolute; inset: 0; background: var(--scrim); backdrop-filter: blur(3px); }
.overlay__panel {
  position: relative;
  width: min(var(--overlay-w, 560px), 100%);
  max-height: min(86dvh, 760px);
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
}

/* ---------------------------------------------------------------- toasts -- */

.toasts {
  position: fixed;
  left: 50%;
  bottom: calc(var(--sp-5) + env(safe-area-inset-bottom));
  transform: translateX(-50%);
  display: grid;
  gap: var(--sp-2);
  width: min(440px, calc(100vw - 2rem));
  z-index: var(--z-toast);
  pointer-events: none;
}
.toast {
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-md);
  background: var(--surface-3);
  border: 1px solid var(--line-strong);
  box-shadow: var(--shadow-md);
  font-size: var(--step--1);
}
.toast--error { border-color: color-mix(in srgb, var(--warn) 55%, var(--line-strong)); }
.toast--ok { border-color: color-mix(in srgb, var(--ok) 55%, var(--line-strong)); }

/* ------------------------------------------------------------ page frame -- */
/* Shared by every view so seven screens read as one product. */

.page {
  max-width: var(--reading);
  margin: 0 auto;
  padding: var(--sp-6) var(--sp-5) var(--sp-8);
}
.page--wide { max-width: 68rem; }
.page__head { margin-bottom: var(--sp-6); }
.page__head .label { display: block; margin-bottom: var(--sp-2); }
.page__lede { margin-top: var(--sp-3); color: var(--text-muted); max-width: 42ch; }

/* ------------------------------------------------------------------ phone -- */

@media (max-width: 860px) {
  .app,
  .app[data-sidebar='collapsed'] { grid-template-columns: minmax(0, 1fr); }

  .sidebar {
    position: fixed;
    inset: 0 auto 0 0;
    width: min(84vw, var(--sidebar-w));
    transform: translateX(-101%);
    transition: transform var(--t-base) var(--ease-settle);
    box-shadow: var(--shadow-lg);
    padding-top: calc(var(--sp-3) + env(safe-area-inset-top));
  }
  .app[data-drawer='open'] .sidebar { transform: translateX(0); }

  /* Collapsed is a desktop idea; on a phone the drawer is either open or gone. */
  .app[data-sidebar='collapsed'] .brand__word,
  .app[data-sidebar='collapsed'] .new-chat__label,
  .app[data-sidebar='collapsed'] .nav__label,
  .app[data-sidebar='collapsed'] .nav__tier,
  .app[data-sidebar='collapsed'] .bridge__text,
  .app[data-sidebar='collapsed'] .user-chip__body { display: revert; }
  .app[data-sidebar='collapsed'] .sidebar__head { justify-content: space-between; padding-left: var(--sp-2); }
  .app[data-sidebar='collapsed'] .new-chat,
  .app[data-sidebar='collapsed'] .nav__item,
  .app[data-sidebar='collapsed'] .bridge,
  .app[data-sidebar='collapsed'] .user-chip { justify-content: flex-start; padding: 0 var(--sp-3); }

  .topbar {
    padding-top: env(safe-area-inset-top);
    min-height: calc(56px + env(safe-area-inset-top));
  }
  .topbar__menu { display: inline-grid; }

  .page { padding: var(--sp-5) var(--sp-4) var(--sp-8); }
}

/* ---------------------------------------------------------------- drawer -- */
/*
 * A bottom sheet that can be thrown away. See drawer() in js/ui.js for why this
 * is native rather than Vaul: the behaviour is what matters, and Vaul brings
 * React and Radix into an app that has neither.
 */

.drawer { position: absolute; inset: 0; }

.drawer__scrim {
  position: absolute;
  inset: 0;
  background: var(--scrim);
  opacity: 0;
  transition: opacity var(--t-base) var(--ease-out);
}
.drawer[data-open='true'] .drawer__scrim { opacity: 1; }

.drawer__sheet {
  position: absolute;
  inset: auto 0 0;
  max-height: 92dvh;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  background: var(--surface);
  border-top: 1px solid var(--line-strong);
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  box-shadow: var(--shadow-lg);
  transform: translateY(100%);
  transition: transform var(--t-slow) var(--ease-settle);
  touch-action: none;                  /* the sheet owns the vertical gesture */
}
.drawer[data-open='true'] .drawer__sheet { transform: translateY(0); }

/* The grip is the affordance: it says the whole surface can be grabbed, which
   a plain edge does not. */
.drawer__grip { display: grid; place-items: center; padding: var(--sp-3) 0 var(--sp-2); cursor: grab; }
.drawer__grip span {
  width: 40px; height: 4px;
  border-radius: var(--r-pill);
  background: var(--line-strong);
}
.drawer__sheet:active .drawer__grip { cursor: grabbing; }

.drawer__body {
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 0 var(--sp-2) calc(var(--sp-4) + env(safe-area-inset-bottom));
}

/* The page behind gives way a little, so the sheet reads as being in front of
   something rather than painted on top of it. */
.is-behind-drawer {
  transform: scale(0.985);
  transform-origin: top center;
  border-radius: var(--r-md);
  overflow: hidden;
  transition: transform var(--t-base) var(--ease-settle);
}

@media (prefers-reduced-motion: reduce) {
  .drawer__sheet, .drawer__scrim, .is-behind-drawer { transition: none !important; }
  .is-behind-drawer { transform: none; }
}

/* ------------------------------------------------------------- palette -- */
/*
 * Summoned navigation, so the screens can stay bare.
 *
 * Anchored near the top rather than dead-centre: this is a thing you type into,
 * and a box that opens under your eyeline puts the results where the eye
 * already went. Centring it vertically would put half the list below the fold
 * on a laptop for no gain.
 */
.palette {
  position: fixed;
  inset: 0;
  z-index: 120;
  display: grid;
  grid-template-rows: minmax(6vh, 12vh) auto 1fr;
  justify-items: center;
  padding: 0 var(--sp-4);
}
.palette__scrim {
  position: fixed;
  inset: 0;
  background: color-mix(in srgb, var(--bg) 62%, transparent);
  backdrop-filter: blur(6px);
  animation: pal-scrim var(--t-base) var(--ease-out) both;
}
@keyframes pal-scrim { from { opacity: 0; } to { opacity: 1; } }

.palette__panel {
  position: relative;
  grid-row: 2;
  width: min(560px, 100%);
  max-height: min(62vh, 30rem);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border-radius: 18px;
  border: 1px solid color-mix(in srgb, white 12%, var(--line-strong));
  background: color-mix(in srgb, var(--surface) 82%, transparent);
  backdrop-filter: blur(28px) saturate(170%);
  box-shadow: var(--shadow-lg);
}
.palette[data-closing] { pointer-events: none; opacity: 0; transition: opacity var(--t-fast) ease; }

.palette__search {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-4);
  border-bottom: 1px solid var(--line);
  color: var(--text-muted);
}
.palette__input {
  flex: 1;
  min-width: 0;
  border: 0;
  background: none;
  color: var(--text);
  font: inherit;
  font-size: var(--step-0);
}
.palette__input:focus { outline: none; }
.palette__kbd {
  padding: 2px 6px;
  border-radius: 5px;
  border: 1px solid var(--line);
  color: var(--text-faint);
  font-family: var(--font-mono);
  font-size: 0.66rem;
}

.palette__list {
  flex: 1;
  margin: 0;
  padding: var(--sp-2);
  list-style: none;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.palette__group {
  padding: var(--sp-3) var(--sp-3) var(--sp-1);
  color: var(--text-faint);
  font-size: 0.68rem;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
}
.palette__row {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  width: 100%;
  padding: var(--sp-3);
  border: 0;
  border-radius: 10px;
  background: none;
  color: var(--text);
  text-align: left;
  cursor: pointer;
}
/* Selection follows the keyboard AND the pointer, and looks the same either
   way - two different highlights for "where I am" is how a list ends up with
   two cursors and no answer to which one Enter will use. */
.palette__row[aria-selected='true'] { background: var(--surface-3); }
.palette__icon { display: grid; place-items: center; color: var(--text-muted); flex: none; }
.palette__row[aria-selected='true'] .palette__icon { color: var(--accent); }
.palette__label { flex: 1; min-width: 0; }
.palette__hint { color: var(--text-faint); font-size: var(--step--1); }
.palette__empty { padding: var(--sp-5); color: var(--text-faint); text-align: center; }

/* The rail widens under the pointer, so the icons keep their labels without
   holding a column open on every screen forever. Pointer only: a touch device
   has no hover, and there the drawer is still the way in. */
@media (hover: hover) and (min-width: 861px) {
  .app[data-sidebar='collapsed'] .sidebar:hover,
  .app[data-sidebar='collapsed'] .sidebar:focus-within {
    width: var(--sidebar-w);
    box-shadow: var(--shade-2-up);
  }
  .app[data-sidebar='collapsed'] .sidebar {
    position: relative;
    z-index: 30;
    width: var(--sidebar-w-collapsed);
    overflow: hidden;
    transition: width var(--t-base) var(--ease-settle),
                box-shadow var(--t-base) var(--ease-out);
  }
}

/* The palette's visible door. Sits where a search field would, because that is
   where people look for one, and shows its own shortcut so using it once teaches
   the faster way. */
.rail-search {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  width: 100%;
  min-height: 38px;
  margin-bottom: var(--sp-2);
  padding: 0 var(--sp-3);
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--text-muted);
  font-size: var(--step--1);
  cursor: pointer;
}
.rail-search:hover { background: var(--surface-3); color: var(--text); }
.rail-search svg { flex: none; }
.rail-search__label { flex: 1; text-align: left; }
.rail-search__kbd {
  padding: 1px 5px;
  border-radius: 4px;
  border: 1px solid var(--line-strong);
  color: var(--text-faint);
  font-family: var(--font-mono);
  font-size: 0.64rem;
}
/* On the rail only the magnifier survives - the label and the key would be a
   scrollbar's worth of text crammed into 68px. They come back on hover with
   everything else. */
.app[data-sidebar='collapsed'] .rail-search__label,
.app[data-sidebar='collapsed'] .rail-search__kbd { display: none; }
.app[data-sidebar='collapsed'] .sidebar:hover .rail-search__label,
.app[data-sidebar='collapsed'] .sidebar:focus-within .rail-search__label,
.app[data-sidebar='collapsed'] .sidebar:hover .rail-search__kbd,
.app[data-sidebar='collapsed'] .sidebar:focus-within .rail-search__kbd { display: block; }

/* The sheet sits one layer under the dialog, so a checkout opened from the
   plans list stacks on top of it instead of replacing it - and cancelling
   returns you to the list you were reading rather than to nothing. */
.overlay-host--drawer { z-index: calc(var(--z-sheet) - 1); }
