/* ==========================================================================
   Tokens
   ========================================================================== */
:root {
  --accent: #c2410c;
  --accent-soft: #fff0e6;
  --accent-text: #fff;

  --bg: #ffffff;
  --bg-alt: #f6f7fb;
  --surface: #ffffff;
  --border: #e4e6ef;
  --border-strong: #cfd2e2;

  --text: #16182b;
  --text-soft: #5b6076;
  --text-faint: #8b90a6;

  --good: #0f9960;
  --good-bg: #e6f7ef;
  --warn: #b25000;
  --warn-bg: #fdf0e5;
  --bad: #c8304b;
  --bad-bg: #fdecef;

  --radius: 12px;
  --radius-lg: 18px;
  --shadow: 0 1px 2px rgba(16, 18, 40, .06), 0 8px 24px -12px rgba(16, 18, 40, .12);
  --shadow-lift: 0 2px 4px rgba(16, 18, 40, .07), 0 16px 32px -16px rgba(16, 18, 40, .22);

  --font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  --wrap: 1140px;
  --narrow: 760px;
}

/* Dark theme.
   Light is the default for everyone. Dark applies only when the visitor picks
   it from the header toggle; the choice is stored in localStorage and
   re-applied by an inline script before first paint, so there is no flash.
   Deliberately NOT keyed to prefers-color-scheme — a visitor arriving with a
   dark OS still gets light until they choose otherwise. */
:root[data-theme="dark"] {
  --accent: #fb923c;
  --accent-soft: #33200f;
  --accent-text: #1a0f07;

  --bg: #0e0f1a;
  --bg-alt: #141625;
  --surface: #171930;
  --border: #262943;
  --border-strong: #363a5c;

  --text: #eceef8;
  --text-soft: #a4a9c4;
  --text-faint: #767c9a;

  --good: #4ade9a;
  --good-bg: #13301f;
  --warn: #f0a55a;
  --warn-bg: #33210f;
  --bad: #ff7d95;
  --bad-bg: #351320;

  --shadow: 0 1px 2px rgba(0, 0, 0, .4), 0 8px 24px -12px rgba(0, 0, 0, .6);
  --shadow-lift: 0 2px 4px rgba(0, 0, 0, .5), 0 16px 32px -16px rgba(0, 0, 0, .7);

  color-scheme: dark;
}

/* ==========================================================================
   Base
   ========================================================================== */
*, *::before, *::after { box-sizing: border-box; }

/* `overflow-y: scroll` y no solo `scrollbar-gutter: stable`: el gutter es lo
   correcto y lo que no pinta nada donde la barra es flotante, pero medido en
   Chrome no reservaba el canal en las páginas que no desbordan, que son
   justamente las que producían el salto. Con los dos, la reserva está
   garantizada y donde el gutter funciona se ve igual que antes. */
html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
  scrollbar-gutter: stable;
  overflow-y: scroll;
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

body {
  margin: 0;
  font-family: var(--font);
  font-size: 17px;
  line-height: 1.65;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 { line-height: 1.2; letter-spacing: -.02em; margin: 0 0 .5em; font-weight: 700; }
h1 { font-size: clamp(2rem, 1.3rem + 2.6vw, 3rem); letter-spacing: -.03em; }
h2 { font-size: clamp(1.4rem, 1.1rem + 1vw, 1.8rem); }
h3 { font-size: 1.15rem; }
p { margin: 0 0 1.1em; }

a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { text-decoration-thickness: 2px; }

code {
  font-family: var(--mono);
  font-size: .87em;
  background: var(--bg-alt);
  border: 1px solid var(--border);
  border-radius: 5px;
  padding: .1em .35em;
}

:focus-visible { outline: 2.5px solid var(--accent); outline-offset: 2px; border-radius: 4px; }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--accent); color: var(--accent-text);
  padding: .7rem 1.1rem; border-radius: 0 0 var(--radius) 0; font-weight: 600;
}
.skip-link:focus { left: 0; }

.wrap { max-width: var(--wrap); margin-inline: auto; padding-inline: 20px; }
.wrap.narrow { max-width: var(--narrow); }
.section { margin-block: 3.5rem; }
.muted { color: var(--text-soft); }

/* ==========================================================================
   Header / footer
   ========================================================================== */
.site-header {
  position: sticky; top: 0; z-index: 30;
  background: color-mix(in srgb, var(--bg) 85%, transparent);
  backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--border);
}
.header-inner { display: flex; align-items: center; justify-content: space-between; gap: 1rem; min-height: 62px; }

.brand {
  display: inline-flex; align-items: center; gap: .55rem;
  font-weight: 700; font-size: 1.12rem; letter-spacing: -.02em;
  color: var(--text); text-decoration: none;
}
.brand-mark { fill: var(--accent); flex: none; }
.brand--footer { font-size: 1rem; margin-bottom: .5rem; }

.site-nav { display: flex; gap: .35rem; flex-wrap: wrap; }
.site-nav a {
  color: var(--text-soft); text-decoration: none; font-size: .94rem; font-weight: 550;
  padding: .45rem .7rem; border-radius: 8px;
}
.site-nav a:hover { color: var(--text); background: var(--bg-alt); }
.nav-short { display: none; }

.site-footer {
  margin-top: 5rem; padding-block: 2.5rem 2rem;
  border-top: 1px solid var(--border); background: var(--bg-alt);
  font-size: .93rem;
}
.footer-top { display: flex; flex-wrap: wrap; gap: 1.5rem 3rem; justify-content: space-between; }
.footer-blurb { color: var(--text-soft); max-width: 44ch; margin: 0; }
.footer-nav { display: flex; flex-wrap: wrap; gap: .3rem 1.4rem; align-content: start; }
.footer-nav a { color: var(--text-soft); text-decoration: none; }
.footer-nav a:hover { color: var(--accent); text-decoration: underline; }
.copyright { margin: 2rem 0 0; color: var(--text-faint); font-size: .87rem; }

