/* =====================================================================
   Plêiade · Biblioteca (CWA) overlay CSS — night-sky editorial
   Path:    infra/library/customizations/pleiade-overlay.css
   Servido: /_pleiade/overlay.css via snippet (library_overlay) do Caddy
            (a CRIAR pelo bonum — espelho de nextcloud_overlay/vikunja_overlay;
            ver "SPEC PARA O BONUM" no fim deste arquivo e no relatório).
   Autor:   gucci-frontend · Wave 4 (item G12-ESTETICA) · 2026-06-03
   Origem:  cloud@Alfred · CachyOS
   ---------------------------------------------------------------------
   ALVO: Calibre-Web-Automated (CWA) em biblioteca.{$PLEIADE_DOMAIN}.
   Stack real (inspecionada ao vivo via Playwright 2026-06-03):
     - Flask/Jinja + Bootstrap 3 + tema caliBlur (Dark) ATIVO e travado
       ("Theme switching is temporarily disabled… v5.0.0"). Não há light
       mode no app hoje → desenho assume base ESCURA (alinha ao night-sky).
     - body.login.blur no login; body.blur no interior.
     - Folhas servidas (em ordem): bootstrap.min.css, style.css, upload.css,
       caliBlur.css, caliBlur_override.css, cwa.css. NOSSO overlay é injetado
       por ÚLTIMO (replace_response antes de </head> via Caddy) → vence em
       igualdade de especificidade; caliBlur usa seletores pesados → usamos
       seletores específicos + !important pontual (mesmo contrato dos outros
       overlays Plêiade).

   POR QUE NIGHT-SKY (e não repaint total agressivo):
     Coerência com a FAMÍLIA visual Wave 4 já aceita em prod (login Authentik
     night-sky, portico Nextcloud, login Vikunja): identidade FORTE na "porta
     de entrada" (login) — verde-garrafa + aglomerado estelar dourado +
     filete de ouro + Cinzel — e INTERIOR calmo/legível. Aqui o interior é a
     "sala de leitura": mantemos a base escura do caliBlur (familiaridade +
     conforto de leitura noturna), apenas TRANSPONDO a cromática do tema
     genérico (slate-cinza + LARANJA berrante) para a paleta Plêiade
     (verde-garrafa + dourado). Tom da BIBLIOTECA = quietude, luz de estrela
     dourada sobre verde-garrafa.

   GANHO DE ACESSIBILIDADE (medido na baseline ao vivo):
     - Botão Login caliBlur = laranja #cc7b19, texto branco → 3.27:1 (FALHA
       WCAG AA p/ texto ~14px). Substituído por CTA forest+ouro AA-safe.
     - Labels amber #f9be03 (fora da paleta) → ouro Plêiade #e4c69d.

   FONTES: self-hosted same-origin via /assets/fonts/* (biblioteca.<dom> já
   importa o snippet pleiade_fonts no Caddy → Cinzel/Lora/Spectral disponíveis
   SEM round-trip a Google Fonts). Cinzel só em brand/headings; Lora em
   captions editoriais. Corpo segue a fonte nativa do CWA (legibilidade de
   listas/tabelas). Zero @import de CDN (privacidade — invariante do projeto).

   ANTI-PATTERNS evitados (gucci-frontend memory):
     - SEM html:has(body) em bloco de tema (pattern_prefers_color_scheme...).
     - SEM animation:...forwards em wrappers de conteúdo (escondeu conteúdo
       em Vikunja — pattern_vikunja_overlay_dark_leak_animation §2).
     - replace_response NÃO pode mutilar o próprio /_pleiade/overlay.css:
       o snippet Caddy DEVE excluir /_pleiade/* do matcher injetável
       (gotcha catalogado pelo bonum: `@injectable not path /_pleiade/*`).
   ===================================================================== */

/* ---------------------------------------------------------------------
   0. FONTES self-hosted (same-origin biblioteca.<dom>/assets/fonts/*)
   ------------------------------------------------------------------ */
