/*
 * KKaio site template stylesheet. Self-contained: no Bootstrap, no icon font.
 * Every color lives in a token so the dark theme is just a second set of values.
 */

/*
 * Atkinson Hyperlegible Next (SIL OFL 1.1, license next to the files), self-hosted: never loaded from a
 * third-party host. Variable files, so one file covers every weight from 200 to 800.
 */
@font-face {
  font-family: "Atkinson Hyperlegible Next";
  src: url("../fonts/atkinson-next/AtkinsonHyperlegibleNext-wght.woff2") format("woff2");
  font-weight: 200 800;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Atkinson Hyperlegible Next";
  src: url("../fonts/atkinson-next/AtkinsonHyperlegibleNext-Italic-wght.woff2") format("woff2");
  font-weight: 200 800;
  font-style: italic;
  font-display: swap;
}

:root {
  --bg: #f6f7f9;
  --surface: #ffffff;
  --surface-2: #f0f2f5;
  --border: #e3e6eb;
  /* Form fields need a boundary of at least 3:1 against their background (WCAG 1.4.11) */
  --border-strong: #858f9f;
  --text: #1c2129;
  --text-muted: #5b6472;
  --accent: #2257d6;
  --accent-hover: #1a46b0;
  --accent-soft: #e8eefc;
  --accent-contrast: #ffffff;
  --warn-bg: #fff6d6;
  --warn-text: #6b4e00;
  --shadow: 0 1px 2px rgba(16, 24, 40, .05), 0 1px 3px rgba(16, 24, 40, .06);
  --shadow-hover: 0 4px 12px rgba(16, 24, 40, .08), 0 2px 4px rgba(16, 24, 40, .05);
  /* The logo keeps its own colors in both themes (black with a grey-blue outline). At the small size in the bar the
     outline gets thinner than a pixel, so on the dark theme a halo of the same grey-blue takes its place */
  --logo-small-filter: none;
  /* One-colour footer logo: black as drawn, turned white on the dark theme */
  --logo-mono-filter: none;
  --thumb-bg: #ffffff;
  --thumb-filter: none;
  --article-img-bg: transparent;
  /* With a unit: a bare 0 would make the calc() that uses it invalid */
  --article-img-pad: 0px;
  /* Square corners: rounding would clip the thin frame of window screenshots */
  --article-img-radius: 0;
  --band-from: #dce6fd;
  --band-to: #f1f5ff;
  --band-dot: rgba(34, 87, 214, .22);

  --radius: 12px;
  --radius-sm: 8px;
  --container: 1200px;
  --gutter: 16px;
  --font-system: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  /* System stack stays as fallback while the web font loads (font-display: swap) */
  --font: "Atkinson Hyperlegible Next", var(--font-system);
  --font-mono: ui-monospace, "Cascadia Code", Consolas, "Liberation Mono", monospace;

  color-scheme: light;
}

/* Dark values are declared twice: once for the explicit choice, once for "follow the system". */
:root[data-theme="dark"] {
  --bg: #0f1216;
  --surface: #171b21;
  --surface-2: #1f242c;
  --border: #2a3039;
  --border-strong: #646e7e;
  --text: #e6e9ee;
  --text-muted: #9aa3b2;
  --accent: #7aa2ff;
  --accent-hover: #a3bfff;
  --accent-soft: #1d2a47;
  --accent-contrast: #0f1216;
  --warn-bg: #3a3112;
  --warn-text: #f3d679;
  --shadow: 0 1px 2px rgba(0, 0, 0, .3);
  --shadow-hover: 0 6px 16px rgba(0, 0, 0, .35);
  --logo-small-filter: drop-shadow(0 0 1px rgba(154, 168, 198, .9)) drop-shadow(0 0 1px rgba(154, 168, 198, .9));
  --logo-mono-filter: invert(1);
  --thumb-bg: #d9dde4;
  --thumb-filter: brightness(.88);
  --article-img-bg: #d9dde4;
  --article-img-pad: 10px;
  --article-img-radius: var(--radius-sm);
  --band-from: #172447;
  --band-to: #12171f;
  --band-dot: rgba(122, 162, 255, .18);
  color-scheme: dark;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]):not([data-theme="dark"]) {
    --bg: #0f1216;
    --surface: #171b21;
    --surface-2: #1f242c;
    --border: #2a3039;
    --border-strong: #646e7e;
    --text: #e6e9ee;
    --text-muted: #9aa3b2;
    --accent: #7aa2ff;
    --accent-hover: #a3bfff;
    --accent-soft: #1d2a47;
    --accent-contrast: #0f1216;
    --warn-bg: #3a3112;
    --warn-text: #f3d679;
    --shadow: 0 1px 2px rgba(0, 0, 0, .3);
    --shadow-hover: 0 6px 16px rgba(0, 0, 0, .35);
    --logo-small-filter: drop-shadow(0 0 1px rgba(154, 168, 198, .9)) drop-shadow(0 0 1px rgba(154, 168, 198, .9));
    --logo-mono-filter: invert(1);
    --thumb-bg: #d9dde4;
    --thumb-filter: brightness(.88);
    --article-img-bg: #d9dde4;
    --article-img-pad: 10px;
  --article-img-radius: var(--radius-sm);
    --band-from: #172447;
    --band-to: #12171f;
    --band-dot: rgba(122, 162, 255, .18);
    color-scheme: dark;
  }
}

/* ---------- Base ---------- */

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

html { -webkit-text-size-adjust: 100%; scroll-padding-top: 80px; }

/* Column layout keeps the footer at the bottom on short pages */
body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 1rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; height: auto; }

a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--accent-hover); text-decoration: underline; }

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

h1, h2, h3 { line-height: 1.25; letter-spacing: -.01em; }