.breadcrumbs {
  display: flex; flex-wrap: wrap; align-items: center; gap: .5rem;
  padding-top: 1.1rem; font-size: .86rem; color: var(--text-faint);
}
.breadcrumbs a { color: var(--text-soft); text-decoration: none; }
.breadcrumbs a:hover { color: var(--accent); text-decoration: underline; }
.breadcrumbs .sep { color: var(--border-strong); }

/* ==========================================================================
   Buttons
   ========================================================================== */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
  background: var(--accent); color: var(--accent-text);
  border: 1px solid transparent; border-radius: 10px;
  padding: .6rem 1.1rem;
  font: inherit; font-weight: 600; font-size: .95rem;
  text-decoration: none; cursor: pointer;
  transition: transform .12s ease, filter .12s ease, background .12s ease;
}
.btn:hover { filter: brightness(1.08); transform: translateY(-1px); }
.btn:active { transform: translateY(0); }
.btn-lg { padding: .8rem 1.5rem; font-size: 1rem; }
.btn-small { padding: .4rem .8rem; font-size: .85rem; border-radius: 8px; }
.btn-ghost {
  background: var(--surface); color: var(--text); border-color: var(--border-strong);
}
.btn-ghost:hover { background: var(--bg-alt); filter: none; }

/* ==========================================================================
   Hero + home
   ========================================================================== */
.hero { padding-block: 3.5rem 2.5rem; text-align: center; }
.hero h1 { max-width: 16ch; margin-inline: auto; }
.hero-sub {
  max-width: 62ch; margin: 0 auto 1.8rem; font-size: 1.1rem; color: var(--text-soft);
}
.hero-actions { display: flex; flex-wrap: wrap; gap: .7rem; justify-content: center; }

.promises {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 1px;
  background: var(--border); border: 1px solid var(--border);
  border-radius: var(--radius-lg); overflow: hidden;
}
.promise { background: var(--surface); padding: 1.2rem 1.3rem; display: grid; gap: .3rem; }
.promise strong { font-size: .97rem; }
.promise span { color: var(--text-soft); font-size: .9rem; line-height: 1.5; }

.section-title { margin-bottom: .3rem; }
.section-sub { color: var(--text-soft); max-width: 68ch; margin-bottom: 1.4rem; }
.section-title + .grid { margin-top: 1.4rem; }

/* ==========================================================================
   Cards
   ========================================================================== */
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(268px, 1fr)); gap: 1rem; }

.card {
  display: grid; align-content: start; gap: .35rem;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 1.15rem 1.2rem 1.1rem;
  text-decoration: none; color: inherit; box-shadow: var(--shadow);
  transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease;
}
.card:hover { transform: translateY(-3px); box-shadow: var(--shadow-lift); border-color: var(--border-strong); }
.card-cat {
  font-size: .71rem; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  color: var(--accent);
}
.card-title { font-size: 1.06rem; margin: 0; }
.card-text { color: var(--text-soft); font-size: .92rem; margin: 0 0 .5rem; line-height: 1.55; }
.card-go { font-size: .87rem; font-weight: 600; color: var(--accent); margin-top: auto; }
.card:hover .card-go span { display: inline-block; transform: translateX(3px); transition: transform .15s ease; }

.related { margin-top: 3.5rem; }

/* ==========================================================================
   Page head + prose
   ========================================================================== */
.page-head { padding-block: 2rem 1.5rem; }
.eyebrow {
  display: inline-block; margin-bottom: .6rem;
  font-size: .73rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--accent); background: var(--accent-soft);
  padding: .25rem .6rem; border-radius: 99px;
}
.lede { font-size: 1.1rem; color: var(--text-soft); margin-bottom: 0; }
.lede p:last-child { margin-bottom: 0; }
.byline { margin-top: 1rem; font-size: .88rem; color: var(--text-faint); }

.prose { margin-top: 3rem; }
.prose h2 { margin-top: 2.4rem; }
.prose h3 { margin-top: 1.8rem; }
.prose ul, .prose ol { padding-left: 1.3rem; margin: 0 0 1.2rem; }
.prose li { margin-bottom: .55rem; }
.prose li::marker { color: var(--text-faint); }
.prose strong { font-weight: 650; }

.updated {
  margin-top: 2.5rem; padding-top: 1.2rem; border-top: 1px solid var(--border);
  font-size: .86rem; color: var(--text-faint);
}
.notice {
  background: var(--warn-bg); border: 1px solid color-mix(in srgb, var(--warn) 30%, transparent);
  color: var(--warn); padding: .9rem 1.1rem; border-radius: var(--radius); font-size: .93rem;
}

/* ==========================================================================
   FAQ
   ========================================================================== */
.faq { margin-top: 3rem; }
.faq-item { border-bottom: 1px solid var(--border); }
.faq-item summary {
  cursor: pointer; padding: 1rem 2rem 1rem 0; font-weight: 600; position: relative;
  list-style: none;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after {
  content: "+"; position: absolute; right: .3rem; top: 50%; transform: translateY(-50%);
  font-size: 1.4rem; font-weight: 400; color: var(--text-faint); line-height: 1;
}
.faq-item[open] summary::after { content: "\2212"; }
.faq-item summary:hover { color: var(--accent); }
.faq-answer { color: var(--text-soft); padding-bottom: .6rem; }
.faq-answer p { margin: 0; }

/* ==========================================================================
   Ad slots
   ========================================================================== */
.ad-slot { margin-block: 2.5rem; min-height: 90px; text-align: center; }
.ad-slot--placeholder {
  display: grid; place-items: center;
  border: 1.5px dashed var(--border-strong); border-radius: var(--radius);
  background: var(--bg-alt); color: var(--text-faint);
  font-size: .8rem; letter-spacing: .05em; text-transform: uppercase;
  min-height: 110px;
}

/* ==========================================================================
   Tool shell
   ========================================================================== */
.tool {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-lg); padding: 1.5rem; box-shadow: var(--shadow);
}
.sub { font-size: .8rem; text-transform: uppercase; letter-spacing: .07em; color: var(--text-faint); margin: 1.8rem 0 .8rem; }
.field-label { display: block; font-size: .85rem; font-weight: 600; color: var(--text-soft); margin: 1.2rem 0 .4rem; }