@font-face {
  font-family: "Cinzel";
  src: url("/assets/fonts/cinzel-regular-latin.woff2") format("woff2");
  font-weight: 400 600; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Lora";
  src: url("/assets/fonts/lora-regular-latin.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Lora";
  src: url("/assets/fonts/lora-400-italic-latin.woff2") format("woff2");
  font-weight: 400; font-style: italic; font-display: swap;
}

/* ---------------------------------------------------------------------
   1. TOKENS Plêiade — paleta canônica (subset p/ overlay escuro)
   ------------------------------------------------------------------ */
:root {
  --pl-green-primary: #003721;   /* verde-garrafa — base/login bg */
  --pl-green-deep:    #002416;    /* mais escuro — fundo do céu */
  --pl-green-forest:  #00472b;    /* card login / superfícies elevadas */
  --pl-green-surface: #073b25;    /* superfície interior (livro/well) */
  --pl-green-muted:   #145a32;    /* CTA base */
  --pl-green-accent:  #14793f;    /* CTA hover */

  --pl-cream:         #e8f3f5;    /* texto principal sobre verde */
  --pl-cream-soft:    #c9dcd4;    /* texto secundário sobre verde (≈7:1) */
  --pl-gold:          #e4c69d;    /* accent ornamental / labels / links */
  --pl-gold-strong:   #efd6b3;    /* gold hover (mais claro) */
  --pl-gold-dim:      rgba(228, 198, 157, 0.35);
  --pl-gold-faint:    rgba(228, 198, 157, 0.14);
  --pl-gold-hair:     rgba(228, 198, 157, 0.22);  /* filetes/bordas funcionais (≥3:1 não-texto) */

  --pl-line:          rgba(228, 198, 157, 0.16);
  --pl-line-strong:   rgba(228, 198, 157, 0.30);

  --pl-error:   #ff8a80;   /* vermelho legível sobre escuro */
  --pl-success: #8fe0ad;   /* verde legível sobre escuro */

  --pl-ease: cubic-bezier(0.0, 0.0, 0.2, 1);
}

/* ---------------------------------------------------------------------
   2. SHELL ESCURO — transpõe o slate-cinza do caliBlur p/ verde-garrafa.
   Mantém a metáfora de leitura noturna; só troca a cromática.
   ------------------------------------------------------------------ */
html, body,
body.blur,
body.login.blur {
  background-color: var(--pl-green-deep) !important;
  color: var(--pl-cream) !important;
}

/* Fundo do app: gradiente verde-garrafa + halos dourado/verde discretos.
   (Substitui blur-noise.webp slate do caliBlur — mantemos a sensação de
   profundidade, mas na cor Plêiade.) */
body.blur,
body.login.blur {
  background-image:
    radial-gradient(circle at 80% 12%, rgba(228,198,157,0.08) 0%, transparent 52%),
    radial-gradient(circle at 16% 88%, rgba(99,156,127,0.10) 0%, transparent 58%),
    linear-gradient(165deg, #00472b 0%, #003721 52%, #002416 100%) !important;
  background-attachment: fixed !important;
}

/* Superfícies elevadas genéricas do caliBlur (cards, painéis, dropdowns) */
.well, .panel, .modal-content, .dropdown-menu,
.book, .container > .row .col-sm-3, .discover, .book-meta {
  background-color: rgba(7, 59, 37, 0.55) !important;
  border-color: var(--pl-line) !important;
  color: var(--pl-cream) !important;
}

/* ---------------------------------------------------------------------
   3. NAVBAR / TOPO — verde-garrafa translúcido + filete dourado inferior.
   ------------------------------------------------------------------ */
.navbar.navbar-default,
.navbar-default,
#main-nav, #sidebar {
  background-color: rgba(0, 36, 22, 0.82) !important;
  background-image: none !important;
  border: 0 !important;
  border-bottom: 1px solid var(--pl-gold-hair) !important;
  box-shadow: 0 1px 0 rgba(0,0,0,0.25) !important;
}
/* Wordmark/brand — Cinzel editorial em ouro.
   GOTCHA (descoberto ao vivo 2026-06-03 via Playwright): caliBlur.css pinta o
   brand do login por um seletor de CAMINHO COMPLETO de altíssima especificidade,
   NÃO pela classe .navbar-brand:
     body.login > div.navbar.navbar-default.navbar-static-top > div
       > div.navbar-header > a   { color:#ccc !important }   (esp. 0,5,3)
   e no interior:
     body > div.navbar... > div > div.navbar-header > a { color: var(--color-primary) }
   Um `.navbar-brand { color … !important }` (0,1,0) PERDE. É preciso igualar/superar
   o caminho. Os 2 seletores abaixo têm esp. 0,6,3 (login, +.blur) e cobrem login +
   interior + o id #main-nav (algumas builds CWA). */
.navbar-brand {
  font-family: "Cinzel", "Trajan Pro", Georgia, serif !important;
  letter-spacing: 0.06em !important;
  font-weight: 600 !important;
  text-transform: uppercase;
  font-size: 1.02rem !important;
}
body.login.blur > div.navbar.navbar-default.navbar-static-top > div > div.navbar-header > a,
body.blur > div.navbar.navbar-default.navbar-static-top > div > div.navbar-header > a,
#main-nav .navbar-header > a.navbar-brand,
.navbar-brand {
  color: var(--pl-gold) !important;
}
body.login.blur > div.navbar.navbar-default.navbar-static-top > div > div.navbar-header > a:hover,
body.blur > div.navbar.navbar-default.navbar-static-top > div > div.navbar-header > a:hover,
.navbar-brand:hover, .navbar-brand:focus { color: var(--pl-gold-strong) !important; }

/* Itens de navegação / ícones do caliBlur */
.navbar-default .navbar-nav > li > a,
.navbar-nav > li > a,
#nav_new, #top_user, #top_tasks, #top_admin,
.profileDrop, .navbar-default .navbar-nav > li > a > span {
  color: var(--pl-cream-soft) !important;
}
.navbar-default .navbar-nav > li > a:hover,
.navbar-default .navbar-nav > li > a:focus,
.navbar-nav > li.active > a,
.navbar-nav > li > a:hover {
  color: var(--pl-gold) !important;
  background-color: var(--pl-gold-faint) !important;
}
/* hamburger bars em mobile (eram claras sobre slate) */
.navbar-toggle .icon-bar { background-color: var(--pl-gold) !important; }
.navbar-toggle { border-color: var(--pl-gold-hair) !important; }

/* ---------------------------------------------------------------------
   4. LOGIN — A PORTA DE ENTRADA: identidade Plêiade FORTE (night-sky).
   DOM real (Playwright 2026-06-03):
     body.login.blur > .container-fluid > .row-fluid > .col-sm-10
       > .well.col-sm-6 > form  (+ navbar-brand acima)
   ------------------------------------------------------------------ */

/* Aglomerado estelar dourado discreto atrás do card (estático — login é
   raro e leve; profundidade sem custo de animação). Espelha o portico NC. */
body.login.blur::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    radial-gradient(circle at 18% 22%, rgba(228,198,157,0.55) 1.2px, transparent 1.8px),
    radial-gradient(circle at 82% 28%, rgba(228,198,157,0.50) 1.3px, transparent 1.9px),
    radial-gradient(circle at 28% 76%, rgba(228,198,157,0.40) 1.0px, transparent 1.6px),
    radial-gradient(circle at 88% 70%, rgba(228,198,157,0.45) 1.1px, transparent 1.7px),
    radial-gradient(circle at 54% 14%, rgba(228,198,157,0.35) 0.9px, transparent 1.5px);
  background-size: 360px 360px, 420px 420px, 300px 300px, 400px 400px, 340px 340px;
  opacity: 0.7;
}
body.login.blur .container-fluid { position: relative; z-index: 1; }

