/* ---------- Design tokens ---------- */
:root {
  --color-bg: #f6efdd;
  --color-surface: #fffbf2;
  --color-header: #2c2c18;
  --color-header-text: #f3ecd8;
  --color-nav: #3c3b21;
  --color-nav-text: #e9e3cc;
  --color-accent: #dd7a2c;
  --color-accent-dark: #bf6620;
  --color-text: #2a2818;
  --color-text-muted: #6d6a54;
  --color-border: #e7dcc0;
  --color-olive: #4c4b2c;

  --radius-md: 10px;
  --radius-lg: 16px;
  --shadow-card: 0 2px 10px rgba(43, 40, 20, 0.08);
  --container-width: 1180px;
}

* {
  box-sizing: border-box;
}

html, body {
  margin: 0;
  padding: 0;
  overflow-x: hidden;
  /* Confirmed live (via Chrome's own "find in page" auto-scrolling the
     document sideways to reveal an off-screen match) that this page has
     genuine horizontal document scroll on mobile - overflow-x: hidden
     alone doesn't prevent that, because it only clips CONTENT relative
     to this element's OWN box; it does nothing if some descendant's
     min-content width forces html/body's own box wider than the
     viewport in the first place. max-width: 100vw is a hard cap tied to
     the actual viewport, independent of how wide any descendant tries
     to make its ancestors. */
  max-width: 100vw;
}

body {
  background: var(--color-bg);
  color: var(--color-text);
  font-family: "Segoe UI", "Helvetica Neue", Arial, sans-serif;
  line-height: 1.45;
  /* overflow-x: hidden above only stops the page itself from scrolling
     sideways - it doesn't stop one long unbroken word (a long compound
     word, a URL, a hashtag) inside a narrow mobile card/column from
     overflowing that element and getting clipped or overlapping
     neighboring content. overflow-wrap is inherited, so setting it once
     here covers headlines/excerpts/body text everywhere instead of
     patching every title/excerpt class that might contain one. */
  overflow-wrap: break-word;
}

a {
  color: inherit;
  text-decoration: none;
}

button, input {
  font-family: inherit;
}

img {
  max-width: 100%;
  display: block;
}

.container {
  max-width: var(--container-width);
  margin: 0 auto;
  padding: 0 20px;
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: none;
  border-radius: 999px;
  padding: 10px 20px;
  font-size: 0.95rem;
  font-weight: 600;
  cursor: pointer;
}

.btn--accent {
  background: var(--color-accent);
  color: #fff;
}
.btn--accent:hover {
  background: var(--color-accent-dark);
}

.btn--outline {
  background: var(--color-surface);
  color: var(--color-text);
  border: 1px solid var(--color-border);
}

.btn--ghost {
  background: transparent;
  color: var(--color-olive);
  border: 1px solid var(--color-border);
}

/* ---------- Splash screen ---------- */
.splash {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(20, 19, 10, 0.96);
  transition: opacity 0.35s ease;
}

.splash--hidden {
  opacity: 0;
  pointer-events: none;
}

.splash-circle {
  position: relative;
  width: 200px;
  height: 200px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.splash-ring {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: conic-gradient(
    var(--color-accent) 0deg,
    #ffb877 90deg,
    rgba(221, 122, 44, 0) 200deg,
    rgba(221, 122, 44, 0) 360deg
  );
  animation: splash-rotate 1.2s linear infinite;
  box-shadow: 0 0 32px rgba(221, 122, 44, 0.7);
}

.splash-icon {
  position: relative;
  width: 120px;
  height: 120px;
  border-radius: 50%;
  overflow: hidden;
  background: var(--color-header);
  box-shadow: 0 0 0 5px #8a6a3a;
  display: flex;
  align-items: center;
  justify-content: center;
}

.splash-icon img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 0.25s ease;
}

.splash-icon img.icon-visible {
  opacity: 1;
}

@keyframes splash-rotate {
  to { transform: rotate(360deg); }
}

/* ---------- Auth ---------- */
.topbar-auth {
  background: none;
  border: 1px solid rgba(243, 236, 216, 0.4);
  border-radius: 999px;
  color: inherit;
  cursor: pointer;
  font-size: 0.8rem;
  padding: 4px 12px;
}

.topbar-auth:hover {
  border-color: var(--color-accent);
  color: var(--color-accent);
}

.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 1100;
  background: rgba(20, 19, 10, 0.7);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
}

.modal-overlay[hidden] {
  display: none;
}

.modal {
  position: relative;
  width: min(360px, 100%);
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  padding: 28px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.35);
}

.modal-close {
  position: absolute;
  top: 16px;
  right: 16px;
  width: 22px;
  height: 22px;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
}

.modal-close::before,
.modal-close::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 18px;
  height: 2px;
  background: var(--color-text-muted);
  transform-origin: center;
}

.modal-close::before {
  transform: translate(-50%, -50%) rotate(45deg);
}

.modal-close::after {
  transform: translate(-50%, -50%) rotate(-45deg);
}

.modal-tabs {
  display: flex;
  gap: 8px;
  margin-bottom: 18px;
}

.modal-tab {
  flex: 1;
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: 999px;
  padding: 8px;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--color-text-muted);
  cursor: pointer;
}

.modal-tab--active {
  background: var(--color-header);
  border-color: var(--color-header);
  color: var(--color-header-text);
}

.modal-title {
  margin: 0 0 18px;
  font-size: 1.2rem;
}

.modal-form {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.modal-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 0.85rem;
  color: var(--color-text-muted);
}

.modal-field input {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 10px 12px;
  font-size: 0.95rem;
  color: var(--color-text);
}

.modal-error {
  margin: 0;
  font-size: 0.85rem;
  color: #b3391f;
}

.modal-submit {
  width: 100%;
  justify-content: center;
}

.modal--search {
  width: min(760px, 100%);
  max-height: 85vh;
  overflow-y: auto;
}

.admin-dialog-message {
  margin: 0 0 16px;
  font-size: 0.95rem;
  color: var(--color-text);
  white-space: pre-wrap;
}

.admin-dialog-input {
  display: block;
  width: 100%;
  margin-bottom: 16px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 10px 12px;
  font-size: 0.95rem;
  color: var(--color-text);
  box-sizing: border-box;
}