.dropzone {
  display: grid; place-items: center; gap: .3rem; text-align: center;
  border: 2px dashed var(--border-strong); border-radius: var(--radius);
  padding: 2.6rem 1.5rem; cursor: pointer; background: var(--bg-alt);
  transition: border-color .15s ease, background .15s ease;
}
.dropzone:hover, .dropzone.is-over { border-color: var(--accent); background: var(--accent-soft); }
.dz-icon { color: var(--accent); margin-bottom: .3rem; }
.dz-title { margin: 0; font-weight: 600; font-size: 1.02rem; }
.dz-hint { margin: 0; font-size: .85rem; color: var(--text-soft); }
.link-look { color: var(--accent); text-decoration: underline; }

.controls {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 1.3rem;
  margin-top: 1.5rem; padding-top: 1.5rem; border-top: 1px solid var(--border);
}
.control { display: grid; gap: .45rem; align-content: start; border: 0; padding: 0; margin: 0; min-width: 0; }
.control--wide { grid-column: 1 / -1; }
.control label, .control legend { font-size: .88rem; font-weight: 600; padding: 0; }
.control-hint { margin: 0; font-size: .8rem; color: var(--text-faint); line-height: 1.45; }

select, input[type="text"] {
  font: inherit; font-size: .93rem; color: var(--text);
  background: var(--bg); border: 1px solid var(--border-strong);
  border-radius: 9px; padding: .55rem .7rem; width: 100%;
}
input[type="range"] { width: 100%; accent-color: var(--accent); }
input[type="color"] { border: 1px solid var(--border-strong); border-radius: 9px; padding: 2px; height: 42px; width: 100%; background: var(--bg); cursor: pointer; }
output { font-variant-numeric: tabular-nums; }

.checks { display: flex; flex-wrap: wrap; gap: .5rem 1.4rem; }
.check { display: inline-flex; align-items: center; gap: .45rem; font-weight: 450; font-size: .92rem; cursor: pointer; }
.check input { accent-color: var(--accent); width: 17px; height: 17px; }

.text-area {
  width: 100%; font: inherit; font-size: .97rem; line-height: 1.6; color: var(--text);
  background: var(--bg); border: 1px solid var(--border-strong);
  border-radius: var(--radius); padding: .9rem 1rem; resize: vertical;
}
.text-area--out { background: var(--bg-alt); }

.tool-bar { display: flex; flex-wrap: wrap; align-items: center; gap: .6rem; margin-top: .9rem; }
.tool-bar-note { font-size: .85rem; color: var(--text-faint); }

.panel { margin-top: 1.2rem; border: 1px solid var(--border); border-radius: var(--radius); background: var(--bg-alt); }
.panel > summary { cursor: pointer; padding: .8rem 1rem; font-weight: 600; font-size: .92rem; }
.panel > *:not(summary) { padding: 0 1rem 1rem; }

/* --- results list --------------------------------------------------------- */
.results { margin-top: 1.5rem; padding-top: 1.3rem; border-top: 1px solid var(--border); }
.results-head { display: flex; flex-wrap: wrap; gap: .8rem; align-items: center; justify-content: space-between; }
.results-summary { margin: 0; font-size: .93rem; color: var(--text-soft); }