.container {
  width: 100%;
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* Moved up by its own height plus a margin, so no edge shows whatever the text size */
.skip-link {
  position: absolute;
  left: 8px; top: 0;
  z-index: 100;
  padding: 8px 14px;
  background: var(--accent);
  color: var(--accent-contrast);
  border-radius: var(--radius-sm);
  transform: translateY(calc(-100% - 8px));
}
.skip-link:focus { transform: translateY(8px); }

/* ---------- Header ---------- */

/*
 * Tinted band shared by header and footer. The circuit pattern is an inline SVG used as a mask, so its
 * color comes from a theme token and nothing is downloaded.
 */
.band {
  position: relative;
  background: linear-gradient(135deg, var(--band-from), var(--band-to));
}
.band > * { position: relative; }
.band::before {
  --circuit: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240' fill='none' stroke='black' stroke-width='1.4'%3E%3Cpath d='M30 0V40L45 55V75M30 240V215M90 0V15L105 30H130M90 240V200L75 185V165M150 0V8M150 240V190L165 175V140M200 0V50L185 65H160M200 240V210L215 195V170M0 20H12M240 20H220M0 70H10M240 70H210L195 85V100M0 130H20L35 145H45M240 130H220M0 180H40L55 195V220M240 180H230M0 225H12M240 225H230M60 110H110L125 95H175M60 120H115L130 105H175M60 130H120L135 115H175M108 170V178M116 170V178M124 170V178M108 150V143M116 150V143M124 150V143'/%3E%3Crect x='100' y='150' width='32' height='20' rx='2'/%3E%3Cg%3E%3Ccircle cx='45' cy='79' r='3.5'/%3E%3Ccircle cx='30' cy='211' r='3.5'/%3E%3Ccircle cx='134' cy='30' r='3.5'/%3E%3Ccircle cx='75' cy='161' r='3.5'/%3E%3Ccircle cx='150' cy='12' r='3.5'/%3E%3Ccircle cx='165' cy='136' r='3.5'/%3E%3Ccircle cx='156' cy='65' r='3.5'/%3E%3Ccircle cx='215' cy='166' r='3.5'/%3E%3Ccircle cx='16' cy='20' r='3.5'/%3E%3Ccircle cx='216' cy='20' r='3.5'/%3E%3Ccircle cx='14' cy='70' r='3.5'/%3E%3Ccircle cx='195' cy='104' r='3.5'/%3E%3Ccircle cx='49' cy='145' r='3.5'/%3E%3Ccircle cx='216' cy='130' r='3.5'/%3E%3Ccircle cx='55' cy='224' r='3.5'/%3E%3Ccircle cx='226' cy='180' r='3.5'/%3E%3Ccircle cx='16' cy='225' r='3.5'/%3E%3Ccircle cx='226' cy='225' r='3.5'/%3E%3Ccircle cx='56' cy='110' r='3.5'/%3E%3Ccircle cx='56' cy='120' r='3.5'/%3E%3Ccircle cx='56' cy='130' r='3.5'/%3E%3Ccircle cx='179' cy='95' r='3.5'/%3E%3Ccircle cx='179' cy='105' r='3.5'/%3E%3Ccircle cx='179' cy='115' r='3.5'/%3E%3C/g%3E%3Cg fill='black' stroke='none'%3E%3Ccircle cx='70' cy='40' r='2'/%3E%3Ccircle cx='120' cy='60' r='2'/%3E%3Ccircle cx='230' cy='100' r='2'/%3E%3Ccircle cx='20' cy='160' r='2'/%3E%3Ccircle cx='140' cy='210' r='2'/%3E%3Ccircle cx='180' cy='225' r='2'/%3E%3C/g%3E%3C/svg%3E");
  content: "";
  position: absolute;
  inset: 0;
  background: var(--band-dot);
  -webkit-mask-image: var(--circuit);
  mask-image: var(--circuit);
  pointer-events: none;
}

/*
 * One-off pulses that template.js draws over the circuit (same 240px tile) and removes when they end.
 * It reads --circuit-y and --circuit-fade-x/y from the band, so the pulses line up with the mask.
 */
.band > .band-pulses { position: absolute; inset: 0; width: 100%; height: 100%; overflow: hidden; pointer-events: none; }
.band-pulses .band-trails { filter: drop-shadow(0 0 3px var(--accent)); }
.band-pulses path { fill: none; stroke: var(--accent); stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.band-pulses circle { fill: var(--accent); }

/* Large centered logo that scrolls away; the menu bar below it sticks to the top */
.site-header {
  /* The band is shorter than the 240px tile: shift it so the busiest middle part (bus lines, chip) shows */
  --circuit-y: -55px;
  --circuit-fade-x: 300px;
  --circuit-fade-y: 80px;
}
.site-header::before {
  /* The radial layer fades the circuit out behind the logo */
  -webkit-mask-image: var(--circuit), radial-gradient(ellipse var(--circuit-fade-x) var(--circuit-fade-y) at center, transparent 30%, black 100%);
  -webkit-mask-composite: source-in;
  mask-image: var(--circuit), radial-gradient(ellipse var(--circuit-fade-x) var(--circuit-fade-y) at center, transparent 30%, black 100%);
  mask-composite: intersect;
  -webkit-mask-repeat: repeat, no-repeat;
  mask-repeat: repeat, no-repeat;
  -webkit-mask-position: 0 var(--circuit-y), center;
  mask-position: 0 var(--circuit-y), center;
}

.masthead { display: flex; justify-content: center; padding: 22px var(--gutter) 20px; }

.brand { display: inline-flex; align-items: center; }
.brand img { display: block; height: 76px; width: auto; }

.navbar {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in srgb, var(--surface) 90%, transparent);
  backdrop-filter: saturate(1.4) blur(10px);
  -webkit-backdrop-filter: saturate(1.4) blur(10px);
  border-bottom: 1px solid var(--border);
  transition: box-shadow .2s ease;
}
.navbar.is-stuck { box-shadow: var(--shadow-hover); }

/*
 * The menu spans the content width, from the left edge of the main column to the buttons on the right.
 * The small logo takes room only once the bar is stuck, so the menu is not pushed in while it is hidden.
 */
.navbar-inner {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas: "brand nav actions";
  align-items: center;
  min-height: 64px;
}

.navbar-brand {
  grid-area: brand;
  justify-self: start;
  max-width: 0;
  overflow: hidden;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px);
  transition: opacity .2s ease, transform .2s ease, visibility .2s, max-width .2s ease, margin .2s ease;
}
.navbar-brand img { display: block; height: 26px; width: auto; max-width: none; filter: var(--logo-small-filter); }
.navbar.is-stuck .navbar-brand { max-width: 200px; margin-right: 16px; opacity: 1; visibility: visible; transform: none; }

.main-nav { grid-area: nav; min-width: 0; }
.main-nav li { flex: 1 1 auto; }
.main-nav a { text-align: center; }
.main-nav ul {
  display: flex;
  gap: 4px;
  margin: 0;
  padding: 5px;
  list-style: none;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 14px;
}
.main-nav a {
  display: block;
  padding: 8px 14px;
  border-radius: 10px;
  color: var(--text-muted);
  font-size: .9rem;
  font-weight: 600;
  white-space: nowrap;
  transition: background-color .15s ease, color .15s ease, box-shadow .15s ease;
}
.main-nav a:hover {
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--shadow);
  text-decoration: none;
}
/*
 * "location" marks the menu item the page being viewed belongs to (e.g. an article inside a menu section).
 * Articles reached from the home page belong to Home, which would then stay lit on every article: the
 * default item is highlighted only when it is the page itself.
 */
