<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Franklin</title>
    <description>The latest articles on DEV Community by Franklin (@ortizfranklindev).</description>
    <link>https://dev.to/ortizfranklindev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2493878%2F8821e986-c182-499a-92e4-d91e7e960256.png</url>
      <title>DEV Community: Franklin</title>
      <link>https://dev.to/ortizfranklindev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ortizfranklindev"/>
    <language>en</language>
    <item>
      <title>Construir un sistema frontend que siga teniendo sentido dentro de diez años</title>
      <dc:creator>Franklin</dc:creator>
      <pubDate>Thu, 10 Sep 2026 10:52:35 +0000</pubDate>
      <link>https://dev.to/ortizfranklindev/construir-un-sistema-frontend-que-siga-teniendo-sentido-dentro-de-diez-anos-242o</link>
      <guid>https://dev.to/ortizfranklindev/construir-un-sistema-frontend-que-siga-teniendo-sentido-dentro-de-diez-anos-242o</guid>
      <description>&lt;p&gt;&lt;em&gt;Also available in &lt;a href="https://dev.to/ortizfranklindev/building-a-front-end-system-that-can-still-make-sense-ten-years-from-now-586l"&gt;Inglés&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  El problema
&lt;/h2&gt;

&lt;p&gt;Abre una base de código lo suficientemente antigua como para que nadie en el equipo actual la haya escrito. El código sigue ejecutándose. Nadie puede decirte por qué se tomó cada decisión.&lt;/p&gt;

&lt;p&gt;¿Fue intencional esa solución temporal de especificidad o un accidente parcheado? ¿Fue deliberada la elección del reset o simplemente lo que incluía la plantilla inicial? El código no lo dice. Nunca lo hizo. Lo que falta no es funcionalidad. Es la capacidad de reconstruir el motivo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por qué existe el problema
&lt;/h2&gt;

&lt;p&gt;Los equipos optimizan para lo que funciona hoy. Esa es la presión que tienen justo enfrente. Un horizonte de diez años no es el plazo de entrega de ningún sprint. Las decisiones se toman de forma correcta, bajo restricciones reales, por personas que entendían exactamente por qué las tomaban y luego el razonamiento se evapora en el momento en que esas personas se marchan, incluso cuando la decisión en sí era completamente sólida.&lt;/p&gt;

&lt;p&gt;El código sobrevive. El contexto no. Ese vacío es lo que esta serie ha estado rodeando, artículo tras artículo, bajo un nombre diferente cada vez.&lt;/p&gt;

&lt;h2&gt;
  
  
  El primer principio
&lt;/h2&gt;

&lt;p&gt;La longevidad no es una propiedad tecnológica. Es una propiedad de legibilidad.&lt;/p&gt;

&lt;p&gt;Un sistema sigue teniendo sentido en diez años si un extraño alguien que nunca conoció a quien lo construyó puede reconstruir por qué está diseñado así, a partir del propio artefacto, sin acceso a las personas que tomaron las decisiones originales. Cada mecanismo que ha cubierto esta serie resulta ser el mismo requisito, aplicado a una escala diferente: declarado en lugar de implícito, y verificable por cualquiera que lo lea en lugar de estar memorizado por quienquiera que estuviera en la sala cuando se decidió.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demostración del principio
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* límite: la base nunca establece valores de color directamente; los tokens son los dueños de eso. */&lt;/span&gt;
&lt;span class="nd"&gt;:where&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;margin-block&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Frente a la misma regla, sin comentario, por lo demás idéntica. Mismo comportamiento hoy. Dentro de diez años, una de ellas todavía le explica a un extraño por qué está construida así. La otra solo le dice lo que hace.&lt;/p&gt;

&lt;h2&gt;
  
  
  quell-base.css y quell-light.js como caso de estudio
&lt;/h2&gt;

&lt;p&gt;Nada de esto es material nuevo. Es la misma evidencia que esta serie ya ha mostrado, leída ahora como una decisión continua en lugar de once decisiones separadas.&lt;/p&gt;

&lt;p&gt;El reset que declaró una opinión visual cero, para que nadie tenga que preguntar más tarde si "reset" significaba en secreto "el gusto de alguien". Las capas que resolvieron previamente las disputas antes de que tuvieran la oportunidad de ocurrir, para que un extraño que lea &lt;code&gt;@layer ghost_tokens, reset, baseline, forms, utilities;&lt;/code&gt; ya conozca la precedencia sin preguntar a nadie. Las superficies de sobrescritura (&lt;em&gt;override surfaces&lt;/em&gt;) que reemplazaron la negociación por tres rutas explícitas y ordenadas, declaradas una vez, válidas para cualquiera que toque el archivo después. El vocabulario de estado en &lt;a href="https://dev.to/ortizfranklindev/por-que-javascript-deberia-mutar-el-estado-en-lugar-de-los-estilos-70k"&gt;&lt;code&gt;quell-light.js&lt;/code&gt;&lt;/a&gt; que no puede desviarse para significar otra cosa, porque nunca fue elegible para significar otra cosa.&lt;/p&gt;

&lt;p&gt;Nada de esto requirió que el autor original siguiera allí para continuar el trabajo. Ese era el objetivo de cada una de esas decisiones, no un accidente de buena suerte.&lt;/p&gt;

&lt;h2&gt;
  
  
  La lección más amplia
&lt;/h2&gt;

&lt;p&gt;Doce artículos, una sola cosa debajo de todos ellos: reemplazar el acuerdo implícito y no documentado con algo declarado, verificable y duradero más allá de las personas que lo construyeron. Resets, especificidad, entropía, límites (&lt;em&gt;boundaries&lt;/em&gt;), capas, orden de resolución, exclusiones, especificidad cero, frameworks, librerías, estado: mecanismos diferentes, el mismo requisito, una y otra vez.&lt;/p&gt;

&lt;p&gt;El objetivo nunca fue construir otro framework. Fue ayudar a los desarrolladores a redescubrir la plataforma que ya tienen, y dejar atrás decisiones que un extraño aún pueda comprender, mucho tiempo después de que todos los que las tomaron hayan pasado a otra cosa.&lt;/p&gt;

</description>
      <category>css</category>
      <category>arquitectura</category>
      <category>desarrolloweb</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Building a Front-End System That Can Still Make Sense Ten Years From Now</title>
      <dc:creator>Franklin</dc:creator>
      <pubDate>Thu, 10 Sep 2026 10:50:42 +0000</pubDate>
      <link>https://dev.to/ortizfranklindev/building-a-front-end-system-that-can-still-make-sense-ten-years-from-now-586l</link>
      <guid>https://dev.to/ortizfranklindev/building-a-front-end-system-that-can-still-make-sense-ten-years-from-now-586l</guid>
      <description>&lt;p&gt;&lt;em&gt;Also available in &lt;a href="https://dev.to/ortizfranklindev/construir-un-sistema-frontend-que-siga-teniendo-sentido-dentro-de-diez-anos-242o"&gt;Español&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Open a codebase old enough that nobody currently on the team wrote it. The code still runs. Nobody can tell you why any particular decision was made the way it was.&lt;/p&gt;

&lt;p&gt;Was that specificity workaround intentional, or an accident someone patched around? Was that reset choice deliberate, or just whatever the starter template shipped with? The code doesn't say. It never did. What's missing isn't functionality. It's the ability to reconstruct a reason.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the Problem Exists
&lt;/h2&gt;

&lt;p&gt;Teams optimize for what works now, because that's the pressure sitting directly in front of them. Ten years out is nobody's sprint deadline. Decisions get made — correctly, under real constraints, by people who understood exactly why they were making them — and then the reasoning evaporates the moment those people move on, even when the decision itself was completely sound.&lt;/p&gt;

&lt;p&gt;The code survives. The context doesn't. That gap is what this entire series has actually been circling, article after article, under a different name each time.&lt;/p&gt;

&lt;h2&gt;
  
  
  The First Principle
&lt;/h2&gt;

&lt;p&gt;Longevity isn't a technology property. It's a legibility property.&lt;/p&gt;

