/* Shared app refinements loaded by base_app.html */

.app-body .page-header {
  gap: 0.8rem;
}

.app-body .page-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
}

.app-body .btn:focus-visible,
.app-body .form-control:focus-visible,
.app-body .form-select:focus-visible,
.app-body a:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(11, 20, 51, 0.14);
}

/* ==========================================================================
 * Content is never hidden by an animation
 * --------------------------------------------------------------------------
 * workspace-fade-in, pane-enter and card-in all animated opacity from 0. That
 * makes the animation load-bearing: if it does not run to completion, whatever
 * it covers stays invisible. It is easy to hit - a throttled background tab,
 * a stalled frame clock, a slow device - and the failure is total: measured
 * here, #main-app sat at opacity 0 with the 220ms animation still reporting
 * "running" twelve seconds after load, which renders the entire workspace
 * blank rather than merely unanimated.
 *
 * These keyframes are redefined (a later definition of the same name wins) to
 * move the element without touching its opacity. The motion still reads, and
 * an animation that never runs now costs nothing but the motion.
 * ======================================================================== */
@keyframes workspace-fade-in {
  from { transform: translateY(4px); }
  to   { transform: translateY(0); }
}

@keyframes pane-enter {
  from { transform: translateY(4px); }
  to   { transform: none; }
}

@keyframes card-in {
  from { transform: translateY(6px); }
  to   { transform: none; }
}

/* Belt and braces: these three carry the whole workspace, so their resting
   opacity is stated rather than inherited from whatever ran last. */
body.app-body[data-app-page="app"] #main-app,
body.app-body[data-app-page="app"] #main-app.visible,
body.app-body[data-app-page="app"] .pane-enter,
body.app-body[data-app-page="app"] .result-item {
  opacity: 1;
}

/* ==========================================================================
 * Booting must not be able to hide the app
 * --------------------------------------------------------------------------
 * The booting state dimmed #main-app to 5% opacity. The loader is already a
 * fixed, near-opaque, full-viewport overlay at z-index 2600, so the dimming
 * hid nothing the loader was not already covering - it only created a way for
 * the workspace to end up invisible: a failed boot never cleared the class, a
 * stalled transition never finished the fade back, and either way the user got
 * a ghost with no message. The app stays at full opacity underneath and the
 * loader does the covering.
 * ======================================================================== */
body.app-body[data-app-page="app"].app-booting #main-app {
  opacity: 1;
}

/* The loader is the first thing anyone sees, and it was the last blue surface
   in the product: pale blue, violet and green washes under a warm app. */
body.app-body[data-app-page="app"] #app-loader {
  background:
    radial-gradient(circle at 12% 14%, rgba(11, 31, 77, 0.16), transparent 38%),
    radial-gradient(circle at 86% 8%, rgba(220, 168, 28, 0.13), transparent 34%),
    radial-gradient(circle at 50% 92%, rgba(192, 190, 181, 0.5), transparent 37%),
    rgba(251, 250, 247, 0.98);
}
body.app-body[data-app-page="app"] #doc-preview-title {
  font-size: 1.06rem;
  font-weight: 650;
  letter-spacing: -0.015em;
  line-height: 1.25;
  color: #0B1433;
  overflow-wrap: anywhere;
}

body.app-body[data-app-page="app"] #doc-preview-meta {
  font-size: 0.8rem;
  color: var(--fc-ink-muted, #959FB2);
  padding-top: 0.2rem;
}
/* The library name was a blue link in a warm product. */
body.app-body[data-app-page="app"] #doc-preview-meta a,
body.app-body[data-app-page="app"] #doc-preview-meta .text-primary {
  color: var(--fc-ink-soft, #3B4860) !important;
  text-decoration: none;
}
body.app-body[data-app-page="app"] #doc-preview-meta a:hover {
  color: var(--fc-accent, #0B1F4D) !important;
  text-decoration: underline;
}

body.app-body[data-app-page="app"] #doc-preview-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  padding-top: 0.45rem;
}