.admin-dialog-input[hidden] {
  /* An author-stylesheet display:block above would otherwise beat the
     UA stylesheet's [hidden] { display: none } at equal specificity. */
  display: none;
}

.admin-dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}

.search-input {
  width: 100%;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 10px 12px;
  font-size: 1rem;
  color: var(--color-text);
  margin-bottom: 16px;
}

.search-hint,
.search-empty {
  margin: 0 0 16px;
  font-size: 0.85rem;
  color: var(--color-text-muted);
}

.search-results.news-grid {
  grid-template-columns: repeat(2, 1fr);
  gap: 16px;
}

/* ---------- Topbar ---------- */
.topbar {
  background: var(--color-header);
  color: var(--color-header-text);
  font-size: 0.85rem;
}

.topbar-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 38px;
}

.topbar-links {
  display: flex;
  align-items: center;
  gap: 18px;
}

.icon-btn {
  background: none;
  border: none;
  color: inherit;
  cursor: pointer;
  padding: 0;
  line-height: 0;
}

.icon-btn img {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  object-fit: cover;
}

.lang-switch {
  line-height: normal;
  padding: 3px 9px;
  border: 1px solid var(--color-border);
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.03em;
}

/* ---------- Masthead ---------- */
.masthead {
  background: var(--color-bg);
  border-bottom: 1px solid var(--color-border);
}

.masthead-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 18px 20px;
  flex-wrap: wrap;
}

.brand {
  display: flex;
  align-items: center;
  gap: 14px;
}

.brand-logo {
  width: 64px;
  height: 64px;
  object-fit: contain;
  border-radius: 50%;
}

.brand-title {
  display: block;
  font-size: 1.7rem;
  font-weight: 800;
  letter-spacing: 0.5px;
  color: var(--color-header);
}

.brand-subtitle {
  display: block;
  font-size: 0.8rem;
  color: var(--color-text-muted);
  font-weight: 600;
}

.subscribe {
  display: flex;
  align-items: center;
  gap: 12px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 10px 16px;
}

.subscribe-icon {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  object-fit: cover;
  flex-shrink: 0;
}

.subscribe-copy {
  display: flex;
  flex-direction: column;
  font-size: 0.8rem;
  color: var(--color-text-muted);
  white-space: nowrap;
}

.subscribe-copy strong {
  color: var(--color-text);
  font-size: 0.9rem;
}

.subscribe-input {
  border: 1px solid var(--color-border);
  border-radius: 999px;
  padding: 8px 14px;
  font-size: 0.85rem;
  min-width: 160px;
}

.subscribe-status {
  margin: 8px 0 0;
  font-size: 0.85rem;
  color: var(--color-olive);
}

.subscribe-status--error {
  color: #b3391f;
}

/* ---------- Main nav ---------- */
.mainnav {
  background: var(--color-nav);
  position: relative;
}

.mainnav-row {
  display: flex;
  overflow-x: auto;
}

.mainnav-toggle {
  display: none;
  position: absolute;
  top: 0;
  right: 0;
  background: none;
  border: none;
  cursor: pointer;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 16px 20px;
}

.mainnav-toggle-dot {
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--color-nav-text);
}

.mainnav-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  color: var(--color-nav-text);
  font-size: 0.8rem;
  font-weight: 600;
  padding: 14px 18px;
  border-bottom: 3px solid transparent;
  white-space: nowrap;
}

.mainnav-item:hover {
  background: rgba(255, 255, 255, 0.05);
}

.mainnav-item--active {
  color: #fff;
  border-bottom-color: var(--color-accent);
}

.mainnav-icon {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  object-fit: cover;
}

/* ---------- Hero row ---------- */
.hero-row {
  display: grid;
  grid-template-columns: 2fr 1fr;
  gap: 24px;
  margin: 28px 0;
  align-items: stretch;
}

.hero-panel {
  position: relative;
  background: var(--color-header);
  color: #fff;
  border-radius: var(--radius-lg);
  padding: 32px;
  overflow: hidden;
  min-height: 380px;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.hero-meta {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 16px;
}

.hero-badge {
  display: inline-block;
  background: var(--color-accent);
  color: #fff;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.5px;
  padding: 4px 12px;
  border-radius: 999px;
  width: fit-content;
}

.hero-time {
  font-size: 0.8rem;
  color: rgba(243, 236, 216, 0.7);
}

.hero-title {
  font-size: 2rem;
  line-height: 1.2;
  margin: 0 0 14px;
  max-width: 60%;
}

.hero-excerpt {
  max-width: 55%;
  color: rgba(243, 236, 216, 0.85);
  margin: 0 0 20px;
}

.hero-media {
  position: absolute;
  right: 0;
  top: 0;
  bottom: 0;
  width: 48%;
}

.hero-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.9;
  -webkit-mask-image: linear-gradient(to right, transparent, black 25%);
  mask-image: linear-gradient(to right, transparent, black 25%);
}

.hero-dots {
  display: flex;
  gap: 8px;
  margin-top: 24px;
}

.hero-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.35);
}

.hero-dot--active {
  background: var(--color-accent);
}

.ticker-panel {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: 24px;
  display: flex;
  flex-direction: column;
}

.panel-title {
  margin: 0 0 16px;
  font-size: 1.1rem;
}

.ticker-list {
  list-style: none;
  margin: 0 0 16px;
  padding: 0;
  flex: 1;
}

.ticker-item {
  display: flex;
  gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid var(--color-border);
  font-size: 0.9rem;
}

.ticker-item:last-child {
  border-bottom: none;
}

.ticker-time {
  color: var(--color-accent);
  font-weight: 700;
  flex-shrink: 0;
  width: 60px;
}

.ticker-link:hover {
  text-decoration: underline;
}

/* ---------- Sections ---------- */
.section {
  margin: 40px 0;
}

.section-title {
  font-size: 1.3rem;
  margin: 0 0 18px;
}

.admin-state {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: 40px;
  text-align: center;
}

.admin-state h1 {
  margin: 0 0 12px;
  font-size: 1.6rem;
}