.file-list { list-style: none; margin: 1rem 0 0; padding: 0; display: grid; gap: .5rem; }
.file-row {
  display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, 1.6fr) auto;
  gap: .5rem 1rem; align-items: center;
  padding: .75rem .9rem; border: 1px solid var(--border);
  border-radius: 10px; background: var(--bg-alt);
}
.file-row.is-error { border-color: color-mix(in srgb, var(--bad) 40%, transparent); }
.file-name {
  font-size: .9rem; font-weight: 550;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.file-meta { display: flex; flex-wrap: wrap; align-items: center; gap: .45rem; font-size: .87rem; }
.file-actions { justify-self: end; }
.arrow { color: var(--text-faint); }
.dims { font-size: .8rem; }
.err { color: var(--bad); }

.badge {
  font-size: .75rem; font-weight: 700; padding: .12rem .45rem; border-radius: 99px;
  font-variant-numeric: tabular-nums;
}
.badge-good { background: var(--good-bg); color: var(--good); }
.badge-warn { background: var(--warn-bg); color: var(--warn); }

/* ==========================================================================
   Password generator
   ========================================================================== */
.password-output {
  display: flex; flex-wrap: wrap; align-items: center; gap: .8rem;
  background: var(--bg-alt); border: 1px solid var(--border-strong);
  border-radius: var(--radius); padding: 1rem 1.1rem;
}
.pw-field {
  flex: 1 1 260px; min-width: 0;
  font-family: var(--mono); font-size: 1.15rem; font-weight: 600;
  word-break: break-all; line-height: 1.45;
}
.pw-field.is-empty { color: var(--text-faint); font-family: var(--font); font-size: .95rem; font-weight: 400; }
.pw-buttons { display: flex; gap: .5rem; margin-left: auto; }

.strength { margin-top: 1rem; }
.strength-bar { height: 7px; border-radius: 99px; background: var(--bg-alt); border: 1px solid var(--border); overflow: hidden; }
.strength-bar span { display: block; height: 100%; width: 0; border-radius: 99px; transition: width .25s ease, background .25s ease; }
.strength-bar span.weak { background: var(--bad); }
.strength-bar span.ok { background: var(--warn); }
.strength-bar span.good { background: var(--good); }
.strength-bar span.great { background: var(--accent); }
.strength-text { margin: .55rem 0 0; font-size: .87rem; color: var(--text-soft); }

/* ==========================================================================
   Word counter
   ========================================================================== */
.stats {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); gap: 1px;
  background: var(--border); border: 1px solid var(--border);
  border-radius: var(--radius); overflow: hidden; margin-bottom: 1.3rem;
}
.stat { background: var(--surface); padding: .85rem .5rem; text-align: center; display: grid; gap: .1rem; }
.stat-num { font-size: 1.45rem; font-weight: 700; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.stat-label { font-size: .73rem; text-transform: uppercase; letter-spacing: .05em; color: var(--text-faint); }

.limits { list-style: none; margin: 0; padding: 0; display: grid; gap: .6rem; }
.limit { display: grid; grid-template-columns: minmax(0, 11rem) 1fr auto; gap: .8rem; align-items: center; font-size: .86rem; }
.limit-name { color: var(--text-soft); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.limit-bar { height: 6px; border-radius: 99px; background: var(--border); overflow: hidden; }
.limit-bar i { display: block; height: 100%; background: var(--accent); }
.limit-left { font-variant-numeric: tabular-nums; color: var(--text-faint); white-space: nowrap; }
.limit.is-over .limit-bar i { background: var(--bad); }
.limit.is-over .limit-left { color: var(--bad); font-weight: 600; }

.keywords { margin: 0; padding-left: 1.4rem; display: grid; gap: .3rem; font-size: .9rem; }
.keywords li { display: flex; justify-content: space-between; gap: 1rem; }

/* ==========================================================================
   Case converter
   ========================================================================== */
.case-buttons { display: flex; flex-wrap: wrap; gap: .45rem; margin: 1rem 0 .3rem; }
.case-btn {
  font: inherit; font-size: .85rem; font-weight: 550; cursor: pointer;
  background: var(--bg-alt); color: var(--text);
  border: 1px solid var(--border-strong); border-radius: 8px; padding: .4rem .75rem;
  transition: background .12s ease, border-color .12s ease, color .12s ease;
}
.case-btn:hover { border-color: var(--accent); color: var(--accent); }
.case-btn.is-active { background: var(--accent); border-color: var(--accent); color: var(--accent-text); }

/* ==========================================================================
   Color converter
   ========================================================================== */
.color-head { display: grid; grid-template-columns: minmax(0, 150px) minmax(0, 1fr); gap: 1.5rem; align-items: start; }
.swatch-big {
  aspect-ratio: 1; border-radius: var(--radius); border: 1px solid var(--border);
  display: grid; place-items: center; overflow: hidden;
}
.swatch-big input[type="color"] { opacity: 0; width: 100%; height: 100%; border: 0; padding: 0; cursor: pointer; }
.color-fields { display: grid; gap: .75rem; }
.field { display: grid; gap: .3rem; }
.field label { font-size: .78rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--text-faint); }
.field input { font-family: var(--mono); }
.field-note { margin: 0; font-size: .84rem; color: var(--bad); min-height: 1.2em; }

.palette { display: grid; grid-template-columns: repeat(auto-fit, minmax(84px, 1fr)); gap: .4rem; }
.swatch {
  border: 1px solid var(--border); border-radius: 9px; cursor: pointer;
  aspect-ratio: 1.6; display: grid; place-items: center; padding: 0;
  font: inherit; font-family: var(--mono); font-size: .72rem; font-weight: 600;
  transition: transform .12s ease;
}
.swatch:hover { transform: scale(1.05); }

.contrast { display: grid; gap: .8rem; }
.contrast-row { display: grid; grid-template-columns: 62px 1fr; gap: 1rem; align-items: center; }
.contrast-demo {
  display: grid; place-items: center; aspect-ratio: 1; border-radius: 10px;
  border: 1px solid var(--border); font-size: 1.3rem; font-weight: 700;
}
.contrast-info { font-size: .89rem; }
.pills { display: flex; flex-wrap: wrap; gap: .35rem; margin-top: .4rem; }
.pill { font-size: .74rem; font-weight: 650; padding: .15rem .5rem; border-radius: 99px; }
.pill.pass { background: var(--good-bg); color: var(--good); }
.pill.fail { background: var(--bad-bg); color: var(--bad); }

/* ==========================================================================
   Responsive
   ========================================================================== */
@media (max-width: 640px) {
  body { font-size: 16px; }
  .tool { padding: 1.1rem; border-radius: var(--radius); }
  .file-row { grid-template-columns: 1fr auto; }
  .file-meta { grid-column: 1 / -1; }
  .file-actions { grid-row: 1; grid-column: 2; }
  .color-head { grid-template-columns: 1fr; }
  .swatch-big { aspect-ratio: 2.6; }
  .limit { grid-template-columns: 1fr auto; }
  .limit-bar { grid-column: 1 / -1; grid-row: 2; }
  .hero { padding-block: 2.5rem 1.5rem; }

  /* Keep the header on one line: short labels, tighter spacing, no wrapping. */
  .header-inner { gap: .4rem; }
  .brand { font-size: 1.02rem; }
  .site-nav { flex-wrap: nowrap; gap: .1rem; }
  /* .nav-link has to be named here as well: `.site-nav .nav-link` outranks
     `.site-nav a`, so the compact padding was losing to the desktop rule and
     the header overflowed on a phone — visibly in Spanish, where the labels
     are longer. */
  .site-nav a,
  .site-nav .nav-link { padding: .4rem .45rem; font-size: .87rem; white-space: nowrap; }
  .nav-long { display: none; }
  .nav-short { display: inline; }
  .theme-toggle,
  .site-nav .nav-icon { width: 32px; height: 32px; margin-left: .15rem; padding: 0; }
}

/* ==========================================================================
   Comparison tables (articles)
   ========================================================================== */
.table-wrap { overflow-x: auto; margin: 0 0 1.6rem; border: 1px solid var(--border); border-radius: var(--radius); }
table { border-collapse: collapse; width: 100%; font-size: .9rem; min-width: 480px; }
thead th {
  text-align: left; background: var(--bg-alt); font-size: .76rem;
  text-transform: uppercase; letter-spacing: .05em; color: var(--text-faint);
  padding: .7rem .9rem; border-bottom: 1px solid var(--border); white-space: nowrap;
}
tbody td { padding: .75rem .9rem; border-bottom: 1px solid var(--border); vertical-align: top; }
tbody tr:last-child td { border-bottom: 0; }
tbody tr:hover { background: var(--bg-alt); }
td strong { white-space: nowrap; }

/* Callout used for the "what to actually pick" summary */
.verdict {
  background: var(--accent-soft); border: 1px solid color-mix(in srgb, var(--accent) 28%, transparent);
  border-radius: var(--radius); padding: 1.2rem 1.35rem; margin: 2rem 0;
}
.verdict h2, .verdict h3 { margin-top: 0; }
.verdict p:last-child { margin-bottom: 0; }

/* Per-option heading with a one-line "best for" strap */
.best-for {
  display: block; font-size: .82rem; font-weight: 650; color: var(--accent);
  text-transform: uppercase; letter-spacing: .05em; margin: -.3em 0 .8em;
}

/* ==========================================================================
   Theme toggle
   ========================================================================== */
.theme-toggle {
  display: inline-grid; place-items: center;
  width: 36px; height: 36px; flex: none;
  margin-left: .35rem; padding: 0;
  background: transparent; color: var(--text-soft);
  border: 1px solid var(--border); border-radius: 9px;
  cursor: pointer;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.theme-toggle:hover { background: var(--bg-alt); color: var(--text); border-color: var(--border-strong); }
.theme-toggle svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

/* Show the icon for the theme you would switch TO, which is the convention
   people expect: a moon while in light mode, a sun while in dark. */
.theme-toggle .icon-moon { display: block; }
.theme-toggle .icon-sun { display: none; }
:root[data-theme="dark"] .theme-toggle .icon-moon { display: none; }
:root[data-theme="dark"] .theme-toggle .icon-sun { display: block; }

/* ==========================================================================
   Password generator — crack-time display
   ========================================================================== */
.mode-tabs {
  display: inline-flex; gap: 2px; padding: 3px; margin-bottom: 1.1rem;
  background: var(--bg-alt); border: 1px solid var(--border); border-radius: 10px;
}
.mode-tab {
  font: inherit; font-size: .88rem; font-weight: 600; cursor: pointer;
  padding: .4rem .9rem; border: 0; border-radius: 7px;
  background: transparent; color: var(--text-soft);
  transition: background .15s ease, color .15s ease;
}
.mode-tab:hover { color: var(--text); }
.mode-tab.is-active { background: var(--surface); color: var(--text); box-shadow: var(--shadow); }

.pw-input-wrap { display: flex; gap: .5rem; align-items: center; }
.pw-input {
  flex: 1; min-width: 0;
  font-family: var(--mono); font-size: 1.05rem; color: var(--text);
  background: var(--bg-alt); border: 1px solid var(--border-strong);
  border-radius: var(--radius); padding: .8rem 1rem;
}
.pw-input::placeholder { font-family: var(--font); font-size: .95rem; color: var(--text-faint); }
.pw-privacy {
  display: flex; align-items: center; gap: .4rem;
  margin: .6rem 0 0; font-size: .82rem; color: var(--text-faint);
}
.pw-privacy svg { flex: none; color: var(--good); }

/* --- the hero ------------------------------------------------------------- */
.crack {
  --crack-color: var(--text-faint);
  --crack-tint: var(--bg-alt);
  position: relative; overflow: hidden;
  margin-top: 1.4rem; padding: 1.5rem 1.4rem 1.2rem;
  text-align: center;
  background: var(--crack-tint);
  border: 1px solid color-mix(in srgb, var(--crack-color) 28%, transparent);
  border-radius: var(--radius-lg);
  transition: background .35s ease, border-color .35s ease;
}
/* A soft wash of the tier colour bleeding up from the bottom. */
.crack::after {
  content: ""; position: absolute; inset: auto 0 0 0; height: 70%;
  background: radial-gradient(ellipse at 50% 120%,
    color-mix(in srgb, var(--crack-color) 22%, transparent), transparent 70%);
  pointer-events: none; transition: background .35s ease;
}
.crack > * { position: relative; z-index: 1; }

.crack-label {
  font-size: .72rem; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
  color: var(--text-faint);
}
.crack-value {
  margin: .35rem 0 .2rem;
  font-size: clamp(1.75rem, 1.1rem + 3.4vw, 3.1rem);
  font-weight: 800; line-height: 1.1; letter-spacing: -.035em;
  font-variant-numeric: tabular-nums;
  color: var(--crack-color);
  transition: color .35s ease;
}
.crack-sub { margin: 0; font-size: .9rem; color: var(--text-soft); min-height: 1.4em; }

.crack[data-tier="none"]     { --crack-color: var(--text-faint); }
.crack[data-tier="instant"]  { --crack-color: var(--bad);  --crack-tint: var(--bad-bg); }
.crack[data-tier="trivial"]  { --crack-color: var(--bad);  --crack-tint: var(--bad-bg); }
.crack[data-tier="weak"]     { --crack-color: var(--warn); --crack-tint: var(--warn-bg); }
.crack[data-tier="fair"]     { --crack-color: var(--warn); --crack-tint: var(--warn-bg); }
.crack[data-tier="good"]     { --crack-color: var(--good); --crack-tint: var(--good-bg); }
.crack[data-tier="strong"]   { --crack-color: var(--good); --crack-tint: var(--good-bg); }
.crack[data-tier="extreme"]  { --crack-color: var(--accent); --crack-tint: var(--accent-soft); }

/* --- log-scale timeline --------------------------------------------------- */
.timeline { margin-top: 1.2rem; }
.timeline-track {
  position: relative; height: 8px; border-radius: 99px;
  background: color-mix(in srgb, var(--text-faint) 18%, transparent);
}
.timeline-fill {
  height: 100%; width: 0; border-radius: 99px;
  background: linear-gradient(90deg,
    color-mix(in srgb, var(--crack-color) 45%, transparent), var(--crack-color));
  transition: width .45s cubic-bezier(.22, 1, .36, 1), background .35s ease;
}
.timeline-pin {
  position: absolute; top: 50%; left: 0; width: 0; height: 0;
  transition: left .45s cubic-bezier(.22, 1, .36, 1);
}
.timeline-pin-dot {
  position: absolute; top: -7px; left: -7px; width: 14px; height: 14px;
  border-radius: 50%; background: var(--crack-color);
  border: 2.5px solid var(--surface);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--crack-color) 50%, transparent);
  transition: background .35s ease;
}
.timeline-ticks {
  display: flex; justify-content: space-between; margin-top: .45rem;
  font-size: .68rem; letter-spacing: .03em; color: var(--text-faint);
}

