/* ==========================================================================
   Orcheum · Workspace Sidebar
   Source of truth: Figma node 576:1812 ("Sidebar").
   Wordmark, Home/Studios segmented control, primary nav (New chat / Projects /
   Artifacts / Search / Settings), then the scrolling "Chats" history list.

   Figma draws this frame at 0.845 scale (its 250px sidebar is our 296px), so
   every measurement here is the design value ÷ 0.845.
   ========================================================================== */

.ws-sidebar {
  display: flex;
  flex-direction: column;
  gap: 24px;                       /* 20.286 */
  flex-shrink: 0;
  width: 296px;
  height: 100%;
  padding: 14px 20px 0;            /* 12 / 16.905 */
  /* No longer an opaque cream panel. The sidebar is glass: the page's own
     warm gradient runs behind it, and cream is washed back in from
     transparent at the top to 73% at the foot, over a 1% black tint — so the
     column reads as a lit surface rather than a separate wall.
     Two stacked layers, exactly as Figma 576:1812 stacks them. */
  background:
    linear-gradient(rgba(0, 0, 0, 0.01), rgba(0, 0, 0, 0.01)),
    linear-gradient(180deg, rgba(251, 247, 239, 0) 0%, rgba(251, 247, 239, 0.73) 100%);
  -webkit-backdrop-filter: blur(42px);
  backdrop-filter: blur(42px);
  border-right: 1px solid var(--color-card-border);
}

/* ---- Wordmark — Figma 615:2640 ---------------------------------------
   Playfair Medium in the warm brown, no sun disc. The mark is the product's
   elsewhere (Amendment 006); here the design deliberately sets the name alone,
   so the sidebar opens on a word rather than a logo. */
.ws-sidebar__brand {
  align-self: flex-start;
  flex-shrink: 0;
  padding: 6px 9px;
  font-family: var(--font-serif);
  font-weight: var(--font-weight-medium);
  font-size: 23px;                 /* 19.219 */
  line-height: 1.25;
  /* Literal fallback on purpose: colors.css arrives via an unversioned @import
     in tokens.css, so a returning browser can hold a cached copy without this
     token yet. Without the fallback the wordmark would resolve to inherited
     dark on exactly those first loads. */
  color: var(--color-brand-wordmark, #81493b);
  text-decoration: none;
  white-space: nowrap;
}

/* ---- Home / Studios segmented control — Figma 615:2653 ----------------
   A two-up switch, centred in the column. Home is this page and carries the
   selection at rest; Studios is a link out. Both hug their labels, so the
   control is as wide as its content — as in the design. */
.ws-seg {
  align-self: center;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  height: 36px;                    /* 30 */
  padding: 5px;                    /* 4 */
  border: 1px solid #dee1e1;
  border-radius: 10px;             /* 8 */
  background: #ffffff;
}
.ws-seg__tab {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 26px;                    /* 22 */
  padding: 0 14px;                 /* 12 */
  border: 0;
  border-radius: 5px;              /* 4 */
  background: transparent;
  font-family: var(--font-sans);
  font-weight: var(--font-weight-medium);
  font-size: 14px;                 /* 12 */
  line-height: 1.3;
  color: #19213d;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition:
    background var(--duration-base, 0.2s) var(--ease-standard, ease),
    color var(--duration-base, 0.2s) var(--ease-standard, ease);
}
.ws-seg__tab:hover:not(.is-selected) { background: rgba(36, 37, 45, 0.06); }
.ws-seg__tab.is-selected {
  background: #272720;
  color: var(--color-background);
}
.ws-seg__tab:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px #ffffff, 0 0 0 4px var(--color-puddle-700, #61686b);
}

/* ---- New Chat / Search slot ----------------------------------------------
   Search takes the CTA's place instead of pushing a field in below the Search
   row: the two states are alternatives, and stacking them there also shoved
   the whole nav down on every keystroke's worth of attention.

   Both children are absolutely placed in this one 38px box, so the swap is a
   true takeover — nothing reflows, and the field arrives exactly where the
   button was. The box holds the height on its own since neither child is in
   flow. */
.ws-cta {
  position: relative;
  flex-shrink: 0;
  height: 34px;                    /* one menu row — 28.524 */
}
.ws-cta > .ws-new-chat,
.ws-cta > .ws-search-field {
  position: absolute;
  inset: 0;
}

/* ---- New chat row — Figma 615:2662 -----------------------------------
   No longer a filled CTA. The design makes it the first row of the menu, which
   is also what it is in meaning: one more place to go, not a banner over the
   nav. It keeps the row geometry below so the two never drift apart. */