.admin-state p {
  color: var(--color-text-muted);
  margin: 0 0 16px;
}

.admin-state p:last-child {
  margin-bottom: 0;
}

.admin-shell {
  display: grid;
  grid-template-columns: 220px 1fr;
  gap: 24px;
  align-items: start;
  /* Belt-and-suspenders on top of the min-width:0 fixes on individual
     children: grid/flex items' automatic minimum sizing can behave
     inconsistently across mobile browsers, so a targeted fix on one
     child doesn't reliably stop the WHOLE grid (and everything else on
     the page, via body's own width growing to fit it) from being forced
     wider than the viewport by whichever descendant misbehaves next.
     Capping the shell itself is unconditional - nothing inside it, no
     matter the cause, can push the page wider than this box's own
     width. Anything that still doesn't fit is contained/clipped here
     instead of propagating up to body. */
  max-width: 100%;
  overflow-x: hidden;
}

.admin-pause-banner {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 12px 18px;
  border-radius: var(--radius-md);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
}

.admin-pause-status {
  font-weight: 600;
  font-size: 0.9rem;
  /* Flex items default to min-width: auto, so this text otherwise refuses
     to shrink below its own full-sentence width even with flex-wrap on
     the parent (that only wraps ITEMS onto new lines, not text within
     one item) - and since this banner spans the whole grid row
     (grid-column: 1/-1) inside .admin-shell, an oversized item here drags
     the entire grid (and everything else on the page) wider than the
     viewport with it. Same fix already applied to .admin-source-input
     below for the same reason. */
  min-width: 0;
}

.admin-sidebar {
  display: flex;
  flex-direction: column;
  gap: 4px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: 12px;
}

.admin-sidebar-link {
  text-align: left;
  background: none;
  border: none;
  border-radius: var(--radius-md);
  padding: 10px 12px;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--color-text-muted);
  cursor: pointer;
}

.admin-sidebar-link:hover {
  background: var(--color-bg);
}

.admin-sidebar-link--active {
  background: var(--color-header);
  color: var(--color-header-text);
}

.admin-content {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: 28px;
}

.admin-panel-title {
  margin: 0 0 6px;
  font-size: 1.3rem;
}

.admin-panel-desc {
  margin: 0 0 20px;
  color: var(--color-text-muted);
  font-size: 0.9rem;
}

.admin-panel-actions {
  margin-bottom: 12px;
}

.admin-tabs {
  display: flex;
  gap: 8px;
  margin-bottom: 18px;
  flex-wrap: wrap;
}

.admin-tab {
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: 999px;
  padding: 6px 14px;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--color-text-muted);
  cursor: pointer;
}

.admin-tab--active {
  background: var(--color-header);
  border-color: var(--color-header);
  color: var(--color-header-text);
}

.admin-source-form {
  display: flex;
  gap: 10px;
  margin-bottom: 8px;
  flex-wrap: wrap;
}

.admin-policy-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 16px;
}

.admin-policy-label {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--color-text);
}

.admin-policy-textarea {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 10px 12px;
  font-size: 0.9rem;
  color: var(--color-text);
  resize: vertical;
}

.admin-policy-status {
  margin: 0 0 12px;
  font-size: 0.85rem;
  color: var(--color-olive);
}

.admin-policy-status--error {
  color: #b3391f;
}

.admin-source-input {
  flex: 1;
  min-width: 200px;
  /* Unconditional hard cap, regardless of viewport - the mobile media
     query below already drops min-width to 0, but that alone depends on
     the surrounding flex-stretch chain (.admin-source-form's
     flex-direction/align-items) working exactly as expected to keep the
     input from exceeding its card. max-width: 100% doesn't depend on any
     of that: whatever the input's other sizing inputs say, it can never
     render wider than its own containing block. Confirmed live: the
     min-width: 0 override on its own wasn't enough - inputs were still
     sticking out past the card's right edge on mobile. */
  max-width: 100%;
  box-sizing: border-box;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 10px 12px;
  font-size: 0.9rem;
  color: var(--color-text);
}

/* ---------- Select dropdowns ----------
   Native <select> chrome (the box AND the arrow) ignored every input style
   above it - this replaces the browser's own arrow with a custom chevron
   so a select actually looks like it belongs with the text inputs next to
   it, instead of falling back to raw OS styling. */
select.admin-source-input,
select.ad-request-input,
.modal-field select {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  background-color: var(--color-surface);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%236d6a54' stroke-width='1.6' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  padding-right: 32px;
  cursor: pointer;
}

.admin-source-input:hover,
.ad-request-input:hover,
.modal-field select:hover {
  border-color: var(--color-accent);
}

.admin-source-input:focus,
.ad-request-input:focus,
.modal-field input:focus,
.modal-field select:focus {
  outline: none;
  border-color: var(--color-accent);
  box-shadow: 0 0 0 3px rgba(221, 122, 44, 0.15);
}

.admin-checkbox-group {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 14px;
}

.admin-checkbox-group label {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 0.85rem;
  color: var(--color-text);
  cursor: pointer;
}

.admin-table-scroll {
  /* Multi-column data tables (URL, status, interval, depth, language...)
     don't shrink to fit a narrow viewport the way text does - without
     this, the table forces the whole page wider than the screen, and
     since body has overflow-x: hidden the excess doesn't scroll into
     view, it just gets silently clipped (confirmed live on mobile:
     unrelated content above the table - the topbar, status banner, tab
     buttons - was clipped at the same right edge, because it all shared
     the same overflowing ancestor). Let the table itself scroll
     horizontally within this wrapper instead of the whole page.
     max-width: 100% + width: 100% keeps it from ever exceeding its
     container even before there's anything to scroll. */
  max-width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.admin-sources-table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 20px;
  font-size: 0.88rem;
}

.admin-sources-table th {
  text-align: left;
  color: var(--color-text-muted);
  font-weight: 600;
  padding: 8px 10px;
  border-bottom: 1px solid var(--color-border);
}

.admin-sources-table td {
  padding: 10px;
  border-bottom: 1px solid var(--color-border);
  vertical-align: middle;
  word-break: break-all;
}

.admin-sources-table tr:last-child td {
  border-bottom: none;
}