/* --- attacker chips ------------------------------------------------------- */
.attackers { border: 0; padding: 0; margin: 1.4rem 0 0; }
.attackers legend {
  padding: 0; margin-bottom: .55rem;
  font-size: .78rem; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  color: var(--text-faint);
}
.attacker-chips { display: flex; flex-wrap: wrap; gap: .4rem; }
.attacker-chip {
  font: inherit; font-size: .84rem; font-weight: 600; cursor: pointer;
  padding: .4rem .8rem; border-radius: 99px;
  background: var(--bg-alt); color: var(--text-soft);
  border: 1px solid var(--border-strong);
  transition: background .14s ease, color .14s ease, border-color .14s ease, transform .14s ease;
}
.attacker-chip:hover { color: var(--text); border-color: var(--accent); transform: translateY(-1px); }
.attacker-chip.is-active {
  background: var(--accent); color: var(--accent-text); border-color: var(--accent);
}
.attacker-desc {
  margin: .7rem 0 0; font-size: .87rem; color: var(--text-soft);
  min-height: 2.6em; max-width: 62ch;
}

/* --- pattern warnings ----------------------------------------------------- */
.pw-warnings { list-style: none; margin: 1.1rem 0 0; padding: 0; display: grid; gap: .4rem; }
.pw-warnings li {
  display: flex; gap: .5rem; align-items: baseline;
  font-size: .87rem; line-height: 1.5;
  background: var(--warn-bg); color: var(--warn);
  border: 1px solid color-mix(in srgb, var(--warn) 25%, transparent);
  border-radius: 9px; padding: .55rem .8rem;
}
.pw-warnings li::before { content: "!"; font-weight: 800; flex: none; }