.main-nav a[aria-current="page"],
.main-nav li:not(.default) > a[aria-current="location"] {
  background: var(--accent);
  color: var(--accent-contrast);
  box-shadow: 0 2px 8px color-mix(in srgb, var(--accent) 35%, transparent);
}
/* The error page is not the page of any menu item, even though Joomla still marks Home as active */
.error-site .main-nav a[aria-current]:not(:hover) {
  background: none;
  color: var(--text-muted);
  box-shadow: none;
}
/* The main menu is a single row: sub levels are not shown */
.main-nav .mod-menu__sub,
.main-nav .mod-menu__toggle-sub { display: none; }

.header-actions { grid-area: actions; justify-self: end; display: flex; align-items: center; gap: 6px; margin-left: 16px; }

.icon-btn {
  display: inline-grid;
  place-items: center;
  width: 40px; height: 40px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
}
.icon-btn:hover { background: var(--surface-2); }
.icon-btn svg { width: 20px; height: 20px; }

/* The toggle shows the icon of the theme you would switch TO. */
.theme-toggle .icon-sun { display: none; }
:root[data-theme="dark"] .theme-toggle .icon-sun { display: block; }
:root[data-theme="dark"] .theme-toggle .icon-moon { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) .theme-toggle .icon-sun { display: block; }
  :root:not([data-theme]) .theme-toggle .icon-moon { display: none; }
}

.nav-toggle {
  grid-area: toggle;
  display: none;
  align-items: center;
  gap: 8px;
  height: 40px;
  padding: 0 14px 0 12px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface-2);
  color: var(--text);
  font: inherit;
  font-size: .9rem;
  font-weight: 600;
  cursor: pointer;
}
.nav-toggle svg { width: 20px; height: 20px; }

/* Site search: opens under the menu bar, so it stays reachable while the bar is stuck to the top */
.search-panel { border-top: 1px solid var(--border); background: var(--surface); }
.search-panel-form { display: flex; align-items: center; gap: 10px; padding-top: 12px; padding-bottom: 12px; }
.search-panel-form > svg { flex-shrink: 0; width: 20px; height: 20px; color: var(--text-muted); }
.search-panel input {
  flex: 1;
  min-width: 0;
  height: 44px;
  padding: 0 14px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: var(--text);
  font: inherit;
  font-size: 1rem;
}
.search-panel input:focus { outline: 2px solid var(--accent); outline-offset: 0; border-color: transparent; }
.search-toggle[aria-expanded="true"] { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }

/* ---------- Layout ---------- */

/* A faint echo of the header band that fades into the page background, tying header and content together */
.site-main {
  flex: 1;
  padding: 32px 0 56px;
  background: linear-gradient(to bottom, color-mix(in srgb, var(--band-from) 55%, var(--bg)), var(--bg) 380px) no-repeat;
}

.layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: 40px;
  align-items: start;
}
.layout.no-sidebar { grid-template-columns: minmax(0, 1fr); }

/* Core breadcrumbs module markup */
.mod-breadcrumbs__wrapper { margin: 0 0 20px; }
.mod-breadcrumbs {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: .85rem;
  color: var(--text-muted);
}
.mod-breadcrumbs .breadcrumb-item + .breadcrumb-item::before { content: "/"; margin-right: 6px; opacity: .6; }
.mod-breadcrumbs a { color: var(--text-muted); }
/* "You are here" stays for screen readers; the divider icon needs an icon font the template does not load */
.mod-breadcrumbs__here {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}
.mod-breadcrumbs__divider { display: none; }

.page-heading { margin: 0 0 20px; font-size: 1.1rem; font-weight: 600; color: var(--text-muted); text-transform: uppercase; letter-spacing: .06em; }

/* ---------- Article cards ---------- */

.card {
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow: hidden;
  transition: box-shadow .15s ease, transform .15s ease;
}
.card:hover { box-shadow: var(--shadow-hover); transform: translateY(-2px); }

/* Article images are mostly logos on white, so they are contained with padding; photos fill the box instead */
.card-thumb {
  position: relative;
  aspect-ratio: 16 / 9;
  background: var(--thumb-bg);
  border-bottom: 1px solid var(--border);
}
.card-thumb img {
  position: absolute;
  inset: 20px;
  width: calc(100% - 40px);
  height: calc(100% - 40px);
  object-fit: contain;
  filter: var(--thumb-filter);
}
.card-thumb.is-photo img { inset: 0; width: 100%; height: 100%; object-fit: cover; }

.card-body { display: flex; flex-direction: column; gap: 10px; padding: 18px 20px 20px; flex: 1; }

.card-title { margin: 0; font-size: 1.15rem; font-weight: 650; }
.card-title a { color: var(--text); }
.card-title a:hover { color: var(--accent); text-decoration: none; }
/* Whole card clickable while keeping a single real link for accessibility */
.card-title a::after { content: ""; position: absolute; inset: 0; }
.card { position: relative; }
.card .chip { position: relative; z-index: 1; }

.card-excerpt { margin: 0; color: var(--text-muted); font-size: .95rem; }

.card-featured { margin-bottom: 28px; }
@media (min-width: 47.5em) {
  .card-featured { flex-direction: row; }
  .card-featured .card-thumb { flex: 0 0 48%; aspect-ratio: auto; min-height: 260px; border-bottom: 0; border-right: 1px solid var(--border); }
  .card-featured .card-body { padding: 28px; justify-content: center; }
  .card-featured .card-title { font-size: 1.6rem; }
  .card-featured .card-excerpt { font-size: 1.02rem; }
}

.card-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 24px;
}

/* ---------- Classic blog list ---------- */

/*
 * Leading articles full width, intro articles in the columns set on the menu item, with Cassiopeia's class
 * names: columns-N fills rows (Across), masonry-N fills one column after the other (Down)
 */
.blog-items { display: grid; grid-template-columns: minmax(0, 1fr); gap: 24px; }
.blog-items + .blog-items { margin-top: 24px; }
.blog-items.columns-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.blog-items.columns-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.blog-items.columns-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.blog-items[class*="masonry-"] { display: block; column-gap: 24px; }
.blog-items.masonry-2 { column-count: 2; }
.blog-items.masonry-3 { column-count: 3; }
.blog-items.masonry-4 { column-count: 4; }
.blog-items[class*="masonry-"] > .post { break-inside: avoid; margin-bottom: 24px; }