&lt;p&gt;A system still makes sense in ten years if a stranger — someone who never met the person who built it — can reconstruct why it's built this way, from the artifact itself, with no access to the people who made the original decisions. Every mechanism this series has covered turns out to be the same requirement, applied at a different scale: declared instead of implicit, and checkable by anyone who reads it rather than memorized by whoever happened to be in the room when it was decided.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demonstrating the Principle
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* boundary: base never sets color values directly — tokens own that */&lt;/span&gt;
&lt;span class="nd"&gt;:where&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;margin-block&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Versus the same rule, no comment, otherwise identical. Same behavior today. Ten years out, one of them still tells a stranger why it's built this way. The other just tells them what it does.&lt;/p&gt;

&lt;h2&gt;
  
  
  quell-base.css and quell-light.js as the Case Study
&lt;/h2&gt;

&lt;p&gt;None of this is new material. It's the same evidence this series has already shown, read now as one continuous decision instead of eleven separate ones.&lt;/p&gt;

&lt;p&gt;The reset that declared zero visual opinion, so nobody has to ask later whether "reset" secretly meant "someone's taste." The layers that pre-resolved arguments before they had the chance to happen, so a stranger reading &lt;code&gt;@layer ghost_tokens, reset, baseline, forms, utilities;&lt;/code&gt; already knows the precedence without asking anyone. The override surfaces that replaced negotiation with three explicit, ranked paths, stated once, holding for anyone who touches the file after. The state vocabulary in &lt;a href="https://dev.to/ortizfranklindev/why-javascript-should-mutate-state-instead-of-styles-m6g"&gt;&lt;code&gt;quell-light.js&lt;/code&gt;&lt;/a&gt; that can't drift into meaning something else, because it was never eligible to mean anything else.&lt;/p&gt;

&lt;p&gt;None of it required the original author to still be around to keep working. That was the point of every one of those decisions, not an accident of good luck.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Broader Lesson
&lt;/h2&gt;

&lt;p&gt;Twelve articles, one thing underneath all of them: replacing implicit, undocumented agreement with something declared, checkable, and durable past the people who built it. Resets, specificity, entropy, boundaries, layers, resolution order, exclusions, zero specificity, frameworks, libraries, state, different mechanisms, the same requirement, over and over.&lt;/p&gt;

&lt;p&gt;The goal was never to build another framework. It was to help developers rediscover the platform they already have, and to leave behind decisions a stranger can still make sense of, long after everyone who made them has moved on to something else.&lt;/p&gt;

</description>
      <category>css</category>
      <category>webdev</category>
      <category>architecture</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Por qué JavaScript debería mutar el estado en lugar de los estilos</title>
      <dc:creator>Franklin</dc:creator>
      <pubDate>Tue, 08 Sep 2026 10:52:39 +0000</pubDate>
      <link>https://dev.to/ortizfranklindev/por-que-javascript-deberia-mutar-el-estado-en-lugar-de-los-estilos-70k</link>
      <guid>https://dev.to/ortizfranklindev/por-que-javascript-deberia-mutar-el-estado-en-lugar-de-los-estilos-70k</guid>
      <description>&lt;p&gt;&lt;em&gt;Also available in &lt;a href="https://dev.to/ortizfranklindev/why-javascript-should-mutate-state-instead-of-styles-m6g"&gt;Inglés&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  El problema
&lt;/h2&gt;

&lt;p&gt;Un menú desplegable debe abrirse. Un modal debe aparecer. Un enlace de navegación debe mostrar en qué sección se encuentra el lector actualmente.&lt;/p&gt;

&lt;p&gt;La ruta directa es &lt;code&gt;element.style.display = 'block'&lt;/code&gt;: el estado y la apariencia se deciden en la misma línea, sin dejar nada en manos de CSS. La mayoría de los desarrolladores experimentados ya evitan esto. El patrón más común es usar una clase en su lugar: &lt;code&gt;classList.toggle('is-open')&lt;/code&gt;. Eso es una mejora real y una abstracción de estado verdadera: CSS decide cómo se ve &lt;code&gt;.is-open&lt;/code&gt;, JavaScript simplemente alterna si la clase está presente o no.&lt;/p&gt;

&lt;p&gt;Aquí es donde se pone más interesante. &lt;code&gt;.is-open&lt;/code&gt; se extrae del mismo espacio de nombres que cualquier otro gancho de estilo en la base de código. Nada en la sintaxis lo marca como estado en lugar de apariencia. Un compañero de equipo dentro de seis meses, al examinar la hoja de estilos, no tendrá forma de distinguir &lt;code&gt;.is-open&lt;/code&gt; de &lt;code&gt;.card-title&lt;/code&gt;, excepto al interpretar la intención en el nombre y confiar en que se haya mantenido la convención.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por qué existe el problema
&lt;/h2&gt;

&lt;p&gt;Los cambios basados en clases funcionan, y lo hacen por convención: el equipo acuerda, de manera informal, que las clases con el prefijo &lt;code&gt;is-&lt;/code&gt; o &lt;code&gt;has-&lt;/code&gt; significan estado, y todo lo demás significa apariencia. Ese acuerdo es real, y en un equipo disciplinado se mantiene durante mucho tiempo.&lt;/p&gt;

&lt;p&gt;También es exactamente la forma de fragilidad que esta serie ya ha diagnosticado. Los límites basados en convenciones sobreviven mientras las personas que los acordaron sigan estando allí para imponerlos. Nada en la sintaxis de una clase impide que se reutilice como una utilidad, que sea capturada por una disputa de especificidad de la misma manera que cualquier otro selector, o que simplemente sea malinterpretada por alguien nuevo en la base de código que nunca ha visto documentada la convención &lt;code&gt;is-&lt;/code&gt; en ninguna parte.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;quell-light.js&lt;/code&gt; da un paso más allá de la convención. Su propio encabezado establece el límite claramente, antes de una sola línea de implementación: no es una biblioteca de componentes, no renderiza nada y su único mandato es la estabilización del comportamiento. La parte interesante no es que evite los estilos en línea; la mayoría del código serio ya lo hace. Es lo que busca en lugar de una clase de estado.&lt;/p&gt;

&lt;h2&gt;
  
  
  El primer principio
&lt;/h2&gt;

&lt;p&gt;El estado debe representarse como estado: legible como estado en la propia sintaxis, no solo por convención.&lt;/p&gt;

&lt;p&gt;Una clase puede hacer esto. &lt;code&gt;data-q-active&lt;/code&gt; lo hace de forma más explícita, porque un atributo &lt;code&gt;data-*&lt;/code&gt; no tiene un significado de estilo con el cual competir. No se puede confundir con una clase de utilidad, no puede verse involucrado en una disputa de especificidad no relacionada y no depende de que una convención de nomenclatura a nivel de equipo se mantenga durante años a través de cada colaborador que toque el archivo. El vocabulario de estado completo de &lt;code&gt;quell-light.js&lt;/code&gt; (&lt;code&gt;data-q-toggle&lt;/code&gt;, &lt;code&gt;data-q-active&lt;/code&gt;, &lt;code&gt;data-q-dismiss&lt;/code&gt;, &lt;code&gt;data-q-spy&lt;/code&gt;, &lt;code&gt;data-q-current&lt;/code&gt;) describe únicamente lo que es verdad. Nada de esto describe la apariencia. CSS posee eso por completo, a través de selectores de atributos ordinarios que reaccionan a cualquiera de estos que esté presente.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demostración del principio
&lt;/h2&gt;

&lt;p&gt;Un cambio basado en clases, el punto de partida común y defendible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;trigger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toggle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;is-open&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.is-open&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Separación real. CSS sigue siendo dueño de la apariencia. Pero &lt;code&gt;.is-open&lt;/code&gt; se encuentra en el mismo espacio de selectores que todo lo demás en la hoja de estilos, y nada lo marca como diferente.&lt;/p&gt;

&lt;p&gt;La versión de atributo, más definida por diseño:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;trigger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;trigger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aria-expanded&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;true&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data-q-active&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;data-q-active&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mismo resultado. La diferencia es lo que la propia sintaxis garantiza: &lt;code&gt;data-q-active&lt;/code&gt; no puede derivar en significar otra cosa, porque nunca fue elegible para significar otra cosa.&lt;/p&gt;

&lt;h2&gt;
  
  
  quell-light.js como caso de estudio
&lt;/h2&gt;