.pwgen .strength { margin-top: 1.4rem; }
.pwgen .controls { margin-top: 1.5rem; }

@media (max-width: 640px) {
  .crack { padding: 1.2rem 1rem 1rem; }
  .timeline-ticks { font-size: .62rem; }
  .attacker-desc { min-height: 3.4em; }
}

/* ==========================================================================
   Blog post closing
   The block that hands the reader the tool and the next post. Styled as a
   quiet aside rather than a CTA banner — Rule 2 wants prose, not a billboard.
   ========================================================================== */
.post-closing {
  margin-top: 2.6rem;
  padding: 1.3rem 1.4rem;
  background: var(--bg-alt);
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius);
}
.post-closing p { margin-bottom: .8rem; }
.post-closing p:last-child { margin-bottom: 0; }
.post-closing a { font-weight: 600; }

/* ==========================================================================
   Support button + Chrome extensions
   ========================================================================== */
.bmc {
  display: inline-flex; align-items: center; gap: .5rem;
  margin-top: 1rem; padding: .5rem .9rem;
  /* The support link used to carry Buy Me a Coffee yellow, hardcoded. The
     icon is our own SVG on currentColor, not their logo, so nothing of
     theirs is being restyled — the button just stops being the only thing
     on the page that ignores the palette. */
  background: var(--accent); color: var(--accent-text);
  border-radius: 9px; font-size: .88rem; font-weight: 650;
  text-decoration: none;
  transition: transform .12s ease, filter .12s ease;
}
.bmc:hover { transform: translateY(-1px); filter: brightness(1.05); }

.ext {
  margin: 2rem 0;
  padding: 1.4rem 1.5rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
}
.ext-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: .8rem; }
.ext-head h2 { margin: 0 0 .2rem; font-size: 1.3rem; }
.ext-cat {
  font-size: .7rem; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  color: var(--accent); background: var(--accent-soft);
  padding: .2rem .55rem; border-radius: 99px;
}
.ext-tagline { font-size: 1.02rem; color: var(--text); font-weight: 550; margin-top: .5rem; }
.ext-why {
  color: var(--text-soft); font-size: .93rem;
  border-left: 2px solid var(--border-strong); padding-left: .9rem;
}
.ext .btn { margin-top: .3rem; }

/* ==========================================================================
   Language switcher
   ========================================================================== */