/* Card de login = .well : forest com filete dourado, centrado */
body.login.blur .well {
  background-color: var(--pl-green-forest) !important;
  background-image: none !important;
  color: var(--pl-cream) !important;
  border: 1px solid var(--pl-gold-dim) !important;
  border-radius: 6px !important;
  box-shadow:
    0 18px 52px rgba(0,18,9,0.50),
    0 2px 8px rgba(0,18,9,0.30),
    inset 0 1px 0 rgba(228,198,157,0.08) !important;
  padding: 34px 30px 36px !important;
  position: relative;
  z-index: 2;
  animation: pl-card-enter 620ms var(--pl-ease) both;
}
@keyframes pl-card-enter {
  0%   { opacity: 0; transform: translateY(14px); }
  100% { opacity: 1; transform: translateY(0); }
}

/* Heading do login (CWA mostra "Calibre-Web Automated" como navbar-brand
   acima do card; reforçamos hierarquia editorial em qualquer h1/h2/legend) */
body.login.blur h1,
body.login.blur h2,
body.login.blur legend,
body.login.blur .well > legend {
  font-family: "Cinzel", "Trajan Pro", Georgia, serif !important;
  color: var(--pl-cream) !important;
  letter-spacing: 0.05em !important;
  text-transform: uppercase !important;
  font-weight: 600 !important;
  text-align: center;
}

/* Labels do login (eram amber #f9be03) → ouro Plêiade */
body.login.blur label,
body.login.blur .control-label,
body.blur label {
  color: var(--pl-gold) !important;
  font-weight: 600 !important;
  letter-spacing: 0.02em;
}