&lt;p&gt;El módulo de divulgación anterior es cercano al mecanismo real en el archivo, menos el manejo de grupos exclusivos y la delegación de eventos. Es la prueba más clara de que esta disciplina se sostiene bajo un requisito de accesibilidad real: un control interactivo accesible necesita tanto un estado ARIA como un gancho estilizable, y el archivo los mantiene como dos atributos explícitas en lugar de una sola clase sobrecargada.&lt;/p&gt;

&lt;p&gt;Los otros dos módulos interactivos mantienen la misma línea bajo condiciones más difíciles. La gestión del foco impone un contenedor estricto de Tab/Shift+Tab dentro de un diálogo abierto y rastrea a qué elemento devolver el foco al cerrar: estado real, con la apariencia del diálogo dejada completamente a CSS. El observador de desplazamiento utiliza &lt;code&gt;IntersectionObserver&lt;/code&gt; en lugar de un receptor de desplazamiento directo para decidir qué sección está activa, expresado como un único &lt;code&gt;aria-current&lt;/code&gt; en un enlace de navegación a la vez; de nuevo, una decisión de estado, renderizada como la hoja de estilos considere oportuno.&lt;/p&gt;

&lt;h2&gt;
  
  
  La lección más amplia
&lt;/h2&gt;

&lt;p&gt;Esto define de forma más precisa el límite del artículo 4, en lugar de simplemente reafirmarlo. La afirmación nunca fue que las clases estuvieran mal. Es que un límite impuesto por convención es solo tan duradero como la memoria del equipo sobre dicha convención, y un límite codificado directamente en la sintaxis no tiene esa dependencia. &lt;code&gt;quell-light.js&lt;/code&gt; no evitó un error. Eligió la versión más explícita de algo que ya valía la pena hacer.&lt;/p&gt;

</description>
      <category>css</category>
      <category>arquitectura</category>
      <category>desarrolloweb</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Why JavaScript Should Mutate State Instead of Styles</title>
      <dc:creator>Franklin</dc:creator>
      <pubDate>Tue, 08 Sep 2026 10:51:10 +0000</pubDate>
      <link>https://dev.to/ortizfranklindev/why-javascript-should-mutate-state-instead-of-styles-m6g</link>
      <guid>https://dev.to/ortizfranklindev/why-javascript-should-mutate-state-instead-of-styles-m6g</guid>
      <description>&lt;p&gt;&lt;em&gt;Also available in &lt;a href="https://dev.to/ortizfranklindev/por-que-javascript-deberia-mutar-el-estado-en-lugar-de-los-estilos-70k"&gt;Español&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;A dropdown needs to open. A modal needs to appear. A nav link needs to show which section the reader is currently in.&lt;/p&gt;

&lt;p&gt;The blunt route is &lt;code&gt;element.style.display = 'block'&lt;/code&gt; state and appearance decided in the same line, nothing left for CSS to own. Most experienced developers already avoid this. The more common pattern is a class instead: &lt;code&gt;classList.toggle('is-open')&lt;/code&gt;. That's a real improvement, and a real state abstraction CSS decides what &lt;code&gt;.is-open&lt;/code&gt; looks like, JavaScript just toggles whether the class is present.&lt;/p&gt;

&lt;p&gt;Here's where it gets more interesting. &lt;code&gt;.is-open&lt;/code&gt; is drawn from the exact same namespace as every styling hook in the codebase. Nothing in the syntax marks it as state rather than appearance. A teammate six months from now, skimming the stylesheet, has no way to tell &lt;code&gt;.is-open&lt;/code&gt; apart from &lt;code&gt;.card-title&lt;/code&gt; except by reading the intent into the name and trusting that convention held.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the Problem Exists
&lt;/h2&gt;

&lt;p&gt;Class-based toggles work, and they work by convention: the team agrees, informally, that classes prefixed &lt;code&gt;is-&lt;/code&gt; or &lt;code&gt;has-&lt;/code&gt; mean state, and everything else means appearance. That agreement is real, and for a disciplined team it holds for a long time.&lt;/p&gt;

&lt;p&gt;It's also exactly the shape of fragility this series has already diagnosed. Convention-based boundaries survive as long as the people who agreed to them are still around to enforce them. Nothing about a class's syntax stops it from being reused as a utility, picked up by a specificity fight the same way any other selector would be, or simply misread by someone new to the codebase who's never seen the &lt;code&gt;is-&lt;/code&gt; convention documented anywhere.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;quell-light.js&lt;/code&gt; takes a step past convention. Its own header states the boundary plainly, before a single line of implementation: it is not a component library, it does not render anything, and its only mandate is behavioral stabilization. The interesting part isn't that it avoids inline styles most serious code already does that. It's what it reaches for instead of a state class.&lt;/p&gt;

&lt;h2&gt;
  
  
  The First Principle
&lt;/h2&gt;

&lt;p&gt;State should be represented as state legible as state in the syntax itself, not just by convention.&lt;/p&gt;

&lt;p&gt;A class can do this. &lt;code&gt;data-q-active&lt;/code&gt; does it more explicitly, because a &lt;code&gt;data-*&lt;/code&gt; attribute has no styling meaning to compete with. It can't be confused for a utility class, can't get pulled into an unrelated specificity fight, and doesn't depend on a team-wide naming convention holding for years across every contributor who touches the file. &lt;code&gt;quell-light.js&lt;/code&gt;'s full state vocabulary: &lt;code&gt;data-q-toggle&lt;/code&gt;, &lt;code&gt;data-q-active&lt;/code&gt;, &lt;code&gt;data-q-dismiss&lt;/code&gt;, &lt;code&gt;data-q-spy&lt;/code&gt;, &lt;code&gt;data-q-current&lt;/code&gt; describes only what's true. None of it describes appearance. CSS owns that entirely, through ordinary attribute selectors reacting to whichever of these happens to be present.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demonstrating the Principle
&lt;/h2&gt;

&lt;p&gt;A class-based toggle, the common and defensible baseline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;trigger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toggle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;is-open&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.is-open&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Real separation. CSS still owns appearance. But &lt;code&gt;.is-open&lt;/code&gt; sits in the same selector space as everything else in the stylesheet, and nothing marks it as different.&lt;/p&gt;

&lt;p&gt;The attribute version, sharper by construction:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;trigger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;trigger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aria-expanded&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;true&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data-q-active&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;data-q-active&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same outcome. The difference is what the syntax itself guarantees: &lt;code&gt;data-q-active&lt;/code&gt; can't drift into meaning something else, because it was never eligible to mean anything else.&lt;/p&gt;

&lt;h2&gt;
  
  
  quell-light.js as the Case Study
&lt;/h2&gt;

&lt;p&gt;The disclosure module above is close to the actual mechanism in the file, minus exclusive-group handling and event delegation. It's the clearest proof that this discipline holds under a real accessibility requirement an accessible toggle needs both an ARIA state and a stylable hook, and the file keeps those as two explicit attributes rather than one overloaded class.&lt;/p&gt;

&lt;p&gt;The other two interactive modules hold the same line under harder conditions. Focus management enforces a strict Tab/Shift+Tab trap inside an open dialog and tracks which element to return focus to on close real state, with the dialog's appearance left entirely to CSS. The scroll watcher uses &lt;code&gt;IntersectionObserver&lt;/code&gt; rather than a raw scroll listener to decide which section is active, expressed as a single &lt;code&gt;aria-current&lt;/code&gt; on one nav link at a time again a state decision, rendered however the stylesheet sees fit.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Broader Lesson
&lt;/h2&gt;

&lt;p&gt;This sharpens article 4's boundary rather than just restating it. The claim was never that classes are wrong. It's that a boundary enforced by convention is only as durable as the team's memory of the convention, and a boundary encoded directly in the syntax doesn't have that dependency. &lt;code&gt;quell-light.js&lt;/code&gt; didn't avoid a mistake. It picked the more explicit version of something already worth doing.&lt;/p&gt;

</description>
      <category>css</category>
      <category>webdev</category>
      <category>architecture</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Biblioteca contra arquitectura</title>
      <dc:creator>Franklin</dc:creator>
      <pubDate>Thu, 03 Sep 2026 10:49:54 +0000</pubDate>
      <link>https://dev.to/ortizfranklindev/biblioteca-contra-arquitectura-hkp</link>
      <guid>https://dev.to/ortizfranklindev/biblioteca-contra-arquitectura-hkp</guid>
      <description>&lt;p&gt;&lt;em&gt;También disponible en &lt;a href="https://dev.to/ortizfranklindev/the-difference-between-a-css-library-and-a-css-architecture-5gl5"&gt;Inglés&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  El problema
