a:link, a:visited, a:hover, a:active{
  text-decoration: none !important;
}

.rounded, .select2-selection, .bootstrap-tagsinput, .bootstrap-tagsinput > .badge{
	border-radius:8px !important;
}

.rounded-start,  .select2-selection, .bootstrap-tagsinput, .bootstrap-tagsinput > .badge{
	border-top-left-radius: 8px !important;
    border-bottom-left-radius: 8px !important;
}

.rounded-end,  .select2-selection, .bootstrap-tagsinput, .bootstrap-tagsinput > .badge{
	border-top-right-radius: 8px !important;
    border-bottom-right-radius: 8px !important;
}

.rounded-top,  .select2-selection, .bootstrap-tagsinput, .bootstrap-tagsinput > .badge{
	border-top-left-radius: 8px !important;
    border-top-right-radius: 8px !important;
}

.rounded-bottom,  .select2-selection, .bootstrap-tagsinput, .bootstrap-tagsinput > .badge{
	border-bottom-left-radius: 8px !important;
    border-bottom-right-radius: 8px !important;
}

.backgroundImage{
	width: 100%;
	background-position: center;
	background-repeat: no-repeat;
	background-size: cover;
	position: relative;
	z-index: 1;
}

.form-check-input{
  width: 1.2em !important;
  height: 1.2em !important;
}

/* Bootstrap reserves a 1.5em gutter for the control and pulls the input into
   it, so the label sits 0.5em to its right. The CMS enlarges the control
   (1.2em here, 1.5em in fms.css), which fills that gutter and glues the label
   to the box. Widen the gutter so every checkbox and radio in the CMS keeps a
   visible gap, whatever size the control ends up being.
   Switches are excluded: they use their own wider 2.5em gutter. */
.form-check:not(.form-switch){
  padding-left: 2em;
}

.form-check:not(.form-switch) .form-check-input{
  margin-left: -2em;
}

/* Same idea for a control placed next to its text without a .form-check
   wrapper (tables, toolbars): never let them touch. */
.form-check-label{
  cursor: pointer;
}

.form-check-input:active,.form-check-input:focus,.btn{
  outline:0 !important;
  box-shadow: none !important;
}

.list-group-item {
  border:0px !important;
}


/* ---------------------------------------------------------------------------
   CMS toggle
   
   Bootstrap's .form-switch does not render as a switch in this panel: the CMS
   enlarges .form-check-input (1.2em here, 1.5em in fms.css), which overrides the
   background image Bootstrap uses to draw the knob and leaves a bare circle. The
   on/off state then cannot be read at a glance, which is the one thing a switch
   exists for.
   
   Use this instead of .form-switch anywhere in the panel:
   
     <label class="cms-toggle" for="my-flag">
       <input type="checkbox" id="my-flag">
       <span class="cms-toggle-track"></span>
       <span class="cms-toggle-text">Label</span>
       <span class="cms-toggle-state"></span>
     </label>
   
   It is a plain checkbox underneath, so JS reads and writes .checked as usual.
--------------------------------------------------------------------------- */
.cms-toggle {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    cursor: pointer;
    user-select: none;
    margin-bottom: 0;
}
.cms-toggle input {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}
.cms-toggle .cms-toggle-track {
    flex: 0 0 auto;
    width: 42px;
    height: 24px;
    border-radius: 999px;
    background: #ced4da;
    position: relative;
    transition: background 0.2s ease;
}
.cms-toggle .cms-toggle-track::after {
    content: "";
    position: absolute;
    top: 3px;
    left: 3px;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
    transition: left 0.2s ease;
}
.cms-toggle input:checked + .cms-toggle-track {
    background: #198754;
}
.cms-toggle input:checked + .cms-toggle-track::after {
    left: 21px;
}
.cms-toggle input:focus-visible + .cms-toggle-track {
    box-shadow: 0 0 0 3px rgba(25, 135, 84, 0.25);
}
/* A switch that cannot be moved has to look it, and the track alone does not
   say it: a grey track at half opacity is the same grey an OFF switch already
   has, so "apagado" and "no puedes encenderlo" rendered identically and the
   only difference was the sentence underneath. The whole label dims. */