/* A segmented control: one track, two segments, sized to its content. */
body.app-body[data-app-page="app"] #doc-preview-modes {
  display: inline-flex;
  /* In a flex column the default align-self: stretch beats width: auto, which
     is why this stayed a full-width bar. */
  align-self: flex-start;
  width: auto;
  flex: 0 0 auto;
  gap: 2px;
  padding: 3px;
  border-radius: 10px;
  border: 1px solid var(--fc-line, #DEDCD6);
  background: #F7F6F2;
}
body.app-body[data-app-page="app"] #doc-preview-modes .btn {
  flex: 0 0 auto;
  min-width: 84px;
  height: 28px;
  padding: 0 0.85rem;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--fc-ink-soft, #3B4860);
  font-size: 0.82rem;
  font-weight: 600;
  box-shadow: none;
  transition: background-color 140ms ease-out, color 140ms ease-out;
}
body.app-body[data-app-page="app"] #doc-preview-modes .btn:hover {
  color: #0B1433;
}
body.app-body[data-app-page="app"] #doc-preview-modes .btn.active,
body.app-body[data-app-page="app"] #doc-preview-modes .btn[aria-pressed="true"] {
  background: #FFFFFF;
  color: #0B1433;
  box-shadow: 0 1px 2px rgba(11, 20, 51, 0.12);
}
body.app-body[data-app-page="app"] #doc-preview-modes .btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(11, 31, 77, 0.24);
}

/* Open is the action; closing is not an equal partner to it. */
body.app-body[data-app-page="app"] #close-preview {
  border: 0;
  background: transparent;
  color: var(--fc-ink-muted, #959FB2);
  width: 30px;
  padding: 0;
}
body.app-body[data-app-page="app"] #close-preview:hover {
  background: #EEEDE8;
  color: #0B1433;
}

.cat-manager[hidden] { display: none; }
.cat-manager {
  position: fixed;
  inset: 0;
  z-index: 3200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2rem 1.5rem;
}
.cat-manager__scrim {
  position: absolute;
  inset: 0;
  background: rgba(11, 20, 51, 0.44);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
}
.cat-manager__panel {
  position: relative;
  display: flex;
  flex-direction: column;
  width: min(760px, 100%);
  max-height: min(80vh, 720px);
  border-radius: 18px;
  background: #FFFFFF;
  box-shadow: 0 30px 70px rgba(11, 20, 51, 0.34);
  overflow: hidden;
  animation: cat-manager-in 200ms ease-out;
}
@keyframes cat-manager-in {
  from { transform: translateY(8px) scale(0.995); }
  to   { transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .cat-manager__panel { animation: none; }
}

.cat-manager__header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.3rem 1.5rem 1rem;
}
/* The action and the close button travel together, so the header keeps its
   two blocks: what this is on the left, what you can do on the right. */
.cat-manager__header-text {
  min-width: 0;
}
.cat-manager__header-actions {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 0.6rem;
}
/* On a phone the two blocks do not fit side by side: "Nouvelle catégorie"
   squeezed the title to one word per line and pushed itself off screen. The
   text takes the row, the actions take the next one. */