.post {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 32px 40px 36px;
}
.post.is-unpublished { border-style: dashed; }
/* Narrow columns: less padding, smaller title */
.blog-items:is([class*="columns-"], [class*="masonry-"]) .post { padding: 24px 24px 28px; }
.blog-items:is([class*="columns-"], [class*="masonry-"]) .post-title { font-size: 1.25rem; }
@media (max-width: 68.75em) {
  .blog-items:is(.columns-3, .columns-4) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .blog-items:is(.masonry-3, .masonry-4) { column-count: 2; }
}
@media (max-width: 47.5em) {
  .blog-items[class*="columns-"] { grid-template-columns: minmax(0, 1fr); }
  .blog-items[class*="masonry-"] { column-count: 1; }
}

.post-header { display: flex; flex-direction: column; gap: 10px; margin-bottom: 22px; padding-bottom: 20px; border-bottom: 1px solid var(--border); }
.post-title { margin: 0; font-size: 1.5rem; font-weight: 700; }
.post-title a { color: var(--text); }
.post-title a:hover { color: var(--accent); text-decoration: none; }
.post-lead .post-title { font-size: clamp(1.5rem, 1.2rem + 1vw, 1.9rem); }

/* Intro text from the article: same typography as the article page, a step smaller for a list */
.post-text { font-size: 1.0625rem; }
.post-text > :last-child { margin-bottom: 0; }

.post .readmore { margin: 22px 0 0; }
.post .readmore .btn { gap: 8px; height: 40px; padding: 0 16px; font-size: .95rem; }
.post .readmore svg { width: 18px; height: 18px; flex-shrink: 0; }

/* ---------- Meta, chips, tags ---------- */

.meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 14px;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: .85rem;
  color: var(--text-muted);
}
.meta li { display: inline-flex; align-items: center; gap: 5px; }
.meta svg { width: 15px; height: 15px; opacity: .75; }

.chip {
  align-self: flex-start;
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--accent);
  font-size: .78rem;
  font-weight: 600;
  letter-spacing: .02em;
}
.chip:hover { text-decoration: none; filter: brightness(.97); }

.tags { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; padding: 0; list-style: none; }
.tags a {
  display: inline-block;
  padding: 4px 12px;
  border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--text-muted);
  font-size: .82rem;
}
.tags a::before { content: "#"; opacity: .55; margin-right: 1px; }
.tags a:hover { border-color: var(--accent); color: var(--accent); text-decoration: none; }

/* ---------- More articles + pagination ---------- */

.more-articles { margin-top: 40px; }
.more-articles h2 { font-size: 1.15rem; margin: 0 0 12px; }
.link-list {
  margin: 0;
  padding: 0;
  list-style: none;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}
.link-list li + li { border-top: 1px solid var(--border); }
.link-list a { display: flex; justify-content: space-between; gap: 12px; padding: 12px 16px; color: var(--text); }
.link-list a:hover { background: var(--surface-2); text-decoration: none; color: var(--accent); }
.link-list time { flex-shrink: 0; color: var(--text-muted); font-size: .85rem; }

/* Core pagination markup: nav.pagination__wrapper > ul.pagination > li.page-item > .page-link */
.pagination-wrap { margin-top: 32px; display: flex; flex-direction: column; align-items: center; gap: 10px; }
.pagination__wrapper { display: flex; justify-content: center; margin-top: 24px; }
.pagination-wrap .pagination__wrapper { margin-top: 0; }
.pagination { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; margin: 0; padding: 0; list-style: none; }
.pagination .page-link {
  display: inline-grid;
  place-items: center;
  min-width: 40px; height: 40px;
  padding: 0 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  font-size: .9rem;
}
.pagination a.page-link:hover { border-color: var(--accent); color: var(--accent); text-decoration: none; }
.pagination .active .page-link { background: var(--accent); border-color: var(--accent); color: var(--accent-contrast); font-weight: 600; }
.pagination .disabled .page-link { opacity: .45; }
.counter { margin: 0; color: var(--text-muted); font-size: .85rem; }

/* Blocks in the main-top / main-bottom positions, e.g. "More articles in this section" */
.module-section { margin-top: 40px; }
.module-section > h2 { font-size: 1.15rem; margin: 0 0 12px; }

/* Title-only article module in the main column: same look as the link list */
.module-section .mod-articles {
  margin: 0;
  padding: 0;
  list-style: none;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}
.module-section .mod-articles li + li { border-top: 1px solid var(--border); }
.module-section .mod-articles a { display: block; padding: 12px 16px; color: var(--text); }
.module-section .mod-articles a:hover { background: var(--surface-2); text-decoration: none; color: var(--accent); }

/* ---------- Sidebar ---------- */

.sidebar { display: flex; flex-direction: column; gap: 24px; position: sticky; top: 88px; }

.widget {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 20px;
}
.widget h2 { margin: 0 0 14px; font-size: 1rem; }

.ranked { margin: 0; padding: 0; list-style: none; counter-reset: rank; }
.ranked li { counter-increment: rank; display: grid; grid-template-columns: 28px 1fr; gap: 8px; padding: 10px 0; }
.ranked li + li { border-top: 1px solid var(--border); }
.ranked li::before { content: counter(rank); font-weight: 700; font-size: 1.15rem; color: var(--accent); line-height: 1.3; }
.ranked a { color: var(--text); font-size: .93rem; line-height: 1.4; }
.ranked a:hover { color: var(--accent); }

/* Alternative article layout "Product cards" (mod_articles/plugins.php): icon, name and one-line summary */
.product-list { margin: 0; padding: 0; list-style: none; }
.product-list li + li { border-top: 1px solid var(--border); }
.product-list a { display: grid; grid-template-columns: 44px minmax(0, 1fr); gap: 12px; align-items: center; padding: 10px 0; color: var(--text); text-decoration: none; }
.product-icon { display: grid; place-items: center; width: 44px; height: 44px; border-radius: 10px; overflow: hidden; background: var(--accent-soft); color: var(--accent); }
.product-icon img { display: block; width: 100%; height: 100%; object-fit: cover; }
.product-icon svg { width: 22px; height: 22px; }
.product-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.product-text strong { font-size: .95rem; line-height: 1.3; }
.product-text span { color: var(--text-muted); font-size: .82rem; line-height: 1.35; }
.product-list a:hover strong { color: var(--accent); }
.product-list a:focus-visible { outline-offset: 2px; border-radius: 8px; }

