/* Editor · cinta de comandos, barra de aplicación, menús y bocadillo del informe.
   Troceado de `compact_workspace.css` (lote C3). Carga en `head_extra` de
   editor/editor.html, ANTES del núcleo: ante una regla del núcleo con la misma
   especificidad, pierde. El orden entre módulos lo fija tests/css_manifest.py. */
/* ---- cinta de comandos: pestañas + una fila por pestaña ----
   Sustituye a la barra de menús y a la barra de formato. Es cromo, no panel:
   superficie propia (tinte azulado sutil, distinto del blanco de los
   paneles) y sombra que la despega del contenido. Server-rendered: los
   listeners se cablean una vez (bindActions) y editor/ribbon.js solo alterna
   atributos — nada aquí depende de re-render. */
.editor-ribbon { position:relative; z-index:30; flex:0 0 auto; background:linear-gradient(180deg, #fdfeff 0%, #f2f7fc 100%); border-bottom:1px solid #cddbe8; box-shadow:0 3px 10px rgba(16,42,67,.08); }
.ribbon-tabs { display:flex; align-items:center; height:32px; padding:0 8px 0 12px; }
/* El carril que se desplaza. `min-width:0` es lo que le permite encogerse por
   debajo de su contenido: sin él, un flex-item no baja de su tamaño natural y
   no habría desplazamiento que valga. */
.ribbon-tabs-scroll { display:flex; align-items:center; gap:2px; flex:1 1 auto; min-width:0; }
/* El velo del borde por el que queda tira. Es el mismo recurso que los chips
   del panel y la lista de ámbitos: la pestaña se desvanece en vez de cortarse
   a cuchillo, que es lo que la hace leerse como «sigue» y no como «se acabó».
   Las clases las pone `syncTabsEdges` en editor/ribbon.js. */
.ribbon-tabs-scroll.has-end-more { -webkit-mask-image:linear-gradient(to right, #000 calc(100% - 26px), transparent); mask-image:linear-gradient(to right, #000 calc(100% - 26px), transparent); }
.ribbon-tabs-scroll.has-start-more { -webkit-mask-image:linear-gradient(to left, #000 calc(100% - 26px), transparent); mask-image:linear-gradient(to left, #000 calc(100% - 26px), transparent); }
.ribbon-tabs-scroll.has-start-more.has-end-more { -webkit-mask-image:linear-gradient(to right, transparent 0, #000 26px, #000 calc(100% - 26px), transparent 100%); mask-image:linear-gradient(to right, transparent 0, #000 26px, #000 calc(100% - 26px), transparent 100%); }
/* Marca y vuelta se turnan en el mismo hueco de la izquierda: en el editor la
   marca (enlace a la portada, el único que queda dentro del editor); en el
   informe y en «Nuevo», la puerta de vuelta. Fuera del carril que se desplaza:
   ninguna de las dos puede irse de la pantalla al arrastrar las pestañas. */
.ribbon-wordmark { display:inline-flex; align-items:baseline; gap:4px; flex:0 0 auto; margin-right:12px; color:var(--ed-accent-dark); font:800 13px/1 var(--font-heading, inherit); letter-spacing:.01em; white-space:nowrap; text-decoration:none; }
.ribbon-wordmark:hover em, .ribbon-wordmark:hover { color:var(--ed-accent); }
.ribbon-wordmark em { font:600 9px/1 var(--font-heading, inherit); font-style:normal; letter-spacing:.09em; text-transform:uppercase; color:var(--insp-muted); }
.ribbon-back { display:none; align-items:center; gap:6px; flex:0 0 auto; height:26px; margin-right:12px; padding:0 10px 0 7px; color:var(--ed-accent-dark); background:var(--ed-active-bg); border:1px solid var(--ed-rail-line); border-radius:8px; font:700 12px var(--font-heading, inherit); cursor:pointer; white-space:nowrap; }
.ribbon-back:hover { background:var(--bg-card); }
.ribbon-back svg { width:15px; height:15px; }

/* ---- barra de aplicación: el extremo derecho de la tira ----
   Lo que vale en las tres vistas. Se lee como cromo y no como comandos: sin
   fondo, con el rótulo al lado del icono, y con el mismo alto que las
   pestañas para que la tira siga siendo UNA línea. */
.ribbon-appbar { display:flex; align-items:center; gap:1px; flex:0 0 auto; margin-left:auto; padding-left:10px; }
.ribbon-appbtn { display:inline-flex; align-items:center; gap:6px; flex:0 0 auto; height:26px; padding:0 9px; color:#52697e; background:transparent; border:0; border-radius:7px; font:600 12px var(--font-heading, inherit); text-decoration:none; cursor:pointer; white-space:nowrap; }
.ribbon-appbtn:hover { color:var(--ed-accent-dark); background:var(--ed-active-bg); }
.ribbon-appbtn svg { width:15px; height:15px; }
/* La vista en la que ya se está no se ofrece como destino. */
.ribbon-appbtn[aria-current="true"] { color:var(--ed-accent-dark); background:#dceaf7; }
/* Apagado no es mudo: mismo criterio que tenía la pastilla del carril azul —el
   clic llega y openReportGate explica qué falta. */
.ribbon-appbtn[aria-disabled="true"] { opacity:.45; cursor:default; }
.ribbon-appbtn[aria-disabled="true"]:hover { color:#52697e; background:transparent; }
/* Salir se separa del resto: es la única que abandona el editor. */
.ribbon-exit { margin-left:6px; box-shadow:inset 1px 0 0 var(--insp-line); padding-left:14px; border-radius:0 7px 7px 0; }
.ribbon-appbtn:focus-visible, .ribbon-back:focus-visible, .ribbon-wordmark:focus-visible { outline:2px solid var(--ed-accent); outline-offset:1px; border-radius:7px; }


/* En el informe y en «Nuevo» la tira se queda, y con ella la vuelta y la
   barra; lo que habla del TEXTO se va, porque ahí no hay texto que mandar.
   El galón de plegar también: no hay fila que plegar. */
.public-editor-shell[data-editor-view="informe"] .ribbon-tabs-scroll,
.public-editor-shell[data-editor-view="nuevo"] .ribbon-tabs-scroll,
.public-editor-shell[data-editor-view="informe"] .ribbon-fold,
.public-editor-shell[data-editor-view="nuevo"] .ribbon-fold,
.public-editor-shell[data-editor-view="informe"] .ribbon-row,
.public-editor-shell[data-editor-view="nuevo"] .ribbon-row,
.public-editor-shell[data-editor-view="informe"] .ribbon-wordmark,
.public-editor-shell[data-editor-view="nuevo"] .ribbon-wordmark { display:none; }
.public-editor-shell[data-editor-view="informe"] .ribbon-back,
.public-editor-shell[data-editor-view="nuevo"] .ribbon-back { display:inline-flex; }
/* Sin fila de comandos, la tira es toda la cinta: la sombra que la despegaba
   del folio sobra y el borde basta. */
.public-editor-shell[data-editor-view="informe"] .editor-ribbon,
.public-editor-shell[data-editor-view="nuevo"] .editor-ribbon { box-shadow:none; }
.ribbon-tab { flex:0 0 auto; height:32px; padding:0 11px; color:#52697e; background:transparent; border:0; border-bottom:2px solid transparent; font:600 12px var(--font-heading, inherit); cursor:pointer; white-space:nowrap; }
.ribbon-tab:hover { color:var(--ed-accent-dark); }
.ribbon-tab[aria-selected="true"] { color:var(--ed-accent-dark); border-bottom-color:var(--ed-accent); }
/* Plegar la cinta: cromo puro, y el único habitante del extremo derecho de
   la tira. Sin fondo ni contorno —no es una acción sobre el texto, es la
   cinta hablando de sí misma—, y el hueco libre lo abre él (margin-left:auto).
   Es un galón que GIRA: apunta a donde va la cinta. Por eso el botón «Más»
   de la fila de abajo no puede ser otro galón (ver el bloque de
   desbordamiento): allí se abre un cajón, no se pliega nada. */
.ribbon-fold { display:grid; place-items:center; flex:0 0 auto; width:28px; height:28px; margin-left:auto; padding:0; color:var(--insp-muted); background:transparent; border:0; border-radius:7px; cursor:pointer; }
.ribbon-fold:hover { color:var(--ed-accent-dark); background:var(--ed-active-bg); }
.ribbon-fold svg { width:15px; height:15px; transition:transform .18s ease; }
.editor-ribbon.is-folded .ribbon-fold svg { transform:rotate(180deg); }
/* Una sola fila de 44px que cambia con la pestaña; nunca crece en vertical.
   Si no cabe, manda el botón «Más» (ver el bloque de desbordamiento, más
   abajo); el overflow-x de aquí es solo la red por si no hay JavaScript. */
.ribbon-row { display:flex; align-items:center; gap:2px; height:44px; padding:0 8px; border-top:1px solid var(--insp-line-2); flex-wrap:nowrap; overflow-x:auto; scrollbar-width:thin; }
.ribbon-row::-webkit-scrollbar { height:6px; }
.ribbon-row::-webkit-scrollbar-thumb { background:#d3dbe6; border-radius:999px; }
.ribbon-row[hidden] { display:none; }
.editor-ribbon.is-folded .ribbon-row { display:none; }
/* Cambio de pestaña, como en Word: los comandos de la fila entrante no
   aparecen de golpe, suben un par de píxeles y se revelan en cascada de
   izquierda a derecha. El escalón es corto a propósito (12 ms): tiene que
   leerse como un gesto, no como una espera. La animación se dispara sola al
   quitar [hidden], porque display:none la reinicia. */
@keyframes ribbon-reveal { from { opacity:0; transform:translateY(-5px); } to { opacity:1; transform:none; } }
.ribbon-row:not([hidden]) > * { animation:ribbon-reveal .22s cubic-bezier(.2,.7,.3,1) both; }
.ribbon-row > :nth-child(1) { animation-delay:0ms; }
.ribbon-row > :nth-child(2) { animation-delay:12ms; }
.ribbon-row > :nth-child(3) { animation-delay:24ms; }
.ribbon-row > :nth-child(4) { animation-delay:36ms; }
.ribbon-row > :nth-child(5) { animation-delay:48ms; }
.ribbon-row > :nth-child(6) { animation-delay:60ms; }
.ribbon-row > :nth-child(7) { animation-delay:72ms; }
.ribbon-row > :nth-child(8) { animation-delay:84ms; }
.ribbon-row > :nth-child(9) { animation-delay:96ms; }
.ribbon-row > :nth-child(n/**/+10) { animation-delay:108ms; }
/* Al desplegar la cinta plegada, la fila entera entra de una pieza. */
.editor-ribbon:not(.is-folded) .ribbon-row:not([hidden]) { animation:ribbon-reveal .18s ease both; }

/* Desbordamiento de la fila (editor/ribbon.js): con JS la fila no se
   desplaza — se mide, la cola que no cabe se esconde (is-overflowed) y el
   botón «Más» la ofrece en un cajón anclado bajo la cinta. Los comandos
   conservan su clase y por tanto su aspecto: solo cambian de contenedor
   mientras el cajón está abierto. */
.editor-ribbon.has-overflow-chrome .ribbon-row { overflow:hidden; }
.ribbon-row > .is-overflowed { display:none; }
/* «Más»: puntos suspensivos dentro de una pastilla con contorno, pegada al
   borde. Deliberadamente distinto del plegador de la tira, que le queda
   justo encima: aquel es un galón sin contorno que gira, este es un menú
   que se abre. Mismo icono en los dos sitios habría sido la misma promesa
   para dos cosas que no se parecen en nada. */
/* `order` y no solo `margin-left:auto`: con la fila al límite el margen
   automático se queda sin holgura que repartir y el botón se colaba entre
   los comandos. El orden lo deja al final pase lo que pase. */
.ribbon-more { order:1; margin-left:auto; min-width:28px; padding:0 6px; color:var(--insp-muted); background:var(--bg-card); border:1px solid var(--insp-line); }
.ribbon-more:hover:not([disabled]) { color:var(--ed-accent); background:var(--ed-active-bg); border-color:#bcd6ee; }
.ribbon-more svg { width:16px; height:16px; }
.ribbon-more.is-open { color:var(--text-inverse); background:var(--ed-accent); border-color:var(--ed-accent); }
.ribbon-overflow { position:absolute; top:100%; right:6px; z-index:55; display:flex; flex-wrap:wrap; align-items:center; gap:2px; max-width:min(480px, calc(100vw - 24px)); padding:6px 8px; background:var(--bg-card); border:1px solid var(--insp-line); border-top:0; border-radius:0 0 12px 12px; box-shadow:0 14px 30px rgba(6,40,70,.16); }
.ribbon-overflow[hidden] { display:none; }
/* Los separadores no viajan al cajón: allí la cola se relee como grupo. */
.ribbon-overflow .ribbon-sep { display:none; }

/* Desplegables de la cinta (editor/ribbon.js): «Descargar como» y los que
   vengan. Mismo material que el cajón «Más» —panel blanco colgado del borde
   inferior de la cinta, sin borde superior porque nace pegado a ella, y la
   misma sombra—, pero en columna: cada formato es una fila con su icono, su
   nombre y la explicación que antes vivía escondida en un title. La izquierda
   la pone el JS, alineada con el botón que lo abrió. */
.ribbon-menu { position:absolute; top:100%; left:6px; z-index:56; display:flex; flex-direction:column; gap:2px; min-width:250px; max-width:min(340px, calc(100vw - 24px)); padding:7px; background:var(--bg-card); border:1px solid var(--insp-line); border-top:0; border-radius:0 0 12px 12px; box-shadow:0 14px 30px rgba(6,40,70,.16); }
.ribbon-menu[hidden] { display:none; }
/* La cascada de la cinta, otra vez: el menú no aparece de golpe, sus filas
   suben y se revelan de arriba abajo. Se dispara sola al quitar [hidden]. */
.ribbon-menu:not([hidden]) > * { animation:ribbon-reveal .2s cubic-bezier(.2,.7,.3,1) both; }
.ribbon-menu > :nth-child(1) { animation-delay:0ms; }
.ribbon-menu > :nth-child(2) { animation-delay:22ms; }
.ribbon-menu > :nth-child(3) { animation-delay:44ms; }
.ribbon-menu > :nth-child(4) { animation-delay:66ms; }
.ribbon-menu > :nth-child(n/**/+5) { animation-delay:88ms; }
.ribbon-menu-item { display:flex; align-items:center; gap:11px; width:100%; min-height:40px; padding:7px 10px; color:#3f4f61; background:transparent; border:0; border-radius:9px; font:inherit; text-align:left; cursor:pointer; }
.ribbon-menu-item:hover:not([disabled]) { color:var(--ed-accent); background:var(--ed-active-bg); }
.ribbon-menu-item:focus-visible { outline:2px solid var(--ed-accent); outline-offset:-2px; }
.ribbon-menu-item[disabled] { color:#c0c9d6; cursor:default; }
.ribbon-menu-item > svg { flex:0 0 auto; width:18px; height:18px; }
.ribbon-menu-text { display:flex; flex-direction:column; gap:1px; min-width:0; }
.ribbon-menu-text strong { font:700 12.5px/1.25 var(--font-heading, inherit); color:inherit; }
.ribbon-menu-text small { font-size:11px; line-height:1.3; color:var(--insp-muted); }
/* El botón que lo abre: un comando de la cinta con galón. Abierto se queda
   encendido —igual que un comando activo—, para que se vea de dónde cuelga
   el panel; el galón gira, como el del plegador. */
.ribbon-menu-btn .ribbon-menu-caret { width:13px; height:13px; margin-left:1px; color:var(--insp-muted); transition:transform .18s ease; }
.ribbon-menu-btn.is-open { color:var(--ed-accent); background:#dceefe; box-shadow:inset 0 0 0 1px #a9d2f3; }
.ribbon-menu-btn.is-open .ribbon-menu-caret { color:inherit; transform:rotate(180deg); }
@media (prefers-reduced-motion: reduce) {
  .ribbon-menu:not([hidden]) > * { animation:none; }
  .ribbon-menu-btn .ribbon-menu-caret { transition:none; }
}

/* La nota de privacidad de la fila de Archivo: rótulo informativo empujado
   al extremo, con la frase completa en su title. */
.ribbon-note { display:inline-flex; align-items:center; gap:6px; flex:0 0 auto; margin-left:auto; padding:0 6px; color:var(--insp-muted); font:600 11px var(--font-heading, inherit); white-space:nowrap; }
.ribbon-note svg { flex:0 0 auto; width:14px; height:14px; color:var(--ed-accent); }

/* La lista del diálogo de ayuda: filas con el cuerpo de botón de la cinta
   (icono plano de 17px, rótulo semibold, mismo hover). */
.editor-help-dialog .help-links { display:flex; flex-direction:column; gap:2px; }
.fm-item { display:flex; align-items:center; gap:9px; width:100%; padding:7px 9px; border:0; border-radius:8px; background:transparent; color:#3f4f61; font:inherit; text-align:left; text-decoration:none; cursor:pointer; }
.fm-item:hover { color:var(--ed-accent); background:var(--ed-active-bg); }
.fm-item:focus-visible { outline:2px solid var(--ed-accent); outline-offset:2px; }
.fm-ico { display:grid; place-items:center; flex:0 0 auto; width:20px; height:20px; color:inherit; }
.fm-ico svg { width:17px; height:17px; }
.fm-text { display:flex; align-items:baseline; gap:7px; min-width:0; }
.fm-text strong { font:600 12.5px/1.3 var(--font-heading, inherit); color:inherit; white-space:nowrap; }
.fm-text small { min-width:0; font-size:11.5px; color:var(--insp-muted); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }

/* Aviso «el informe aún no está listo»: un bocadillo anclado al acceso
   pulsado (no un modal — la pregunta es pequeña). positionReportGate lo
   coloca del lado con sitio (is-right/is-left) y la flecha apunta al centro
   del botón. La razón en una frase y el remedio como acción principal, en
   el azul de Analizar: es la misma acción. */
.report-gate-pop { position:fixed; z-index:150; width:272px; padding:12px 14px; background:var(--bg-card); border:1px solid var(--insp-line); border-radius:12px; box-shadow:0 14px 34px rgba(6,40,70,.22); }
.report-gate-pop[hidden] { display:none; }
.report-gate-pop > strong { display:block; margin-bottom:3px; font:700 13px/1.35 var(--font-heading, inherit); color:var(--insp-ink); }
.report-gate-pop > p { margin:0 0 10px; font-size:12.5px; line-height:1.5; color:var(--insp-muted); }
.report-gate-arrow { position:absolute; width:10px; height:10px; background:var(--bg-card); }
.report-gate-pop.is-right .report-gate-arrow { left:-5.5px; border-left:1px solid var(--insp-line); border-bottom:1px solid var(--insp-line); transform:rotate(45deg); }
.report-gate-pop.is-left .report-gate-arrow { right:-5.5px; border-right:1px solid var(--insp-line); border-top:1px solid var(--insp-line); transform:rotate(45deg); }
.report-gate-analyze { display:inline-flex; width:100%; align-items:center; justify-content:center; gap:8px; padding:9px 14px; color:var(--text-inverse); background:var(--ed-accent); border:0; border-radius:9px; font:600 12.5px var(--font-heading, inherit); cursor:pointer; }
.report-gate-analyze:hover { background:var(--ed-accent-dark); }
.report-gate-analyze svg { width:15px; height:15px; }
.report-gate-analyze[hidden] { display:none; }
@media (prefers-reduced-motion: reduce) {
  .ribbon-row:not([hidden]) > *,
  .editor-ribbon:not(.is-folded) .ribbon-row:not([hidden]) { animation:none; }
}
.ribbon-sep { flex:0 0 auto; width:1px; height:22px; margin:0 6px; background:var(--insp-line); }
.ribbon-label { flex:0 0 auto; padding:0 4px; color:var(--insp-muted); font:600 11px var(--font-heading, inherit); white-space:nowrap; }
.ribbon-btn { flex:0 0 auto; display:inline-flex; align-items:center; justify-content:center; gap:7px; min-width:31px; height:31px; padding:0 7px; color:#3f4f61; background:transparent; border:0; border-radius:8px; font:600 12px var(--font-heading, inherit); cursor:pointer; white-space:nowrap; text-decoration:none; }
.ribbon-btn:hover:not([disabled]) { color:var(--ed-accent); background:var(--ed-active-bg); }
.ribbon-btn svg { width:17px; height:17px; }
.ribbon-btn.is-labeled { padding:0 10px 0 8px; }
.ribbon-btn[disabled] { color:#c0c9d6; cursor:default; }
.ribbon-btn-state { font-size:10px; color:var(--insp-muted); }
/* Estados perceptibles (negrita activa, corrector encendido…): mismo
   tratamiento que tenía la barra de formato. */
.ribbon-btn.is-active,
.ribbon-btn[aria-pressed="true"],
.ribbon-btn[aria-checked="true"] { color:var(--ed-accent); background:#dceefe; box-shadow:inset 0 0 0 1px #a9d2f3; }
/* Selectores compactos, en azul de marca. */
.ribbon-select { flex:0 0 auto; min-width:0; width:72px; height:31px; padding:0 22px 0 10px; color:var(--ed-accent-dark); background:#f2f6fb; border:1px solid transparent; border-radius:8px; font:700 12px var(--font-heading, inherit); cursor:pointer; }
.ribbon-select:hover { background:var(--ed-active-bg); }
.ribbon-select-font { width:106px; }
/* El selector de estilo de párrafo necesita el suyo: los 72px de la base
   están calculados para el tamaño de letra («12», «14»…) y aquí caben
   «Texto», «Título 1» y, la más larga de las tres lenguas, «Heading 1».
   Sin él se leía «Te…» y no se sabía qué decía (Sara, 02/09). */
.ribbon-select-block { width:112px; }
/* Botones-radio de espaciado/márgenes como pastilla segmentada (mismo dato y
   mismos data-attributes que sincroniza editor_chrome: is-selected). */
.ribbon-seg { display:inline-flex; flex:0 0 auto; padding:2px; gap:1px; background:#e6edf5; border-radius:999px; }
.ribbon-seg button { border:0; background:transparent; padding:3px 9px; border-radius:999px; font:600 11.5px var(--font-heading, inherit); color:var(--insp-muted); cursor:pointer; white-space:nowrap; }
.ribbon-seg button:hover { color:var(--insp-ink); }
.ribbon-seg button.is-selected { background:var(--bg-card); color:var(--insp-ink); box-shadow:0 1px 3px rgba(15,23,42,.18); }
.ribbon-seg button[disabled] { color:#c0c9d6; cursor:default; }
/* ---- pestaña contextual (patrón de Word) ----
   Aparece al final de la tira cuando el cursor entra en un objeto con
   comandos propios. Lleva rótulo encima y color propio —violeta, ajeno a la
   paleta del cromo— para que se lea como algo que ha aparecido y se irá, no
   como una pestaña más del editor. */
.ribbon-ctx-wrap { display:flex; flex-direction:column; align-items:stretch; align-self:stretch; justify-content:flex-end; flex:0 0 auto; margin-left:10px; }
.ribbon-ctx-wrap[hidden] { display:none; }
.ribbon-ctx-label { padding:1px 12px 0; color:var(--ed-ctx); background:var(--ed-ctx-wash); border-radius:7px 7px 0 0; font:800 9px/1.35 var(--font-heading, inherit); letter-spacing:.09em; text-transform:uppercase; text-align:center; }
.ribbon-ctx-tab { height:23px; padding:0 12px; border:0; border-bottom:2px solid var(--ed-ctx); background:var(--ed-ctx-wash); color:var(--ed-ctx); font:700 12px var(--font-heading, inherit); cursor:pointer; }
.ribbon-ctx-tab[aria-selected="true"] { background:var(--bg-card); }
.ribbon-row-ctx { background:linear-gradient(180deg,#faf8ff,#f5f1ff); border-top-color:#e4dcfb; }
.ribbon-row-ctx .ribbon-btn { color:#4c2d92; }
.ribbon-row-ctx .ribbon-btn:hover:not([disabled]) { color:var(--ed-ctx); background:#ece5fd; }
.ribbon-row-ctx .ribbon-label { color:var(--ed-ctx); font-weight:800; }
.ribbon-btn-danger { color:#b42318 !important; }
.ribbon-btn-danger:hover:not([disabled]) { color:#912018 !important; background:#fee4e2 !important; }