.ws-new-chat {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 10px;
  width: 100%;
  height: 34px;
  flex-shrink: 0;
  padding: 8px 12px;
  border: 0;
  border-radius: var(--radius-8);
  background: none;
  font-family: var(--font-sans);
  font-weight: var(--font-weight-normal);
  font-size: 14px;
  line-height: 1.25;
  color: var(--color-foreground);
  text-align: left;
  cursor: pointer;
  transition: background var(--duration-base, 0.2s) var(--ease-standard, ease);
}
.ws-new-chat:hover { background: rgba(189, 196, 198, 0.22); }
.ws-new-chat:active { background: rgba(189, 196, 198, 0.34); }
.ws-new-chat__icon { width: 16px; height: 16px; display: block; flex: 0 0 auto; }

/* ---- Scroll region ---- */
.ws-sidebar__scroll {
  display: flex;
  flex-direction: column;
  gap: 24px;
  flex: 1 0 0;
  min-height: 0;
  overflow-y: auto;
  margin: 0 -8px;
  padding: 0 8px 16px;
}
/* Quiet scrollbar */
.ws-sidebar__scroll::-webkit-scrollbar { width: 6px; }
.ws-sidebar__scroll::-webkit-scrollbar-thumb {
  background: rgba(189, 196, 198, 0.5);
  border-radius: 999px;
}
.ws-sidebar__scroll::-webkit-scrollbar-track { background: transparent; }

.ws-nav {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

/* Shared row (nav item + chat item + section title) */
.ws-nav-item,
.ws-chat-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 12px;
  border: 0;
  border-radius: var(--radius-8);
  background: none;
  font-family: var(--font-sans);
  color: var(--color-foreground);
  text-align: left;
  cursor: pointer;
  transition: background var(--duration-base, 0.2s) var(--ease-standard, ease);
}
.ws-nav-item {
  font-size: 14px;
  font-weight: var(--font-weight-normal);
  line-height: 1.25;
  text-decoration: none;
}
.ws-nav-item:hover,
.ws-chat-item:hover { background: rgba(189, 196, 198, 0.22); }
.ws-nav-item.is-active { background: rgba(189, 196, 198, 0.34); }

.ws-nav-item__icon { width: 16px; height: 16px; display: block; flex: 0 0 auto; }
.ws-nav-item__label { flex: 1 1 auto; min-width: 0; }

/* Search field — lives in .ws-cta, shown in place of New Chat.
   Visibility is opacity/visibility rather than `display`, which cannot be
   transitioned; `visibility` also takes the hidden state out of the tab order,
   so the field is not focusable while it is the button's turn. The two swap on
   a single class on the sidebar, so they can never both be visible. */
.ws-search-field {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  height: 34px;
  padding: 8px 12px;
  border: 1px solid var(--color-button-secondary-border);
  border-radius: var(--radius-8);
  background: rgba(189, 196, 198, 0.18);
}

.ws-new-chat,
.ws-search-field {
  transition:
    opacity var(--duration-base, 0.2s) var(--ease-standard, ease),
    transform var(--duration-base, 0.2s) var(--ease-standard, ease),
    visibility 0s linear var(--duration-base, 0.2s);
}

/* Resting: the button holds the slot, the field waits just under it. */
.ws-search-field {
  opacity: 0;
  visibility: hidden;
  transform: translateY(-3px);
  pointer-events: none;
}

/* Searching: they trade places. `visibility` flips immediately on the way in
   (0s delay) and only after the fade on the way out (delay above). */
.ws-sidebar.is-searching .ws-new-chat {
  opacity: 0;
  visibility: hidden;
  transform: translateY(3px);
  pointer-events: none;
}
.ws-sidebar.is-searching .ws-search-field {
  opacity: 1;
  visibility: visible;
  transform: none;
  pointer-events: auto;
  transition-delay: 0s, 0s, 0s;
}

.ws-search-field:focus-within {
  border-color: var(--color-field-border);
  background: rgba(189, 196, 198, 0.28);
}
.ws-search-field__icon { width: 16px; height: 16px; flex: 0 0 auto; display: block; }
.ws-search-field input {
  flex: 1 1 auto;
  min-width: 0;
  border: 0;
  outline: 0;
  background: transparent;
  font-family: var(--font-sans);
  font-size: 14px;
  color: var(--color-foreground);
}
.ws-search-field input::placeholder { color: var(--color-text-placeholder); }

/* ---- Chats section ---- */
.ws-section { display: flex; flex-direction: column; }
.ws-section__title {
  padding: 8px 12px;
  font-family: var(--font-sans);
  font-size: 12px;
  font-weight: var(--font-weight-medium);
  line-height: 1.25;
  color: var(--color-text-secondary);
}

.ws-chat-item {
  font-size: 12px;                 /* 9.97 — history sits a step under the nav */
  font-weight: var(--font-weight-normal);
  line-height: 1.25;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  display: block;
}
.ws-chat-item.is-hidden { display: none; }