.cms-toggle input:disabled + .cms-toggle-track {
    opacity: 0.5;
    cursor: not-allowed;
}
.cms-toggle input:disabled ~ .cms-toggle-text,
.cms-toggle input:disabled ~ .cms-toggle-state {
    opacity: 0.45;
}
.cms-toggle:has(input:disabled) {
    cursor: not-allowed;
}
.cms-toggle .cms-toggle-text {
    flex: 0 0 auto;
}
/* Reads the state in words, so it does not depend on colour alone. */
.cms-toggle .cms-toggle-state {
    flex: 0 0 auto;
    font-weight: 700;
    font-size: 0.75rem;
}
.cms-toggle .cms-toggle-state::before {
    content: "Desactivado";
    color: #adb5bd;
}
.cms-toggle input:checked ~ .cms-toggle-state::before {
    content: "Activado";
    color: #198754;
}

/* ---------------------------------------------------------------------------
   CMS choice — elegir UNA opción entre varias

   Reemplaza a los radios. El punto negro/blanco de un radio es diminuto, no
   dice qué pasa si lo eliges, y en una lista de dos opciones parecidas obliga
   a mirar de cerca cuál está marcada. Acá la opción elegida se lee de lejos:
   se pinta el borde, el fondo y una marca de verificación.

   Estructura (el <input type="radio"> sigue abajo, así que el JS lee y escribe
   igual que siempre, y el teclado sigue funcionando con las flechas):

     <div class="cms-choice-group">
       <label class="cms-choice">
         <input type="radio" name="visibilidad" value="private" checked>
         <span class="cms-choice-body">
           <span class="cms-choice-title">Privados</span>
           <span class="cms-choice-help">solo se descargan por el sistema</span>
         </span>
       </label>
       ...
     </div>

   Para un on/off usa .cms-toggle, no esto.
--------------------------------------------------------------------------- */
.cms-choice-group {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.cms-choice {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    margin: 0;
    padding: 12px 14px;
    border: 2px solid #dee2e6;
    border-radius: 10px;
    background: #fff;
    cursor: pointer;
    transition: border-color 0.15s ease, background 0.15s ease;
}
.cms-choice:hover {
    border-color: #adb5bd;
    background: #f8f9fa;
}
.cms-choice input {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}
/* La marca de verificación: vacía por defecto, verde al elegir. */
.cms-choice .cms-choice-body::before {
    content: "";
    float: left;
    width: 20px;
    height: 20px;
    margin: 2px 10px 0 0;
    border: 2px solid #ced4da;
    border-radius: 50%;
    background: #fff;
    transition: border-color 0.15s ease, background 0.15s ease;
}
.cms-choice input:checked ~ .cms-choice-body::before {
    border-color: #198754;
    background: #198754 url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3E%3Cpath d='M6.2 11.6 2.9 8.3l1.2-1.2 2.1 2.1 5.6-5.6 1.2 1.2z'/%3E%3C/svg%3E") center/14px no-repeat;
}
.cms-choice input:checked ~ .cms-choice-body {
    color: #0f5132;
}
.cms-choice:has(input:checked) {
    border-color: #198754;
    background: #f1f9f4;
}
.cms-choice:has(input:focus-visible) {
    box-shadow: 0 0 0 3px rgba(25, 135, 84, 0.25);
}
.cms-choice-body {
    flex: 1 1 auto;
    min-width: 0;
}
.cms-choice-title {
    display: block;
    font-weight: 600;
}
.cms-choice-help {
    display: block;
    color: #6c757d;
    font-size: 0.875rem;
    margin-top: 2px;
}
.cms-choice input:disabled ~ .cms-choice-body {
    opacity: 0.6;
}

/* ---------------------------------------------------------------------------
   CMS dialog and data shell  (regla #10)

   Every dialog in the panel — core and plugins — and every list that shows
   objects (documents, records, files) is built from these pieces. They exist
   because each screen used to draw itself with bare Bootstrap: titles of
   different weights, the explanation demoted to a footnote in the footer, and
   rows of loose text that never looked like something you could act on. No two
   screens started at the same left edge, which is what makes a whole module
   read as amateur.

   The pieces:
     .cms-modal          shell for .modal-content (header + body + footer bar)
     .cms-modal-icon     the dialog's mark, top-left of its header
     .cms-modal-sub      what the dialog is for, under its title
     .cms-section        a block of the body
     .cms-section-label  its label, with .cms-count for "how many"
     .cms-card           a row you can act on: icon, title, help, actions
     .cms-chip           a state or a value, said in one word
     .cms-icon-btn       a secondary action; never as loud as the primary one
     .cms-note           what is true right now (.is-active in use, .is-warning
                         when it is true AND something has to be done about it)
     .cms-empty          nothing here yet, and the way to make the first one

   Markup templates live in CLAUDE.md, rule #10.
--------------------------------------------------------------------------- */

/*=============================================
ONE ACCENT PER SURFACE
===============================================
These dialogs open from the panel, where every action is the CMS blue, and
from the builder, whose canvas chrome is purple. Painting their buttons purple
put two accents on the same screen. The dialogs take the panel's blue; the
purple stays inside the canvas, where it marks what is selected.
=============================================*/
.cms-modal {
    --cms-accent: #0d6efd;
    --cms-accent-soft: #e7f0ff;
}

/* The shell itself. This rule and the header below were lost when the pieces
   moved out of the builder's stylesheet, so every dialog had been falling back
   to Bootstrap's own corners and header spacing — which is why the icon tile
   sat glued to the title: the gap that separates them lives here. */
.cms-modal {
    border: 0;
    border-radius: 14px;
    box-shadow: 0 24px 60px -12px rgba(15, 23, 42, .35);
    overflow: hidden;
}

.cms-modal .modal-header {
    align-items: flex-start;
    gap: 14px;
    padding: 18px 20px 14px;
    border-bottom: 1px solid #eef2f7;
}

/* The icon stops being decoration in the title line and becomes the dialog's
   mark: one saturated element, top-left, where the eye lands first. */
.cms-modal-icon {
    flex: 0 0 auto;
    width: 34px;
    height: 34px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 9px;
    background: var(--cms-accent-soft);
    color: var(--cms-accent);
    font-size: 17px;
}

.cms-modal .modal-title {
    font-size: 17px;
    font-weight: 600;
    line-height: 1.3;
    color: #0f172a;
}

/* What the dialog is for, said once, under its name — instead of a footnote
   in the footer that reads as an afterthought. */
.cms-modal-sub {
    display: block;
    margin-top: 2px;
    font-size: 12.5px;
    line-height: 1.45;
    color: #64748b;
}

.cms-modal .modal-body { padding: 18px 20px; }

.cms-modal .modal-footer {
    padding: 12px 20px;
    gap: 8px;
    background: #f8fafc;
    border-top: 1px solid #eef2f7;
}

.cms-modal .modal-footer .btn-light {
    background: #fff;
    border: 1px solid #e2e8f0;
    color: #475569;
}
.cms-modal .modal-footer .btn-light:hover {
    background: #f1f5f9;
    border-color: #cbd5e1;
}

/* Section label: small, quiet and countable — a bold sentence looked like a
   row of the list it was introducing. */
.cms-section-label {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 10px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: #94a3b8;
}
.cms-section-label + .cms-section-label,
.cms-section + .cms-section { margin-top: 22px; }

.cms-count {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0;
    color: #64748b;
    background: #f1f5f9;
    border-radius: 999px;
    padding: 1px 7px;
}

/* A row you can act on: bordered, hoverable, with its own icon and one
   saturated action. */
.cms-card {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    text-align: left;
    padding: 12px 14px;
    border: 1px solid #e2e8f0;
    border-radius: 10px;
    background: #fff;
    transition: border-color .15s ease, box-shadow .15s ease, background-color .15s ease;
}
.cms-card + .cms-card { margin-top: 8px; }

button.cms-card { cursor: pointer; }
button.cms-card:hover,
.cms-card.is-clickable:hover {
    border-color: var(--cms-accent);
    background: #f8fbff;
    box-shadow: 0 4px 14px -6px rgba(13, 110, 253, .4);
}
button.cms-card:focus-visible {
    outline: 2px solid var(--cms-accent);
    outline-offset: 2px;
}

.cms-card-icon {
    flex: 0 0 auto;
    width: 36px;
    height: 36px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 9px;
    background: #f1f5f9;
    color: #475569;
    font-size: 16px;
}

.cms-card-body { flex: 1 1 auto; min-width: 0; }

.cms-card-title {
    display: flex;
    align-items: center;
    /* Los chips bajan a su propia línea antes que estrujar el nombre. Sin
       esto, "Portada" y "Sin tabla" se quedaban con todo el ancho de la
       tarjeta y el nombre de la página desaparecía del todo. */
    flex-wrap: wrap;
    gap: 8px;
    font-size: 14.5px;
    font-weight: 600;
    color: #0f172a;
}

/* The name, when it is longer than its card.
   A title is a flex row of "name + chips", so a long name pushed the chips
   aside and wrapped into a one-word-per-line column that made the card three
   times taller than the one beside it. Cut it with an ellipsis instead: the
   whole name still shows on hover and in the tooltip of its card. */
.cms-card-name {
    /* Su base es lo que mide el nombre: uno corto deja al chip en la misma
       línea, y uno que no cabe se queda con la línea entera y se recorta al
       final. Una base fija hacía lo contrario en los dos casos. */
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.cms-card-help {
    margin-top: 2px;
    font-size: 12.5px;
    line-height: 1.45;
    color: #64748b;
}

/* Same cut for the line under the name: a file path or a summary never earns a
   second line inside a row. */
.cms-card-help.is-single-line {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* An identifier is not an error.
   Bootstrap paints <code> pink, and in this panel red means one thing: a
   problem. A folio, a batch code, a placeholder like {N3} or a file path
   painted red reads as «these are the broken ones» (regla #8.5). Panel-wide,
   because the fix used to live inside .cms-card and the same identifier went
   on reading as an error in every help text, table and dialog around it. */
code {
    color: #334155;
    background: #eef2f6;
    padding: .1em .35em;
    border-radius: 4px;
}
/* A block of code is already set apart by its box; a second background inside
   it just draws a grey rectangle over the whole thing. */
pre code {
    color: inherit;
    background: transparent;
    padding: 0;
}
/* Inside a card the text is already small and tight: a chip per identifier
   turns one line into a row of boxes. */
.cms-card-help code,
.cms-card-title code {
    color: inherit;
    background: transparent;
    padding: 0;
}

.cms-card-actions {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 6px;
}

/* Chip: where a document shows, in words, without competing with its name. */
.cms-chip {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    /* Inside a title the name is the one that gives way, never the chip:
       "Sin tabla" broken into two lines reads as two different states. */
    flex: 0 0 auto;
    white-space: nowrap;
    font-size: 12px;
    color: #475569;
    background: #f1f5f9;
    border-radius: 999px;
    padding: 2px 9px;
}
.cms-chip .bi { font-size: 12px; color: #64748b; }
.cms-chip.is-draft { background: #fef3c7; color: #92400e; }
.cms-chip.is-draft .bi { color: #b45309; }

/* Ghost icon action: present, never louder than the row's primary button. */
.cms-icon-btn {
    width: 32px;
    height: 32px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid transparent;
    border-radius: 8px;
    background: transparent;
    color: #64748b;
    transition: background-color .15s ease, color .15s ease, border-color .15s ease;
}
.cms-icon-btn:hover { background: #f1f5f9; color: #0f172a; border-color: #e2e8f0; }
.cms-icon-btn.is-danger:hover { background: #fee2e2; color: #b91c1c; border-color: #fecaca; }

/* A state note: what is true right now, not an error and not a row. */
/* Block flow, not flex.
   As a flex container every inline child became its own column, so a note
   reading "deja el cupo <strong>en blanco</strong> para no ponerle tope"
   came out as four stacked fragments. The icon hangs inline instead, which
   is what it always looked like when the note carried no bold. */
.cms-note {
    display: block;
    margin-top: 10px;
    padding: 10px 12px;
    font-size: 12.5px;
    line-height: 1.5;
    color: #64748b;
    background: #f8fafc;
    border: 1px solid #eef2f7;
    border-radius: 8px;
}
.cms-note .bi { color: #94a3b8; margin-right: 6px; }
.cms-note b, .cms-note strong { color: #334155; font-weight: 600; }
.cms-note.is-active {
    background: #f0fdf4;
    border-color: #dcfce7;
    color: #3f6212;
}
.cms-note.is-active .bi { color: #65a30d; }
/*
 * True right now, and something has to be done about it: the site closed to
 * the public, a credential about to expire. `.is-active` is green and means
 * "this is in use", which over "your visitors cannot get in" reads backwards.
 */
.cms-note.is-warning {
    background: #fffbeb;
    border-color: #fde68a;
    color: #92400e;
}
.cms-note.is-warning b, .cms-note.is-warning strong { color: #78350f; }
.cms-note.is-warning .bi { color: #b45309; }

/* Nothing here yet — and the way to make the first one. */
.cms-empty {
    padding: 18px 16px;
    text-align: center;
    border: 1px dashed #cbd5e1;
    border-radius: 10px;
    background: #fbfcfe;
}
/* Direct child only: the same rule applied to the icon inside the empty
   state's own button and blew it up to a 26px block. */
.cms-empty > .bi {
    display: block;
    font-size: 24px;
    color: #b8c4d4;
    margin-bottom: 4px;
}
.cms-empty-text {
    font-size: 13px;
    color: #64748b;
    margin-bottom: 12px;
}

/* The picker's search: one control, full width, icon inside. */
.cms-modal-search .input-group-text {
    background: #fff;
    border-right: 0;
    color: #94a3b8;
}
.cms-modal-search .form-control {
    border-left: 0;
    padding-left: 0;
}
.cms-modal-search .form-control:focus {
    border-color: #e2e8f0;
    box-shadow: none;
}
.cms-modal-search .form-control:focus + .input-group-text,
.cms-modal-search:focus-within .input-group-text { border-color: #e2e8f0; }

/* A chip standing on the footer's grey needs its own ground to read as a
   chip and not as one more muted line. */
.cms-modal .modal-footer .cms-chip {
    background: #fff;
    border: 1px solid #e2e8f0;
}

/* A dialog whose title still carries its icon inline — not every header has
   been moved to the tile yet — still reads as one of ours instead of falling
   back to bare Bootstrap. */
.cms-modal .modal-title > .bi:first-child { color: var(--cms-accent); }
.cms-modal .modal-header > .modal-title { flex: 1 1 auto; }

/* Bootstrap's own close button sits on the header's top line, next to the
   title, not floating against a taller icon tile. */
.cms-modal .modal-header .btn-close { margin: 2px 0 0; }

/*=============================================
Select2: the panel's accent, not Bootstrap's blue

Select2 ships its own highlight colour. Left alone, a searchable field is the
one blue thing on a screen whose accent is set in Apariencia — and on this
panel colour carries meaning (rule #8.5), so a stray blue reads as another
kind of state. These follow --cms-accent, which the theme already drives.
=============================================*/
/* An upgraded dropdown looks like the plain one beside it.
   `.select2-selection` is pinned to 8px further up, from when Select2 appeared
   on one screen in the whole panel. Now that any long dropdown gains a search
   box, an 8px box sits next to a 4px `<select>` in the same form row and the
   form reads as two different forms. The form controls' radius wins: the search
   box is an upgrade to the control, not a different control. */
.select2-container--bootstrap4 .select2-selection {
    border-radius: var(--bs-border-radius, 0.25rem) !important;
}

/* Hovering is not choosing.
   Filling every row the cursor crosses with solid accent gives a passing hover
   the same weight as the option actually chosen — and on an installation whose
   accent is red, a solid red row in a dropdown reads as an error. The hover is
   a soft tint of the same themeable accent; the fill is kept for the decision. */
.select2-container--bootstrap4 .select2-results__option--highlighted[aria-selected] {
    background: #eef2f7;
    background: color-mix(in srgb, var(--cms-accent) 10%, #fff);
    color: #1e293b;
}

.select2-container--bootstrap4 .select2-results__option[aria-selected="true"] {
    background: var(--cms-accent);
    color: #fff;
}

.select2-container--bootstrap4.select2-container--focus .select2-selection,
.select2-container--bootstrap4.select2-container--open .select2-selection {
    border-color: var(--cms-accent);
    box-shadow: 0 0 0 .2rem color-mix(in srgb, var(--cms-accent) 22%, transparent);
}

.select2-container--bootstrap4 .select2-search--dropdown .select2-search__field:focus {
    border-color: var(--cms-accent);
    outline: none;
}

/*=============================================
LA BARRA DE ACCIONES DE UNA SECCIÓN

Ocho acciones en una fila que no envuelve terminan como en Páginas Web: cada
botón se estrecha hasta partir su propia etiqueta —«Datos del / sitio», «CSS y
JavaScript del / sitio»— y la fila queda con alturas distintas y palabras
cortadas a la mitad. Apretado, y encima ilegible.

Dos reglas lo resuelven: la etiqueta no se parte nunca, y lo que envuelve es la
BARRA, no la palabra. Los botones se agrupan por lo que hacen, así que cuando
la barra baja a dos líneas cada línea sigue siendo un grupo con sentido y no
una mitad arbitraria.

Separación en el ritmo de 8: 8 px entre botones del mismo grupo, 16 entre
grupos, que es lo que hace ver los grupos sin dibujar ninguna línea.
=============================================*/
.cms-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    /* Alineada a la izquierda POR DENTRO: cuando la barra baja a dos filas, las
       dos arrancan en la misma línea vertical que el título y que las tarjetas
       de abajo (regla #8.2). Alineadas a la derecha, la segunda fila quedaba
       flotando contra el borde con un hueco delante. Que la barra entera se vaya
       a la derecha cuando cabe al lado del título lo decide su contenedor. */
    justify-content: flex-start;
    gap: .5rem 1rem;
}

.cms-toolbar-group {
    display: flex;
    align-items: center;
    gap: .5rem;
}

/* Una etiqueta partida a la mitad no se lee: antes se estrecha la barra. */
.cms-toolbar .btn { white-space: nowrap; }

/*=============================================
THE "I AM WORKING" INDICATOR

Bootstrap draws it with three borders of a rounded square and the fourth one
transparent. At a large size that passes; at the 16 px a button carries it comes
out a thin arc with its ends cut on the diagonal and a quarter-turn gap — and
spinning, it reads as a comma going round rather than as something loading.

Replaced by the usual ring: the whole track faint, and a solid head turning on
top of it. It goes on `.spinner-border`, the class every busy button in the
panel already uses (cms/views/assets/js/ui/busy-buttons.js) and the plugins'
dialogs too, so no screen has to change anything.

The colour comes from `currentColor`: on a blue button the track is a faint
white, on a light one it is grey. A browser that does not know color-mix() drops
the whole declaration and keeps Bootstrap's arc, which is ugly but works.
=============================================*/
.spinner-border {
    border-style: solid;
    border-color: color-mix(in srgb, currentColor 22%, transparent);
    border-top-color: currentColor;
    /* Bootstrap leaves this one transparent; here the track must be whole. */
    border-right-color: color-mix(in srgb, currentColor 22%, transparent);
}

/* Inside a button the ring keeps the text company: no heavier than its stroke,
   no smaller than it takes to be seen among the letters. */
.btn .spinner-border-sm,
.cms-icon-btn .spinner-border-sm {
    width: 1.05em;
    height: 1.05em;
    border-width: .16em;
}

/*=============================================
LA COMUNIDAD EN QUE SE ESTÁ TRABAJANDO
===============================================
La barra que pinta views/modules/community-switcher.php, compartida por los
seis módulos de la suite de condominios. Va arriba de todo y antes que el
título de la sección: quien atiende tres edificios y mira el equivocado ve una
pantalla idéntica, y carga el egreso donde no era.
=============================================*/

/* One quiet line, not a banner. Which community this is has to be legible
   without costing a strip at the top of eight screens; changing it happens at
   the door (Mis comunidades), not here. */
.cms-community-bar {
    display: flex;
    align-items: baseline;
    gap: 8px;
    flex-wrap: wrap;
    margin-bottom: 12px;
    font-size: 14px;
    color: #1e3a8a;
}
.cms-community-bar .bi { color: #2563eb; }
.cms-community-bar strong { font-weight: 600; }
.cms-community-place { font-size: 13px; color: #5b7bb5; }
.cms-community-place::before { content: '\00b7'; margin-right: 6px; color: #9db6e0; }
.cms-community-change { font-size: 13px; color: #2563eb; text-decoration: none; }
.cms-community-change:hover { text-decoration: underline; }

/* The header of a suite screen: an icon plate, a title and one line saying what
   the screen is for.
   It lives here and not in one plugin's stylesheet because four screens use it
   — Sucursales, Consolidado, Producción and Ventas del día — and the first one
   that forgot to load that stylesheet lost its plate and looked like another
   product. */
.br-header-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border-radius: 12px;
    background: #dcfce7;
    color: #16a34a;
    font-size: 20px;
    flex: 0 0 auto;
}

/* Which branch this session is working on.
   Same job as the community bar above and deliberately the same shape, so an
   installation running both suites does not look like two products stapled
   together. The difference is the dropdown: switching branch happens many
   times an hour for whoever runs two shops, and sending them to another screen
   each time would charge a toll for working. */
.cms-branch-bar {
    display: flex;
    align-items: baseline;
    gap: 8px;
    flex-wrap: wrap;
    margin-bottom: 12px;
    font-size: 14px;
    color: #14532d;
}
.cms-branch-bar .bi { color: #16a34a; }
.cms-branch-bar strong { font-weight: 600; }
.cms-branch-code {
    font-size: 12px;
    letter-spacing: .04em;
    color: #4d7c5a;
    background: #dcfce7;
    border-radius: 4px;
    padding: 1px 6px;
}
/* Nobody chose one yet: it says so in words, not in a colour nobody reads. */
.cms-branch-none { color: #92400e; font-weight: 600; }
.cms-branch-switch .btn-link {
    font-size: 13px;
    color: #16a34a;
    text-decoration: none;
}
.cms-branch-switch .btn-link:hover { text-decoration: underline; }
.cms-branch-switch .dropdown-menu { font-size: 14px; }
.cms-branch-switch .dropdown-item.active { background: #dcfce7; color: #14532d; }
/* An open drawer pins its cashier here: amber because it is a state to notice,
   not an error — red would read as something broken. */
.cms-branch-pin {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 1px 8px;
    border-radius: 999px;
    background: #fef3c7;
    color: #92400e;
    font-size: 12px;
    font-weight: 600;
}
.cms-branch-pin .bi { color: #b45309; font-size: 11px; }
/* The note inside the dropdown is muted prose: its lock must not borrow the
   bar's green, which marks the active branch and nothing else. */
.cms-branch-switch .dropdown-item-text .bi { color: inherit; }

/* Who attends a community: the card lives in a half-width column, so the toggle
   must not squeeze the address into one letter per line. */
#cm-operators-card .cms-card { flex-wrap: wrap; }
#cm-operators-card .cms-card-body { min-width: 12rem; }
#cm-operators-card .cm-op-mail { overflow-wrap: anywhere; }
#cm-operators-card .cms-card-actions { flex: 0 0 auto; }

/* ---------------------------------------------------------------------------
   A SETTINGS DIALOG THAT SCALES  (.cms-settings)

   Four or more sections stacked in one column is a form somebody has to scroll
   end to end, and every setting added later makes it worse. Two panes instead:
   the groups on the left, ONE group at a time on the right. Growing is one more
   pill, not more scroll.

   Markup and when to use it: CLAUDE.md, rule #12.
--------------------------------------------------------------------------- */

.cms-settings {
    display: grid;
    grid-template-columns: 208px minmax(0, 1fr);
    gap: 24px;
    align-items: start;
}

.cms-settings-nav {
    position: sticky;
    top: 0;
    flex-direction: column;
    gap: 4px;
    border-right: 1px solid #e9ecef;
    padding-right: 16px;
}

.cms-settings-nav .nav-link {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    text-align: left;
    padding: 10px 12px;
    border-radius: 10px;
    color: #495057;
    font-weight: 500;
    /* 150–300 ms: the state change has to be felt, not waited for. */
    transition: background-color .15s ease, color .15s ease;
}

.cms-settings-nav .nav-link .bi { font-size: 16px; opacity: .75; }
.cms-settings-nav .nav-link:hover { background: #f1f3f5; color: #212529; }
.cms-settings-nav .nav-link.active { background: #eef2ff; color: #4338ca; }
.cms-settings-nav .nav-link.active .bi { opacity: 1; }

/* Inside a pane the first section no longer needs the top margin its stacked
   version used to separate it from the previous one. */
.cms-settings-pane .cms-section:first-child { margin-top: 0; }

/* A group that holds ONE section does not repeat its name: the pill already
   said it, and «NOMBRE» sitting under the «Nombre» pill is a word twice on a
   screen that has no room for words twice. A group of two or more keeps its
   labels — there they are what tells the two apart. */
.cms-settings-pane .tab-pane > .cms-section:first-child:last-child
    > .cms-section-label:first-child { display: none; }

/* Under md the rail becomes a scrollable strip: a 208 px column on a phone
   leaves the form itself with nothing. */
@media (max-width: 991.98px) {
    .cms-settings { grid-template-columns: minmax(0, 1fr); gap: 16px; }
    .cms-settings-nav {
        position: static;
        flex-direction: row;
        flex-wrap: nowrap;
        overflow-x: auto;
        border-right: 0;
        border-bottom: 1px solid #e9ecef;
        padding: 0 0 8px;
    }
    .cms-settings-nav .nav-link { width: auto; white-space: nowrap; }
}

/*=============================================
DATA TABLE INSIDE A CARD (.cms-table)
===============================================
Rule #10 keeps tables as tables when the columns are comparable — this is that
table, panel-wide. What it settles once: the header row used to weigh the same
as the data it labels; Bootstrap's cell padding (.5rem) never met the card
header's line (1rem, rule #8.2); and digits set in a proportional font wobble,
so amounts never stacked into readable columns. Use it on a .table that is the
only content of a .card-body.p-0.
=============================================*/
.cms-table { margin-bottom: 0; }
.cms-table thead th {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: #64748b;
    background: #f8fafc;
    border-bottom: 1px solid #e2e8f0;
    padding: 10px 12px;
    white-space: nowrap;
}
.cms-table tbody td {
    padding: 10px 12px;
    vertical-align: middle;
}
/* Flush inside a bare card body, the first and last columns start on the card
   header's own line. Inside a padded container the container already sets the
   line, so the edge padding stays at the cell's own. */
.card-body.p-0 .cms-table thead th:first-child,
.card-body.p-0 .cms-table tbody td:first-child { padding-left: 16px; }
.card-body.p-0 .cms-table thead th:last-child,
.card-body.p-0 .cms-table tbody td:last-child  { padding-right: 16px; }
.cms-table.table > :not(caption) > * > * { border-bottom-color: #eef2f7; }
.cms-table tbody tr:last-child td { border-bottom: 0; }
.cms-table tbody tr:hover { background: #f8fafc; }
/* Amounts read as columns of digits, not as ragged text. */
.cms-table .text-end { font-variant-numeric: tabular-nums; }

/*=============================================
THE PAGER OF A LONG LIST (.cms-pager)
===============================================
Drawn by cms/views/assets/js/ui/pager.js. It sits under its table, inside the
same card, and reads as the table's own footer rather than as a separate
control: a strip of its own colour under a flush table is one more edge to
explain.
=============================================*/
.cms-pager {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 8px;
    padding: 12px 16px;
    border-top: 1px solid #e2e8f0;
    background: #f8fafc;
}
.cms-pager-range {
    font-size: 13px;
    color: #64748b;
    font-variant-numeric: tabular-nums;
}
.cms-pager-actions { display: inline-flex; gap: 8px; }
/* Hung straight off the card it belongs to, it IS the card's last edge: with a
   ground of its own and square corners it would poke out past the rounded ones
   the card already has. */
.card > .cms-pager:last-child,
.card > *:last-child > .cms-pager:last-child {
    border-bottom-left-radius: inherit;
    border-bottom-right-radius: inherit;
}
/* A closed way is shown, not hidden: a button that appears and disappears
   moves the one beside it under the cursor that was about to click it. */
.cms-pager-actions .btn:disabled { opacity: .45; }

/*=============================================
THE SELECTION BAR OF A LIST (.cms-bulkbar)
===============================================
Sits between a card's header and its table, and only while something is
selected: it says how much was picked and offers the actions that act on the
whole selection.

It is tinted, not white, on purpose. A selection is a temporary state of the
screen, and a bar that looks like one more toolbar leaves the user unsure
whether "Eliminar" removes the checked rows or all of them. The count is
spelled out for the same reason — "2 paquetes · 48,30 MB" is checkable before
pressing a button that does not ask twice.
=============================================*/
.cms-bulkbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 8px;
    padding: 12px 16px;
    background: #eff6ff;
    border-bottom: 1px solid #dbeafe;
}
.cms-bulkbar-count {
    font-size: 13px;
    color: #1e40af;
    font-variant-numeric: tabular-nums;
}
.cms-bulkbar-actions {
    display: inline-flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
}
/* The label of an action never breaks in two: the bar wraps instead. */
.cms-bulkbar-actions .btn { white-space: nowrap; }