/* Article module with the standard layout in the sidebar: same rows as the ranking, without numbers */
.widget .mod-articles { margin: 0; padding: 0; list-style: none; }
.widget .mod-articles li { padding: 10px 0; }
.widget .mod-articles li + li { border-top: 1px solid var(--border); }
.widget .mod-articles a { color: var(--text); font-size: .93rem; line-height: 1.4; }
.widget .mod-articles a:hover { color: var(--accent); }

/* Menus in the sidebar and on the error page are shown as chips */
.section-list,
.widget .mod-menu,
.error-links .mod-menu { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; padding: 0; list-style: none; }
.section-list a,
.widget .mod-menu a,
.error-links .mod-menu a {
  display: inline-block;
  padding: 6px 12px;
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  color: var(--text);
  font-size: .88rem;
}
.section-list a:hover,
.widget .mod-menu a:hover,
.error-links .mod-menu a:hover { background: var(--accent-soft); color: var(--accent); text-decoration: none; }
.widget .mod-menu a[aria-current],
.widget .mod-menu .active > a { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.error-links .mod-menu { justify-content: center; }

/* ---------- Single article ---------- */

.article {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 40px 48px 44px;
}
.article-header { display: flex; flex-direction: column; gap: 14px; margin-bottom: 28px; padding-bottom: 24px; border-bottom: 1px solid var(--border); }
.article-header h1 { margin: 0; font-size: clamp(1.6rem, 1.2rem + 1.6vw, 2.25rem); font-weight: 750; }
.article-subtitle { margin: 0; font-size: 1.15rem; color: var(--text-muted); }

/* Unpublished / not yet published / expired: only visible to editors */
.status-badges { display: flex; flex-wrap: wrap; gap: 6px; margin: 0; }
.badge-warn {
  display: inline-block;
  padding: 2px 10px;
  border-radius: 999px;
  background: var(--warn-bg);
  color: var(--warn-text);
  font-size: .78rem;
  font-weight: 700;
}
.card.is-unpublished { border-style: dashed; }

.article .item-image { margin: 0 0 1.5em; }
.article .item-image img { display: block; margin: 0 auto; border-radius: var(--article-img-radius); }

/* Body copy: larger and high contrast, across the whole panel so articles line up with header and footer */
.article-body { font-size: 1.0625rem; line-height: 1.75; }
.article-body p { margin: 0 0 1.15em; }
.article-body h2 { font-size: 1.45rem; margin: 1.8em 0 .6em; }
.article-body h3 { font-size: 1.2rem; margin: 1.5em 0 .5em; }
/*
 * Article images keep the layout written in the article: the large ones are already centred on their own line
 * by an inline display:block style, while small ones (arrows, spacer GIFs) sit inside the text.
 * Those large images are mostly logos/screenshots made for a white page: in the dark theme they get a light
 * mat so transparent PNGs with dark lettering stay readable. Inline images are left alone.
 */
.article-body img { vertical-align: middle; }

/* Older articles lay out images and text with tables: paragraphs in a cell get tighter spacing than in the flow */
.article-body table { margin-bottom: 1.15em; }
.article-body td p { margin: 0 0 .6em; }
.article-body td p:last-child { margin-bottom: 0; }
.article-body img[style*="display: block"],
.article-body img[style*="display:block"] {
  /* The mat is added around the image instead of eating into its width/height, so it keeps its real size;
     the max-width leaves room for the mat on narrow screens */
  box-sizing: content-box;
  max-width: calc(100% - 2 * var(--article-img-pad));
  padding: var(--article-img-pad);
  border-radius: var(--article-img-radius);
  background: var(--article-img-bg);
  filter: var(--thumb-filter);
}
.article-body a { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; }
.article-body strong { font-weight: 650; }
.article-body ul, .article-body ol { padding-left: 1.4em; margin: 0 0 1.15em; }
.article-body li { margin-bottom: .35em; }
.article-body code { font-family: var(--font-mono); font-size: .9em; padding: .15em .4em; border-radius: 4px; background: var(--surface-2); }
.article-body blockquote { margin: 1.5em 0; padding: .4em 0 .4em 1.2em; border-left: 3px solid var(--accent); color: var(--text-muted); }

.callout {
  margin: 1.5em 0;
  padding: 14px 18px;
  border-radius: var(--radius-sm);
  background: var(--warn-bg);
  color: var(--warn-text);
  font-size: 1rem;
}
.callout strong { font-weight: 700; }

/*
 * Note boxes already used inside existing articles and custom modules (legacy editor classes, kept so old
 * content still looks right)
 */
.xtypo_info,
.xtypo_warning {
  display: block;
  margin: 1.5em 0;
  padding: 14px 18px;
  border-left: 4px solid;
  border-radius: var(--radius-sm);
  font-size: 1rem;
}
.xtypo_info { background: var(--accent-soft); border-left-color: var(--accent); color: var(--text); }
.xtypo_warning { background: var(--warn-bg); border-left-color: var(--warn-text); color: var(--warn-text); }
.module-section .xtypo_info,
.module-section .xtypo_warning { margin: 0; }

/* Code blocks: the script wraps each <pre> and adds a copy button in the top-right corner */
.article-body pre {
  margin: 0 0 1.15em;
  padding: 16px 18px;
  overflow-x: auto;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-family: var(--font-mono);
  font-size: .9rem;
  line-height: 1.6;
  white-space: pre;
}
.code-block { position: relative; margin: 0 0 1.15em; }
/* Room above the text for the button, so long commands that scroll sideways never run underneath it */
.code-block pre { margin: 0; padding-top: 48px; }
.code-copy {
  position: absolute;
  top: 8px;
  right: 8px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 32px;
  padding: 0 10px;
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-size: .8rem;
  font-weight: 600;
  cursor: pointer;
}
.code-copy:hover { border-color: var(--accent); color: var(--accent); }
.code-copy svg { width: 16px; height: 16px; }
.code-copy .icon-check { display: none; }
.code-copy.is-copied { border-color: var(--accent); color: var(--accent); }
.code-copy.is-copied .icon-copy { display: none; }
.code-copy.is-copied .icon-check { display: block; }

/* Shown above the text of articles older than the threshold set in the template options */
.notice-outdated {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  margin: 0 0 28px;
  padding: 14px 18px;
  border: 1px solid var(--border);
  border-left: 4px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  color: var(--text-muted);
  font-size: .95rem;
  line-height: 1.5;
}
.notice-outdated svg { flex-shrink: 0; width: 20px; height: 20px; margin-top: 1px; }
.notice-outdated p { margin: 0; }
.notice-outdated strong { color: var(--text); font-weight: 650; }

.article-footer { margin-top: 32px; padding-top: 24px; border-top: 1px solid var(--border); display: flex; flex-direction: column; gap: 20px; }

.article-nav { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-top: 24px; }
.article-nav a {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 16px 18px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text);
}
.article-nav a:hover { border-color: var(--accent); text-decoration: none; }
.article-nav span { font-size: .8rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: .06em; }
.article-nav .next { text-align: right; }
/* A lone "next" card stays in the right column */
.article-nav .next:only-child { grid-column: 2; }