&lt;/h2&gt;

&lt;p&gt;Un equipo adopta una biblioteca de componentes. Los botones se ven bien. Las tarjetas son consistentes. Los modales se comportan como deben comportarse.&lt;/p&gt;

&lt;p&gt;Seis meses después, nadie puede predecir con certeza cuál de dos reglas en conflicto ganará en una página determinada. No porque la biblioteca haya hecho un mal trabajo; hizo exactamente lo que prometió. Solo que nunca prometió nada sobre eso.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por qué existe el problema
&lt;/h2&gt;

&lt;p&gt;Las bibliotecas se evalúan según la calidad y la integridad de lo que entregan: cuántos componentes incluyen, qué tan consistentes lucen, qué tan bien los cubre la documentación. Son aspectos razonables a verificar. Ninguno de ellos influye en la precedencia, los límites o el orden de resolución.&lt;/p&gt;

&lt;p&gt;Una biblioteca puede calificar alto en cada eje evaluado y, aun así, dejar la cascada tan desatendida como antes de su llegada. No es un fallo oculto que nadie haya detectado. Es una categoría que la evaluación nunca consideró, porque ¿qué tan buenos son los componentes? y ¿qué garantiza este sistema? son preguntas distintas. Y solo una se suele formular en voz alta.&lt;/p&gt;

&lt;h2&gt;
  
  
  El primer principio
&lt;/h2&gt;

&lt;p&gt;Una biblioteca es una colección de componentes. Una arquitectura es una colección de garantías.&lt;/p&gt;

&lt;p&gt;Una biblioteca responde qué puedo usar. Una arquitectura responde en qué puedo confiar. Un equipo puede tener una respuesta excelente y bien documentada para la primera pregunta y ninguna para la segunda. Poseer un gran conjunto de componentes no implica nada sobre cómo se resuelven entre sí, ni frente a cualquier otro elemento que ya esté en la página.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demostración del principio
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.card-title&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.25rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.text-lg&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ambos provienen de la misma biblioteca. Aplicados al mismo elemento, uno de ellos gana, decidido por la especificidad ordinaria, el &lt;em&gt;source order&lt;/em&gt; o lo que esté presente en la hoja de estilo ese día. La biblioteca nunca declaró una respuesta en ningún sentido. Entregó dos componentes y dejó su relación mutua completamente sin resolver. Abordar esa relación nunca formó parte de lo que significaba biblioteca.&lt;/p&gt;

&lt;h2&gt;
  
  
  quell como caso de estudio
&lt;/h2&gt;

&lt;p&gt;quell no es una biblioteca de componentes con una arquitectura añadida a posteriori. Las garantías son lo primero; los componentes son su superficie visible.&lt;/p&gt;

&lt;h2&gt;
  
  
  La lección general
&lt;/h2&gt;

&lt;p&gt;La misma confusión aparece dondequiera que la abundancia se confunda con la estructura. Una caja de herramientas bien surtida no es un diseño sobre cómo deben usarse esas herramientas juntas, sin importar cuántas contenga ni qué tan bien fabricada esté cada una.&lt;/p&gt;

&lt;p&gt;Esa es la distinción sobre la que continúan construyendo los dos últimos artículos.&lt;/p&gt;

</description>
      <category>css</category>
      <category>arquitectura</category>
      <category>desarrolloweb</category>
      <category>frontend</category>
    </item>
    <item>
      <title>The Difference Between a CSS Library and a CSS Architecture</title>
      <dc:creator>Franklin</dc:creator>
      <pubDate>Thu, 03 Sep 2026 10:48:40 +0000</pubDate>
      <link>https://dev.to/ortizfranklindev/the-difference-between-a-css-library-and-a-css-architecture-5gl5</link>
      <guid>https://dev.to/ortizfranklindev/the-difference-between-a-css-library-and-a-css-architecture-5gl5</guid>
      <description>&lt;p&gt;&lt;em&gt;Also available in &lt;a href="https://dev.to/ortizfranklindev/biblioteca-contra-arquitectura-hkp"&gt;Español&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;A team adopts a component library. Buttons look great. Cards are consistent. Modals behave the way modals are supposed to behave.&lt;/p&gt;

&lt;p&gt;Six months in, someone still can't confidently predict which of two conflicting rules will win on a given page. Not because the library did a bad job — it did exactly what it promised. It just never promised anything about that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the Problem Exists
&lt;/h2&gt;

&lt;p&gt;Libraries get evaluated on the quality and completeness of what they ship: how many components, how consistent they look, how well the documentation covers them. Those are reasonable things to check. None of them touch precedence, boundaries, or resolution order.&lt;/p&gt;

&lt;p&gt;A library can score well on every axis anyone thought to check and still leave the cascade exactly as unmanaged as it was before the library arrived. That's not a hidden flaw someone failed to catch. It's a category the evaluation never asked about in the first place, because "how good are the components" and "what does this system guarantee" are different questions, and only one of them tends to get asked out loud.&lt;/p&gt;

&lt;h2&gt;
  
  
  The First Principle
&lt;/h2&gt;

&lt;p&gt;A library is a collection of components. An architecture is a collection of guarantees.&lt;/p&gt;

&lt;p&gt;A library answers "what can I use." An architecture answers "what can I rely on." A team can have an excellent, well-documented answer to the first question and no answer at all to the second, because nothing about owning a large set of components implies anything about how those components resolve against each other, or against anything else already on the page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demonstrating the Principle
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.card-title&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.25rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.text-lg&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both from the same library. Applied to the same element, one of them wins — decided by ordinary specificity, source order, whatever's actually present in the stylesheet that day. The library never declared an answer either way. It shipped two components and left their relationship to each other entirely unaddressed, because addressing it was never part of what "library" meant.&lt;/p&gt;

&lt;h2&gt;
  
  
  quell as the Case Study
&lt;/h2&gt;

&lt;p&gt;quell isn't a component library with architecture bolted on afterward. The guarantees come first; the components are the visible surface of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Broader Lesson
&lt;/h2&gt;

&lt;p&gt;The same confusion shows up anywhere abundance gets mistaken for structure. A well-stocked toolbox isn't a design for how the tools are meant to be used together, no matter how many tools it holds or how well each one is made.&lt;/p&gt;

&lt;p&gt;That's the distinction the final two articles keep building on.&lt;/p&gt;

</description>
      <category>css</category>
      <category>webdev</category>
      <category>architecture</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Los frameworks no resolvieron el problema de CSS; lo evitaron.</title>
      <dc:creator>Franklin</dc:creator>
      <pubDate>Tue, 01 Sep 2026 10:46:40 +0000</pubDate>
      <link>https://dev.to/ortizfranklindev/los-frameworks-no-resolvieron-el-problema-de-css-lo-evitaron-jfk</link>
      <guid>https://dev.to/ortizfranklindev/los-frameworks-no-resolvieron-el-problema-de-css-lo-evitaron-jfk</guid>
      <description>&lt;p&gt;&lt;em&gt;También disponible en&lt;/em&gt; &lt;a href="https://dev.to/ortizfranklindev/frameworks-didnt-solve-css-they-avoided-it-4e8o"&gt;Inglés.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  El problema
&lt;/h2&gt;

&lt;p&gt;“No tenemos problemas de CSS, usamos Tailwind”. “Bootstrap se encarga de eso”. Casi todos los equipos que han adoptado un &lt;em&gt;framework&lt;/em&gt; pronuncian alguna versión de esa frase. Generalmente, con un alivio real.&lt;/p&gt;

&lt;p&gt;Tampoco es del todo cierto. Los &lt;em&gt;frameworks&lt;/em&gt; resolvieron problemas reales. La cascada nunca fue uno de ellos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por qué existe el problema
&lt;/h2&gt;

&lt;p&gt;Los &lt;em&gt;frameworks&lt;/em&gt; se construyeron para solucionar problemas que realmente requerían atención: el marcado inconsistente de los componentes en un equipo, el tedio de crear a mano los mismos patrones de botones y tarjetas por décima vez, y una brecha de herramientas real en torno a los pasos de compilación, la depuración de estilos no utilizados y la distribución de &lt;em&gt;tokens&lt;/em&gt; a escala. Resolver estos problemas justificó un esfuerzo de ingeniería serio. Los &lt;em&gt;frameworks&lt;/em&gt; se ganaron su adopción de forma honesta: resolviéndolos bien.&lt;/p&gt;

