/*
 * Loosely follows the eCorpus UI theme (https://ecorpus.holusion.com/ui/).
 * Only the tokens needed by the current pages are pulled in; extend as the
 * interface grows rather than importing the whole theme up front.
 */
:root {
  --color-primary: #e6b900;
  --color-secondary: #4735df;
  --color-dark: #343434;
  --color-light: #eee;
  --color-text: var(--color-light);
  --color-background: var(--color-dark);
  --color-section: rgba(0, 0, 0, 0.15);
  --color-muted: color-mix(in srgb, var(--color-light), transparent 35%);
  --color-hover: color-mix(in oklch, var(--color-primary), black 20%);
  --color-success: #8ae65c;
  --color-warning: #e6a345;
  --color-error: #e64545;

  --font-body: "Open Sans", "Liberation Sans", "Roboto", sans-serif;
  --font-heading: "Noto Serif", serif;

  --nav-height: 44px;
  --content-width: 48rem;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family: var(--font-body);
  line-height: 1.5;
  color: var(--color-text);
  background: var(--color-background);
}

.site-header {
  display: flex;
  align-items: center;
  gap: 1rem;
  min-height: var(--nav-height);
  padding: 0 1.5rem;
  border-bottom: 1px solid var(--color-section);
  background: var(--color-section);

  h1 {
    margin: 0;
    font-family: var(--font-heading);
    font-size: 1.25rem;
    font-weight: 600;
  }
}

/* Build identifier, in small print right after the brand. */
.site-header__version {
  margin-left: -0.5rem;
  font-size: 0.7rem;
  font-family: ui-monospace, monospace;
  color: var(--color-muted);
  cursor: default;
}

/* Admin button sits at the far right of the header. */
.site-header__admin {
  margin-left: auto;
  padding: 0.3rem 0.9rem;
  font-size: 0.85rem;
}

/* Small solid badge, e.g. the "admin" marker on instances/identities. */
.pill {
  display: inline-block;
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 0.1rem 0.5rem;
  border-radius: 1rem;
}

.pill--admin {
  color: var(--color-light);
  background: var(--color-secondary);
}

.site-main {
  max-width: var(--content-width);
  margin: 0 auto;
  padding: 2rem 1.5rem;
}

.lead {
  margin: 0 0 2rem;
  color: var(--color-muted);
}

.button-link {
  display: inline-block;
  padding: 0.5rem 1.25rem;
  font-weight: 600;
  text-decoration: none;
  color: var(--color-dark);
  background: var(--color-primary);
  border-radius: 0.25rem;

  &:hover {
    background: var(--color-hover);
  }
}

.session {
  button {
    padding: 0.5rem 1.25rem;
    font: inherit;
    font-weight: 600;
    color: var(--color-text);
    background: transparent;
    border: 1px solid var(--color-muted);
    border-radius: 0.25rem;
    cursor: pointer;

    &:hover {
      border-color: var(--color-primary);
    }
  }
}

.onboarding {

  .domain-picker {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    align-items: flex-start;
    padding: 1.5rem;
    border-radius: 0.5rem;
    background: var(--color-section);

    label {
      font-weight: 600;
    }

    select {
      width: 100%;
      max-width: 24rem;
      padding: 0.5rem 0.75rem;
      font: inherit;
      color: var(--color-text);
      background: var(--color-dark);
      border: 1px solid var(--color-muted);
      border-radius: 0.25rem;

      &:focus-visible {
        outline: 2px solid var(--color-primary);
        outline-offset: 1px;
      }
    }

    button {
      padding: 0.5rem 1.25rem;
      font: inherit;
      font-weight: 600;
      color: var(--color-dark);
      background: var(--color-primary);
      border: none;
      border-radius: 0.25rem;
      cursor: pointer;

      &:hover {
        background: var(--color-hover);
      }

      &:disabled {
        cursor: not-allowed;
        opacity: 0.5;
      }
    }

    .domain-picker__empty {
      margin: 0;
      color: var(--color-muted);
      font-size: 0.9rem;

      code {
        font-family: ui-monospace, "Liberation Mono", monospace;
      }
    }
  }
}