/* Inputs do login: pergaminho translúcido (metáfora página) sobre o card.
   NOTA WCAG 1.4.11: a borda do input não é o limite VISUAL real (o pergaminho
   quase-branco vs card forest já dá >12:1); ainda assim usamos um ouro mais
   sólido (rgba 0.65 ≈ 3.4:1 sobre forest) para a borda funcional passar ≥3:1
   por si só, sem depender só do contraste de superfície. */
body.login.blur input.form-control,
body.login.blur input[type="text"],
body.login.blur input[type="password"],
body.login.blur input[type="email"] {
  background-color: rgba(255,253,247,0.97) !important;
  color: var(--pl-green-primary) !important;
  border: 1px solid rgba(228,198,157,0.65) !important;
  border-radius: 5px !important;
  box-shadow: none !important;
}
body.login.blur input.form-control::placeholder { color: rgba(0,55,33,0.45) !important; font-style: italic; }
body.login.blur input.form-control:focus {
  border-color: rgba(228,198,157,0.85) !important;
  outline: none !important;
  box-shadow: 0 0 0 3px rgba(228,198,157,0.22) !important;
}

/* checkboxes (Show Password / Lembre-se de mim) legíveis */
body.login.blur .checkbox label,
body.login.blur .checkbox { color: var(--pl-cream-soft) !important; }
body.login.blur input[type="checkbox"] { accent-color: var(--pl-gold); }

/* ---------------------------------------------------------------------
   5. BOTÕES — CTA forest+ouro (substitui o LARANJA caliBlur).
   Login = primário forest; SSO Plêiade = filete dourado (destaque suave).
   ------------------------------------------------------------------ */
.btn.btn-default,
button.btn-default,
input[type="submit"].btn,
#submit, .btn-primary {
  background-color: var(--pl-green-muted) !important;
  background-image: none !important;
  border: 1px solid var(--pl-gold-dim) !important;
  color: var(--pl-cream) !important;
  font-weight: 600 !important;
  letter-spacing: 0.05em !important;
  border-radius: 5px !important;
  min-height: 44px;
  text-shadow: none !important;
  transition: background-color 160ms var(--pl-ease),
              border-color 160ms var(--pl-ease),
              transform 140ms var(--pl-ease) !important;
}
.btn.btn-default:hover, button.btn-default:hover,
#submit:hover, .btn-primary:hover {
  background-color: var(--pl-green-accent) !important;
  border-color: var(--pl-gold) !important;
  color: var(--pl-cream) !important;
  transform: translateY(-1px);
}
.btn.btn-default:focus-visible, button.btn-default:focus-visible, #submit:focus-visible {
  outline: 2px solid var(--pl-gold) !important;
  outline-offset: 2px !important;
}
.btn.btn-default:active, #submit:active { transform: translateY(0); background-color: var(--pl-green-primary) !important; }

/* Botão SSO Plêiade (a.generic / .pull-right.generic) — destaque dourado:
   é o caminho preferencial (login corporativo) → filete de ouro + texto ouro */
a.generic, a.generic.pull-right, .pull-right.generic,
a[href*="/link/generic"] {
  background-color: rgba(228,198,157,0.10) !important;
  border: 1px solid var(--pl-gold) !important;
  color: var(--pl-gold-strong) !important;
  font-weight: 600 !important;
  letter-spacing: 0.05em !important;
  border-radius: 5px !important;
  min-height: 44px;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background-color 160ms var(--pl-ease), color 160ms var(--pl-ease) !important;
}
a.generic:hover, .pull-right.generic:hover, a[href*="/link/generic"]:hover {
  background-color: rgba(228,198,157,0.20) !important;
  color: var(--pl-gold-strong) !important;
}
a.generic:focus-visible, a[href*="/link/generic"]:focus-visible {
  outline: 2px solid var(--pl-gold) !important;
  outline-offset: 2px !important;
}

/* ---------------------------------------------------------------------
   6. LINKS — ouro AA sobre escuro (e2 sobre forest ≥ 7:1)
   ------------------------------------------------------------------ */
a:not(.btn):not(.navbar-brand):not(.generic):not(.navbar-nav a) {
  color: var(--pl-gold) !important;
  text-decoration: none;
  transition: color 150ms var(--pl-ease);
}
a:not(.btn):not(.navbar-brand):not(.generic):hover {
  color: var(--pl-gold-strong) !important;
  text-decoration: underline;
  text-underline-offset: 3px;
}
a:focus-visible { outline: 2px solid var(--pl-gold); outline-offset: 2px; border-radius: 2px; }