.admin-row--clickable {
  cursor: pointer;
}

.admin-row--clickable:hover td {
  background: var(--color-bg);
}

.admin-sources-table td:last-child {
  white-space: nowrap;
  word-break: normal;
}

.admin-remove-btn {
  background: none;
  border: 1px solid var(--color-border);
  border-radius: 999px;
  padding: 4px 12px;
  font-size: 0.8rem;
  color: #b3391f;
  cursor: pointer;
  white-space: nowrap;
}

.admin-remove-btn:hover {
  border-color: #b3391f;
}

.admin-status {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 600;
  white-space: nowrap;
}

.admin-toggle-details-btn {
  color: var(--color-text);
}

.admin-toggle-details-btn:hover {
  border-color: var(--color-text);
}

.admin-submission-details td {
  background: var(--color-surface-alt, rgba(0, 0, 0, 0.03));
  white-space: normal;
  word-break: break-word;
}

.admin-submission-body {
  white-space: pre-wrap;
  max-height: 280px;
  overflow-y: auto;
  padding: 10px;
  border: 1px solid var(--color-border);
  border-radius: 8px;
  font-size: 0.85rem;
}

.admin-submission-history {
  list-style: none;
  padding: 0;
  margin: 0;
  max-height: 280px;
  overflow-y: auto;
}

.admin-submission-history li {
  padding: 8px 10px;
  border: 1px solid var(--color-border);
  border-radius: 8px;
  margin-bottom: 8px;
  font-size: 0.85rem;
}

.btn--small {
  padding: 6px 14px;
  font-size: 0.82rem;
}

.admin-submission-fullname-input,
.admin-submission-title-input {
  display: block;
  width: 100%;
  margin-bottom: 8px;
}

.admin-submission-body-input {
  /* Both inputs here default to inline-block with no display set, and the
     generated markup has no whitespace between the </input> and <textarea>
     tags - with no line-break opportunity between two adjacent inline-block
     boxes, the textarea was flowing onto the same line as the title input
     instead of wrapping below it, overflowing far off the right edge of the
     page (looked like a missing/blank field - confirmed via the element's
     own bounding rect landing hundreds of px past the viewport). */
  display: block;
  width: 100%;
  min-height: 220px;
  padding: 10px;
  border: 1px solid var(--color-border);
  border-radius: 8px;
  font-size: 0.85rem;
  font-family: inherit;
  resize: vertical;
  box-sizing: border-box;
}

.admin-save-status {
  font-size: 0.82rem;
  color: var(--color-text-muted);
}

.admin-write-form {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-width: 720px;
}

.admin-write-label {
  display: block;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--color-text-muted);
  margin-top: 10px;
}

.admin-write-row {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
}

.admin-write-row > div {
  flex: 1;
  min-width: 200px;
}

.admin-status--ok {
  background: #e3f0d8;
  color: #3d6b1f;
}

.admin-status--empty {
  background: #f3ecd8;
  color: #8a6a1f;
}

.admin-status--error {
  background: #f6dcd4;
  color: #b3391f;
}

.admin-status--unknown {
  background: var(--color-bg);
  color: var(--color-text-muted);
}

.admin-edit-btn,
.admin-save-btn,
.admin-cancel-btn,
.admin-archive-btn {
  background: none;
  border: 1px solid var(--color-border);
  border-radius: 999px;
  padding: 4px 12px;
  font-size: 0.8rem;
  cursor: pointer;
  white-space: nowrap;
  margin-right: 6px;
}

.admin-edit-btn:hover,
.admin-save-btn:hover,
.admin-archive-btn:hover {
  border-color: var(--color-accent);
  color: var(--color-accent);
}

.admin-save-btn {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: #fff;
}

.admin-save-btn:hover {
  color: #fff;
  background: var(--color-accent-dark);
}

.admin-row--editing {
  background: var(--color-bg);
}

.admin-inline-input {
  width: 100%;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 6px 8px;
  font-size: 0.85rem;
  color: var(--color-text);
}

.admin-inline-input--narrow {
  width: 80px;
}

.admin-icon-btn {
  background: none;
  border: 1px solid var(--color-border);
  border-radius: 50%;
  width: 30px;
  height: 30px;
  padding: 0;
  margin-right: 6px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  vertical-align: middle;
}

.admin-icon-btn img {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  object-fit: cover;
}

.admin-icon-btn:hover {
  border-color: var(--color-accent);
}

.admin-icon-btn:disabled {
  opacity: 0.5;
  cursor: default;
}

.btn-icon {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  object-fit: cover;
}