&lt;p&gt;Ninguno de esos esfuerzos afectó al origen, al orden de las capas, a la especificidad o al &lt;em&gt;source order&lt;/em&gt;. La secuencia de resolución que esta serie explicó en su segunda fase siguió funcionando exactamente como siempre, por debajo de las clases del &lt;em&gt;framework&lt;/em&gt; en lugar de las del propio autor. Un equipo podría adoptar la biblioteca de componentes más disciplinada del mercado y, aun así, heredar cada guerra de sobrescrituras, cada estilo base accidentalmente demasiado específico y cada interacción impredecible que esta serie ha diagnosticado a lo largo de ocho artículos. El &lt;em&gt;framework&lt;/em&gt; cambió lo que se escribe. Nunca tocó cómo el navegador decide cuál de ellos gana.&lt;/p&gt;

&lt;h2&gt;
  
  
  El primer principio
&lt;/h2&gt;

&lt;p&gt;La composición y la reutilización son problemas del tiempo de autoría: qué tan conveniente resulta construir la interfaz de usuario. La cascada es un problema del tiempo de resolución: cómo decide el navegador qué gana cuando hay un conflicto entre reglas.&lt;/p&gt;

&lt;p&gt;Se trata de dos capas diferentes del mismo sistema, resueltas por dos tipos distintos de ingeniería. Un &lt;em&gt;framework&lt;/em&gt; puede mejorar drásticamente la autoría y, al mismo tiempo, dejar la resolución igual de impredecible. Mejorar una capa nunca iba a afectar a la otra. Eso no es un defecto en los objetivos de los &lt;em&gt;frameworks&lt;/em&gt;. Es una categoría a la que nunca estuvieron dirigidos en primer lugar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demostración del principio
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.btn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.5rem&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.btn-primary&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dos clases con estilo de &lt;em&gt;framework&lt;/em&gt;, aplicadas juntas al mismo botón. Cuál de ellas gana si alguna vez hay un conflicto en la misma propiedad no se decide por nada que el &lt;em&gt;framework&lt;/em&gt; haya introducido: sigue dependiendo del &lt;em&gt;source order&lt;/em&gt; y de la especificidad, resueltos por la secuencia exacta explicada anteriormente en esta serie. El vocabulario cambió. El mecanismo que decide el resultado, no.&lt;/p&gt;

&lt;h2&gt;
  
  
  quell como caso de estudio
&lt;/h2&gt;

&lt;p&gt;quell existe para abordar esa capa de resolución directamente, en lugar de ofrecer comodidad sobre una cascada que queda sin resolver por debajo.&lt;/p&gt;

&lt;h2&gt;
  
  
  La lección general
&lt;/h2&gt;

&lt;p&gt;Este es un patrón familiar también fuera de CSS: una solución real y valiosa a un problema se confunde con la solución a un problema diferente y adyacente, simplemente porque ambos aparecieron empaquetados en la misma herramienta. Ese empaquetado no fue deshonesto. Solo significó que un problema se resolvió con tanto ruido que el otro se silenció, sin llegar a desaparecer realmente.&lt;/p&gt;

&lt;p&gt;Las herramientas de composición y las garantías arquitectónicas no pertenecen a la misma categoría. Los próximos dos artículos trazan esa línea con mayor precisión.&lt;/p&gt;

</description>
      <category>css</category>
      <category>arquitectura</category>
      <category>desarrolloweb</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Frameworks Didn't Solve CSS. They Avoided It.</title>
      <dc:creator>Franklin</dc:creator>
      <pubDate>Tue, 01 Sep 2026 10:45:26 +0000</pubDate>
      <link>https://dev.to/ortizfranklindev/frameworks-didnt-solve-css-they-avoided-it-4e8o</link>
      <guid>https://dev.to/ortizfranklindev/frameworks-didnt-solve-css-they-avoided-it-4e8o</guid>
      <description>&lt;p&gt;&lt;em&gt;Also available in &lt;a href="https://dev.to/ortizfranklindev/los-frameworks-no-resolvieron-el-problema-de-css-lo-evitaron-jfk"&gt;Español&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;"We don't have CSS problems, we use Tailwind." "Bootstrap handles that for us." Some version of that sentence gets said on nearly every team that's adopted a framework, and it's usually said with real relief.&lt;/p&gt;

&lt;p&gt;It's also not quite true. Frameworks solved real problems. The cascade was never one of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the Problem Exists
&lt;/h2&gt;

&lt;p&gt;Frameworks were built to fix things that genuinely needed fixing: inconsistent component markup across a team, the tedium of hand-rolling the same button and card patterns for the tenth time, and a real tooling gap around build steps, purging unused styles, and distributing design tokens at scale. Solving those was worth serious engineering effort, and frameworks earned their adoption honestly by solving them well.&lt;/p&gt;

&lt;p&gt;None of that effort touched origin, layer order, specificity, or source order. The resolution sequence this series spent its second phase explaining kept operating exactly as it always had, underneath the framework's classes instead of an author's own. A team could adopt the most disciplined component library available and still inherit every override war, every accidentally-too-specific base style, every unpredictable interaction this series has spent eight articles diagnosing. The framework changed what got written. It never touched how the browser decides which of it wins.&lt;/p&gt;

&lt;h2&gt;
  
  
  The First Principle
&lt;/h2&gt;

&lt;p&gt;Composition and reuse are authoring-time problems: how convenient is it to build UI. The cascade is a resolution-time problem: how the browser decides what wins when rules conflict.&lt;/p&gt;

&lt;p&gt;Those are two different layers of the same system, solved by two different kinds of engineering. A framework can make authoring dramatically better while leaving resolution exactly as unpredictable as it was, because making one layer better was never going to touch the other. That's not a flaw in what frameworks set out to do. It's a category they were never aimed at in the first place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demonstrating the Principle
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.btn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.5rem&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.btn-primary&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two framework-style classes, applied together to the same button. Which wins if they ever conflict on the same property isn't decided by anything the framework introduced — it still comes down to source order and specificity, resolved by the exact sequence from earlier in this series. The vocabulary changed. The mechanism deciding the outcome didn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  quell as the Case Study
&lt;/h2&gt;

&lt;p&gt;quell exists to address that resolution layer directly, rather than offering convenience on top of a cascade left unresolved underneath it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Broader Lesson
&lt;/h2&gt;

&lt;p&gt;This is a familiar shape outside CSS too: a real, valuable solution to one problem gets mistaken for a solution to a different, adjacent problem, because the two showed up bundled together in the same tool. The bundling wasn't dishonest. It just meant one problem got solved loudly enough that the other one went quiet without actually going away.&lt;/p&gt;

&lt;p&gt;Composition tools and architectural guarantees aren't the same category of thing. The next two articles draw that line more precisely.&lt;/p&gt;

</description>
      <category>css</category>
      <category>webdev</category>
      <category>architecture</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Notas desde el pase: qué pasa cuando el estado se esconde dentro de un token</title>
      <dc:creator>Franklin</dc:creator>
      <pubDate>Sat, 29 Aug 2026 10:51:32 +0000</pubDate>
      <link>https://dev.to/ortizfranklindev/notas-desde-el-pase-que-pasa-cuando-el-estado-se-esconde-dentro-de-un-token-7j1</link>
      <guid>https://dev.to/ortizfranklindev/notas-desde-el-pase-que-pasa-cuando-el-estado-se-esconde-dentro-de-un-token-7j1</guid>
      <description>&lt;p&gt;&lt;em&gt;Also available in &lt;a href="https://dev.to/ortizfranklindev/notes-from-the-pass-what-happens-when-state-hides-inside-a-token-1oel"&gt;Inglés&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  La afirmación a prueba
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/ortizfranklindev/la-mejor-arquitectura-css-comienza-al-decidir-que-no-debe-hacer-css-jamas-1a7k"&gt;La última entrega de esta serie&lt;/a&gt; sostuvo que un sistema sin exclusiones declaradas terminará recibiendo la petición de hacerlo todo, porque nada dentro de él tiene argumentos para negarse. El ejemplo fue una sola línea: &lt;code&gt;--is-modal-open&lt;/code&gt; junto a &lt;code&gt;--spacing-md&lt;/code&gt;. Sintácticamente idénticas. Semánticamente sin ninguna relación.&lt;/p&gt;