/* --- Instance selector with per-instance connection status --- */
.instance-list {
  list-style: none;
  margin: 0 0 2rem;
  padding: 0;

  .instance {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.75rem 1rem;
    border: 1px solid var(--color-section);
    border-radius: 0.375rem;
    background: var(--color-section);

    &+.instance {
      margin-top: 0.5rem;
    }

    .instance__name {
      flex: 1;
      font-weight: 600;
    }
  }
}

.status {
  font-size: 0.8rem;
  padding: 0.15rem 0.6rem;
  border-radius: 1rem;
  border: 1px solid currentColor;

  &.status--connected {
    color: var(--color-success);
  }

  &.status--stale {
    color: var(--color-warning);
  }

  &.status--disconnected {
    color: var(--color-muted);
  }
}

.button-link--ghost {
  color: var(--color-text);
  background: transparent;
  border: 1px solid var(--color-muted);

  &:hover {
    background: transparent;
    border-color: var(--color-primary);
  }
}

.inline {
  display: inline;
}

.link-button {
  font: inherit;
  color: var(--color-muted);
  background: none;
  border: none;
  text-decoration: underline;
  cursor: pointer;

  &:hover {
    color: var(--color-text);
  }
}

/* --- Administration page --- */
.admin-panel {
  margin: 0 0 2.5rem;
  padding: 1.5rem;
  border: 1px solid var(--color-section);
  border-radius: 0.5rem;
  background: var(--color-section);

  h2 {
    margin: 0 0 0.5rem;
    font-family: var(--font-heading);
  }

  .admin-panel__hint {
    margin: 0 0 1rem;
    color: var(--color-muted);
    font-size: 0.9rem;

    code {
      font-family: ui-monospace, "Liberation Mono", monospace;
    }
  }

  .admin-panel__empty {
    margin: 0 0 1rem;
    color: var(--color-muted);
  }
}

.admin-list {
  list-style: none;
  margin: 0 0 1.5rem;
  padding: 0;

  .admin-list__item {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.5rem 0.75rem;
    border-radius: 0.375rem;
    background: var(--color-background);

    &+.admin-list__item {
      margin-top: 0.4rem;
    }
  }

  .admin-list__main {
    flex: 1;
    font-weight: 600;
  }

  .admin-list__meta {
    color: var(--color-muted);
    font-size: 0.8rem;
  }
}

.admin-form {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.75rem;

  label {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    font-weight: 600;
    font-size: 0.9rem;
  }

  input,
  select {
    padding: 0.5rem 0.75rem;
    font: inherit;
    color: var(--color-text);
    background: var(--color-dark);
    border: 1px solid var(--color-muted);
    border-radius: 0.25rem;

    &:focus-visible {
      outline: 2px solid var(--color-primary);
      outline-offset: 1px;
    }
  }

  button {
    padding: 0.5rem 1.25rem;
    font: inherit;
    font-weight: 600;
    color: var(--color-dark);
    background: var(--color-primary);
    border: none;
    border-radius: 0.25rem;
    cursor: pointer;

    &:hover {
      background: var(--color-hover);
    }
  }
}

/* --- Connected workspace: search + build --- */
.workspace {
  margin-top: 2.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--color-section);

  h2 {
    font-family: var(--font-heading);
    margin: 0 0 0.5rem;
  }

  .scene-search,
  .build-panel {

    label {
      font-weight: 600;
      display: block;
      /*force line breaks after labels*/
    }

    input[type="search"],
    select {
      flex: 1;
      width: 100%;
      min-width: 12rem;
      padding: 0.5rem 0.75rem;
      font: inherit;
      color: var(--color-text);
      background: var(--color-dark);
      border: 1px solid var(--color-muted);
      border-radius: 0.25rem;

      &:focus-visible {
        outline: 2px solid var(--color-primary);
        outline-offset: 1px;
      }
    }

    button {
      padding: 0.5rem 1.25rem;
      font: inherit;
      font-weight: 600;
      color: var(--color-dark);
      background: var(--color-primary);
      border: none;
      border-radius: 0.25rem;
      cursor: pointer;

      &:disabled {
        opacity: 0.5;
        cursor: not-allowed;
      }

      &:hover:not(:disabled) {
        background: var(--color-hover);
      }
    }
  }

  .scene-search {
    position: sticky;
    top: 0;
    padding-top: 1rem;
    margin-bottom: 4px;
    z-index: 20;
    /* keep the bar (and the expanded stash overlay) above results */
    background-color: var(--color-background);
    display: flex;
    flex-direction: row;
    align-items: end;
    gap: 4px;

    /* Reserve room at the right for the absolutely-positioned collapsed stash. */
    input[type="search"] {
      padding-right: 10.5rem;
    }

    >.scene-search-bar {
      flex: 1 1 auto;

      >label {
        margin: .5rem 0;
      }

    }

  }
}