@media (max-width: 720px) {
  /* Four targeted fixes (grid containment, a flex item's min-width,
     input max-width, then html/body max-width: 100vw) each got deployed
     and verified live, and NONE changed anything visible - confirmed via
     Chrome's own "find in page" that this was genuine horizontal
     document scroll, not a caching or narrow-container illusion. That
     level of persistence points at flexbox/grid's automatic-minimum-size
     rules themselves behaving inconsistently on the actual mobile
     browser in play, not at any single wrong property value. Rather than
     keep patching individual flex/grid items, mobile drops flex/grid
     entirely for the admin shell's own layout and uses plain block
     stacking instead - a block element's width is simply "100% of its
     parent, full stop", with none of flexbox/grid's content-based
     automatic-minimum-width behavior to fight. */
  .admin-shell {
    display: block;
  }
  /* A single horizontally-scrolling row works but hides most of the 9
     tabs off-screen with no visual hint they're there - wrapping into a
     pill grid keeps every tab visible and tappable at once. Safe to use
     flex here (unlike .admin-shell/.admin-source-form above): each tab's
     own label is short, bounded text, not an unpredictable sentence, so
     none of the automatic-minimum-width behavior that broke those is in
     play here. */
  .admin-sidebar {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 16px;
  }
  .admin-sidebar-link {
    flex: 0 1 auto;
  }
  .admin-content {
    padding: 16px;
  }
  /* Every admin table (sources, articles, partners, ad slots, channels...)
     shares this one class - horizontal scroll technically worked but hid
     most columns off-screen with no visual cue they existed. Each row
     becomes its own card instead: header row hidden, each <td> a
     "label: value" line with the label pulled from data-label (injected
     client-side by js/admin-table-mobile-labels.js, which reads each
     table's own <thead> - no need to touch the 8 separate JS files that
     render these rows). */
  .admin-sources-table thead {
    display: none;
  }
  .admin-sources-table,
  .admin-sources-table tbody,
  .admin-sources-table tr {
    display: block;
    width: 100%;
  }
  .admin-sources-table tr {
    margin-bottom: 12px;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    padding: 4px 10px;
    background: var(--color-surface);
  }
  .admin-sources-table td {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 8px 0;
    border-bottom: 1px solid var(--color-border);
    text-align: right;
  }
  .admin-sources-table td:last-child {
    border-bottom: none;
  }
  .admin-sources-table td::before {
    content: attr(data-label);
    font-weight: 600;
    font-size: 0.8rem;
    color: var(--color-text-muted);
    text-align: left;
    flex-shrink: 0;
  }
  /* The label (::before) and the cell's real content (a link, an inline
     input, plain text) are both flex items in td's row - without this,
     a long URL/value would hit the same automatic-minimum-width problem
     that broke .admin-shell/.admin-source-form above instead of
     wrapping inside its own card. */
  .admin-sources-table td > * {
    min-width: 0;
    overflow-wrap: break-word;
  }
  .admin-source-form {
    display: block;
  }
  .admin-source-input {
    display: block;
    width: 100%;
    max-width: 100%;
    box-sizing: border-box;
    margin-bottom: 10px;
  }
  .admin-pause-banner {
    display: block;
  }
  .admin-pause-banner #pauseToggleBtn {
    display: block;
    width: 100%;
    margin-top: 10px;
    box-sizing: border-box;
  }
}

.news-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 20px;
}

.news-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
  box-shadow: var(--shadow-card);
  display: flex;
  flex-direction: column;
}

.news-card--ad {
  background: #fbe9d3;
  border-color: var(--color-accent);
}

/* Magazine layout (js/render.js) - breaks the flat 4-col matrix into
   repeating groups of 3: one "lg" lead card spanning 2 columns plus two
   normal-size companions, so the page reads as a sequence of lead+companion
   rows instead of a grid of identical tiles. Used on the homepage, category
   pages, and search results - anywhere LisinderRender.newsGrid/categories
   is called. */
.news-grid--magazine {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.news-group {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 20px;
}

.news-card--lg {
  grid-column: span 2;
}

.news-card--lg .news-card-media img {
  aspect-ratio: 16 / 9;
}

.news-card--lg .news-card-title {
  font-size: 1.4rem;
  line-height: 1.25;
}

.news-card--lg .news-card-excerpt {
  font-size: 0.95rem;
  -webkit-line-clamp: 3;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Random per-card tint applied only to wide ("lg") cards - see
   js/render.js randomTintClass - so the "featured" slots read as
   deliberately highlighted rather than just larger versions of the same
   white card. Palette stays within the site's yellow-green-orange
   ("fox") family - no blues/pinks - and is deliberately subtle: barely
   a shade off --color-surface (#fffbf2), not a saturated pastel. */
.news-card--tint-a {
  background: #fdf6ea;
}

.news-card--tint-b {
  background: #fbf3dc;
}

.news-card--tint-c {
  background: #f5f3dc;
}

.news-card--tint-d {
  background: #f2f4e2;
}

.news-card-category--ad {
  cursor: default;
}

.news-card-media img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}

/* Progressive image loading (js/progressive-image.js): tiny blur-up
   placeholder while the medium/original tiers load in behind it. */
.progressive-img {
  filter: blur(14px);
  transition: filter 0.35s ease;
}

.progressive-img--loaded {
  filter: none;
}

.news-card-body {
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex: 1;
}

.news-card-meta {
  display: flex;
  justify-content: space-between;
  font-size: 0.75rem;
}

.news-card-category {
  color: var(--color-accent);
  font-weight: 700;
  text-transform: uppercase;
}

.news-card-time {
  color: var(--color-text-muted);
}

.type-badge {
  display: inline-block;
  font-size: 0.7rem;
  font-weight: 600;
  color: var(--color-text-muted);
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: 999px;
  padding: 2px 10px;
  white-space: nowrap;
}

.type-badge--editorial {
  color: var(--color-accent-dark);
  border-color: var(--color-accent);
  background: rgba(221, 122, 44, 0.12);
}

.type-badge--retold {
  color: var(--color-olive);
  border-color: var(--color-olive);
}

.news-card-type {
  align-self: flex-start;
}

/* Star rating widget (js/rating.js) - two stacked 5-star rows (AI-drawn
   star-empty.png/star-filled.png, identical silhouette), the filled one
   clipped to a percentage width so half-star precision is a continuous
   clip rather than five discrete image states. */
.rating {
  position: relative;
  display: inline-flex;
  vertical-align: middle;
  line-height: 0;
}

.rating-stars {
  display: flex;
  gap: 2px;
}

.rating-stars img {
  width: 14px;
  height: 14px;
  display: block;
}

.rating-stars--filled {
  position: absolute;
  top: 0;
  left: 0;
  overflow: hidden;
  white-space: nowrap;
}

.news-card-rating-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  margin: 2px 0 4px;
}

.hero-rating,
.article-rating {
  margin: 0;
}

.rating--lg .rating-stars img {
  width: 18px;
  height: 18px;
}

.article-rating-row,
.hero-rating-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 16px;
}

.article-rating-row {
  margin: 6px 0 12px;
}

.hero-rating-row {
  margin: 6px 0;
}

/* Anonymous like/dislike (js/vote.js) - one vote per browser via
   localStorage, no login required, no vote counts shown. */
.vote-widget {
  display: flex;
  gap: 6px;
}

.vote-btn {
  display: inline-flex;
  align-items: center;
  background: none;
  border: 1px solid var(--color-border);
  border-radius: 999px;
  padding: 4px 8px;
  cursor: pointer;
}

.vote-btn img {
  width: 16px;
  height: 16px;
  display: block;
}

.vote-btn--active {
  border-color: var(--color-accent);
  background: rgba(221, 122, 44, 0.12);
}