/* ---------- Category list (table layout) ---------- */

.com-content-category__articles { margin-top: 4px; }
.com-content__filter { display: inline-flex; flex-wrap: wrap; gap: 8px; margin-bottom: 16px; }
.com-content-category__pagination { float: right; margin-bottom: 16px; }

.content input[type="text"],
.content input[type="search"],
.content select {
  height: 40px;
  padding: 0 12px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-size: .95rem;
}
.content input[type="text"]:focus,
.content input[type="search"]:focus,
.content select:focus { outline: 2px solid var(--accent); outline-offset: 0; border-color: transparent; }

/* Core buttons inside component output (filters, Smart Search results) */
.content .btn-primary,
.content .btn-secondary {
  display: inline-flex;
  align-items: center;
  height: 40px;
  padding: 0 16px;
  border-radius: var(--radius-sm);
  font: inherit;
  font-size: .9rem;
  font-weight: 600;
  cursor: pointer;
}
.content .btn-primary { border: 0; background: var(--accent); color: var(--accent-contrast); }
.content .btn-primary:hover { background: var(--accent-hover); color: var(--accent-contrast); text-decoration: none; }
.content .btn-secondary { border: 1px solid var(--border-strong); background: var(--surface); color: var(--text); }
.content .btn-secondary:hover { background: var(--surface-2); color: var(--text); text-decoration: none; }

.com-content-category__table {
  clear: both;
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}
.com-content-category__table th,
.com-content-category__table td { padding: 12px 16px; text-align: left; vertical-align: top; border-top: 1px solid var(--border); }
.com-content-category__table thead th {
  border-top: 0;
  background: var(--surface-2);
  color: var(--text-muted);
  font-size: .78rem;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
}
.com-content-category__table thead a { color: inherit; }
.com-content-category__table .list-title { font-weight: 600; }
.com-content-category__table .list-title a { color: var(--text); }
.com-content-category__table .list-title a:hover { color: var(--accent); }
.com-content-category__table tbody tr:hover { background: var(--surface-2); }
.com-content-category__table .list-date { width: 1%; white-space: nowrap; color: var(--text-muted); font-size: .85rem; }

/* ---------- Category index (core categories view) ---------- */

/* The core accordion stylesheet hardcodes a light grey: borders follow the theme instead */
.com-content-categories__item { border-bottom-color: var(--border); }
.com-content-categories__children { border-top-color: var(--border); }
.com-content-categories__item-title-wrapper { align-items: center; gap: 8px; padding: 10px 0; }
.com-content-categories__item-title a { font-weight: 600; }

/*
 * Expand/collapse button: the core swaps icon-plus/icon-minus classes from an icon font the template does
 * not load, so the sign is drawn with two bars and follows aria-expanded, which the core script also toggles.
 */
.content .com-content-categories__item-title-wrapper [id^="category-btn-"] {
  display: inline-block;
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background-color: var(--surface);
  background-image: linear-gradient(currentColor, currentColor), linear-gradient(currentColor, currentColor);
  background-size: 12px 2px, 2px 12px;
  background-position: center;
  background-repeat: no-repeat;
  color: var(--text);
  cursor: pointer;
}
.content .com-content-categories__item-title-wrapper [id^="category-btn-"][aria-expanded="true"] { background-size: 12px 2px, 0 0; }
.content .com-content-categories__item-title-wrapper [id^="category-btn-"]:hover { border-color: var(--accent); color: var(--accent); }
.com-content-categories__item-title-wrapper [id^="category-btn-"] > span { display: none; }

/* Counters such as "Articoli: 340" (core uses Bootstrap badge classes) */
.badge {
  display: inline-block;
  margin-left: 6px;
  padding: 2px 10px;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--text-muted);
  font-size: .78rem;
  font-weight: 600;
  line-height: 1.5;
  vertical-align: middle;
}

/*
 * Subtitle added by the KAutoSubtitle plugin in list views. Its own stylesheet fades it with opacity, which
 * on top of the muted color would drop below 4.5:1: here the color comes from the token instead.
 * Size and italic are left to the plugin's options.
 */
.content p.kautosubtitle-text { margin: 4px 0 0; color: var(--text-muted); opacity: 1; font-weight: 400; }

/* ---------- Error page ---------- */

.error-page { text-align: center; padding: 48px 0 24px; max-width: 640px; margin: 0 auto; }
.error-page .error-code { font-size: clamp(4.5rem, 3rem + 8vw, 8rem); font-weight: 800; line-height: 1; margin: 0; color: var(--accent); letter-spacing: -.04em; }
.error-page h1 { margin: 12px 0 8px; font-size: 1.6rem; }
.error-page p { color: var(--text-muted); margin: 0 0 28px; }
.search-form { display: flex; gap: 8px; max-width: 460px; margin: 0 auto 32px; }
.search-form input {
  flex: 1;
  min-width: 0;
  height: 44px;
  padding: 0 14px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  font: inherit;
}
.search-form input:focus { outline: 2px solid var(--accent); outline-offset: 0; border-color: transparent; }
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 44px;
  padding: 0 18px;
  border: 0;
  border-radius: var(--radius-sm);
  background: var(--accent);
  color: var(--accent-contrast);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}
.btn:hover { background: var(--accent-hover); color: var(--accent-contrast); text-decoration: none; }

/*
 * Bootstrap button classes written inside articles (the extension pages: Download / Support / Documentation).
 * Only the variants in use are mapped; the vertical margin keeps wrapped rows apart on narrow screens.
 */
.article-body .btn { height: auto; min-height: 44px; margin: 4px 0; padding: 8px 18px; font-size: 1rem; line-height: 1.3; text-align: center; text-decoration: none; vertical-align: middle; }
.article-body .btn-lg { min-height: 52px; padding: 10px 24px; font-size: 1.1rem; }
.article-body .btn-sm { min-height: 36px; padding: 6px 12px; font-size: .875rem; }
.article-body .btn-outline-primary { background: transparent; color: var(--accent); box-shadow: inset 0 0 0 2px var(--accent); }
.article-body .btn-outline-primary:hover { background: var(--accent); color: var(--accent-contrast); }
.article-body .btn-secondary,
.article-body .btn-outline-secondary { background: var(--surface); color: var(--text); box-shadow: inset 0 0 0 1px var(--border-strong); }
.article-body .btn-secondary:hover,
.article-body .btn-outline-secondary:hover { background: var(--surface-2); color: var(--text); }