/* ---------------------------------------------------------------------
   7. AVISOS / ALERTAS caliBlur — alinhar à paleta (info/cwa banners)
   ------------------------------------------------------------------ */
.alert.alert-info, .alert-cwa, .alert.alert-cwa {
  background-color: rgba(7, 59, 37, 0.70) !important;
  border: 1px solid var(--pl-gold-hair) !important;
  color: var(--pl-cream-soft) !important;
  border-radius: 6px !important;
}
.alert .close { color: var(--pl-gold) !important; opacity: 0.8; text-shadow: none !important; }
.alert.alert-danger { color: var(--pl-error) !important; border-color: rgba(255,138,128,0.45) !important; }
.alert.alert-success { color: var(--pl-success) !important; border-color: rgba(143,224,173,0.45) !important; }

/* ---------------------------------------------------------------------
   8. INTERIOR — sala de leitura: grade de livros + sidebar + tabelas.
   Mantém base escura legível; só recolore accents p/ Plêiade.
   (Calibre-Web caliBlur DOM padrão: #main-nav, .book, .cover, .discover,
    #books, .meta, #sidebar a, .list-group-item)
   ------------------------------------------------------------------ */
/* Capas de livro: borda fina dourada no hover (vitrine editorial) */
.book .cover, .book img, .cover img {
  border-radius: 6px !important;
  transition: transform 180ms var(--pl-ease), box-shadow 180ms var(--pl-ease) !important;
}
.book:hover .cover, .book:hover img, .cover:hover img {
  transform: translateY(-2px);
  box-shadow: 0 10px 26px rgba(0,16,8,0.5), 0 0 0 1px var(--pl-gold-hair) !important;
}
.book .meta .title, .book-title, h2.book-title, .media-body h2 {
  font-family: "Cinzel", "Trajan Pro", Georgia, serif !important;
  color: var(--pl-cream) !important;
  letter-spacing: 0.01em;
}
.book .meta .author, .author a, .author-name {
  font-family: "Lora", "Spectral", Georgia, serif !important;
  font-style: italic !important;
  color: var(--pl-cream-soft) !important;
}

/* Sidebar (#sidebar / .list-group) — item ativo com faixa dourada */
#sidebar .list-group-item, .list-group-item, #scnd-nav .nav > li > a {
  background-color: transparent !important;
  color: var(--pl-cream-soft) !important;
  border-color: var(--pl-line) !important;
}
#sidebar .list-group-item:hover, .list-group-item:hover,
#sidebar .list-group-item.active, .list-group-item.active,
#scnd-nav .nav > li.active > a {
  background-color: var(--pl-gold-faint) !important;
  color: var(--pl-gold) !important;
  border-left: 3px solid var(--pl-gold) !important;
}

/* Seções "Discover/Hot/New" headings — Cinzel */
.discover h2, .container-fluid h2.title, #books > h2, .col-sm-10 > h2,
h2.section, .section-title {
  font-family: "Cinzel", "Trajan Pro", Georgia, serif !important;
  color: var(--pl-cream) !important;
  letter-spacing: 0.04em !important;
  border-bottom: 1px solid var(--pl-gold-hair) !important;
  padding-bottom: 0.4rem !important;
}

/* Inputs do interior (busca, edição de metadados): forest-surface translúcido */
body.blur:not(.login) input.form-control,
body.blur:not(.login) textarea.form-control,
body.blur:not(.login) select.form-control,
.form-control {
  background-color: rgba(232,243,245,0.06) !important;
  color: var(--pl-cream) !important;
  border: 1px solid var(--pl-line) !important;
  border-radius: 5px !important;
}
body.blur:not(.login) input.form-control::placeholder,
.form-control::placeholder { color: rgba(201,220,212,0.55) !important; }
body.blur:not(.login) input.form-control:focus,
.form-control:focus {
  border-color: var(--pl-line-strong) !important;
  outline: none !important;
  box-shadow: 0 0 0 3px var(--pl-gold-faint) !important;
}