.vote-btn:disabled {
  opacity: 0.6;
  cursor: default;
}

.article-author {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.article-author-photo {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  object-fit: cover;
}

.news-card-title {
  margin: 0;
  font-size: 1rem;
  line-height: 1.3;
}

.news-card-title a:hover {
  text-decoration: underline;
}

.news-card-excerpt {
  margin: 0;
  font-size: 0.85rem;
  color: var(--color-text-muted);
  flex: 1;
}

.news-card-link {
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--color-olive);
}

/* ---------- Categories ---------- */
.categories-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 18px;
  margin-bottom: 18px;
}

.category-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.category-icon {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  object-fit: cover;
}

.category-title {
  margin: 0;
  font-size: 1.05rem;
}

.category-desc {
  margin: 0;
  font-size: 0.85rem;
  color: var(--color-text-muted);
  flex: 1;
}

.category-link {
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--color-accent);
}

.category-section {
  margin-bottom: 32px;
}

.category-section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 14px;
}

.category-section-title {
  margin: 0;
  font-size: 1.15rem;
}

.category-section-title a {
  color: inherit;
}

.category-section-more {
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--color-accent);
  white-space: nowrap;
}

/* ---------- Editorial team ---------- */
.team-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
  margin: 24px 0;
}

.team-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 20px;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 6px;
  box-shadow: var(--shadow-card);
}

.team-photo {
  width: 96px;
  height: 96px;
  border-radius: 50%;
  object-fit: cover;
  margin-bottom: 6px;
}

.team-name {
  margin: 0;
  font-size: 1rem;
}

.team-role {
  font-size: 0.8rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--color-accent);
}

.team-bio {
  margin: 4px 0 0;
  font-size: 0.85rem;
  color: var(--color-text-muted);
}

.category-page-header {
  display: flex;
  align-items: center;
  gap: 20px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 24px;
  margin-bottom: 32px;
}

.category-page-icon {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  object-fit: cover;
  flex-shrink: 0;
}

.category-page-title {
  margin: 0 0 6px;
  font-size: 1.75rem;
}

.category-page-desc {
  margin: 0;
  color: var(--color-text-muted);
}

.footer-promo {
  background: var(--color-header);
  color: var(--color-header-text);
  border-radius: var(--radius-lg);
  padding: 24px;
  display: flex;
  align-items: center;
  gap: 20px;
}

.footer-promo-image {
  width: 90px;
  height: 90px;
  object-fit: contain;
  flex-shrink: 0;
}

.footer-promo-body p {
  margin: 0 0 14px;
  font-weight: 600;
}

/* ---------- Skeletons ---------- */
.skeleton {
  background: linear-gradient(90deg, var(--color-border) 25%, #f2ead2 37%, var(--color-border) 63%);
  background-size: 400% 100%;
  animation: skeleton-shine 1.4s ease infinite;
  border-radius: var(--radius-md);
}

@keyframes skeleton-shine {
  0% { background-position: 100% 0; }
  100% { background-position: 0 0; }
}

.skeleton--hero { min-height: 320px; }
.skeleton--ticker { min-height: 320px; }
.skeleton--grid { min-height: 220px; grid-column: 1 / -1; }
.skeleton--promo { min-height: 90px; }

.block-error {
  grid-column: 1 / -1;
  color: var(--color-text-muted);
  font-size: 0.9rem;
  text-align: center;
  padding: 20px;
}

/* ---------- Article page ---------- */
.skeleton--article { min-height: 480px; margin: 40px 0; }

.article-page {
  max-width: 760px;
  margin: 40px auto;
}

.article-back {
  display: block;
  margin-bottom: 20px;
  font-size: 0.9rem;
  color: var(--color-olive);
  font-weight: 700;
}

.article-back:hover {
  text-decoration: underline;
}

.article-topline {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 8px;
}

.article-category {
  display: inline-block;
  color: var(--color-accent);
  font-weight: 700;
  text-transform: uppercase;
  font-size: 0.8rem;
  letter-spacing: 0.03em;
}

.article-type {
  font-size: 0.8rem;
  color: var(--color-text-muted);
}

.article-title {
  margin: 0 0 16px;
  font-size: 2rem;
  line-height: 1.25;
}

.article-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  font-size: 0.85rem;
  color: var(--color-text-muted);
  margin-bottom: 24px;
}

.article-listen-btn {
  margin-left: auto;
}

.article-media {
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-card);
  margin-bottom: 28px;
}

.article-media img {
  width: 100%;
  display: block;
}

/* ---------- 404 page ---------- */
.notfound-page {
  max-width: 640px;
  margin: 48px auto 64px;
  text-align: center;
}

.notfound-eyebrow {
  display: inline-block;
  margin-bottom: 16px;
  padding: 4px 14px;
  border-radius: 999px;
  background: var(--color-accent);
  color: #fff;
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.02em;
}

.notfound-image {
  max-width: 320px;
  margin: 0 auto 24px;
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-card);
}

.notfound-title {
  margin: 0 0 12px;
  font-size: 1.8rem;
  line-height: 1.3;
}

.notfound-text {
  margin: 0 0 28px;
  color: var(--color-text-muted);
  font-size: 1rem;
}

.article-processing {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
  padding: 80px 20px;
  text-align: center;
  color: var(--color-text-muted);
}

.article-processing-icon {
  width: 96px;
  height: 96px;
  animation: article-processing-spin 2.2s linear infinite;
}

@keyframes article-processing-spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

.article-body {
  font-size: 1.05rem;
  line-height: 1.7;
}

.article-body h2,
.article-body h3,
.article-body h4 {
  margin: 28px 0 12px;
  line-height: 1.3;
}

.article-body p {
  margin: 0 0 18px;
}

.article-body ul {
  margin: 0 0 18px;
  padding-left: 22px;
}

.fnr-cta {
  margin: 8px 0 26px;
}

.article-body li {
  margin-bottom: 8px;
}

.article-body blockquote {
  margin: 0 0 18px;
  padding: 4px 20px;
  border-left: 3px solid var(--color-accent);
  color: var(--color-text-muted);
  font-style: italic;
}