&lt;p&gt;Esa es una afirmación sobre los sistemas en general. Esto es lo que parece dentro de un archivo que realmente existe, con un mecanismo que depende en la práctica de que el límite se mantenga.&lt;/p&gt;

&lt;h2&gt;
  
  
  El artefacto
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;quell-base.css&lt;/code&gt; declara una capa &lt;code&gt;ghost_tokens&lt;/code&gt;. Su propósito, expresado de forma simple en el comentario de cabecera del propio archivo, es proveer valores de respaldo (&lt;em&gt;fallback&lt;/em&gt;) completamente resueltos antes del pintado (&lt;em&gt;paint&lt;/em&gt;) para cada token que consume la base. No es decoración: es un cortafuegos contra el FOUC (&lt;em&gt;Flash of Unstyled Content&lt;/em&gt;). Las llamadas &lt;code&gt;var()&lt;/code&gt; descendientes nunca se quedan con una cadena vacía, incluso si una hoja de estilos de un tema aún no se ha cargado.&lt;/p&gt;

&lt;p&gt;Aquí hay un fragmento real:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@layer&lt;/span&gt; &lt;span class="n"&gt;ghost_tokens&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="py"&gt;--color-accent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;          &lt;span class="m"&gt;#0057cc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c"&gt;/* WCAG AA on white; override freely */&lt;/span&gt;
    &lt;span class="py"&gt;--color-accent-hover&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="m"&gt;#003fa3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--color-accent-subtle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="m"&gt;#dbeafe&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--color-surface&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;         &lt;span class="m"&gt;#ffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--color-surface-subtle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--color-neutral-50&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora imagina que el commit que describió el último artículo aterriza aquí:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@layer&lt;/span&gt; &lt;span class="n"&gt;ghost_tokens&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="py"&gt;--color-accent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;          &lt;span class="m"&gt;#0057cc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--color-accent-hover&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="m"&gt;#003fa3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--color-accent-subtle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="m"&gt;#dbeafe&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--is-modal-open&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;         &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c"&gt;/* tracks modal visibility */&lt;/span&gt;

  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La sintaxis no pone objeciones. El navegador procesa &lt;code&gt;--is-modal-open&lt;/code&gt; con la misma facilidad que &lt;code&gt;--color-accent&lt;/code&gt;. Nada en la capa &lt;code&gt;@layer ghost_tokens&lt;/code&gt; lo rechaza. Ese es el punto central del último artículo, ahora ubicado dentro de un archivo con una tarea documentada que proteger.&lt;/p&gt;

&lt;p&gt;Ya existe otro límite en el archivo: la convención de nomenclatura de tokens define el vocabulario esperado como &lt;code&gt;font&lt;/code&gt;, &lt;code&gt;color&lt;/code&gt;, &lt;code&gt;space&lt;/code&gt;, &lt;code&gt;size&lt;/code&gt;, &lt;code&gt;radius&lt;/code&gt;, &lt;code&gt;border&lt;/code&gt;, &lt;code&gt;shadow&lt;/code&gt; y &lt;code&gt;motion&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;--color-accent&lt;/code&gt; pertenece a ese vocabulario.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;--is-modal-open&lt;/code&gt; no.&lt;/p&gt;

&lt;p&gt;El navegador no puede imponer esa distinción. La arquitectura tiene que hacerlo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué se rompe realmente
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;ghost_tokens&lt;/code&gt; no solo contiene valores: hace una promesa específica sobre cuándo están disponibles esos valores. Se resuelven como respaldos de la base antes del pintado, antes de que exista necesariamente una hoja de estilos de tema. Para un color, esa promesa es inofensiva. &lt;code&gt;--color-accent&lt;/code&gt; no cambia de significado según el estado de la aplicación (&lt;em&gt;application state&lt;/em&gt;); el azul resuelto temprano sigue siendo el azul resuelto más tarde.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;--is-modal-open&lt;/code&gt; es diferente. En el momento en que vive en esta capa, se trata como si el estado de la aplicación fuera otro valor base. El valor de respaldo ya no es un simple respaldo. Es una afirmación: la página ahora tiene una opinión sobre el estado del modal antes de que la aplicación haya establecido ese estado.&lt;/p&gt;

&lt;p&gt;Ese es el cortafuegos contra el FOUC que la capa fue construida para proporcionar, al que ahora se le pide proteger una suposición del estado de la aplicación en lugar de un valor base.&lt;/p&gt;

&lt;p&gt;El archivo también documenta tres formas en que los autores descendientes pueden tomar el control del sistema, en orden de poder ascendente: volver a declarar una propiedad personalizada (&lt;em&gt;custom property&lt;/em&gt;) en un &lt;code&gt;:root&lt;/code&gt; sin capa, añadir contenido a una capa existente o escribir una regla sin capa directamente. La primera es la sobrescritura de tokens documentada; las otras operan a nivel de capas y de hojas de estilo.&lt;/p&gt;

&lt;p&gt;Todos estos mecanismos asumen que el contrato subyacente permanece intacto: los tokens son valores que los autores descendientes son libres de reemplazar. Un autor de temas que sobrescribe &lt;code&gt;--color-accent&lt;/code&gt; cambia lo que significa el azul. Un autor de temas que sobrescribe &lt;code&gt;--is-modal-open&lt;/code&gt; no está personalizando un valor de diseño. Está afirmando un hecho sobre el estado de la aplicación mediante un mecanismo que fue diseñado para proporcionar valores base.&lt;/p&gt;

&lt;h2&gt;
  
  
  El momento en que realmente divergir
&lt;/h2&gt;

&lt;p&gt;Redúcelo a dos declaraciones, la misma capa, la misma sintaxis:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;--color-accent&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="err"&gt;#0057&lt;/span&gt;&lt;span class="nt"&gt;cc&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;  &lt;span class="c"&gt;/* a value */&lt;/span&gt;
&lt;span class="nt"&gt;--is-modal-open&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;        &lt;span class="c"&gt;/* application state */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En el momento del análisis (&lt;em&gt;parse time&lt;/em&gt;), el navegador no puede distinguirlos. Nada en el algoritmo de la cascada diferencia un valor de diseño de un valor de estado de la aplicación. Ambos son propiedades personalizadas (&lt;em&gt;custom properties&lt;/em&gt;). Ambos son declaraciones válidas.&lt;/p&gt;

&lt;p&gt;Esa distinción debe decidirse antes de que la capa exista, por quienquiera que escriba la regla en la que se permite cualquiera de los dos tokens.&lt;/p&gt;

&lt;p&gt;El navegador nunca lo hará por ti.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lo que esto realmente demuestra
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;ghost_tokens&lt;/code&gt; no se rompe por &lt;code&gt;--is-modal-open&lt;/code&gt;. Hace exactamente aquello para lo que fue construido: resolver la propiedad personalizada como parte de la base antes del pintado. El problema es arquitectónico: &lt;strong&gt;el contrato de la capa consiste en proporcionar valores de respaldo base, mientras que el estado de la aplicación es un hecho establecido por la aplicación.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;CSS puede responder al estado. &lt;code&gt;quell&lt;/code&gt; hace esto en otras partes del sistema: su capa de formularios (&lt;code&gt;forms&lt;/code&gt;) proporciona valores por defecto accesibles para estados como &lt;code&gt;disabled&lt;/code&gt;, &lt;code&gt;readonly&lt;/code&gt; e &lt;code&gt;invalid&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Por lo tanto, el límite no es que CSS nunca debe contener estado.&lt;/p&gt;

&lt;p&gt;El límite es más estrecho y más útil:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Una capa de tokens base no debe convertirse en el almacén de estado de la aplicación solo porque CSS otorgue la misma sintaxis a ambos tipos de información.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Eso es lo que expone el ejemplo de &lt;code&gt;--is-modal-open&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;El límite del último artículo no es una preferencia de estilo. Es la diferencia entre una capa que cumple su promesa y otra que ha sido redirigida silenciosamente para cumplir una promesa para la que nunca fue diseñada.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/ortizfranklindev/la-mejor-arquitectura-css-comienza-al-decidir-que-no-debe-hacer-css-jamas-1a7k"&gt;La mejor arquitectura de CSS comienza por decidir qué no debe hacer nunca CSS&lt;/a&gt;&lt;/p&gt;