/* Tabelas (admin/listas) — zebra discreta verde, header dourado */
table.table > thead > tr > th, .table > thead > tr > th {
  color: var(--pl-gold) !important;
  border-bottom: 1px solid var(--pl-gold-hair) !important;
  font-family: "Lora", Georgia, serif !important;
}
table.table > tbody > tr > td, .table > tbody > tr > td {
  color: var(--pl-cream-soft) !important;
  border-color: var(--pl-line) !important;
}
table.table-striped > tbody > tr:nth-of-type(odd) { background-color: rgba(7,59,37,0.35) !important; }

/* ---------------------------------------------------------------------
   9. SELECTION + SCROLLBAR + SPINNER — toque dourado Plêiade
   ------------------------------------------------------------------ */
::selection { background: var(--pl-gold-dim) !important; color: var(--pl-green-primary) !important; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: rgba(0,0,0,0.18); }
::-webkit-scrollbar-thumb { background: rgba(228,198,157,0.28); border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: rgba(228,198,157,0.45); }
.spinner > div, .spinner-border, .loadcontent { border-top-color: var(--pl-gold) !important; color: var(--pl-gold) !important; }

/* ---------------------------------------------------------------------
   10. RESPONSIVE / COMPOSIÇÃO do card de login.
   caliBlur dá ao card .well a classe Bootstrap col-sm-6 col-sm-offset-2 →
   no desktop o card fica MUITO largo (~683px @1366) e empurrado pelo offset.
   A família Wave 4 (Vikunja/NC/Authentik) usa card ~440px centrado. Aqui
   transformamos o WRAPPER (.col-sm-10.content-expanded) em flex-center e
   capamos o .well a 440px, neutralizando float + offset Bootstrap.
   (Provado ao vivo @1366: centeredGap 0, width 440.)
   ------------------------------------------------------------------ */
@media (min-width: 768px) {
  body.login.blur .col-sm-10.content-expanded {
    display: flex !important;
    justify-content: center !important;
    align-items: flex-start !important;
  }
  body.login.blur .well.col-sm-6.col-sm-offset-2,
  body.login.blur .well {
    max-width: 440px !important;
    width: 440px !important;
    float: none !important;
    margin: 24px 0 0 !important;
    left: 0 !important;
  }
}

@media (max-width: 480px) {
  body.login.blur .well {
    width: calc(100vw - 28px) !important;
    max-width: calc(100vw - 28px) !important;
    margin: 14px auto !important;
    padding: 26px 20px 28px !important;
    float: none !important;
    left: 0 !important;
  }
  /* caliBlur usa col-sm-6 col-sm-offset-2 — neutraliza offset em mobile */
  body.login.blur .col-sm-offset-2 { margin-left: 0 !important; }
  .navbar-brand { font-size: 0.92rem !important; }
}

/* ---------------------------------------------------------------------
   11. REDUCED MOTION (acessibilidade — obrigatório)
   ------------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* =====================================================================
   SPEC PARA O BONUM — wiring no Caddyfile (NÃO aplicado aqui; escopo infra).
   ---------------------------------------------------------------------
   Espelhar o snippet (nextcloud_overlay) / (vikunja_overlay). Esboço:

   (library_overlay) {
     @injectable {
       header_regexp Content-Type text/html
       not path /_pleiade/*          # << GOTCHA: não mutilar o próprio CSS
     }
     replace_response @injectable {
       "</head>" "<link rel=\"stylesheet\" href=\"/_pleiade/overlay.css\"></head>"
     }
     handle /_pleiade/overlay.css {
       root * /srv/library-overlay        # bind-mount deste arquivo
       file_server
       header Content-Type text/css
       header Cache-Control "public, max-age=300"
     }
   }

   No vhost biblioteca.{$PLEIADE_DOMAIN} { ... }:
     import library_overlay     # ANTES do reverse_proxy library:8083
   E no compose.caddy.yaml, bind-mount:
     - ../library/customizations:/srv/library-overlay:ro

   GOTCHAS herdados (catálogo bonum):
     - `encode` + replace_response no MESMO bloco: replace_response não opera
       se o upstream comprime. O vhost já tem `encode gzip zstd`; o módulo
       custom (caddyserver/replace-response) precisa ver body text/html plain.
       Conferir o mesmo trade-off aplicado em tasks.<dom>/drive.<dom>
       (Caddyfile já documenta isso nesses blocos).
     - bind-mount file-level fica STALE após rsync (inode novo): usar
       `--inplace` no rsync OU `docker compose up -d --force-recreate caddy`.
     - CSP do vhost já permite style-src 'self' 'unsafe-inline' e font-src
       'self' → <link> same-origin + @font-face /assets/fonts/* OK, sem mexer.
   ===================================================================== */