@media (max-width: 640px) {
  .cat-manager__header {
    flex-wrap: wrap;
    row-gap: 0.75rem;
  }
  .cat-manager__header-text {
    flex: 1 1 100%;
    order: 2;
  }
  .cat-manager__header-actions {
    order: 1;
    width: 100%;
    justify-content: space-between;
  }
}
.cat-manager__title {
  margin: 0 0 0.25rem;
  font-size: 1.2rem;
  font-weight: 650;
  letter-spacing: -0.018em;
  color: #0B1433;
}
.cat-manager__subtitle {
  margin: 0;
  font-size: 0.86rem;
  line-height: 1.5;
  color: var(--fc-ink-muted, #959FB2);
  max-width: 52ch;
}
.cat-manager__close {
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 9px;
  background: transparent;
  color: var(--fc-ink-muted, #959FB2);
}
.cat-manager__close:hover { background: #EEEDE8; color: #0B1433; }

.cat-manager__body {
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
  padding: 0.25rem 1.5rem 1rem;
}
.cat-manager__loading {
  margin: 0;
  padding: 1.5rem 0;
  color: var(--fc-ink-muted, #959FB2);
  font-size: 0.88rem;
}

.cat-manager__footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.9rem 1.5rem 1.2rem;
  border-top: 1px solid rgba(192, 190, 181, 0.7);
}
.cat-manager__hint {
  font-size: 0.8rem;
  color: var(--fc-ink-muted, #959FB2);
}

/* Rows here have room, so the controls are simply present. */
.cat-manager__tree li.category-node {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  min-height: 36px;
}
.cat-manager__tree li.category-node > .label-text {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.4rem 0.5rem;
  border-radius: 9px;
  font-size: 0.92rem;
  color: #0B1433;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  cursor: grab;
}
.cat-manager__tree li.category-node > .label-text:hover { background: #F7F6F2; }
.cat-manager__tree li.category-node > .node-actions {
  position: static;
  transform: none;
  flex: 0 0 auto;
  display: inline-flex;
  flex-wrap: nowrap;
  gap: 0.15rem;
  opacity: 0;
  visibility: hidden;
  background: transparent;
  box-shadow: none;
  transition: opacity 120ms ease-out;
}
.cat-manager__tree li.category-node:hover > .node-actions,
.cat-manager__tree li.category-node:focus-within > .node-actions {
  opacity: 1;
  visibility: visible;
}
.cat-manager__tree li.category-node > ul.children {
  flex: 0 0 100%;
  width: 100%;
  margin-left: 1rem;
  padding-left: 0.75rem;
  border-left: 1px solid rgba(192, 190, 181, 0.9);
  list-style: none;
}
.cat-manager__tree .node-action {
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: #596378;
  font-size: 0.8rem;
}
.cat-manager__tree .node-action:hover { background: #EEEDE8; color: #0B1433; }
.cat-manager__tree .node-action.delete-cat:hover { background: #FFE2DD; color: #C32324; }
.cat-manager__tree .node-action:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(11, 31, 77, 0.24);
}

/* Dragging: the row lifts, and the destination is unmistakable. */
.cat-manager__tree li.category-node.dragging > .label-text { opacity: 0.4; cursor: grabbing; }
.cat-manager__tree li.category-node.drop-target > .label-text {
  background: rgba(11, 31, 77, 0.14);
  box-shadow: inset 0 0 0 1px rgba(11, 31, 77, 0.6);
}

body.cat-manager-open { overflow: hidden; }

/* The library being organised is stated, and chosen deliberately. */
.cat-manager__libs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  padding: 0 1.5rem 0.9rem;
}
.cat-manager__libs[hidden] { display: none; }
.cat-manager__lib {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.4rem 0.75rem;
  border-radius: 999px;
  border: 1px solid var(--fc-line, #DEDCD6);
  background: #FFFFFF;
  color: var(--fc-ink-soft, #3B4860);
  font-size: 0.85rem;
  font-weight: 600;
  transition: background-color 140ms ease-out, color 140ms ease-out,
    border-color 140ms ease-out, transform 100ms ease-out;
}
.cat-manager__lib i { color: var(--fc-ink-muted, #959FB2); font-size: 0.8rem; }
.cat-manager__lib:hover { border-color: var(--fc-accent, #0B1F4D); color: #0B1433; }
.cat-manager__lib:active { transform: scale(0.98); }
.cat-manager__lib:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(11, 31, 77, 0.24);
}
.cat-manager__lib.is-active {
  background: rgba(11, 31, 77, 0.12);
  border-color: rgba(11, 31, 77, 0.5);
  color: #0B1433;
}
.cat-manager__lib.is-active i { color: var(--fc-accent, #0B1F4D); }
.cat-manager__lib-note {
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--fc-ink-muted, #959FB2);
}


/* ==========================================================================
 * The filters are reachable at every width
 * --------------------------------------------------------------------------
 * Below 992px the search surface's left column becomes a drawer: fixed,
 * translated off the left edge, waiting for `.show`. Nothing on this page ever
 * defined what `.show` meant - those rules lived in style.css, which the app
 * has never loaded - so the drawer could not open, and its only button was
 * written inside the results container and destroyed by the first search. The
 * categories, the libraries and the date filters were simply gone on any
 * window under 992px, with nothing saying so.
 *
 * The button is part of the pane now (index.html), and here is what opening
 * means.
 * ======================================================================== */
body.app-body[data-app-page="app"] .search-filters-toggle {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  margin: 0.75rem 0.75rem 0;
}