.ws-chats__empty {
  padding: 10px 12px;
  font-family: var(--font-sans);
  font-size: 13px;
  color: var(--color-text-placeholder);
}

@media (max-width: 1024px) {
  .ws-sidebar { width: 260px; }
}
@media (max-width: 820px) {
  .ws-sidebar { display: none; }
}

/* ══ The rail ══════════════════════════════════════════════════════════════
   The sidebar collapses to a column of icons. Two reasons it exists, and they
   are different reasons:

   1. The reader asks for it, anywhere, with the toggle at the top of the
      column. That choice is theirs and it persists.
   2. Studios takes it by default. The room is a *place*; a place should not be
      read past a column of links, and the shelf wants the width. But this is a
      default, not a rule — see the two stored preferences in workspace.html.

   Nothing is removed from the DOM: every row keeps its `aria-label`, so a
   screen reader hears the same sidebar at either width. Only the words go.
   ========================================================================== */

.ws-sidebar__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  flex-shrink: 0;
}

.ws-rail-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-8);
  background: none;
  color: var(--color-foreground);
  opacity: 0.55;
  cursor: pointer;
  transition:
    background var(--duration-base, 0.2s) var(--ease-standard, ease),
    opacity var(--duration-base, 0.2s) var(--ease-standard, ease);
}
.ws-rail-toggle svg { width: 18px; height: 18px; display: block; }
.ws-rail-toggle:hover { background: rgba(189, 196, 198, 0.22); opacity: 1; }
.ws-rail-toggle:active { background: rgba(189, 196, 198, 0.34); }

/* The panel's own divider slides across as the sidebar closes, so the icon
   reads as the column narrowing rather than as a generic square. */
.ws-rail-toggle svg path { transform-origin: center; }
.ws-sidebar.is-rail-ready .ws-rail-toggle svg path {
  transition: transform 0.34s var(--ease-emphasized, cubic-bezier(0.22, 1, 0.36, 1));
}
.ws-sidebar.is-rail .ws-rail-toggle svg path { transform: translateX(5px); }

/* ---- Icons in the segmented control -------------------------------------
   Present at both widths; at full width they sit beside the word, in the rail
   they are the whole control. */
.ws-seg__icon {
  width: 16px;
  height: 16px;
  display: block;
  flex: 0 0 auto;
  opacity: 0.75;
}
.ws-seg__tab.is-selected .ws-seg__icon { opacity: 1; }
.ws-seg__tab { gap: 7px; }

/* ---- The collapsed column ------------------------------------------------
   68px = 16px icon + 12px row padding either side + 14px column padding
   either side. Width and padding are the only things that animate; the rows
   below simply lose their labels. */
/* `is-rail-ready` is added one committed frame after the boot state lands, so
   arriving straight into Studios shows a rail rather than a full sidebar
   swinging shut. Only reader-driven changes animate. */
.ws-sidebar.is-rail-ready {
  transition:
    width 0.34s var(--ease-emphasized, cubic-bezier(0.22, 1, 0.36, 1)),
    padding 0.34s var(--ease-emphasized, cubic-bezier(0.22, 1, 0.36, 1));
}

.ws-sidebar.is-rail {
  width: 68px;
  padding-left: 14px;
  padding-right: 14px;
  gap: 18px;
  overflow: hidden;
}

.ws-sidebar.is-rail .ws-sidebar__brand,
.ws-sidebar.is-rail .ws-section,
.ws-sidebar.is-rail .ws-search-field,
.ws-sidebar.is-rail .ws-seg__label,
.ws-sidebar.is-rail .ws-nav-item__label { display: none; }

.ws-sidebar.is-rail .ws-sidebar__head { justify-content: center; }

/* The two-up switch stands up into a two-high one. It keeps its frame, so it
   still reads as one control with one of two states chosen — the thing that
   would be lost if it became two loose icons. */
.ws-sidebar.is-rail .ws-seg {
  flex-direction: column;
  align-self: center;
  height: auto;
  gap: 4px;
  padding: 4px;
}
.ws-sidebar.is-rail .ws-seg__tab {
  width: 30px;
  height: 30px;
  padding: 0;
}

.ws-sidebar.is-rail .ws-nav-item,
.ws-sidebar.is-rail .ws-new-chat {
  justify-content: center;
  padding-left: 0;
  padding-right: 0;
}

/* The scroll region has nothing left to scroll once Chats is gone. */
.ws-sidebar.is-rail .ws-sidebar__scroll {
  overflow-y: visible;
  margin: 0;
  padding-left: 0;
  padding-right: 0;
}

@media (prefers-reduced-motion: reduce) {
  .ws-sidebar,
  .ws-rail-toggle svg path { transition: none; }
}