.docs-code {
  margin: 0 0 18px;
  padding: 14px 16px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  font-family: "Consolas", "Menlo", monospace;
  font-size: 0.85rem;
  line-height: 1.5;
  overflow-x: auto;
  white-space: pre;
}

.article-body code {
  font-family: "Consolas", "Menlo", monospace;
  font-size: 0.9em;
  background: var(--color-surface);
  padding: 1px 5px;
  border-radius: 4px;
}

.article-figure {
  margin: 0 0 18px;
}

.article-figure img {
  width: 100%;
  border-radius: var(--radius-md);
}

.article-source {
  margin-top: 32px;
  padding-top: 16px;
  border-top: 1px solid var(--color-border);
  font-size: 0.8rem;
  color: var(--color-text-muted);
  word-break: break-all;
}

.ad-request-panel {
  margin-top: 24px;
  padding: 24px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
}

.ad-request-panel h2 {
  margin: 0 0 6px;
  font-size: 1.15rem;
}

.ad-request-panel > p {
  margin: 0 0 16px;
  color: var(--color-text-muted);
  font-size: 0.9rem;
}

.ad-request-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-width: 420px;
}

.ad-request-input {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 10px 12px;
  font-size: 0.95rem;
  color: var(--color-text);
  background: var(--color-bg);
}

.ad-request-textarea {
  min-height: 90px;
  resize: vertical;
  font-family: inherit;
}

.ad-request-form--wide {
  max-width: 720px;
}

.ad-request-form--wide .ad-request-textarea {
  min-height: 320px;
}

.ad-request-checkbox {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  font-size: 0.85rem;
  color: var(--color-text-muted);
}

.ad-request-checkbox input {
  margin-top: 3px;
  flex-shrink: 0;
}

.related-pages {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0 0 28px;
}

.related-pages-link {
  border: 1px solid var(--color-border);
  border-radius: 999px;
  padding: 6px 14px;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--color-text-muted);
  text-decoration: none;
  background: var(--color-bg);
}

.related-pages-link:hover {
  color: var(--color-text);
  border-color: var(--color-text-muted);
}

/* ---------- Footer ---------- */
.sitefooter {
  background: var(--color-header);
  color: var(--color-header-text);
  margin-top: 40px;
}

.sitefooter-row {
  display: grid;
  grid-template-columns: 1.6fr 1fr 1fr 1fr 1fr 1fr 1.2fr;
  gap: 24px;
  padding: 40px 20px;
}

.brand--footer .brand-title,
.brand--footer .brand-subtitle {
  color: var(--color-header-text);
}

.sitefooter-col {
  display: flex;
  flex-direction: column;
  gap: 10px;
  font-size: 0.9rem;
}

.sitefooter-col h5 {
  margin: 0 0 4px;
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--color-accent);
}

.sitefooter-col a {
  color: rgba(243, 236, 216, 0.85);
}

.sitefooter-col a:hover {
  color: #fff;
}

.sitefooter-meta {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: space-between;
  font-size: 0.8rem;
  color: rgba(243, 236, 216, 0.7);
  text-align: right;
}

.sitefooter-meta > span {
  white-space: nowrap;
}

/* Simple two-item footer (brand + meta only, no nav columns) - let meta
   claim the rest of the row instead of being squeezed into the grid's
   narrow second column, which wrapped the copyright line. */
.sitefooter-row > .brand--footer + .sitefooter-meta {
  grid-column: 2 / -1;
}

.sitefooter-social {
  display: flex;
  gap: 12px;
  margin-bottom: 12px;
}

.sitefooter-social img {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  object-fit: cover;
}

/* ---------- Responsive ---------- */
@media (max-width: 960px) {
  .hero-row {
    grid-template-columns: 1fr;
  }
  .hero-media {
    display: none;
  }
  .hero-title,
  .hero-excerpt {
    max-width: 100%;
  }
  .news-grid,
  .categories-grid,
  .team-grid {
    grid-template-columns: repeat(2, 1fr);
  }
  .news-group {
    grid-template-columns: repeat(2, 1fr);
  }
  .news-card--lg {
    grid-column: 1 / -1;
  }
  .sitefooter-row {
    grid-template-columns: 1fr 1fr;
  }
}

@media (max-width: 600px) {
  .topbar-tagline {
    display: none;
  }
  .topbar-row {
    justify-content: flex-end;
    height: auto;
    padding: 6px 0;
  }
  .topbar-links {
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 10px;
  }
  .masthead-row {
    flex-direction: column;
    align-items: flex-start;
  }
  .subscribe {
    /* The inline masthead subscribe widget doesn't fit a narrow viewport -
       icon + nowrap copy + input + button together are wider than any
       phone screen, and were poking out past the edge instead of wrapping.
       subscribe.html, the footer link and the topbar nav link all still
       reach the same form, so just drop this convenience widget on mobile
       rather than trying to reflow it. */
    display: none;
  }
  .mainnav-toggle {
    display: flex;
  }
  .mainnav-row {
    display: none;
    flex-direction: column;
    align-items: stretch;
    overflow-x: visible;
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    z-index: 500;
    background: var(--color-nav);
    box-shadow: var(--shadow-card);
    padding: 6px 0;
  }
  .mainnav-row.mainnav-row--open {
    display: flex;
  }
  .mainnav-item {
    flex-direction: row;
    justify-content: flex-start;
    gap: 12px;
    padding: 12px 20px;
    border-bottom: none;
    border-left: 3px solid transparent;
    white-space: normal;
  }
  .mainnav-item--active {
    border-bottom-color: transparent;
    border-left-color: var(--color-accent);
    background: rgba(255, 255, 255, 0.05);
  }
  .news-grid,
  .categories-grid,
  .team-grid {
    grid-template-columns: 1fr;
  }
  .news-group {
    grid-template-columns: 1fr;
  }
  .sitefooter-row {
    grid-template-columns: 1fr;
  }
  /* At a single grid column, "column 2" from the desktop override below
     no longer exists - .sitefooter-meta was landing back in column 1,
     overlapping .brand--footer instead of stacking under it. */
  .sitefooter-row > .brand--footer + .sitefooter-meta {
    grid-column: 1;
    align-items: flex-start;
    text-align: left;
    margin-top: 16px;
  }
}