/* --- Workspace header: title + switch action --- */
.workspace__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;

  h2 {
    margin: 0;
  }
}

/* --- Build progress page --- */
.build-run {
  progress {
    width: 100%;
    height: 0.75rem;
  }

  .build-status {
    margin: 0.75rem 0;
    color: var(--color-muted);
  }

  .build-actions {
    display: flex;
    gap: 0.75rem;
    align-items: center;

    button {
      padding: 0.5rem 1.25rem;
      font: inherit;
      font-weight: 600;
      color: var(--color-text);
      background: transparent;
      border: 1px solid var(--color-muted);
      border-radius: 0.25rem;
      cursor: pointer;

      &:hover {
        border-color: var(--color-primary);
      }
    }
  }
}

/* --- htmx search indicator --- */
.htmx-indicator {
  opacity: 0;
  margin-left: 0.5rem;
  color: var(--color-muted);
  font-size: 0.85rem;
  transition: opacity 0.2s;
}

.htmx-request .htmx-indicator,
.htmx-request.htmx-indicator {
  opacity: 1;
}

/* --- Scene search results --- */
.scene-results {
  margin: 0;
}

.scene-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: 1fr;
  grid-template-rows: auto;
  gap: 4px;
}

.scene-card {
  .scene-card__add {
    display: flex;
    flex-direction: row;
    width: 100%;
    padding: 0;
    gap: 4px;
    font: inherit;
    text-align: left;
    color: var(--color-text);
    background: var(--color-section);
    border: 1px solid transparent;
    border-radius: 0.375rem;
    overflow: hidden;
    cursor: pointer;

    &:hover {
      border-color: var(--color-primary);
    }
  }

  .thumb {
    display: block;
    aspect-ratio: 1;
    background: var(--color-dark);
    width: 64px;
    height: 64px;

    img {
      width: 100%;
      height: 100%;
      object-fit: cover;
    }
  }

  .scene-card__body {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;

    .scene-card__title {
      padding: 0 0.5rem;
      font-weight: 600;
      overflow-wrap: anywhere;
    }

    .scene-card__mtime {
      padding: 0 0.5rem 0.5rem;
      font-size: 0.78rem;
      color: var(--color-muted);
      align-self: flex-start;
    }

  }

  &.is-selected .scene-card__add {
    border-color: var(--color-success);
  }
}

.scene-results__empty {
  color: var(--color-muted);
}

/* Toolbar above the results grid (currently just "Select all"). */
.scene-toolbar {
  display: flex;
  justify-content: flex-start;
  margin: 0 0 4px;
}

.scene-toolbar__select-all {
  padding: 0.25rem 0.75rem;
  font: inherit;
  font-weight: 600;
  color: var(--color-text);
  background: var(--color-section);
  border: 1px solid var(--color-primary);
  border-radius: 0.25rem;
  cursor: pointer;

  &:hover {
    background: var(--color-hover);
  }
}

/* When no listed card is still unselected, every result is already in the
   stash, so "Select all" has nothing left to do — disable it in pure CSS. */
.scene-results:not(:has(.scene-card:not(.is-selected))) .scene-toolbar__select-all {
  color: var(--color-muted);
  background: var(--color-section);
  border-color: transparent;
  pointer-events: none;
  cursor: default;
  opacity: 0.6;
}

/* Pagination controls below the grid. */
.scene-pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  margin-top: 0.75rem;
}

.scene-pager__page {
  font-size: 0.85rem;
  color: var(--color-muted);
}

.scene-pager__btn {
  padding: 0.25rem 0.75rem;
  font: inherit;
  color: var(--color-text);
  background: var(--color-section);
  border: 1px solid var(--color-primary);
  border-radius: 0.25rem;
  cursor: pointer;

  &:hover {
    background: var(--color-hover);
  }

  &:disabled {
    color: var(--color-muted);
    border-color: transparent;
    cursor: default;
    opacity: 0.6;
  }
}