.lang-switch { position: relative; display: inline-block; }
.lang-btn {
  display: inline-flex; align-items: center; gap: .3rem;
  height: 36px; padding: 0 .55rem; margin-left: .2rem;
  font: inherit; font-size: .82rem; font-weight: 650;
  background: transparent; color: var(--text-soft);
  border: 1px solid var(--border); border-radius: 9px; cursor: pointer;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.lang-btn:hover { background: var(--bg-alt); color: var(--text); border-color: var(--border-strong); }
.lang-btn svg { flex: none; }
.lang-caret { opacity: .6; transition: transform .18s ease; }
.lang-btn[aria-expanded="true"] { background: var(--bg-alt); color: var(--text); border-color: var(--border-strong); }
.lang-btn[aria-expanded="true"] .lang-caret { transform: rotate(180deg); }

/* The menu floats above the page instead of taking part in the header's
   layout: absolute inside the .lang-switch, so opening it cannot move a
   single pixel of anything else. */
.lang-menu {
  position: absolute; top: calc(100% + .45rem); right: 0; z-index: 60;
  min-width: 190px; max-width: calc(100vw - 2rem);
  margin: 0; padding: .35rem;
  list-style: none;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: 14px;
  box-shadow: 0 18px 40px -12px rgba(0, 0, 0, .3), 0 4px 12px -4px rgba(0, 0, 0, .12);
  animation: lang-pop .16s ease-out;
}
@keyframes lang-pop {
  from { opacity: 0; transform: translateY(-6px); }
  to { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .lang-menu { animation: none; }
  .lang-caret { transition: none; }
}

.lang-menu li { margin: 0; }
.lang-item {
  display: flex; align-items: center; gap: .6rem;
  padding: .5rem .55rem; border-radius: 9px;
  font-size: .92rem; color: var(--text); text-decoration: none;
  transition: background .12s ease;
}
.lang-item:hover, .lang-item:focus-visible { background: var(--bg-alt); }
.lang-code {
  flex: none; min-width: 30px; padding: .15rem 0;
  font-size: .68rem; font-weight: 750; letter-spacing: .06em; text-align: center;
  color: var(--text-soft); background: var(--bg-alt);
  border: 1px solid var(--border); border-radius: 6px;
}
.lang-name { flex: 1; }
.lang-check { flex: none; color: var(--accent); }
.lang-item[aria-current="true"] { font-weight: 650; }
.lang-item[aria-current="true"] .lang-code {
  color: var(--accent); background: var(--accent-soft); border-color: transparent;
}

@media (max-width: 640px) {
  .lang-btn { height: 32px; padding: 0 .4rem; font-size: .78rem; }
  .lang-btn svg { width: 14px; height: 14px; }
  .lang-caret { width: 11px; height: 11px; }
  .lang-menu { min-width: 170px; }
}

/* ==========================================================================
   Navigation dropdowns
   ========================================================================== */
.nav-item { position: relative; display: inline-block; }
.site-nav .nav-link {
  display: inline-flex; align-items: center; gap: .25rem;
  color: var(--text-soft); text-decoration: none; font-size: .94rem; font-weight: 550;
  padding: .45rem .7rem; border-radius: 8px;
}
.site-nav .nav-link:hover { color: var(--text); background: var(--bg-alt); }
.nav-caret { opacity: .55; flex: none; transition: transform .18s ease; }
.nav-link[aria-expanded="true"] { color: var(--text); background: var(--bg-alt); }
.nav-link[aria-expanded="true"] .nav-caret { transform: rotate(180deg); }

/* Absolute, like the language menu: opening one must not move a pixel of the
   page. The bridge on ::before covers the gap between the trigger and the
   panel so the pointer can cross it without the menu closing underneath. */
.nav-menu {
  position: absolute; top: calc(100% + .45rem); left: 0; z-index: 60;
  min-width: 230px; max-width: calc(100vw - 2rem);
  padding: .35rem;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: 14px;
  box-shadow: 0 18px 40px -12px rgba(0, 0, 0, .3), 0 4px 12px -4px rgba(0, 0, 0, .12);
  animation: lang-pop .16s ease-out;
}
.nav-menu::before {
  content: ""; position: absolute; left: 0; right: 0; top: -.5rem; height: .5rem;
}
@media (prefers-reduced-motion: reduce) { .nav-menu { animation: none; } }

.nav-menu-list { list-style: none; margin: 0; padding: 0; }
.nav-menu-list li { margin: 0; }
.nav-menu-list a {
  display: flex; align-items: center; justify-content: space-between; gap: .8rem;
  padding: .45rem .55rem; border-radius: 9px;
  font-size: .92rem; color: var(--text); text-decoration: none;
}
.nav-menu-list a:hover, .nav-menu-list a:focus-visible { background: var(--bg-alt); }
.nav-menu-label { min-width: 0; }
.nav-menu-count {
  flex: none; font-size: .72rem; font-weight: 700; color: var(--text-faint);
  background: var(--bg-alt); border-radius: 99px; padding: .1rem .45rem;
}
.nav-menu-list a:hover .nav-menu-count { color: var(--text-soft); }
.nav-menu-all {
  display: block; margin-top: .3rem; padding: .5rem .55rem;
  border-top: 1px solid var(--border);
  font-size: .86rem; font-weight: 650; color: var(--accent); text-decoration: none;
}
.nav-menu-all:hover { background: var(--bg-alt); border-radius: 9px; }

/* A category card leads with its count, so the badge reads as a quantity
   rather than as a label. */
.card--cat .card-cat { color: var(--accent); background: var(--accent-soft); }

.chip-row { display: flex; flex-wrap: wrap; gap: .5rem; margin: 0; }
.chip {
  display: inline-flex; align-items: center; gap: .4rem;
  padding: .4rem .75rem; border-radius: 99px;
  background: var(--surface); border: 1px solid var(--border);
  font-size: .88rem; font-weight: 550; color: var(--text); text-decoration: none;
}
.chip:hover { border-color: var(--border-strong); background: var(--bg-alt); }
.chip-count { font-size: .74rem; font-weight: 700; color: var(--text-faint); }
.section-title a { color: inherit; text-decoration: none; }
.section-title a:hover { color: var(--accent); }

@media (max-width: 860px) {
  /* Below this the header has no room for a panel wide enough to read, and a
     hover menu is meaningless on a touch screen anyway. The links still work;
     they just go straight to the index. */
  .nav-menu { display: none !important; }
  .nav-caret { display: none; }
}


/* The credit and the verse sit with the footer links rather than across the
   bottom of the page: they belong to the same column, directly under About,
   Contact, Privacy Policy and Terms of Use. Below the breakpoint the footer
   is one column anyway, so they simply follow. */
/* Three rows in the right-hand column, beside the brand block — where the
   footer links have always been. Top to bottom: the links on one line, the
   copyright, then the credit and the verse sharing a line. */
.footer-bottom { display: flex; flex-direction: column; align-items: flex-end; text-align: right; }
.footer-bottom .footer-nav { flex-wrap: nowrap; gap: 1.4rem; }
.footer-bottom .copyright { margin-top: 1.1rem; }
.footer-meta {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: .1rem .6rem;
  margin: .4rem 0 0; color: var(--text-faint); font-size: .84rem;
}
.footer-meta a { color: var(--text-soft); text-decoration: none; border-bottom: 1px solid var(--border-strong); }
.footer-meta a:hover { color: var(--accent); border-bottom-color: currentColor; }
.footer-sep { color: var(--border-strong); }

/* The separator is a join between two lines, not a bullet in a list: when the
   line wraps on a narrow screen it has nothing left to separate. */
@media (max-width: 520px) {
  .footer-sep { display: none; }
  .footer-meta { gap: .15rem 0; flex-direction: column; }
}

/* Once the footer stacks there is no right-hand column to sit in, and the
   links need to be allowed to wrap again. */
@media (max-width: 720px) {
  .footer-bottom { align-items: flex-start; text-align: left; }
  .footer-bottom .footer-nav { flex-wrap: wrap; gap: .3rem 1.2rem; }
  .footer-meta { justify-content: flex-start; }
}

/* Source order matters here: the compact header rules live in a media query
   earlier in this file, and `.site-nav .nav-link` further down has the same
   specificity, so the desktop padding was winning on a phone and pushing the
   header wider than the screen. Restating them after the dropdown section is
   what makes them stick. */
@media (max-width: 640px) {
  .site-nav { gap: .05rem; }
  .site-nav .nav-link { padding: .35rem .35rem; font-size: .85rem; white-space: nowrap; }
  .lang-btn { margin-left: .1rem; padding: 0 .35rem; gap: .2rem; }
  .lang-btn svg:not(.lang-caret) { width: 13px; height: 13px; }
}

/* On a phone the wordmark costs about 70px that four nav links, the language
   button and the theme toggle need more. The mark alone still identifies the
   site and still goes home. */
@media (max-width: 640px) {
  .site-header .brand span { display: none; }
}

/* The consent settings entry point. Quiet, and hidden until Google's message
   is actually live — a "privacy settings" link that opens nothing reads as a
   dark pattern. */
.consent-settings {
  margin-top: .9rem; padding: 0;
  background: none; border: 0; cursor: pointer;
  font: inherit; font-size: .84rem; color: var(--text-soft);
  border-bottom: 1px solid var(--border-strong);
}
.consent-settings:hover { color: var(--accent); border-bottom-color: currentColor; }

/* --------------------------------------------------------------------------
   Lead image
   The credit line is generated from the piece's attribution fields, never
   written by hand, so it is styled as what it is: a legal notice that has to
   be readable without competing with the article.
   -------------------------------------------------------------------------- */
.lead-img { margin: 0 0 1.6rem; }
.lead-img img {
  display: block; width: 100%; height: auto;
  border-radius: var(--radius-lg); border: 1px solid var(--border);
  background: var(--surface);
}
.lead-img figcaption {
  margin-top: .5rem;
  font-size: .8rem; line-height: 1.45; color: var(--muted);
}
.lead-img figcaption a { color: var(--muted); text-decoration: underline; }
.lead-img figcaption a:hover { color: var(--accent); }

/* --------------------------------------------------------------------------
   "You might also like"
   Built from the piece's tags, brand and kind — never a hand-written list.
   -------------------------------------------------------------------------- */
.also { margin: 2.6rem 0 0; padding-top: 2rem; border-top: 1px solid var(--border); }
.also-title { margin: 0 0 1.1rem; font-size: 1.25rem; }

/* ---------------------------------------------------------------------------
   Búsqueda
   Vive solo en /search/. El campo es lo primero que se ve y recibe el foco al
   cargar, así que no necesita botón: escribir ya es buscar.
   -------------------------------------------------------------------------- */
.site-search { margin: 0 0 1.2rem; }

.search-input {
  width: 100%;
  box-sizing: border-box;
  padding: .85rem 1rem;
  font: inherit;
  font-size: 1.05rem;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  -webkit-appearance: none;
  appearance: none;
}
.search-input::placeholder { color: var(--text-faint); }
.search-input:focus-visible {
  outline: 2.5px solid var(--accent);
  outline-offset: 2px;
  border-color: var(--accent);
}

.search-status {
  margin: 0 0 1.6rem;
  color: var(--text-soft);
  font-size: .95rem;
}

.search-results { display: grid; gap: 1.4rem; }

.search-hit {
  padding-bottom: 1.4rem;
  border-bottom: 1px solid var(--border);
}
.search-results .search-hit:last-child { border-bottom: 0; padding-bottom: 0; }

.search-hit-title { margin: 0 0 .3rem; font-size: 1.15rem; line-height: 1.35; }
.search-hit-title a { text-decoration: none; }
.search-hit-title a:hover { text-decoration: underline; }

.search-hit-meta {
  margin: 0 0 .4rem;
  font-size: .82rem;
  color: var(--text-faint);
  text-transform: uppercase;
  letter-spacing: .04em;
}
.search-hit-desc { margin: 0; color: var(--text-soft); }

/* La lupa del menú. Mismo tamaño y mismo tratamiento que el interruptor de
   tema, para que los dos iconos del header se lean como un par y no como dos
   cosas distintas que quedaron juntas. */
.site-nav .nav-icon {
  display: inline-grid; place-items: center;
  width: 36px; height: 36px; flex: none;
  margin-left: .35rem; padding: 0;
  color: var(--text-soft);
  border: 1px solid var(--border); border-radius: 9px;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.site-nav .nav-icon:hover { background: var(--bg-alt); color: var(--text); border-color: var(--border-strong); }
.site-nav .nav-icon svg { width: 17px; height: 17px; }