</description>
      <category>css</category>
      <category>webdev</category>
      <category>architecture</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Notes from the Pass: What Happens When State Hides Inside a Token</title>
      <dc:creator>Franklin</dc:creator>
      <pubDate>Sat, 29 Aug 2026 10:48:01 +0000</pubDate>
      <link>https://dev.to/ortizfranklindev/notes-from-the-pass-what-happens-when-state-hides-inside-a-token-1oel</link>
      <guid>https://dev.to/ortizfranklindev/notes-from-the-pass-what-happens-when-state-hides-inside-a-token-1oel</guid>
      <description>&lt;p&gt;&lt;em&gt;Also available in &lt;a href="https://dev.to/ortizfranklindev/notas-desde-el-pase-que-pasa-cuando-el-estado-se-esconde-dentro-de-un-token-7j1"&gt;Español&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Claim Being Tested
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/ortizfranklindev/the-best-css-architecture-starts-by-deciding-what-css-should-never-do-1d5o"&gt;The last piece in this series&lt;/a&gt; argued that a system with no declared exclusions will eventually be asked to do everything, because nothing inside it has grounds to refuse. The example was a single line: &lt;code&gt;--is-modal-open&lt;/code&gt; sitting next to &lt;code&gt;--spacing-md&lt;/code&gt;, syntactically identical, semantically nothing alike.&lt;/p&gt;

&lt;p&gt;That's a claim about systems in general. Here's what it looks like inside a file that actually exists, with a mechanism that actually depends on the boundary holding.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Artifact
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;quell-base.css&lt;/code&gt; declares a &lt;code&gt;ghost_tokens&lt;/code&gt; layer. Its job, stated plainly in the file's own header comment, is to provide fully-resolved fallback values for every token the baseline consumes, resolved before paint. That's not decoration — it's a FOUC firewall. Downstream &lt;code&gt;var()&lt;/code&gt; calls are never left with an empty string, even if a theme sheet hasn't loaded yet.&lt;/p&gt;

&lt;p&gt;Here's a real slice of it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@layer&lt;/span&gt; &lt;span class="n"&gt;ghost_tokens&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="py"&gt;--color-accent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;          &lt;span class="m"&gt;#0057cc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c"&gt;/* WCAG AA on white; override freely */&lt;/span&gt;
    &lt;span class="py"&gt;--color-accent-hover&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="m"&gt;#003fa3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--color-accent-subtle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="m"&gt;#dbeafe&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--color-surface&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;         &lt;span class="m"&gt;#ffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--color-surface-subtle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--color-neutral-50&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now imagine the commit the last essay described actually landing here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@layer&lt;/span&gt; &lt;span class="n"&gt;ghost_tokens&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="py"&gt;--color-accent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;          &lt;span class="m"&gt;#0057cc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--color-accent-hover&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="m"&gt;#003fa3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--color-accent-subtle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="m"&gt;#dbeafe&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--is-modal-open&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;         &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c"&gt;/* tracks modal visibility */&lt;/span&gt;

  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing about the syntax objects. The browser parses &lt;code&gt;--is-modal-open&lt;/code&gt; exactly as readily as &lt;code&gt;--color-accent&lt;/code&gt;. Nothing in &lt;code&gt;@layer ghost_tokens&lt;/code&gt; refuses it. That's the whole point of the last essay, now sitting inside a file with a documented job to protect.&lt;/p&gt;

&lt;p&gt;There's another boundary already present in the file: the token naming convention defines the expected vocabulary as &lt;code&gt;font&lt;/code&gt;, &lt;code&gt;color&lt;/code&gt;, &lt;code&gt;space&lt;/code&gt;, &lt;code&gt;size&lt;/code&gt;, &lt;code&gt;radius&lt;/code&gt;, &lt;code&gt;border&lt;/code&gt;, &lt;code&gt;shadow&lt;/code&gt;, and &lt;code&gt;motion&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;--color-accent&lt;/code&gt; belongs to that vocabulary.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;--is-modal-open&lt;/code&gt; does not.&lt;/p&gt;

&lt;p&gt;The browser cannot enforce that distinction. The architecture has to.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Actually Breaks
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;ghost_tokens&lt;/code&gt; doesn't just hold values — it makes a specific promise about when those values are available: they are resolved as baseline fallbacks before paint, before a theme sheet necessarily exists. For a color, that promise is harmless. &lt;code&gt;--color-accent&lt;/code&gt; doesn't change meaning based on application state; blue resolved early is still blue resolved later.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;--is-modal-open&lt;/code&gt; is different. The moment it lives in this layer, it is being treated as though application state were another baseline value. The fallback value isn't merely a fallback anymore. It's an assertion — the page now has an opinion about modal state before the application has established that state.&lt;/p&gt;

&lt;p&gt;That's the FOUC firewall the layer was built to provide, now being asked to protect an application-state assumption instead of a baseline value.&lt;/p&gt;

&lt;p&gt;The file also documents three ways downstream authors can take control of the system, in ascending power: re-declare a custom property on an unlayered &lt;code&gt;:root&lt;/code&gt;, append to an existing layer, or write an unlayered rule outright. The first is the documented token override; the others operate at the layer and stylesheet levels.&lt;/p&gt;

&lt;p&gt;All of these mechanisms assume the underlying contract remains intact: tokens are values that downstream authors are free to replace. A theme author who overrides &lt;code&gt;--color-accent&lt;/code&gt; changes what blue means. A theme author who overrides &lt;code&gt;--is-modal-open&lt;/code&gt; isn't customizing a design value. They're asserting a fact about application state through a mechanism that was designed to provide baseline values.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Moment It Actually Diverges
&lt;/h2&gt;

&lt;p&gt;Strip it down to two declarations, same layer, same syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;--color-accent&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="err"&gt;#0057&lt;/span&gt;&lt;span class="nt"&gt;cc&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;  &lt;span class="c"&gt;/* a value */&lt;/span&gt;
&lt;span class="nt"&gt;--is-modal-open&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;        &lt;span class="c"&gt;/* application state */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At parse time, the browser cannot tell these apart. Nothing in the cascade algorithm distinguishes a design value from an application-state value. Both are custom properties. Both are valid declarations.&lt;/p&gt;

&lt;p&gt;That distinction has to be decided before the layer exists, by whoever writes the rule that either token is allowed in.&lt;/p&gt;

&lt;p&gt;The browser will never do it for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Actually Shows
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;ghost_tokens&lt;/code&gt; isn't broken by &lt;code&gt;--is-modal-open&lt;/code&gt;. It does exactly what it was built to do — resolve the custom property as part of the baseline before paint. The problem is architectural: &lt;strong&gt;the layer's contract is about providing baseline fallback values, while application state is a fact established by the application.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;CSS can respond to state. &lt;code&gt;quell&lt;/code&gt; does this elsewhere in the system: its &lt;code&gt;forms&lt;/code&gt; layer provides accessible defaults for states such as disabled, readonly, and invalid.&lt;/p&gt;

&lt;p&gt;The boundary is not therefore "CSS must never contain state."&lt;/p&gt;

&lt;p&gt;The boundary is narrower, and more useful:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A baseline token layer should not become the application-state store merely because CSS gives both kinds of information the same syntax.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's what the &lt;code&gt;--is-modal-open&lt;/code&gt; example exposes.&lt;/p&gt;

&lt;p&gt;The boundary in the last essay isn't a style preference. It's the difference between a layer that keeps its promise and one that's been quietly repurposed into keeping a promise it was never designed to make.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/ortizfranklindev/the-best-css-architecture-starts-by-deciding-what-css-should-never-do-1d5o"&gt;The Best CSS Architecture Starts by Deciding What CSS Should Never Do&lt;/a&gt;&lt;/p&gt;