/* A grey written inline in articles (the "current version" lines) would be too faint on the dark theme */
.article-body [style*="color: #666"] { color: var(--text-muted) !important; }
/*
 * Other inline colours left in old articles by earlier editors: the yellow highlight keeps dark text whatever the
 * theme, the light grey code boxes take the theme's panel colour, and black text follows the theme's text colour.
 */
.article-body [style*="background-color: #ffff00"] { color: #1b1b1b; }
.article-body blockquote[style*="background-color: #eeeeee"] { background-color: var(--surface-2) !important; color: var(--text); padding-right: 1.2em; }
.article-body [style*="color: #000000"]:not([style*="background"]) { color: var(--text) !important; }
.article-body hr { border: 0; border-top: 1px solid var(--border); }

.error-page .section-list { justify-content: center; }
.error-debug { margin-top: 32px; text-align: left; font-size: .85rem; overflow-x: auto; }

/* ---------- Offline page ---------- */

/*
 * A live circuit board: pulses of light run along the traces towards the centre, where the logo and a frosted
 * card hold the message and the login form. Everything stands still for visitors who ask for reduced motion.
 */
.offline-page {
  position: relative;
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 40px var(--gutter);
  overflow: hidden;
  background: radial-gradient(ellipse at center, var(--band-to), var(--band-from) 75%);
}
.offline-circuit { position: absolute; inset: 0; width: 100%; height: 100%; }
.offline-circuit path { fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.offline-traces path { stroke: var(--band-dot); }
.offline-pulses path {
  stroke: var(--accent);
  stroke-width: 3;
  /* One 9-unit pulse per 200-unit period on a 100-unit path: no second copy ever shows on the trace */
  stroke-dasharray: 9 191;
  stroke-dashoffset: 9;
  filter: drop-shadow(0 0 4px var(--accent));
  animation: offline-pulse var(--pulse-time, 4s) linear var(--pulse-delay, 0s) infinite;
}
.offline-pads circle {
  fill: var(--surface);
  stroke: var(--accent);
  stroke-width: 2.5;
  animation: offline-pad 3.6s ease-in-out var(--pad-delay, 0s) infinite;
}
/* From just before the edge (offset 9) to just past the pad (offset -100) */
@keyframes offline-pulse {
  from { stroke-dashoffset: 9; }
  to { stroke-dashoffset: -100; }
}
@keyframes offline-pad {
  0%, 100% { opacity: .45; }
  50% { opacity: 1; filter: drop-shadow(0 0 6px var(--accent)); }
}

.offline-main { position: relative; width: 100%; max-width: 440px; text-align: center; }
.offline-logo { position: relative; margin: 0 0 28px; animation: offline-rise .9s cubic-bezier(.2, .7, .2, 1) both; }
/* Breathing glow behind the logo */
.offline-logo::before {
  content: "";
  position: absolute;
  inset: -40% -10%;
  z-index: -1;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--accent) 28%, transparent), transparent);
  animation: offline-glow 4s ease-in-out infinite;
}
.offline-logo img { display: inline-block; height: 92px; width: auto; max-width: 100%; }
.offline-card {
  position: relative;
  overflow: hidden;
  padding: 32px 32px 28px;
  background: color-mix(in srgb, var(--surface) 82%, transparent);
  -webkit-backdrop-filter: blur(14px) saturate(1.3);
  backdrop-filter: blur(14px) saturate(1.3);
  border: 1px solid color-mix(in srgb, var(--accent) 25%, var(--border));
  border-radius: var(--radius);
  box-shadow: var(--shadow-hover), 0 24px 60px -24px color-mix(in srgb, var(--accent) 45%, transparent);
  animation: offline-rise .9s cubic-bezier(.2, .7, .2, 1) .15s both;
}
/* Progress strip running along the top edge */
.offline-card::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 3px;
  background: linear-gradient(90deg, transparent, var(--accent), transparent) no-repeat;
  background-size: 40% 100%;
  animation: offline-progress 2.4s ease-in-out infinite;
}
.offline-status {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 14px;
  padding: 4px 12px;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--accent);
  font-size: .8rem;
  font-weight: 700;
}
.offline-status span {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: currentColor;
  box-shadow: 0 0 0 0 currentColor;
  animation: offline-beacon 1.8s ease-out infinite;
}
@keyframes offline-rise {
  from { opacity: 0; transform: translateY(18px); }
  to { opacity: 1; transform: none; }
}
@keyframes offline-glow {
  0%, 100% { opacity: .55; transform: scale(.96); }
  50% { opacity: 1; transform: scale(1.04); }
}
@keyframes offline-progress {
  from { background-position: -60% 0; }
  to { background-position: 160% 0; }
}
@keyframes offline-beacon {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, currentColor 60%, transparent); }
  100% { box-shadow: 0 0 0 9px transparent; }
}
@media (prefers-reduced-motion: reduce) {
  .offline-pulses path, .offline-pads circle, .offline-logo, .offline-logo::before, .offline-card, .offline-card::before, .offline-status span { animation: none; }
  .offline-pulses path { stroke-dashoffset: -55; }
}
.offline-image { display: block; max-width: 100%; height: auto; margin: 0 auto 20px; }
.offline-card h1 { margin: 0 0 10px; font-size: 1.5rem; }
.offline-message { margin: 0; color: var(--text-muted); }
/* Login errors appear between the message and the form */
.offline-card joomla-alert { margin: 16px 0 0; }
.offline-login { display: flex; flex-direction: column; gap: 6px; margin-top: 24px; padding-top: 22px; border-top: 1px solid var(--border); text-align: left; }
.offline-login h2 { margin: 0 0 6px; font-size: .8rem; font-weight: 700; color: var(--text-muted); text-transform: uppercase; letter-spacing: .06em; text-align: center; }
.offline-login label { font-size: .9rem; font-weight: 600; }
.offline-login input {
  height: 44px;
  margin-bottom: 8px;
  padding: 0 14px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  font: inherit;
}
.offline-login input:focus { outline: 2px solid var(--accent); outline-offset: 0; border-color: transparent; }
.offline-login .btn { width: 100%; margin-top: 6px; gap: 8px; }
.offline-login .btn-secondary { background: var(--surface); color: var(--text); box-shadow: inset 0 0 0 1px var(--border-strong); }
.offline-login .btn-secondary:hover { background: var(--surface-2); color: var(--text); }
.offline-login .btn svg { width: 18px; height: 18px; }
.offline-copyright { margin: 24px 0 0; font-size: .85rem; color: var(--text-muted); }
@media (max-width: 40em) {
  .offline-logo img { height: 56px; }
  .offline-card { padding: 24px 20px 22px; }
}