/* ================================================================
   Кстати — newspaper restyle
   Everything above this line is Lisinder's original layout, unmodified
   (grid/flex structure, spacing, component markup contract). Everything
   below overrides only the visual design tokens with the black-and-white
   newspaper look from d:\REPO\taskforce38 (css/tokens.css, fonts.css) -
   per the user's split: layout stays Lisinder's, style comes from
   taskforce38. Cascade order (later wins) does the restyling instead of
   touching a single selector above.
   ================================================================ */

/* ---------- Fonts (copied from taskforce38/fonts, SIL OFL) ---------- */
@font-face {
  font-family: "Old Standard TT";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/old-standard-tt/old-standard-tt-400.woff2") format("woff2");
}
@font-face {
  font-family: "Old Standard TT";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/old-standard-tt/old-standard-tt-700.woff2") format("woff2");
}
@font-face {
  font-family: "Old Standard TT";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/old-standard-tt/old-standard-tt-400-italic.woff2") format("woff2");
}
@font-face {
  font-family: "Public Sans";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("../fonts/public-sans/public-sans-var.woff2") format("woff2-variations"),
       url("../fonts/public-sans/public-sans-var.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/ibm-plex-mono/ibm-plex-mono-400.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/ibm-plex-mono/ibm-plex-mono-500.woff2") format("woff2");
}

:root {
  /* Ink/paper monochrome + one restrained red accent, replacing the
     original warm "fox" orange/olive palette. Every rule above that
     reads a --color-* / --radius-* / --shadow-card variable picks this
     up automatically - only the handful of hardcoded exceptions below
     need a direct override. */
  --color-bg: #f6f6f4;
  --color-surface: #ffffff;
  --color-header: #141414;
  --color-header-text: #f6f6f4;
  --color-nav: #141414;
  --color-nav-text: #f6f6f4;
  --color-accent: #7a1f1f;
  --color-accent-dark: #5c1717;
  --color-text: #141414;
  --color-text-muted: #5f5f5f;
  --color-border: #c9c9c7;
  --color-olive: #3a3a3a;

  --radius-md: 2px;
  --radius-lg: 2px;
  --shadow-card: none;
}

body {
  font-family: "Public Sans", -apple-system, "Segoe UI", Helvetica, Arial, sans-serif;
}

/* Serif display face for headlines/nameplate - everywhere else keeps the
   body sans, same split as taskforce38's --tf-font-display vs --tf-font-body. */
.brand-title,
.hero-title,
.article-title,
.section-title,
.panel-title,
.news-card-title,
.category-section-title,
.notfound-title {
  font-family: "Old Standard TT", Georgia, "Times New Roman", serif;
  font-weight: 700;
  letter-spacing: 0;
}

/* Masthead as a real nameplate: double-rule border, centered serif title,
   mono uppercase kicker - the single most visible branding surface. */
.masthead {
  background: var(--color-surface);
  border-top: 3px solid var(--color-text);
  border-bottom: 1px solid var(--color-text);
  padding-top: 4px;
}

.masthead-row {
  justify-content: center;
  text-align: center;
  padding: 22px 20px 18px;
}

.brand-title {
  font-size: 2.4rem;
  letter-spacing: 0.5px;
}

.brand-subtitle {
  font-family: "IBM Plex Mono", "SFMono-Regular", Consolas, monospace;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 500;
}

/* kstati.net's real logo is a wide wordmark, not a square/circular icon
   (unlike Lisinder's fox mark that .brand-logo/.splash-icon were sized
   for) - override the fixed square/circle boxes to fit it. */
.brand-logo {
  width: auto;
  height: 48px;
  max-width: 260px;
  border-radius: 0;
  object-fit: contain;
}

.splash-icon {
  width: 260px;
  height: 90px;
  border-radius: var(--radius-md);
  background: var(--color-surface);
}

.splash-icon img {
  object-fit: contain;
  padding: 10px;
}

.splash-circle {
  width: 300px;
  height: 130px;
  border-radius: var(--radius-md);
}

.splash-ring {
  border-radius: var(--radius-md);
}

/* Flatten every pill-shaped control (hardcoded 999px, not a --radius-*
   var) to the same crisp trim as the rest of the page. */
.btn,
.hero-badge,
.type-badge,
.subscribe-input,
.notfound-eyebrow {
  border-radius: var(--radius-md);
}

.btn {
  font-family: "IBM Plex Mono", "SFMono-Regular", Consolas, monospace;
  text-transform: uppercase;
  font-size: 0.8rem;
  letter-spacing: 0.04em;
}

/* News-card "featured slot" tints: the original cycles through four warm
   pastel shades; a black-and-white paper doesn't do pastel, so every tint
   collapses to the same flat off-white with a slightly heavier rule
   instead of a color shift. */
.news-card--tint-a,
.news-card--tint-b,
.news-card--tint-c,
.news-card--tint-d {
  background: var(--color-surface);
  border-color: var(--color-text);
}

/* Editorial photography reads as newsprint halftone, not full color -
   the single strongest "this is a newspaper" signal on the page. UI
   icons (logo, nav, star/thumb icons) are untouched. */
.hero-media img,
.news-card-media img,
.article-media img,
.article-figure img {
  filter: grayscale(1) contrast(1.05);
}

.article-media {
  border: 1px solid var(--color-border);
}

.rating-stars img,
.vote-btn img {
  filter: grayscale(1);
}

/* Splash: ink ring instead of the orange "fox" glow. */
.splash {
  background: rgba(20, 20, 20, 0.97);
}

.splash-ring {
  background: conic-gradient(
    var(--color-text) 0deg,
    #6a6a6a 90deg,
    rgba(20, 20, 20, 0) 200deg,
    rgba(20, 20, 20, 0) 360deg
  );
  box-shadow: none;
}

.splash-icon {
  box-shadow: 0 0 0 5px #3a3a3a;
}

.article-back {
  font-family: "IBM Plex Mono", "SFMono-Regular", Consolas, monospace;
  text-transform: uppercase;
  font-size: 0.8rem;
  letter-spacing: 0.04em;
}