</description>
      <category>css</category>
      <category>webdev</category>
      <category>architecture</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Por qué la especificidad cero lo cambia todo</title>
      <dc:creator>Franklin</dc:creator>
      <pubDate>Thu, 27 Aug 2026 10:48:08 +0000</pubDate>
      <link>https://dev.to/ortizfranklindev/por-que-la-especificidad-cero-lo-cambia-todo-12e0</link>
      <guid>https://dev.to/ortizfranklindev/por-que-la-especificidad-cero-lo-cambia-todo-12e0</guid>
      <description>&lt;p&gt;&lt;em&gt;También disponible en&lt;/em&gt; &lt;a href="https://dev.to/ortizfranklindev/why-zero-specificity-changes-everything-2kik"&gt;Inglés&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  El problema
&lt;/h2&gt;

&lt;p&gt;Un estilo base se escribe para ser silencioso. Algo destinado a establecer un valor por defecto sensato y luego apartarse en el momento en que aparezca algo más específico para sobrescribirlo.&lt;/p&gt;

&lt;p&gt;No se aparta. El estilo propio de un componente, escrito más tarde con lo que parece un selector perfectamente razonable, pierde contra él de todos modos. El desarrollador que escribió el estilo base nunca quiso que ganara. Ganó de todos modos, porque nada en la forma en que fue escrito declaró jamás debería perder siempre.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por qué existe el problema
&lt;/h2&gt;

&lt;p&gt;La mayoría de los selectores acumulan especificidad como un efecto secundario de la forma en que resultan estar escritos, no como una elección deliberada que alguien haya tomado a propósito. &lt;code&gt;:is()&lt;/code&gt; es un buen ejemplo de esto en la práctica: genuinamente útil para agrupar varios selectores en una sola regla, pero asume silenciosamente la especificidad de su argumento más específico. Un selector elegido por conveniencia puede convertirse en un peso pesado sin que nadie pretenda ese resultado.&lt;/p&gt;

&lt;p&gt;Nada en el CSS ordinario permite a un autor decir, directamente, «agrupa estos, pero mantén el resultado en cero». Así que los valores por defecto se vuelven silenciosamente más poderosos de lo que se pretendía, y los mismos problemas de sobrescritura mencionados anteriormente en esta serie resurgen aquí con una nueva forma; no porque alguien haya sido descuidado, sino porque la especificidad se acumulaba como un subproducto en lugar de declararse como una decisión.&lt;/p&gt;

&lt;h2&gt;
  
  
  El primer principio
&lt;/h2&gt;

&lt;p&gt;La especificidad de cero no es una ausencia de poder. Es una intención declarada: esta regla debe ser siempre lo más fácil de sobrescribir en la base de código.&lt;/p&gt;

&lt;p&gt;Esa no es una regla más débil. Es una regla con un rol permanente y declarado; la misma idea de declarado, no calculado de una fase anterior, que ahora vive dentro de un solo selector en lugar de un sistema de ordenamiento completo. Elegir especificidad cero a propósito resulta ser un movimiento más sofisticado que el manejo cuidadoso de la especificidad de forma ascendente.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demostración del principio
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nd"&gt;:is&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;margin-block&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pistas de especificidad según los argumentos: &lt;code&gt;:is()&lt;/code&gt; recoge especificidad real de sus argumentos; esta regla aún puede competir con un selector de clase y, dependiendo de qué más esté anidado dentro, a veces ganar cuando no debería.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nd"&gt;:where&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;margin-block&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La alternativa con &lt;code&gt;:where()&lt;/code&gt; aporta cero especificidad, independientemente de lo que se agrupe dentro de ella. Una sola clase supera esto siempre, por diseño; no porque el selector sea débil, sino porque fue escrito para perder siempre a propósito.&lt;/p&gt;

&lt;h2&gt;
  
  
  quell como caso de estudio
&lt;/h2&gt;

&lt;p&gt;quell usa &lt;code&gt;:where()&lt;/code&gt; en toda su capa base específicamente para que nada destinado a ser un valor por defecto silencioso pueda superar accidentalmente a algo destinado a sobrescribirlo.&lt;/p&gt;

&lt;h2&gt;
  
  
  La lección más amplia
&lt;/h2&gt;

&lt;p&gt;La Fase Dos cierra aquí, y vale la pena nombrar lo que ha sido cierto en estos cuatro artículos: Capas. El orden de resolución completo. Exclusiones deliberadas. Ahora, especificidad cero. Cada uno tiene la misma forma subyacente: la precedencia, el alcance y el poder son más fuertes cuando se declaran a propósito, no cuando se dejan acumular como un efecto secundario de cómo se escribió algo.&lt;/p&gt;

&lt;p&gt;Esa es todo el cambio que ha venido realizando esta fase, un mecanismo a la vez: de una cascada que la gente gestionaba de forma defensiva, regla por regla, a una cascada contra la que la gente realmente puede diseñar, a propósito y de antemano.&lt;/p&gt;

</description>
      <category>css</category>
      <category>arquitectura</category>
      <category>desarrolloweb</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Why Zero Specificity Changes Everything</title>
      <dc:creator>Franklin</dc:creator>
      <pubDate>Thu, 27 Aug 2026 10:40:06 +0000</pubDate>
      <link>https://dev.to/ortizfranklindev/why-zero-specificity-changes-everything-2kik</link>
      <guid>https://dev.to/ortizfranklindev/why-zero-specificity-changes-everything-2kik</guid>
      <description>&lt;p&gt;&lt;em&gt;Also available in &lt;a href="https://dev.to/ortizfranklindev/por-que-la-especificidad-cero-lo-cambia-todo-12e0"&gt;Español&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;A base style gets written to be quiet. Something meant to set a sensible default and then get out of the way the moment anything more specific shows up to override it.&lt;/p&gt;

&lt;p&gt;It doesn't get out of the way. A component's own styling, written later, with what looks like a perfectly reasonable selector, loses to it anyway. The developer who wrote the base style never wanted it to win. It won regardless, because nothing in how it was written ever declared "I should always lose."&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the Problem Exists
&lt;/h2&gt;

&lt;p&gt;Most selectors accumulate specificity as a side effect of how they happen to be written, not as a deliberate choice anyone made on purpose. &lt;code&gt;:is()&lt;/code&gt; is a good example of this in practice: genuinely useful for grouping several selectors into one rule, but it quietly takes on the specificity of its most specific argument. A selector reached for out of convenience can become a heavyweight one without anyone intending that outcome.&lt;/p&gt;

&lt;p&gt;Nothing in ordinary CSS lets an author say, directly, "group these together, but keep the result at zero." So defaults quietly become more powerful than they were meant to be, and the same override problems named earlier in this series resurface here in a new shape not because anyone was careless, but because specificity was accumulating as a byproduct instead of being declared as a decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  The First Principle
&lt;/h2&gt;

&lt;p&gt;Specificity of zero isn't an absence of power. It's a declared intention: this rule should always be the easiest thing in the codebase to override.&lt;/p&gt;

&lt;p&gt;That's not a weaker rule. It's a rule with a stated, permanent role the same "declared, not calculated" idea from earlier in this phase, now living inside a single selector instead of an entire ordering system. Choosing zero specificity on purpose turns out to be a more sophisticated move than carefully managing specificity upward ever was.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demonstrating the Principle
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nd"&gt;:is&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;margin-block&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Picks up real specificity from its arguments this rule can still fight a class selector and, depending on what else is nested inside, sometimes win when it shouldn't.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nd"&gt;:where&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;margin-block&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;:where()&lt;/code&gt; Contributes zero specificity, regardless of what's grouped inside it. A single class beats this every time, by design — not because the selector is weak, but because it was written to always lose on purpose.&lt;/p&gt;

&lt;h2&gt;
  
  
  quell as the Case Study
&lt;/h2&gt;

&lt;p&gt;quell uses &lt;code&gt;:where()&lt;/code&gt; throughout its base layer specifically so nothing meant to be a quiet default can ever accidentally out-rank something meant to override it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Broader Lesson
&lt;/h2&gt;

&lt;p&gt;Phase Two closes here, and it's worth naming what's been true across all four of these articles. Layers. The full resolution order. Deliberate exclusions. Now zero specificity. Every one of them has the same shape underneath: precedence, scope, and power are strongest when they're declared on purpose, not left to accumulate as a side effect of how something happened to get written.&lt;/p&gt;

&lt;p&gt;That's the whole shift this phase has been making, one mechanism at a time: from a cascade people managed defensively, rule by rule, to a cascade people can actually design against, on purpose, in advance.&lt;/p&gt;

</description>
      <category>css</category>
      <category>architecture</category>
      <category>frontend</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