/* ---------- Footer ---------- */

.site-footer {
  border-top: 1px solid var(--border);
  font-size: .925rem;
  color: var(--text-muted);
}
/* Text sits on top of the pattern here, so it is kept fainter than in the header */
.site-footer::before { opacity: .5; }

/* Compact single row: the about block takes the free space, link groups (one per module position) sit on the right */
.footer-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-auto-flow: column;
  grid-auto-columns: auto;
  /* One text line across the row: the tagline, the link groups and the cookie button share a baseline */
  align-items: baseline;
  gap: 16px 40px;
  padding-top: 22px;
  padding-bottom: 22px;
}

/* Baseline alignment puts the tagline's text baseline on the logo's bottom edge */
.footer-about { display: flex; align-items: baseline; gap: 16px; }
.footer-about img { display: block; flex-shrink: 0; height: 28px; width: auto; filter: var(--logo-small-filter); }
.footer-about img.is-mono { filter: var(--logo-mono-filter); }
.footer-about p { margin: 0; font-size: .875rem; line-height: 1.45; }

/* Group titles stay for screen readers only: the links are self-explanatory in a single row */
.footer-col h2 {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}
.footer-col ul { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 20px; margin: 0; padding: 0; list-style: none; }
.footer-col a { color: var(--text-muted); }
.footer-col a:hover { color: var(--accent); text-decoration: none; }

/* Reopens the KConsensio preferences panel through its data-kconsensio-action="manage" handler */
.cookie-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px 6px 10px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-size: .875rem;
  font-weight: 600;
  cursor: pointer;
}
.cookie-btn:hover { border-color: var(--accent); color: var(--accent); text-decoration: none; }
/* The Legalblink variant is a link: keep it from taking the muted footer link colour */
.footer-col a.cookie-btn { color: var(--text); }
.footer-col a.cookie-btn:hover { color: var(--accent); }
/* Baseline-aligned text with a centred icon: the button then takes its baseline from the text, not from the
   icon, and lines up with the footer links */
.cookie-btn { align-items: baseline; }
.cookie-btn svg { align-self: center; width: 18px; height: 18px; }

.footer-bottom { border-top: 1px solid color-mix(in srgb, var(--border) 70%, transparent); }
.footer-bottom-inner {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 8px 24px;
  padding-top: 12px;
  padding-bottom: 12px;
  font-size: .85rem;
}
/* Below this width the fixed back-to-top button reaches the container edge: keep the last row clear of it */
@media (max-width: 89.9375em) {
  .footer-bottom-inner { padding-right: calc(var(--gutter) + 56px); }
}
.footer-bottom a { color: var(--text-muted); }
.footer-bottom a:hover { color: var(--accent); }

/* Back-to-top: shown by the script once the visitor has scrolled down a fair way */
.back-to-top {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 40;
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: var(--accent);
  color: var(--accent-contrast);
  box-shadow: var(--shadow-hover);
  cursor: pointer;
  opacity: 0;
  visibility: hidden;
  transform: translateY(12px);
  transition: opacity .2s ease, transform .2s ease, visibility .2s, background-color .15s ease;
}
.back-to-top.is-visible { opacity: 1; visibility: visible; transform: none; }
.back-to-top:hover { background: var(--accent-hover); }
.back-to-top svg { width: 22px; height: 22px; }

/* ---------- Responsive ---------- */

/*
 * Breakpoints are in em (16px each at the default text size): in a media query the em follows the text size
 * set in the browser, so with larger text the layout and the menu switch to their narrow form sooner,
 * instead of overflowing sideways.
 */
@media (max-width: 63.9375em) {
  .layout { grid-template-columns: minmax(0, 1fr); }
  .sidebar { position: static; }
  .article { padding: 32px 28px 36px; }
}

/* Nine menu items no longer fit on one line: switch to a dropdown */
@media (max-width: 68.6875em) {
  .navbar-inner {
    position: relative;
    grid-template-columns: auto 1fr auto;
    grid-template-areas: "toggle brand actions";
    gap: 16px;
    min-height: 60px;
  }
  .navbar-brand, .navbar.is-stuck .navbar-brand { justify-self: center; margin-right: 0; }
  .header-actions { margin-left: 0; }
  .main-nav a { text-align: left; }
  .nav-toggle { display: inline-flex; }
  .main-nav {
    display: none;
    position: absolute;
    left: 0; right: 0; top: 100%;
    padding: 8px var(--gutter) 16px;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    box-shadow: var(--shadow-hover);
  }
  .main-nav.is-open { display: block; }
  .main-nav ul { flex-direction: column; gap: 2px; padding: 0; background: none; border: 0; }
  .main-nav a { padding: 12px 14px; font-size: 1rem; }
}

@media (max-width: 40em) {
  .masthead { padding: 16px var(--gutter) 14px; }
  .brand img { height: 48px; }
}

@media (max-width: 40em) {
  .site-main { padding-top: 20px; }
  .card-grid { grid-template-columns: minmax(0, 1fr); gap: 16px; }
  .blog-items { gap: 16px; }
  .blog-items + .blog-items { margin-top: 16px; }
  .post, .blog-items:is([class*="columns-"], [class*="masonry-"]) .post { padding: 24px 18px 28px; border-radius: 0; border-left: 0; border-right: 0; margin-left: calc(var(--gutter) * -1); margin-right: calc(var(--gutter) * -1); }
  .post-title, .post-lead .post-title { font-size: 1.3rem; }
  .article { padding: 24px 18px 28px; border-radius: 0; border-left: 0; border-right: 0; margin: 0 calc(var(--gutter) * -1); }
  .article-nav { grid-template-columns: minmax(0, 1fr); }
  .article-nav .next { text-align: left; }
  .link-list a { flex-direction: column; gap: 2px; }
  .footer-grid { grid-auto-flow: row; gap: 16px; padding-top: 22px; padding-bottom: 18px; }
  .footer-about { flex-direction: column; align-items: flex-start; gap: 8px; }
  .back-to-top { right: 14px; bottom: 14px; }
}

@media (prefers-reduced-motion: reduce) {
  .back-to-top { transition: none; }
  .card { transition: none; }
  .card:hover { transform: none; }
}