/* --- Stash (selected scenes): a floating, expandable panel by the search bar.
   Collapsed it shows a count + an overlapping thumbnail "stack"; expanded it
   becomes a scrolling grid. The #stash-expanded checkbox (a preceding sibling,
   outside #stash so it survives htmx swaps) drives the two states.

   The whole component is nested under `#stash` on purpose: every rule then
   carries id-level specificity (1,0,0+), which keeps the stash's bespoke buttons
   above the generic `.workspace .scene-search button`/input theme (0,3,x) that
   would otherwise bleed in. It also scopes the component in one readable block
   instead of a dozen loose `.stash__*` rules competing across the file. --- */

/* The toggle is the one bit that can't live under #stash: it's a *preceding*
   sibling of the panel (so its state survives htmx swaps), which no nesting can
   reach. It's `hidden`; keep it out of flow regardless. */
.stash-toggle {
  position: absolute;
}

#stash {
  position: relative;
  display: flex;
  flex-direction: column;
  max-width: min(20rem, 70vw);
  margin: 0;
  border: 1px solid var(--color-section);
  border-radius: 0.375rem;
  background: var(--color-background);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.35);
  overflow: hidden;

  /* Collapsed face: count + stack + caret, one click target (expands on click). */
  .stash__summary {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.35rem 0.6rem;
    cursor: pointer;
    user-select: none;
  }

  .stash__count {
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    min-width: 1.1rem;
    text-align: center;
  }

  .stash__stack {
    display: flex;
    align-items: flex-start;
  }

  .stash__stack-item {
    position: relative;
    flex: 0 0 auto;
    width: 40px;
    height: 40px;

    /* Overlap older thumbnails behind the newer ones; the newest (last child,
       painted last) sits on top and slightly higher than the ones behind it. */
    &+& {
      margin-left: -36px;
    }

    &:nth-last-child(1) {
      z-index: 5;
    }

    &:nth-last-child(2) {
      z-index: 4;
      transform: translateY(-2px);
    }

    &:nth-last-child(3) {
      z-index: 3;
      transform: translateY(-4px);
    }

    &:nth-last-child(4) {
      z-index: 2;
      transform: translateY(-6px);
    }

    &:nth-last-child(5) {
      z-index: 1;
      transform: translateY(-8px);
    }
  }

  .stash__stack-thumb {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 0.25rem;
    border: 1px solid var(--color-background);
    background: var(--color-dark);
  }

  /* Down caret signalling the panel can be expanded; flips when open. */
  .stash__caret {
    margin-left: auto;
    width: 0;
    height: 0;
    border-left: 5px solid transparent;
    border-right: 5px solid transparent;
    border-top: 6px solid currentColor;
    transition: transform 0.15s ease;
  }

  /* While collapsed, only the summary face shows; the drawer is tucked away. */
  .stash__drawer {
    display: none;
  }

  /* The deselect-all button: quiet by default, danger-tinted on hover. */
  .stash__clear {
    padding: 0.2rem 0.6rem;
    font: inherit;
    font-size: 0.8rem;
    color: var(--color-muted);
    background: transparent;
    border: 1px solid var(--color-section);
    border-radius: 0.25rem;
    cursor: pointer;

    &:hover {
      color: #fff;
      background: var(--color-error);
      border-color: var(--color-error);
    }
  }

  .stash-item {
    position: relative;
    flex: 0 0 auto;
    width: 100%;
    border-radius: 0.25rem;
    overflow: hidden;
    background: var(--color-dark);

    .stash-item__thumb {
      display: block;
      width: 100%;
      aspect-ratio: 1;
      object-fit: cover;
    }

    .stash-item__name {
      position: absolute;
      left: 0;
      right: 0;
      bottom: 0;
      padding: 0.15rem 0.35rem;
      font-size: 0.7rem;
      color: var(--color-light);
      background: rgba(0, 0, 0, 0.6);
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      transition: font-size 0.15s;
    }

    &:hover .stash-item__name {
      font-size: 0.85rem;
      white-space: normal;
      line-break: anywhere;
    }
  }

  /* --- Remove buttons, shared by the collapsed stack thumbnail and the expanded
     grid tiles. Nesting under #stash already gives them (1,1,0), which outranks
     the generic `.scene-search button` theme — crucially its :hover (0,3,1) — so
     they no longer need to repeat the id anchor by hand. --- */
  .stash__stack-remove,
  .stash-item__remove {
    position: absolute;
    padding: 0;
    line-height: 1;
    color: #fff;
    background: var(--color-error);
    border: none;
    border-radius: 50%;
    cursor: pointer;
    opacity: 0.85;

    &:hover {
      opacity: 1;
    }
  }

  /* Top thumbnail of the collapsed stack: small, hugging the corner. */
  .stash__stack-remove {
    top: -5px;
    right: -5px;
    z-index: 6;
    width: 1.05rem;
    height: 1.05rem;
    font-size: 0.75rem;
  }

  /* Grid tile in the expanded panel: slightly larger, inset from the corner. */
  .stash-item__remove {
    top: 0.2rem;
    right: 0.2rem;
    width: 1.25rem;
    height: 1.25rem;
    font-size: 0.85rem;
  }

  /* --- Expanded state ---
     The summary stays in flow as a fixed-width flex item, so it *reserves
     horizontal space* and the search bar shrinks beside it (no overlap). The
     drawer, however, is lifted out of flow (absolute) and hangs under the
     summary, so its height does NOT grow the sticky search row — it overflows
     downward over the results, the way the old absolute-positioned panel did.

     `&` here is #stash, so this reads "when the sibling toggle is checked". */
  .stash-toggle:checked~& {
    width: min(26rem, calc(100vw - 2rem));
    max-width: none;
    flex: 0 0 auto; /* hold the reserved width; don't let the row squeeze it */
    overflow: visible; /* let the drawer escape the summary's box */
    /* The summary becomes the drawer's header: square its bottom and drop the
       bottom border so it reads as one continuous panel. */
    border-bottom: none;
    border-bottom-left-radius: 0;
    border-bottom-right-radius: 0;

    .stash__stack {
      display: none; /* the grid below supersedes the preview */
    }

    .stash__caret {
      /* Flip to an up-caret in place (swap which border is coloured rather than
         rotating, which would pivot around the triangle's apex and shift it). */
      border-top: 0;
      border-bottom: 6px solid currentColor;
    }

    .stash__drawer {
      display: flex;
      flex-direction: column;
      /* Out of flow, anchored just under the summary and slightly wider so its
         side borders sit exactly over the summary's. */
      position: absolute;
      top: 100%;
      left: -1px;
      right: -1px;
      z-index: 1;
      max-height: min(70vh, 32rem);
      background: var(--color-background);
      border: 1px solid var(--color-section);
      border-top: none;
      border-radius: 0 0 0.375rem 0.375rem;
      box-shadow: 0 10px 18px rgba(0, 0, 0, 0.35);
      overflow: hidden; /* clip the grid to the rounded bottom corners */
    }

    .stash__actions {
      display: flex;
      flex: 0 0 auto; /* pinned above the scrolling grid */
      justify-content: flex-end;
      padding: 0.4rem 0.6rem 0;
    }

    .stash__list {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(112px, 1fr));
      grid-auto-rows: min-content; /* rows hug the square thumbnails, never stretch */
      align-content: start;
      gap: 6px;
      list-style: none;
      margin: 0;
      padding: 0.5rem;
      flex: 1 1 auto;
      min-height: 0; /* allow the flex child to shrink below content and scroll */
      overflow-y: auto;
    }

    .stash__empty {
      display: block;
      margin: 0;
      padding: 0.6rem;
      color: var(--color-muted);
      font-size: 0.9rem;
    }
  }

  /* On narrow screens the stash can't float: it sits in flow and spans full
     width, and the drawer expands in place instead of hanging off as a dropdown. */
  @media (max-width: 640px) {
    position: static;
    width: 100%;
    max-width: none;
    margin-bottom: 0.5rem;
    box-shadow: none;

    .stash-toggle:checked~& {
      width: 100%;
      border-bottom: 1px solid var(--color-section);
      border-radius: 0.375rem;

      .stash__drawer {
        position: static;
        max-height: min(60vh, 28rem);
        border: none;
        border-radius: 0;
        box-shadow: none;
      }
    }
  }
}

/* The collapsed stash sits in flow on mobile, so the search field no longer
   needs room reserved on its right. */
@media (max-width: 640px) {
  .scene-search input[type="search"] {
    padding-right: 0.75rem;
  }
}