/* =============================================================================
   WHISPERS IN THE CORRIDORS — Phase 15 Frontend Overhaul
   ----------------------------------------------------------------------------
   Editorial newspaper aesthetic. Restrained color, heavy typography,
   generous whitespace. Built on top of Bootstrap 5.3 utilities — extends,
   doesn't fight.

   File structure (sections marked with §):
     §1  DESIGN TOKENS         (CSS custom properties)
     §2  RESET + BASE          (typography, links, lists, headings)
     §3  LAYOUT PRIMITIVES     (container, grid helpers, dividers)
     §4  COMPONENTS            (buttons, cards, badges, forms, alerts)
     §5  HEADER + NAV          (top bar, mega-menu, mobile drawer, ticker)
     §6  FOOTER                (grid, newsletter, socials, copyright)
     §7  ARTICLE CARDS         (story tiles, list rows, hero variants)
     §8  HOMEPAGE              (hero blocks, category strips, magazine teaser)
     §9  ARTICLE DETAIL        (reading layout, byline, related)
     §10 LISTING + SEARCH      (grid, filter bar, pagination)
     §11 MAGAZINE              (cover grid, reader UI)
     §12 AUTHORS               (directory, profile)
     §13 AUTH PAGES            (login/signup card, social buttons)
     §14 ACCOUNT DASHBOARD     (sidebar, KPI cards, tables)
     §15 COMMERCE              (packages grid, checkout summary)
     §16 STATIC + CMS          (page, contact, 404)
     §17 UTILITIES             (helpers, animations, print)
============================================================================= */

/* ============================================================================
   §1  DESIGN TOKENS
============================================================================ */
:root {
  /* — brand — */
  --brand: #d70000;
  --brand-700: #a30000;
  --brand-100: #fef0f0;
  --brand-50:  #fff7f7;

  /* — ink (text) — */
  --ink:      #0f0f0f;
  --ink-2:    #2a2a2a;
  --ink-3:    #4a4a4a;
  --muted:    #6b7280;
  --muted-2:  #9ca3af;
  --line:     #e5e7eb;
  --line-2:   #f0f0eb;

  /* — paper (surfaces) — */
  --paper:    #ffffff;
  --paper-2:  #fafaf7;     /* very subtle cream */
  --paper-3:  #f5f5f0;     /* light cream */
  --paper-4:  #ebebe5;
  --ink-bg:   #111111;     /* dark sections */

  /* — accents — */
  --accent-gold:   #c9a341;
  --accent-gold-2: #b08c2b;
  --accent-ink:    #1a1a1a;

  /* — semantic — */
  --success: #15803d;
  --success-bg: #ecfdf5;
  --warning: #b45309;
  --warning-bg: #fffbeb;
  --danger:  #b91c1c;
  --danger-bg: #fef2f2;
  --info:    #1e40af;
  --info-bg: #eff6ff;

  /* — type scale — */
  --fs-xxs:  11px;
  --fs-xs:   12px;
  --fs-sm:   14px;
  --fs-base: 16px;
  --fs-md:   18px;
  --fs-lg:   20px;
  --fs-xl:   24px;
  --fs-2xl:  32px;
  --fs-3xl:  40px;
  --fs-4xl:  56px;
  --fs-5xl:  72px;
  --fs-6xl:  96px;

  /* — spacing scale — */
  --sp-1:  4px;
  --sp-2:  8px;
  --sp-3:  12px;
  --sp-4:  16px;
  --sp-5:  20px;
  --sp-6:  24px;
  --sp-7:  32px;
  --sp-8:  48px;
  --sp-9:  64px;
  --sp-10: 96px;
  --sp-11: 128px;

  /* — radii — Phase 15.2.77: reduced site-wide for sharper corners on cards.
     (was 4/8/12/16/24). */
  --r-1:    2px;
  --r-2:    4px;
  --r-3:    6px;
  --r-4:    8px;
  --r-5:    12px;
  --r-full: 9999px;
  /* Phase 15.2.81 — default soft-rounded corners for IMAGES everywhere. */
  --r-img:  8px;

  /* — shadows — */
  --shadow-xs: 0 1px 2px rgba(15,15,15,.04);
  --shadow-sm: 0 1px 3px rgba(15,15,15,.06), 0 1px 2px rgba(15,15,15,.04);
  --shadow-md: 0 4px 8px rgba(15,15,15,.06), 0 2px 4px rgba(15,15,15,.04);
  --shadow-lg: 0 10px 24px rgba(15,15,15,.08), 0 4px 8px rgba(15,15,15,.04);
  --shadow-xl: 0 20px 50px rgba(15,15,15,.12), 0 8px 16px rgba(15,15,15,.06);
  --shadow-brand: 0 6px 20px rgba(215,0,0,.18);

  /* — transitions — */
  --t-fast:   .15s ease;
  --t-normal: .25s cubic-bezier(.4,0,.2,1);
  --t-slow:   .4s  cubic-bezier(.4,0,.2,1);
  --t-spring: .5s  cubic-bezier(.34,1.56,.64,1);

  /* — fonts — */
  --f-display: 'Abril Fatface', Georgia, serif;
  --f-serif:   'Merriweather', Georgia, 'Times New Roman', serif;
  --f-serif-2: 'Lora', Georgia, serif;
  --f-ui:      'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --f-mono:    'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  /* — layout — */
  --container-max: 1280px;
  --container-pad: clamp(16px, 4vw, 32px);
  --header-h: 124px;            /* desktop only; mobile is shorter */
  --rail-w: 300px;             /* Phase 15.3 — homepage in-content ad-rail width */
  --rail-gap: 28px;

  /* — z-index scale — */
  --z-base: 1;
  --z-elevated: 10;
  --z-sticky: 100;
  --z-dropdown: 200;
  --z-overlay: 800;
  --z-modal: 900;
  --z-toast: 1000;
}

/* ============================================================================
   §2  RESET + BASE
============================================================================ */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; -webkit-tap-highlight-color: transparent; }

body {
  margin: 0;
  font-family: var(--f-ui);
  font-size: var(--fs-base);
  line-height: 1.55;
  color: var(--ink);
  background: var(--paper);
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3, h4, h5, h6 {
  font-family: var(--f-serif);
  font-weight: 700;
  line-height: 1.2;
  color: var(--ink);
  margin: 0 0 var(--sp-4) 0;
  letter-spacing: -0.01em;
}
h1 { font-size: clamp(28px, 5vw, var(--fs-3xl)); line-height: 1.15; }
h2 { font-size: clamp(24px, 4vw, var(--fs-2xl)); }
h3 { font-size: clamp(20px, 3vw, var(--fs-xl)); }
h4 { font-size: var(--fs-lg); }
h5 { font-size: var(--fs-md); }
h6 { font-size: var(--fs-base); }

p { margin: 0 0 var(--sp-4) 0; }
p:last-child { margin-bottom: 0; }

a {
  color: var(--ink);
  text-decoration: none;
  transition: color var(--t-fast);
}
a:hover { color: var(--brand); }

/* Link with hover underline that grows from left */
.link-underline {
  position: relative;
  display: inline-block;
}
.link-underline::after {
  content: '';
  position: absolute;
  left: 0; bottom: -2px;
  width: 100%; height: 1px;
  background: currentColor;
  transform: scaleX(0); transform-origin: left;
  transition: transform var(--t-normal);
}
.link-underline:hover::after { transform: scaleX(1); }

ul, ol { padding-left: 1.25em; margin: 0 0 var(--sp-4) 0; }
li { margin-bottom: var(--sp-1); }

img, picture, video, svg { display: block; max-width: 100%; }
/* Phase 15.2.81 — give every content image a soft rounded corner by default,
   site-wide. More specific rules (circular avatars/pills, the logo) override
   this automatically because element selectors have the lowest specificity. */
img { border-radius: var(--r-img, 8px); }
.wh-logo img, .wh-footer-logo img { border-radius: 0; }   /* keep logos crisp */

hr {
  border: 0;
  border-top: 1px solid var(--line);
  margin: var(--sp-6) 0;
}

/* Selection */
::selection { background: var(--brand); color: #fff; }

/* Focus visible (a11y) — clean ring, not browser default */
:focus { outline: none; }
:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
  border-radius: var(--r-1);
}

/* Skip link (visually hidden until focused) */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  padding: var(--sp-3) var(--sp-4);
  background: var(--ink);
  color: #fff;
  z-index: var(--z-toast);
  font-weight: 600;
  font-size: var(--fs-sm);
  text-decoration: none;
}
.skip-link:focus { left: var(--sp-4); top: var(--sp-4); color: #fff; }

/* ============================================================================
   §3  LAYOUT PRIMITIVES
============================================================================ */
.wh-container {
  width: 100%;
  max-width: var(--container-max);
  margin: 0 auto;
  padding-inline: var(--container-pad);
}
.wh-container-narrow { max-width: 820px; margin-inline: auto; }   /* Phase 15.2.85 — centre so article headline/image/body all align */
.wh-container-wide   { max-width: 1440px; }

/* Phase 15.2.55 — MacBook 13.6" and similar mid-density laptops have ~1500px
   CSS viewports at default scaling. With a 1280px container, that left ~110px
   dead space per side, making content look small and sparse. Bump the
   container to 1440px on screens 1440px+ so content uses the available
   width without being too wide on standard 27" displays.

   Why not just bump :root max to 1440px? Because that would also widen
   readable text columns on big desktops, hurting line length. Constraining
   the bump to a media query keeps the change targeted to laptop-size
   viewports. */
@media (min-width: 1440px) {
  .wh-container { max-width: 1440px; }
}
/* On true big desktops, allow a slight further bump for hero/grid density.
   Reading-width text is still constrained by article-body CSS.
   Phase 15.2.66 — bumped from 1920px → 2000px so it matches the side-rail
   gutter math: a 1520px container needs ≥216px gutters for the rails, which
   only exist from ~2000px up. Bumping earlier left the rails with no room and
   they overlapped the content's right edge (the off-centre look reported). */
@media (min-width: 2000px) {
  .wh-container { max-width: 1520px; }
}

.wh-section { padding-block: var(--sp-8); }
.wh-section-sm { padding-block: var(--sp-6); }
.wh-section-lg { padding-block: var(--sp-10); }

/* Section label (small uppercase tracked-out caption used everywhere) */
.wh-label {
  display: inline-block;
  font-family: var(--f-ui);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--brand);
  position: relative;
}
.wh-label-ink     { color: var(--ink); }
.wh-label-muted   { color: var(--muted); }
.wh-label-line {
  padding-left: 28px;
}
.wh-label-line::before {
  content: '';
  position: absolute;
  left: 0; top: 50%;
  width: 20px; height: 2px;
  background: var(--brand);
}

/* Section title (the big headline above a strip) */
.wh-section-title {
  font-family: var(--f-display);
  font-size: clamp(28px, 4vw, var(--fs-3xl));
  line-height: 1.1;
  margin: var(--sp-2) 0 var(--sp-6);
  letter-spacing: -0.01em;
}

/* Section header row (label/title + "view all" link) */
.wh-section-head {
  display: flex;
  justify-content: space-between;
  align-items: end;
  gap: var(--sp-4);
  margin-bottom: var(--sp-6);
  padding-bottom: var(--sp-3);
  border-bottom: 2px solid var(--ink);
}
.wh-section-head .wh-section-title { margin: var(--sp-1) 0 0; }
.wh-section-head-link {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--ink-2);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.wh-section-head-link::after {
  content: '→';
  transition: transform var(--t-fast);
}
.wh-section-head-link:hover { color: var(--brand); }
.wh-section-head-link:hover::after { transform: translateX(3px); }

/* Bleed background sections */
.wh-bleed-paper-2 { background: var(--paper-2); }
.wh-bleed-paper-3 { background: var(--paper-3); }
.wh-bleed-ink {
  background: var(--ink-bg);
  color: rgba(255,255,255,.92);
}
.wh-bleed-ink h1, .wh-bleed-ink h2, .wh-bleed-ink h3 { color: #fff; }
.wh-bleed-ink a { color: #fff; }
.wh-bleed-ink .wh-label { color: var(--accent-gold); }

/* ============================================================================
   §4  COMPONENTS
============================================================================ */

/* —————— Buttons —————— */
.wh-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-5);
  border: 1px solid transparent;
  border-radius: var(--r-2);
  font-family: var(--f-ui);
  font-size: var(--fs-sm);
  font-weight: 600;
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  transition: all var(--t-fast);
  white-space: nowrap;
  letter-spacing: 0.01em;
}
.wh-btn:disabled, .wh-btn.is-disabled {
  opacity: .5;
  cursor: not-allowed;
  pointer-events: none;
}

.wh-btn-primary {
  background: var(--brand);
  color: #fff;
  border-color: var(--brand);
}
.wh-btn-primary:hover { background: var(--brand-700); border-color: var(--brand-700); color: #fff; }

.wh-btn-ink {
  background: var(--ink);
  color: #fff;
  border-color: var(--ink);
}
.wh-btn-ink:hover { background: var(--ink-2); color: #fff; }

.wh-btn-outline {
  background: transparent;
  color: var(--ink);
  border-color: var(--ink);
}
.wh-btn-outline:hover { background: var(--ink); color: #fff; }

.wh-btn-outline-brand {
  background: transparent;
  color: var(--brand);
  border-color: var(--brand);
}
.wh-btn-outline-brand:hover { background: var(--brand); color: #fff; }

.wh-btn-ghost {
  background: transparent;
  color: var(--ink);
  border-color: transparent;
}
.wh-btn-ghost:hover { background: var(--paper-3); color: var(--ink); }

.wh-btn-link {
  background: transparent;
  color: var(--ink);
  border: 0;
  padding: 0;
  font-weight: 600;
}
.wh-btn-link:hover { color: var(--brand); }

.wh-btn-sm { padding: 8px 14px; font-size: var(--fs-xs); }
.wh-btn-lg { padding: 16px 28px; font-size: var(--fs-base); }
.wh-btn-block { width: 100%; }
.wh-btn-icon { padding: var(--sp-3); }

/* —————— Badges / Chips —————— */
.wh-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 10px;
  border-radius: var(--r-1);
  font-size: var(--fs-xxs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  background: var(--paper-3);
  color: var(--ink-2);
  line-height: 1;
}
.wh-badge-brand   { background: var(--brand);    color: #fff; }
.wh-badge-ink     { background: var(--ink);      color: #fff; }
.wh-badge-success { background: var(--success-bg); color: var(--success); }
.wh-badge-warning { background: var(--warning-bg); color: var(--warning); }
.wh-badge-danger  { background: var(--danger-bg);  color: var(--danger); }
.wh-badge-info    { background: var(--info-bg);    color: var(--info); }
.wh-badge-gold {
  background: var(--accent-gold);
  color: var(--ink);
}
.wh-badge-dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--success);
  display: inline-block;
  animation: pulse-dot 2s infinite;
}
@keyframes pulse-dot {
  0%, 100% { opacity: 1; }
  50%      { opacity: .4; }
}

.wh-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: var(--r-full);
  font-size: var(--fs-xs);
  font-weight: 500;
  color: var(--ink-2);
  transition: all var(--t-fast);
  text-decoration: none;
}
.wh-chip:hover { background: var(--paper-3); border-color: var(--ink); color: var(--ink); }
.wh-chip.is-active { background: var(--ink); border-color: var(--ink); color: #fff; }

/* —————— Cards —————— */
.wh-card {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
  overflow: hidden;
  transition: all var(--t-normal);
}
.wh-card-elevated {
  border: 0;
  box-shadow: var(--shadow-sm);
}
.wh-card-elevated:hover { box-shadow: var(--shadow-md); }
.wh-card-body { padding: var(--sp-5); }
.wh-card-header {
  padding: var(--sp-4) var(--sp-5);
  border-bottom: 1px solid var(--line);
  background: var(--paper-2);
}
.wh-card-footer {
  padding: var(--sp-4) var(--sp-5);
  border-top: 1px solid var(--line);
  background: var(--paper-2);
}

/* —————— Forms —————— */
.wh-form-group {
  margin-bottom: var(--sp-5);
}
.wh-label-field {
  display: block;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--ink-2);
  margin-bottom: var(--sp-2);
  letter-spacing: 0.01em;
}
.wh-input,
.wh-textarea,
.wh-select {
  width: 100%;
  padding: 12px 14px;
  font-family: var(--f-ui);
  font-size: var(--fs-base);
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-2);
  transition: all var(--t-fast);
  line-height: 1.4;
}
.wh-input:hover, .wh-textarea:hover, .wh-select:hover { border-color: var(--ink-3); }
.wh-input:focus, .wh-textarea:focus, .wh-select:focus {
  border-color: var(--ink);
  box-shadow: 0 0 0 3px rgba(15,15,15,.06);
  outline: none;
}
.wh-input.is-invalid, .wh-textarea.is-invalid, .wh-select.is-invalid {
  border-color: var(--danger);
}
.wh-input.is-invalid:focus, .wh-textarea.is-invalid:focus, .wh-select.is-invalid:focus {
  box-shadow: 0 0 0 3px rgba(185,28,28,.12);
}
.wh-textarea { resize: vertical; min-height: 96px; }
.wh-select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg width='12' height='8' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%236b7280' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  padding-right: 36px;
}
.wh-help { font-size: var(--fs-xs); color: var(--muted); margin-top: 6px; }
.wh-error { font-size: var(--fs-xs); color: var(--danger); margin-top: 6px; }

/* Input with leading icon */
.wh-input-group {
  position: relative;
}
.wh-input-group > i {
  position: absolute;
  left: 14px; top: 50%;
  transform: translateY(-50%);
  color: var(--muted);
  pointer-events: none;
}
.wh-input-group > .wh-input { padding-left: 40px; }

/* Checkbox / radio (custom) */
.wh-check {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  cursor: pointer;
  font-size: var(--fs-sm);
  color: var(--ink-2);
}
.wh-check input[type="checkbox"], .wh-check input[type="radio"] {
  appearance: none;
  width: 18px; height: 18px;
  border: 1.5px solid var(--line);
  border-radius: var(--r-1);
  background: var(--paper);
  cursor: pointer;
  display: inline-grid;
  place-content: center;
  transition: all var(--t-fast);
  margin: 0;
}
.wh-check input[type="radio"] { border-radius: 50%; }
.wh-check input:hover { border-color: var(--ink); }
.wh-check input:checked {
  background: var(--ink);
  border-color: var(--ink);
}
.wh-check input[type="checkbox"]:checked::before {
  content: '';
  width: 10px; height: 10px;
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 10 10' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 5l3 3 5-7' stroke='%23fff' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
  background-size: contain;
}
.wh-check input[type="radio"]:checked::before {
  content: '';
  width: 8px; height: 8px;
  background: #fff;
  border-radius: 50%;
}

/* —————— Alerts —————— */
.wh-alert {
  display: flex;
  align-items: start;
  gap: var(--sp-3);
  padding: var(--sp-4);
  border-radius: var(--r-2);
  border-left: 3px solid var(--ink);
  background: var(--paper-2);
  font-size: var(--fs-sm);
  margin-bottom: var(--sp-4);
}
.wh-alert > i { font-size: 18px; flex-shrink: 0; margin-top: 1px; }
.wh-alert-success { background: var(--success-bg); border-left-color: var(--success); color: var(--success); }
.wh-alert-warning { background: var(--warning-bg); border-left-color: var(--warning); color: var(--warning); }
.wh-alert-danger  { background: var(--danger-bg);  border-left-color: var(--danger);  color: var(--danger); }
.wh-alert-info    { background: var(--info-bg);    border-left-color: var(--info);    color: var(--info); }

/* —————— Breadcrumbs —————— */
.wh-breadcrumb {
  font-size: var(--fs-xs);
  color: var(--muted);
  margin-bottom: var(--sp-4);
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
}
.wh-breadcrumb a { color: var(--muted); }
.wh-breadcrumb a:hover { color: var(--brand); }
.wh-breadcrumb-sep { opacity: .5; }
.wh-breadcrumb-current { color: var(--ink-2); font-weight: 600; }

/* —————— Pagination —————— */
.wh-pagination {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 4px;
  margin: var(--sp-7) 0;
  flex-wrap: wrap;
}
.wh-pagination a, .wh-pagination span {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 40px;
  height: 40px;
  padding: 0 12px;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--ink-2);
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-2);
  text-decoration: none;
  transition: all var(--t-fast);
}
.wh-pagination a:hover { border-color: var(--ink); color: var(--ink); }
.wh-pagination .is-current {
  background: var(--ink);
  border-color: var(--ink);
  color: #fff;
}
.wh-pagination .is-disabled {
  opacity: .35;
  pointer-events: none;
}

/* —————— Meta row (byline + date + category) —————— */
.wh-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-3);
  font-size: var(--fs-xs);
  color: var(--muted);
}
.wh-meta a { color: inherit; font-weight: 500; }
.wh-meta a:hover { color: var(--brand); }
.wh-meta-sep { width: 3px; height: 3px; background: currentColor; border-radius: 50%; opacity: .5; }
.wh-meta-author { color: var(--ink-2); font-weight: 600; }

/* —————— Tag (category pill on article cards) —————— */
.wh-cat-tag {
  display: inline-block;
  padding: 4px 10px;
  font-size: var(--fs-xxs);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #fff;
  background: var(--brand);
  border-radius: 2px;
  text-decoration: none;
  line-height: 1.3;
}
.wh-cat-tag:hover { color: #fff; opacity: .9; }
/* Phase 15.6.4 — EVERY category label is red (#d70000) with white text
   (the old per-category colours are gone — all uniform now). */
.wh-cat-tag[data-cat] { background: #d70000 !important; color: #fff !important; }
/* Bureaucracy: the label is REMOVED from card images. It stays on the article
   DETAILS page (which renders it in .wh-article-hero, not .wh-article-cat). */
.wh-article-cat .wh-cat-tag[data-cat="bureaucracy"] { display: none !important; }

/* —————— Divider (decorative red bar) —————— */
.wh-divider {
  height: 4px;
  background: var(--brand);
  width: 60px;
  margin: var(--sp-3) 0;
}
.wh-divider-center {
  margin-left: auto;
  margin-right: auto;
}

/* —————— Flash messages (toast-style) —————— */
.wh-flash {
  position: fixed;
  top: var(--sp-5);
  left: 50%;
  transform: translateX(-50%);
  z-index: var(--z-toast);
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-5);
  background: var(--ink);
  color: #fff;
  border-radius: var(--r-5);
  font-size: var(--fs-sm);
  font-weight: 500;
  box-shadow: var(--shadow-lg);
  max-width: calc(100vw - 32px);
  animation: flash-in .35s var(--t-spring);
}
.wh-flash-success { background: var(--success); }
.wh-flash-danger  { background: var(--danger); }
.wh-flash-close {
  background: transparent;
  border: 0;
  color: inherit;
  opacity: .7;
  cursor: pointer;
  padding: 4px;
  font-size: 18px;
  line-height: 1;
}
.wh-flash-close:hover { opacity: 1; }
@keyframes flash-in {
  from { opacity: 0; transform: translate(-50%, -20px); }
  to   { opacity: 1; transform: translate(-50%, 0); }
}

/* ============================================================================
   §5  HEADER + NAV
============================================================================ */
.wh-header {
  background: var(--paper);
  border-bottom: 1px solid var(--line);
  position: relative;
  z-index: var(--z-sticky);
}

/* — Top utility bar (date, weather, social) — */
.wh-header-utility {
  background: var(--ink-bg);
  color: rgba(255,255,255,.7);
  font-size: var(--fs-xxs);
  letter-spacing: 0.05em;
}
.wh-header-utility-inner {
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 32px;
  gap: var(--sp-4);
}
.wh-header-utility-left { display: flex; align-items: center; gap: var(--sp-4); }
.wh-header-utility-left .wh-date { text-transform: uppercase; letter-spacing: 0.1em; }
.wh-header-utility-right { display: flex; align-items: center; gap: var(--sp-3); }
.wh-header-utility a {
  color: rgba(255,255,255,.7);
  display: inline-flex;
  align-items: center;
  padding: 4px;
  transition: color var(--t-fast);
}
.wh-header-utility a:hover { color: #fff; }
.wh-utility-divider { width: 1px; height: 14px; background: rgba(255,255,255,.18); }

/* — Brand bar (logo + CTA + account) — */
.wh-header-brand {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  padding: var(--sp-5) 0;
  gap: var(--sp-4);
}
.wh-header-brand-left { display: flex; align-items: center; gap: var(--sp-4); }
.wh-header-brand-right {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: var(--sp-3);
}
.wh-logo {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  color: var(--ink);
}
.wh-logo img { height: 56px; width: auto; }
.wh-logo-wordmark {
  font-family: var(--f-display);
  font-size: clamp(28px, 4vw, 40px);
  letter-spacing: -0.01em;
  line-height: 1;
  color: var(--ink);
}
.wh-logo-tagline {
  font-size: var(--fs-xxs);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
  margin-top: 4px;
  font-weight: 500;
}
/* Phase 15.3 — uploaded logo image (Settings → Branding). Replaces the text
   wordmark when set; capped so a wide logo never overflows the header. */
.wh-logo img { max-width: min(340px, 56vw); object-fit: contain; }
.wh-logo--img { padding: 4px 0; }
.wh-logo-img--drawer { height: 34px; width: auto; max-width: 200px; object-fit: contain; }
.wh-footer-logo--img img { width: auto; max-width: 220px; object-fit: contain; }
@media (max-width: 575px) {
  .wh-logo img { height: 42px; max-width: 56vw; }
}

.wh-header-search-mini {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 12px;
  background: var(--paper-3);
  border: 1px solid transparent;
  border-radius: var(--r-full);
  color: var(--ink-2);
  font-size: var(--fs-xs);
  font-weight: 500;
  transition: all var(--t-fast);
}
.wh-header-search-mini:hover { background: var(--paper-4); color: var(--ink); }

/* — Main nav (sticky, below brand bar) — */
.wh-nav {
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  background: var(--paper);
}
.wh-nav.is-stuck {
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
  box-shadow: var(--shadow-sm);
}

/* Phase 15.2.18 — sticky-header mode (admin-toggleable).
   When the page scrolls past the brand bar, we make a compact sticky bar
   containing BOTH the logo (shrunk) AND the main nav, on desktop AND mobile.
   Triggered by the JS adding .is-sticky-mode to the <header data-sticky="1">. */
.wh-header[data-sticky="1"].is-sticky-mode .wh-sticky-shell {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: var(--z-sticky);
  background: var(--paper);
  box-shadow: 0 2px 8px rgba(0,0,0,0.08);
  border-bottom: 1px solid var(--line);
  display: block;
  animation: wh-sticky-slide-in .18s ease-out;
}
@keyframes wh-sticky-slide-in {
  from { transform: translateY(-100%); }
  to   { transform: translateY(0); }
}
/* Hidden by default; only appears when JS toggles .is-sticky-mode */
.wh-sticky-shell {
  display: none;
}
.wh-sticky-shell-inner {
  max-width: 1280px;
  margin: 0 auto;
  padding: 8px var(--sp-4);
  display: flex;
  align-items: center;
  gap: var(--sp-4);
}
.wh-sticky-logo {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  color: var(--ink);
  flex-shrink: 0;
}
.wh-sticky-logo .wh-sticky-logo-text {
  font-family: var(--f-display);
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -.01em;
  white-space: nowrap;
}
.wh-sticky-logo .wh-sticky-logo-img {
  height: 32px; width: auto; display: block;
}
.wh-sticky-nav {
  flex: 1;
  overflow-x: auto;
  scrollbar-width: none;  /* Firefox */
}
.wh-sticky-nav::-webkit-scrollbar { display: none; }  /* Chrome/Safari */
.wh-sticky-nav-list {
  display: flex;
  align-items: center;
  gap: 0;
  list-style: none;
  margin: 0;
  padding: 0;
  white-space: nowrap;
}
.wh-sticky-nav-list .wh-nav-link {
  display: inline-block;
  padding: 8px 14px;
  font-size: 14px;
  font-weight: 500;
  color: var(--ink);
  text-decoration: none;
  position: relative;
}
.wh-sticky-nav-list .wh-nav-link:hover { color: var(--brand-red, #d70000); }
.wh-sticky-nav-list .wh-nav-link.is-active {
  color: var(--brand-red, #d70000);
}
.wh-sticky-nav-list .wh-nav-link.is-active::after {
  content: '';
  position: absolute;
  bottom: -2px; left: 12px; right: 12px;
  height: 2px;
  background: var(--brand-red, #d70000);
}
.wh-sticky-actions {
  display: flex; align-items: center; gap: 8px; flex-shrink: 0;
}
.wh-sticky-search-btn,
.wh-sticky-menu-btn {
  background: none;
  border: 1px solid transparent;
  cursor: pointer;
  padding: 6px 10px;
  border-radius: 4px;
  color: var(--ink);
  font-size: 18px;
  line-height: 1;
}
.wh-sticky-search-btn:hover,
.wh-sticky-menu-btn:hover { background: var(--paper-2); }
.wh-sticky-menu-btn { display: none; }

/* Mobile: hide the inline nav, show hamburger to open the existing drawer */
@media (max-width: 768px) {
  .wh-sticky-nav { display: none; }
  .wh-sticky-menu-btn { display: inline-block; }
  .wh-sticky-shell-inner { padding: 8px var(--sp-3); }
}
/* When sticky mode is OFF (setting disabled), make sure the shell stays hidden
   no matter what JS does */
.wh-header[data-sticky="0"] .wh-sticky-shell { display: none !important; }

.wh-nav-inner {
  display: flex;
  align-items: center;
  justify-content: center;   /* Phase 15.2.81 — centre the main menu */
  height: 52px;
  gap: var(--sp-4);
}
.wh-nav-list {
  display: flex;
  align-items: stretch;
  gap: 0;
  list-style: none;
  margin: 0;
  padding: 0;
}
.wh-nav-item { position: relative; }
.wh-nav-link {
  display: inline-flex;
  align-items: center;
  height: 100%;
  padding: 0 var(--sp-4);
  font-family: var(--f-ui);
  font-size: var(--fs-sm);
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-2);
  text-decoration: none;
  position: relative;
  transition: color var(--t-fast);
}
.wh-nav-link:hover { color: var(--brand); }
.wh-nav-link.is-active { color: var(--brand); }
.wh-nav-link.is-active::after,
.wh-nav-link:hover::after {
  content: '';
  position: absolute;
  left: var(--sp-4); right: var(--sp-4);
  bottom: 0; height: 3px;
  background: var(--brand);
}

/* Mega-menu dropdown */
.wh-nav-mega {
  position: absolute;
  top: 100%;
  left: 0;
  min-width: 480px;
  max-width: 720px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-2);
  box-shadow: var(--shadow-lg);
  padding: var(--sp-5);
  opacity: 0;
  visibility: hidden;
  transform: translateY(8px);
  transition: all var(--t-normal);
  z-index: var(--z-dropdown);
}
.wh-nav-item:hover > .wh-nav-mega,
.wh-nav-item:focus-within > .wh-nav-mega {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}
.wh-nav-mega-grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: var(--sp-4);
}
.wh-nav-mega-item {
  display: block;
  padding: var(--sp-2);
  border-radius: var(--r-2);
  transition: background var(--t-fast);
}
.wh-nav-mega-item:hover { background: var(--paper-2); }
.wh-nav-mega-item-img {
  width: 100%;
  aspect-ratio: 16/10;
  object-fit: cover;
  border-radius: var(--r-1);
  margin-bottom: var(--sp-2);
  background: var(--paper-3);
}
.wh-nav-mega-item-title {
  font-family: var(--f-serif);
  font-size: var(--fs-sm);
  font-weight: 700;
  line-height: 1.3;
  color: var(--ink);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.wh-nav-search {
  display: inline-flex;
  align-items: center;
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: var(--r-full);
  padding: 4px;
  transition: all var(--t-normal);
}
.wh-nav-search input {
  background: transparent;
  border: 0;
  padding: 6px 12px;
  font-size: var(--fs-sm);
  width: 0;
  transition: width var(--t-normal);
  font-family: var(--f-ui);
}
.wh-nav-search input:focus { outline: none; }
.wh-nav-search button {
  background: transparent;
  border: 0;
  padding: 6px 10px;
  cursor: pointer;
  color: var(--ink-2);
}
.wh-nav-search.is-open input,
.wh-nav-search:focus-within input { width: 200px; }

/* Mobile menu toggle */
.wh-nav-toggle {
  display: none;
  background: transparent;
  border: 0;
  padding: 8px;
  cursor: pointer;
  color: var(--ink);
}

/* — Mobile drawer — */
.wh-mobile-drawer {
  position: fixed;
  top: 0; right: 0;
  /* Phase 15.4.3 — full-width on phones so the red LIVE ticker / hamburger no
     longer peek through the left strip behind the drawer (only capped on
     tablets). */
  width: min(430px, 100vw);
  /* 100dvh = the VISIBLE viewport height on mobile (excludes the browser's
     address/tool bars) so the last menu items + footer are always reachable.
     100vh is the pre-dvh fallback. */
  height: 100vh;
  height: 100dvh;
  background: var(--paper);
  z-index: var(--z-modal);
  transform: translateX(100%);
  transition: transform var(--t-normal);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  box-shadow: var(--shadow-xl);
  display: flex;
  flex-direction: column;
}
.wh-mobile-drawer.is-open { transform: translateX(0); }
.wh-mobile-backdrop {
  position: fixed; inset: 0;
  background: rgba(0,0,0,.5);
  z-index: var(--z-overlay);
  opacity: 0;
  visibility: hidden;
  transition: all var(--t-normal);
}
.wh-mobile-backdrop.is-open { opacity: 1; visibility: visible; }
.wh-mobile-drawer-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: var(--sp-4) var(--sp-5);
  border-bottom: 1px solid var(--line);
  /* Phase 15.4.3 — keep the header (and its close ✕) pinned + opaque while the
     menu scrolls, so nothing ever scrolls over/under the close button. */
  position: sticky;
  top: 0;
  z-index: 3;
  background: var(--paper);
}
.wh-mobile-drawer-close {
  background: transparent;
  border: 0;
  padding: 8px;
  cursor: pointer;
  font-size: 20px;
}
.wh-mobile-drawer-search { padding: var(--sp-4) var(--sp-5); border-bottom: 1px solid var(--line); }
.wh-mobile-drawer-search form {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: var(--r-2);
  padding: 4px 12px;
}
.wh-mobile-drawer-search input {
  flex: 1;
  border: 0;
  background: transparent;
  padding: 10px 0;
  font-size: var(--fs-sm);
  font-family: var(--f-ui);
}
.wh-mobile-drawer-search input:focus { outline: none; }
.wh-mobile-drawer-nav {
  flex: 1;
  list-style: none;
  margin: 0;
  padding: var(--sp-3) 0;
}
.wh-mobile-drawer-nav li { margin: 0; }
.wh-mobile-drawer-nav a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--sp-4) var(--sp-5);
  font-size: var(--fs-md);
  font-weight: 600;
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1px solid var(--line-2);
  transition: all var(--t-fast);
}
.wh-mobile-drawer-nav a:hover, .wh-mobile-drawer-nav a.is-active {
  background: var(--paper-2);
  color: var(--brand);
}
.wh-mobile-drawer-footer {
  padding: var(--sp-5);
  /* Phase 15.4.3 — extra bottom breathing room + iOS safe-area inset so the
     Sign in / Subscribe row is never hidden behind the phone's browser bar. */
  padding-bottom: calc(var(--sp-5) + env(safe-area-inset-bottom, 0px) + 18px);
  border-top: 1px solid var(--line);
  background: var(--paper-2);
}
.wh-mobile-drawer-socials {
  display: flex;
  justify-content: center;
  gap: var(--sp-3);
  margin-top: var(--sp-3);
}
.wh-mobile-drawer-socials a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px; height: 38px;
  border-radius: 50%;
  background: var(--paper);
  border: 1px solid var(--line);
  color: var(--ink-2);
  transition: all var(--t-fast);
}
.wh-mobile-drawer-socials a:hover {
  background: var(--ink);
  border-color: var(--ink);
  color: #fff;
}

/* — Ticker — */
.wh-ticker {
  background: var(--ink-bg);
  color: #fff;
  height: 40px;
  display: flex;
  align-items: center;
  overflow: hidden;
  position: relative;
}
.wh-ticker-label {
  flex-shrink: 0;
  background: var(--brand);
  color: #fff;
  height: 100%;
  display: inline-flex;
  align-items: center;
  padding: 0 var(--sp-4);
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  gap: 6px;
  position: relative;
  z-index: 2;
}
.wh-ticker-label::after {
  content: '';
  position: absolute;
  right: -10px; top: 0;
  width: 0; height: 0;
  border-left: 10px solid var(--brand);
  border-top: 20px solid transparent;
  border-bottom: 20px solid transparent;
}
.wh-ticker-outer {
  flex: 1;
  overflow: hidden;
  padding-left: 16px;
  position: relative;
  mask-image: linear-gradient(to right, transparent 0, #000 24px, #000 calc(100% - 24px), transparent 100%);
}
.wh-ticker-inner {
  display: inline-flex;
  white-space: nowrap;
  animation: ticker-scroll 50s linear infinite;
}
.wh-ticker-inner:hover { animation-play-state: paused; }
.wh-ticker-item {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 0 var(--sp-6);
  font-size: var(--fs-sm);
  color: rgba(255,255,255,.92);
}
.wh-ticker-item::before {
  content: '';
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--brand);
  flex-shrink: 0;
}
@keyframes ticker-scroll {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

/* ============================================================================
   §6  FOOTER
============================================================================ */
.wh-footer {
  background: var(--ink-bg);
  color: rgba(255,255,255,.7);
  padding-top: var(--sp-10);
  margin-top: var(--sp-10);
}
.wh-footer-grid {
  display: grid;
  grid-template-columns: 1.5fr 1fr 1fr 1.5fr;
  gap: var(--sp-7);
  padding-bottom: var(--sp-9);
}
.wh-footer-brand-block { max-width: 340px; }
.wh-footer-logo {
  font-family: var(--f-display);
  font-size: var(--fs-2xl);
  color: #fff;
  line-height: 1;
  margin-bottom: var(--sp-3);
  display: inline-block;
  text-decoration: none;
}
.wh-footer-logo img { height: 44px; }
.wh-footer-tagline {
  font-size: var(--fs-sm);
  color: var(--accent-gold);
  font-style: italic;
  margin-bottom: var(--sp-3);
}
.wh-footer-desc {
  font-size: var(--fs-sm);
  line-height: 1.6;
  color: rgba(255,255,255,.6);
  margin-bottom: var(--sp-4);
}
.wh-footer-col-title {
  font-family: var(--f-ui);
  font-size: var(--fs-xxs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: #fff;
  margin: 0 0 var(--sp-4) 0;
  padding-bottom: var(--sp-2);
  border-bottom: 1px solid rgba(255,255,255,.12);
}
.wh-footer-list {
  list-style: none;
  padding: 0;
  margin: 0;
}
.wh-footer-list li { margin-bottom: var(--sp-2); }
.wh-footer-list a {
  color: rgba(255,255,255,.7);
  font-size: var(--fs-sm);
  text-decoration: none;
  transition: all var(--t-fast);
  display: inline-block;
}
.wh-footer-list a:hover { color: #fff; transform: translateX(2px); }

.wh-footer-newsletter-form {
  display: flex;
  background: rgba(255,255,255,.08);
  border-radius: var(--r-full);
  overflow: hidden;
  margin-bottom: var(--sp-4);
}
.wh-footer-newsletter-form input {
  flex: 1;
  background: transparent;
  border: 0;
  padding: 12px 18px;
  color: #fff;
  font-size: var(--fs-sm);
  font-family: var(--f-ui);
}
.wh-footer-newsletter-form input::placeholder { color: rgba(255,255,255,.4); }
.wh-footer-newsletter-form input:focus { outline: none; }
.wh-footer-newsletter-form button {
  background: var(--brand);
  border: 0;
  padding: 0 var(--sp-5);
  color: #fff;
  font-weight: 600;
  cursor: pointer;
  transition: background var(--t-fast);
}
.wh-footer-newsletter-form button:hover { background: var(--brand-700); }

.wh-footer-socials {
  display: flex;
  gap: var(--sp-2);
  margin-top: var(--sp-3);
}
.wh-footer-socials a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px; height: 38px;
  border-radius: 50%;
  background: rgba(255,255,255,.08);
  color: #fff;
  text-decoration: none;
  font-size: 16px;
  transition: all var(--t-fast);
}
.wh-footer-socials a:hover {
  background: var(--brand);
  transform: translateY(-2px);
}

.wh-footer-bottom {
  border-top: 1px solid rgba(255,255,255,.08);
  padding: var(--sp-5) 0;
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-3);
  font-size: var(--fs-xs);
  color: rgba(255,255,255,.5);
}
.wh-footer-bottom-links {
  display: flex;
  gap: var(--sp-4);
}
.wh-footer-bottom-links a { color: rgba(255,255,255,.5); }
.wh-footer-bottom-links a:hover { color: #fff; }
.wh-footer-privacy-note {
  font-size: 11px;
  color: rgba(255,255,255,.35);
  text-align: center;
  padding-bottom: var(--sp-3);
}

/* — Back to top — */
.wh-back-top {
  position: fixed;
  bottom: 24px; right: 24px;
  width: 44px; height: 44px;
  background: var(--ink);
  color: #fff;
  border: 0;
  border-radius: 50%;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  visibility: hidden;
  transform: translateY(10px);
  transition: all var(--t-normal);
  z-index: var(--z-elevated);
  box-shadow: var(--shadow-lg);
}
.wh-back-top.is-visible { opacity: 1; visibility: visible; transform: translateY(0); }
.wh-back-top:hover { background: var(--brand); }

/* ============================================================================
   §17 UTILITIES + RESPONSIVE
============================================================================ */

/* Aspect ratio holder for images */
.wh-aspect-16-9 { aspect-ratio: 16 / 9; overflow: hidden; }
.wh-aspect-4-3  { aspect-ratio: 4 / 3;  overflow: hidden; }
.wh-aspect-1-1  { aspect-ratio: 1 / 1;  overflow: hidden; }
.wh-aspect-3-4  { aspect-ratio: 3 / 4;  overflow: hidden; }
.wh-aspect-21-9 { aspect-ratio: 21 / 9; overflow: hidden; }

.wh-img-cover {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform var(--t-slow);
}
.wh-img-cover-hover:hover .wh-img-cover { transform: scale(1.05); }

/* Hide on different breakpoints */
.wh-hide-desktop { display: none !important; }
.wh-hide-mobile  { display: initial; }

@media (max-width: 991px) {
  .wh-hide-desktop { display: initial !important; }
  .wh-hide-mobile  { display: none !important; }

  .wh-nav-toggle { display: inline-flex !important; align-items: center; padding: 6px 6px 6px 0; }
  /* Flexbox brand bar: [hamburger] [logo grows + centred] [search]. Flexbox
     avoids the grid min-width quirk that was letting the long wordmark overflow
     across (and hide) the search icon. */
  .wh-header-brand { display: flex; align-items: center; gap: 6px; padding: 10px 0; }
  .wh-header-brand-left  { flex: 0 0 40px; }
  /* reserve matching width on the right so the masthead sits dead-centre */
  .wh-header-brand-right { flex: 0 0 40px; }
  .wh-logo { flex: 1 1 auto; min-width: 0; display: flex; justify-content: center; overflow: hidden; }
  .wh-logo > div { min-width: 0; }
  .wh-logo-wordmark {
    font-size: clamp(13px, 3.5vw, 18px);
    line-height: 1.1;
    white-space: nowrap;
  }
  .wh-logo-tagline { font-size: 8px; margin-top: 2px; }

  /* Phase 15.2.69 — Category bar (Times of India style), horizontally scrollable
     in the initial header. Sticky-on-scroll is handled by the FIXED sticky-shell
     (below) — NOT position:sticky on this bar, because the bar's parent (the
     short <header>) scrolls away and would drag it off-screen. */
  .wh-nav > .wh-container { padding-inline: 0; }
  .wh-nav-inner { height: 46px; justify-content: flex-start; gap: 0; }
  .wh-nav-list {
    display: flex;
    flex-wrap: nowrap;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    width: 100%;
    padding-inline: 10px;
  }
  .wh-nav-list::-webkit-scrollbar { display: none; }
  .wh-nav-item { flex: 0 0 auto; }
  .wh-nav-link { white-space: nowrap; padding: 0 13px; height: 46px; font-size: 12.5px; }

  /* Phase 15.2.69 — mobile sticky-shell: compact masthead + scrollable category
     nav + hamburger, so the fixed sticky bar is genuinely useful on phones.
     NOTE: override the older ≤768 rule that hid .wh-sticky-nav behind only a
     hamburger — we want the Times-of-India style category strip here. */
  .wh-sticky-shell-inner { padding: 5px 12px; gap: 8px; align-items: center; }
  .wh-sticky-logo { flex: 0 1 auto; min-width: 0; overflow: hidden; align-self: center; }
  .wh-sticky-logo .wh-sticky-logo-text {
    font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  /* stretch the nav to the full bar height and vertically centre its links so
     they line up with the search/hamburger icons (the reported misalignment). */
  .wh-sticky-nav { display: block !important; flex: 1 1 auto; min-width: 0; overflow-x: auto; align-self: stretch; }
  .wh-sticky-nav-list { display: flex; align-items: center; height: 100%; }
  .wh-sticky-nav-list .wh-nav-link {
    display: inline-flex; align-items: center; height: 100%;
    padding: 0 11px; font-size: 12.5px;
  }
  .wh-sticky-actions { gap: 4px; flex: 0 0 auto; align-self: center; align-items: center; }
  .wh-sticky-search-btn, .wh-sticky-menu-btn {
    width: 36px; height: 36px; display: inline-flex; align-items: center; justify-content: center;
  }

  .wh-footer-grid { grid-template-columns: 1fr 1fr; gap: var(--sp-6); }
}


@media (max-width: 575px) {
  .wh-footer-grid { grid-template-columns: 1fr; }
  .wh-section { padding-block: var(--sp-6); }
  .wh-section-lg { padding-block: var(--sp-7); }
  .wh-header-utility-left .wh-date { display: none; }
  /* Phones: the masthead is too long for the sticky bar — drop it and give the
     whole bar to the scrollable category nav + hamburger. */
  .wh-sticky-logo { display: none; }
}

/* Body lock for modal/drawer open */
body.no-scroll { overflow: hidden; }

/* Print friendly */
@media print {
  .wh-header, .wh-footer, .wh-back-top, .wh-ticker { display: none !important; }
  body { background: #fff; }
}

/* ============================================================================
   §7  ARTICLE CARDS
============================================================================ */

/* Base article card (used everywhere) */
.wh-article {
  display: flex;
  flex-direction: column;
  text-decoration: none;
  color: var(--ink);
  transition: all var(--t-normal);
  height: 100%;
}
.wh-article:hover { color: var(--ink); }
.wh-article-media {
  position: relative;
  background: var(--paper-3);
  overflow: hidden;
  margin-bottom: var(--sp-3);
  border-radius: var(--r-img, 8px);   /* Phase 15.2.81 — rounded card images site-wide */
}
.wh-article-media img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform var(--t-slow);
}
.wh-article:hover .wh-article-media img { transform: scale(1.05); }

.wh-article-cat {
  position: absolute;
  top: var(--sp-3); left: var(--sp-3);
  z-index: 1;
}
.wh-article-title {
  font-family: var(--f-serif);
  font-weight: 700;
  color: var(--ink);
  line-height: 1.25;
  margin: 0 0 var(--sp-2) 0;
  letter-spacing: -0.005em;
  transition: color var(--t-fast);
  display: -webkit-box;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.wh-article:hover .wh-article-title { color: var(--brand); }
.wh-article-summary {
  font-size: var(--fs-sm);
  color: var(--ink-3);
  line-height: 1.55;
  margin-bottom: var(--sp-3);
  display: -webkit-box;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* — Card sizes — */
.wh-article-xl .wh-article-media   { aspect-ratio: 16 / 10; }
.wh-article-xl .wh-article-title   { font-size: clamp(24px, 3vw, 36px); -webkit-line-clamp: 3; }
.wh-article-xl .wh-article-summary { font-size: var(--fs-md); -webkit-line-clamp: 3; }

.wh-article-lg .wh-article-media   { aspect-ratio: 16 / 9; }
.wh-article-lg .wh-article-title   { font-size: var(--fs-xl); -webkit-line-clamp: 3; }

.wh-article-md .wh-article-media   { aspect-ratio: 16 / 10; }
.wh-article-md .wh-article-title   { font-size: var(--fs-md); -webkit-line-clamp: 3; }
.wh-article-md .wh-article-summary { display: none; }

.wh-article-sm .wh-article-media   { aspect-ratio: 4 / 3; }
.wh-article-sm .wh-article-title   { font-size: var(--fs-sm); -webkit-line-clamp: 3; line-height: 1.4; }
.wh-article-sm .wh-article-summary { display: none; }

/* Horizontal card (image left, text right) */
.wh-article-row {
  display: grid;
  /* minmax(0,1fr) lets the text column shrink so long titles/words WRAP instead
     of overflowing off the right edge (was a mobile overflow on /search). */
  grid-template-columns: 180px minmax(0, 1fr);
  gap: var(--sp-4);
  align-items: start;
}
.wh-article-row > * { min-width: 0; }
.wh-article-row .wh-article-media { aspect-ratio: 4 / 3; margin-bottom: 0; }
.wh-article-row .wh-article-title { font-size: var(--fs-md); -webkit-line-clamp: 3; }
.wh-article-row .wh-article-summary { display: none; }
@media (max-width: 575px) {
  .wh-article-row { grid-template-columns: 104px minmax(0, 1fr); gap: var(--sp-3); }
}

/* Tiny list item (no image) — for "trending" sidebar */
.wh-article-mini {
  display: flex;
  align-items: start;
  gap: var(--sp-3);
  padding: var(--sp-3) 0;
  border-bottom: 1px solid var(--line);
  text-decoration: none;
}
.wh-article-mini:last-child { border-bottom: 0; }
.wh-article-mini-num {
  font-family: var(--f-display);
  font-size: 32px;
  line-height: 1;
  color: var(--brand);
  flex-shrink: 0;
}
.wh-article-mini-content { flex: 1; min-width: 0; }
.wh-article-mini-title {
  font-family: var(--f-serif);
  font-size: var(--fs-sm);
  font-weight: 700;
  color: var(--ink);
  margin: 0 0 4px 0;
  line-height: 1.35;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.wh-article-mini:hover .wh-article-mini-title { color: var(--brand); }

/* Hero overlay variant — text over full-bleed image */
.wh-article-overlay {
  position: relative;
  display: block;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  border-radius: var(--r-img);   /* Phase 15.2.81 — unified rounded image corner */
  background: var(--ink);
  color: #fff;
  text-decoration: none;
}
.wh-article-overlay img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform var(--t-slow);
  opacity: .85;
}
.wh-article-overlay:hover img { transform: scale(1.05); }
.wh-article-overlay-gradient {
  position: absolute; left: 0; right: 0; bottom: 0;
  height: 75%;
  background: linear-gradient(180deg, transparent 0%, rgba(0,0,0,.85) 100%);
}
.wh-article-overlay-body {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: clamp(20px, 4vw, 40px);
  color: #fff;
  z-index: 1;
}
.wh-article-overlay-body .wh-article-title {
  color: #fff;
  font-size: clamp(22px, 3.5vw, 40px);
  line-height: 1.15;
  margin-bottom: var(--sp-3);
  text-shadow: 0 2px 6px rgba(0,0,0,.4);
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.wh-article-overlay-body .wh-meta { color: rgba(255,255,255,.85); }
.wh-article-overlay-body .wh-meta a { color: inherit; }

/* Placeholder fallback for missing images */
.wh-article-placeholder {
  width: 100%; height: 100%;
  background: linear-gradient(135deg, var(--paper-3), var(--paper-4));
  display: flex; align-items: center; justify-content: center;
  color: var(--muted-2);
  font-family: var(--f-display);
  font-size: 48px;
}

/* ============================================================================
   §8  HOMEPAGE
============================================================================ */

/* Web Stories strip (Instagram-style avatars) */
.wh-stories-strip-wrap {
  border-bottom: 1px solid var(--line);
  background: var(--paper);
}
.wh-stories-strip {
  display: flex;
  gap: var(--sp-4);
  overflow-x: auto;
  padding: var(--sp-4) 0;
  scrollbar-width: thin;
  /* Phase 15.2.72 — centre the pills when they fit the row (no blank tail on
     the right); fall back to normal left-aligned scrolling when they overflow. */
  width: fit-content;
  max-width: 100%;
  margin-inline: auto;
}
.wh-stories-strip::-webkit-scrollbar { height: 0; }
.wh-story-pill {
  flex: 0 0 auto;
  width: 84px;
  text-decoration: none;
  color: inherit;
  text-align: center;
}
.wh-story-pill-ring {
  width: 76px; height: 76px;
  border-radius: 50%;
  padding: 3px;
  background: linear-gradient(135deg, var(--brand) 0%, #ff5757 60%, var(--accent-gold) 100%);
  margin: 0 auto var(--sp-2);
  transition: transform var(--t-fast);
}
.wh-story-pill:hover .wh-story-pill-ring { transform: scale(1.05); }
.wh-story-pill-ring img, .wh-story-pill-fallback {
  width: 100%; height: 100%;
  border-radius: 50%;
  border: 2px solid var(--paper);
  object-fit: cover;
  display: block;
}
.wh-story-pill-fallback {
  background: linear-gradient(135deg, #1a1a1a, #333);
  color: #fff;
  font-family: var(--f-display);
  font-size: 26px;
  display: flex; align-items: center; justify-content: center;
}
.wh-story-pill-label {
  font-size: var(--fs-xxs);
  line-height: 1.3;
  color: var(--ink-2);
  font-weight: 500;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Hero block (featured + side rail) */
.wh-hero {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
  gap: var(--sp-7);
  /* Phase 15.2.72 — was --sp-9; trimmed so the below-hero banner sits close to
     the slider instead of leaving a big blank gap. */
  margin-bottom: var(--sp-4);
  align-items: stretch;
}

/* Phase 15.2.66 — on desktop the headline rail (right) is usually taller than
   a single 16:10 lead card, which left a blank band under the lead. Make the
   lead carousel FILL the row height so both columns end flush — no blank. */
@media (min-width: 992px) {
  .wh-hero-main { display: flex; min-height: 380px; }
  .wh-hero-main > .wh-hero-carousel { flex: 1 1 auto; width: 100%; }
  .wh-hero-main .wh-hero-carousel,
  .wh-hero-main .wh-hero-carousel-track,
  .wh-hero-main .wh-hero-carousel-slide.is-active { height: 100%; }
  .wh-hero-main .wh-article-overlay {
    aspect-ratio: auto;
    height: 100%;
    min-height: 100%;
  }
}

/* Phase 15.2.55 — banner ad immediately below the hero slider. Same width as
   the slider (full container) so the creative reads as a continuation of
   the hero. Tight top/bottom margins so it doesn't push down the next
   section too far. Empty slot collapses cleanly. */
.wh-slider-banner-ad {
  /* Phase 15.2.72 — the hero section adds large bottom spacing; pull the banner
     up so the gap below the slider is tight instead of a big blank band. */
  margin-top: -28px;
  margin-bottom: 18px;
}
.wh-slider-banner-ad .wh-ad-slot {
  width: 100%;
  /* Phase 15.2.72 — the inline zone width (e.g. 970px leaderboard) was applied
     as max-width on the slot, leaving blank space to the right inside the wider
     container. Force full container width so the banner spans edge-to-edge. */
  max-width: 100% !important;
  margin: 0;
  /* Phase 15.2.58 — same defensive override as wh-ad-rail */
  min-height: 0 !important;
}
.wh-slider-banner-ad .wh-ad-slot img {
  /* Stretch the creative to the full banner width (override any inline/zone
     max-width on the image itself). */
  width: 100% !important;
  max-width: 100% !important;
  height: auto;
  display: block;
  border-radius: 6px;
  object-fit: cover;
  /* Phase 15.2.56 — this is a hero-position banner, so the global ad
     max-height cap (250px) is intentionally relaxed here. Cap higher so
     a real banner creative (e.g. 1280×280 leaderboard) can show fully. */
  max-height: 320px !important;
}
.wh-slider-banner-ad .wh-ad-slot a { width: 100%; }
.wh-slider-banner-ad .wh-ad-slot a {
  display: block;
  width: 100%;
}
.wh-slider-banner-ad:has(.wh-ad-slot:empty) { display: none; }

@media (max-width: 991px) {
  .wh-slider-banner-ad .wh-ad-slot img { max-height: 200px !important; }
}
@media (max-width: 575px) {
  .wh-slider-banner-ad .wh-ad-slot img { max-height: 140px !important; }
}
.wh-hero-side {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}
.wh-hero-side .wh-article-row {
  /* Phase 15.2.25 — premium card matching the design mockup:
     image left, red category label above title, single-line meta below. */
  display: grid;
  grid-template-columns: 88px 1fr;
  gap: 12px;
  align-items: center;
  background: #fff;
  border: 1px solid #ececec;
  border-radius: 10px;
  padding: 10px 12px;
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
  transition: box-shadow .18s ease, transform .18s ease, border-color .18s ease;
  text-decoration: none;
  color: inherit;
}
.wh-hero-side .wh-article-row:hover {
  border-color: #dcdcdc;
  box-shadow: 0 6px 16px rgba(15, 23, 42, 0.08);
  transform: translateY(-1px);
}
.wh-hero-side .wh-article-row .wh-article-media {
  width: 88px;
  height: 88px;
  border-radius: 6px;
  overflow: hidden;
  aspect-ratio: 1 / 1;
  margin-bottom: 0;
  position: relative;
}
.wh-hero-side .wh-article-row .wh-article-media img,
.wh-hero-side .wh-article-row .wh-article-media .wh-article-placeholder {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.wh-hero-side .wh-article-row-body {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.wh-hero-side .wh-article-row-cat {
  color: var(--brand-red, #d70000);
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: none;
  letter-spacing: 0;
  line-height: 1.2;
}
.wh-hero-side .wh-article-row .wh-article-title {
  font-size: 0.95rem;
  line-height: 1.3;
  font-weight: 700;
  margin: 0;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  color: #111;
}
.wh-hero-side .wh-article-row-meta {
  font-size: 0.72rem;
  color: #888;
  display: flex;
  gap: 6px;
  align-items: center;
  flex-wrap: nowrap;
  margin: 0;
  line-height: 1.2;
}
.wh-hero-side .wh-article-row-sep {
  color: #ccc;
}

/* Phase 15.2.26 — BREAKING badge (visible effect for is_breaking flag).
   Phase 15.2.27 — moved to TOP-RIGHT so it doesn't overlap the category
   tag at top-left. The two badges now occupy opposite corners on every
   card variant (hero overlay, lg/md cards, listing cards). */
.wh-breaking-badge {
  position: absolute;
  top: 10px;
  right: 10px;
  background: #d70000;
  color: #fff;
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 4px 8px;
  border-radius: 4px;
  z-index: 3;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  line-height: 1;
  box-shadow: 0 2px 6px rgba(215, 0, 0, 0.35);
  animation: wh-breaking-pulse 2s ease-in-out infinite;
}
.wh-breaking-badge-sm {
  font-size: 0.55rem;
  padding: 2px 4px;
  top: 4px;
  right: 4px;
}
.wh-breaking-badge-sm i { font-size: 0.7rem; }
.wh-breaking-badge-sm > :not(i) { display: none; }
/* Phase 15.2.38 — inline (no-image) variant, used in the mini sidebar list.
   Sits to the left of the title text instead of in a positioned corner. */
.wh-breaking-badge-inline {
  position: static;
  display: inline-flex;
  align-items: center;
  font-size: 0.6rem;
  padding: 2px 5px;
  margin-right: 4px;
  vertical-align: 1px;
}
.wh-breaking-badge-inline i { font-size: 0.7rem; }
.wh-breaking-badge-inline > :not(i) { display: none; }
@keyframes wh-breaking-pulse {
  0%, 100% { box-shadow: 0 2px 6px rgba(215, 0, 0, 0.35); }
  50%      { box-shadow: 0 2px 12px rgba(215, 0, 0, 0.65); }
}
/* Detail page breaking pill (above title) */
.wh-breaking-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: #d70000;
  color: #fff;
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 5px 12px;
  border-radius: 4px;
  margin-bottom: 12px;
}

/* Phase 15.2.26 — Latest sidebar widget title 2-line ellipsis */
.wh-widget .wh-article-mini-title {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 0.92rem;
  line-height: 1.35;
  font-weight: 600;
}

/* Phase 15.2.26 — Bureaucracy section + any 2-up category strip — give each
   secondary card a subtle "box" treatment (border + radius + soft shadow)
   without changing the existing card sizes. Same look as the home sidebar's
   premium cards, just at a larger scale. */
.wh-cat-strip-side .wh-article,
.wh-cat-strip-list .wh-article {
  background: #fff;
  border: 1px solid #ececec;
  border-radius: 10px;
  padding: 10px;
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
  transition: box-shadow .18s ease, transform .18s ease, border-color .18s ease;
}
.wh-cat-strip-side .wh-article:hover,
.wh-cat-strip-list .wh-article:hover {
  border-color: #dcdcdc;
  box-shadow: 0 6px 16px rgba(15, 23, 42, 0.08);
  transform: translateY(-1px);
}
.wh-cat-strip-side .wh-article .wh-article-media,
.wh-cat-strip-list .wh-article .wh-article-media {
  border-radius: 6px;
  overflow: hidden;
}

/* Phase 15.2.26 — site-wide sticky bottom banner (dismissable) */
.wh-sticky-bottom {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 80;
  background: #fff;
  border-top: 1px solid #e5e5e5;
  box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.08);
  padding: 12px 56px 12px 16px;
  transform: translateY(0);
  transition: transform .25s ease;
}
.wh-sticky-bottom.is-dismissed { transform: translateY(110%); pointer-events: none; }
.wh-sticky-bottom-inner {
  max-width: 1200px;
  margin: 0 auto;
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 50px;
}
.wh-sticky-bottom-inner img { max-height: 90px; width: auto; }
.wh-sticky-bottom-close {
  position: absolute;
  top: 50%;
  right: 12px;
  transform: translateY(-50%);
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 0;
  background: rgba(0, 0, 0, 0.06);
  color: #333;
  font-size: 24px;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background .15s;
}
.wh-sticky-bottom-close:hover { background: rgba(0, 0, 0, 0.12); }
@media (max-width: 768px) {
  .wh-sticky-bottom { padding: 8px 48px 8px 12px; }
  .wh-sticky-bottom-inner img { max-height: 60px; }
}

/* Inline ad slot between listing articles */
.wh-listing-inline-ad {
  margin: var(--sp-5, 24px) 0;
  display: flex;
  justify-content: center;
}
.wh-listing-inline-ad:empty { display: none; }

/* Phase 15.2.35 — Bureaucracy section: uniform 10-card grid.
   5 cols × 2 rows on desktop, 3 cols on smaller laptops, 2 cols on tablets,
   1 col on phones. All cards the same size — no hero treatment. */
.wh-bureau-grid-10 {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: var(--sp-4, 16px);
}
.wh-bureau-grid-10-item .wh-article {
  height: 100%;
  display: flex;
  flex-direction: column;
}
.wh-bureau-grid-10-item .wh-article .wh-article-media {
  aspect-ratio: 4 / 3;
}
@media (max-width: 1199px) {
  .wh-bureau-grid-10 { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 767px) {
  .wh-bureau-grid-10 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 420px) {
  /* Phase 15.2.55 — same 2-column rule as wh-cat-uni-grid for consistency */
  .wh-bureau-grid-10 { grid-template-columns: repeat(2, 1fr); }
}

/* =========================================================================
   Phase 15.2.39 — Generic category section layouts.
   Admin-configurable via /admin/categories/edit. Five layout styles:
     grid       — uniform cards, N columns
     hero_grid  — 1+ big cards, then grid below
     hero_side  — big card(s) left, sidebar right (used by Politics + ads)
     split      — paired with the next 'split' category (50/50)
     hidden     — not rendered
   ========================================================================= */

/* Background wrappers for sections that need a paper-2/paper-3 bleed */
.wh-section-bg-wrap { padding-block: var(--sp-6, 24px) var(--sp-7, 32px); }

/* Uniform grid — used by 'grid' layout and as the inner grid in hero_grid */
.wh-cat-uni-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--sp-4, 16px);
}
.wh-cat-uni-grid[data-cols="2"] { grid-template-columns: repeat(2, 1fr); }
.wh-cat-uni-grid[data-cols="3"] { grid-template-columns: repeat(3, 1fr); }
.wh-cat-uni-grid[data-cols="4"] { grid-template-columns: repeat(4, 1fr); }
.wh-cat-uni-grid[data-cols="5"] { grid-template-columns: repeat(5, 1fr); }
.wh-cat-uni-item .wh-article {
  height: 100%;
  display: flex;
  flex-direction: column;
}
.wh-cat-uni-item .wh-article .wh-article-media {
  aspect-ratio: 4 / 3;
}
@media (max-width: 1199px) {
  .wh-cat-uni-grid[data-cols="5"] { grid-template-columns: repeat(3, 1fr); }
  .wh-cat-uni-grid[data-cols="4"] { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 767px) {
  .wh-cat-uni-grid { grid-template-columns: repeat(2, 1fr); }
  .wh-cat-uni-grid[data-cols],
  .wh-cat-uni-grid[data-cols="5"],
  .wh-cat-uni-grid[data-cols="4"],
  .wh-cat-uni-grid[data-cols="3"],
  .wh-cat-uni-grid[data-cols="2"] { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 420px) {
  /* Phase 15.2.55 — client requested 2 columns on small phones for all
     category sections (previously single-column stacked). Two columns gives
     a denser scroll, ~2× more headlines visible per screen. */
  .wh-cat-uni-grid,
  .wh-cat-uni-grid[data-cols],
  .wh-cat-uni-grid[data-cols="5"],
  .wh-cat-uni-grid[data-cols="4"],
  .wh-cat-uni-grid[data-cols="3"],
  .wh-cat-uni-grid[data-cols="2"] { grid-template-columns: repeat(2, 1fr); }
  /* Tighter gap on small phones so two cards fit comfortably */
  .wh-cat-uni-grid { gap: 10px; }
}

/* hero_grid layout — large hero(es) on top, grid below */
.wh-cat-hero-grid {
  display: flex;
  flex-direction: column;
  gap: var(--sp-5, 20px);
}
.wh-cat-hero-block {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-4, 16px);
}
.wh-cat-hero-block:has(> :nth-child(2)) {
  grid-template-columns: repeat(2, 1fr);
}
.wh-cat-hero-block:has(> :nth-child(3)) {
  grid-template-columns: repeat(3, 1fr);
}
@media (max-width: 767px) {
  /* Phase 15.2.82 — on mobile a hero section shows the BIG hero full-width on
     top, then the small cards (the rest) below. So the hero block always
     stacks full-width (1 column) regardless of how many heroes there are. */
  .wh-cat-hero-block,
  .wh-cat-hero-block:has(> :nth-child(2)),
  .wh-cat-hero-block:has(> :nth-child(3)) { grid-template-columns: 1fr; }
  .wh-cat-hero-grid { gap: var(--sp-4, 16px); }
  .wh-cat-hero-block { gap: 12px; }
  /* The small cards beneath the hero: 2-up grid on mobile. */
  .wh-cat-hero-rest { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; gap: 12px; }
}
@media (max-width: 420px) {
  .wh-cat-hero-block { gap: 10px; }
}

/* Section eyebrow styling for sections without bespoke color */
.wh-cat-section .wh-section-head { margin-bottom: var(--sp-4, 16px); }

@media (max-width: 991px) {
  .wh-hero { grid-template-columns: 1fr; gap: var(--sp-6); margin-bottom: var(--sp-7); }

  /* Phase 15.2.24 — mobile horizontal carousel (1.3 cards visible) */
  .wh-hero-side {
    flex-direction: row;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    margin: 0 calc(-1 * var(--sp-4, 16px));
    padding: 4px var(--sp-4, 16px) 12px;
    gap: 12px;
  }
  .wh-hero-side::-webkit-scrollbar { display: none; }
  .wh-hero-side .wh-article-row {
    flex: 0 0 76%;
    scroll-snap-align: start;
    min-width: 0;
  }
}
@media (max-width: 575px) {
  .wh-hero-side .wh-article-row { flex: 0 0 82%; }
  .wh-hero-side .wh-article-row .wh-article-media { width: 80px; height: 80px; }
  .wh-hero-side .wh-article-row { grid-template-columns: 80px 1fr; }
}

/* Phase 15.2.22 — hero carousel of featured articles */
.wh-hero-carousel {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-2);
}
.wh-hero-carousel-track {
  position: relative;
}
.wh-hero-carousel-slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  pointer-events: none;
  transition: opacity .45s ease;
}
.wh-hero-carousel-slide.is-active {
  position: relative;
  opacity: 1;
  pointer-events: auto;
}
/* Arrows */
.wh-hero-carousel-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: rgba(0, 0, 0, .55);
  color: #fff;
  border: 0;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 20px;
  z-index: 4;
  transition: background .15s;
}
.wh-hero-carousel-arrow:hover { background: rgba(0, 0, 0, .8); }
.wh-hero-carousel-prev { left: 12px; }
.wh-hero-carousel-next { right: 12px; }

/* Dots */
.wh-hero-carousel-dots {
  position: absolute;
  bottom: 14px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 8px;
  z-index: 4;
}
.wh-hero-carousel-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: rgba(255, 255, 255, .5);
  border: 1px solid rgba(0, 0, 0, .2);
  cursor: pointer;
  padding: 0;
  transition: all .15s;
}
.wh-hero-carousel-dot.is-active {
  background: var(--brand-red, #d70000);
  border-color: var(--brand-red, #d70000);
  transform: scale(1.25);
}
@media (max-width: 480px) {
  .wh-hero-carousel-arrow { width: 36px; height: 36px; font-size: 16px; }
  .wh-hero-carousel-prev { left: 6px; }
  .wh-hero-carousel-next { right: 6px; }
}

/* Category strip (3-up + side list) */
.wh-cat-strip { margin-bottom: var(--sp-9); }
.wh-cat-strip-grid {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
  gap: var(--sp-6);
}
.wh-cat-strip-main {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-5);
}
.wh-cat-strip-main > .wh-article:first-child {
  grid-column: span 2;
}
.wh-cat-strip-side {
  display: flex;
  flex-direction: column;
}
@media (max-width: 991px) {
  .wh-cat-strip-grid { grid-template-columns: 1fr; }
  .wh-cat-strip-main { grid-template-columns: 1fr; }
  .wh-cat-strip-main > .wh-article:first-child { grid-column: auto; }
  /* Phase 15.2.56 — when sidebar collapses below main on mobile, its ad slots
     stacked into full-width banners that ate entire viewport heights. Constrain
     them to behave like the rest of the in-flow ads on mobile. */
  .wh-cat-strip-side .wh-ad-slot {
    max-width: 600px;
    margin-left: auto;
    margin-right: auto;
    /* Phase 15.2.58 — override inline min-height from zone height column */
    min-height: 0 !important;
  }
  .wh-cat-strip-side .wh-ad-slot img {
    max-height: 180px !important;
  }
}
@media (max-width: 575px) {
  .wh-cat-strip-side .wh-ad-slot img {
    max-height: 140px !important;
  }
}

/* Magazine teaser block — full-bleed dark with cover preview */
.wh-mag-teaser {
  background: var(--ink-bg);
  color: #fff;
  border-radius: var(--r-4);
  overflow: hidden;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr);
  align-items: stretch;
  margin-bottom: var(--sp-9);
}
.wh-mag-teaser-cover {
  background: linear-gradient(135deg, #1a1a1a, #2a2a2a);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-8);
  position: relative;
}
.wh-mag-teaser-cover::before {
  content: ''; position: absolute; inset: 0;
  background:
    radial-gradient(circle at 30% 30%, rgba(215,0,0,.12), transparent 60%),
    radial-gradient(circle at 80% 80%, rgba(201,163,65,.08), transparent 60%);
  pointer-events: none;
}
.wh-mag-teaser-cover img {
  max-height: 360px;
  width: auto;
  object-fit: contain;
  box-shadow: var(--shadow-xl), 0 0 0 1px rgba(255,255,255,.06);
  border-radius: var(--r-1);
  position: relative;
  transform: rotate(-2deg);
  transition: transform var(--t-slow);
}
.wh-mag-teaser:hover .wh-mag-teaser-cover img { transform: rotate(0deg) scale(1.02); }
.wh-mag-teaser-cover-fallback {
  width: 240px; height: 320px;
  background: linear-gradient(135deg, var(--brand) 0%, var(--brand-700) 100%);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--f-display);
  font-size: 64px;
  color: #fff;
  border-radius: var(--r-2);
  box-shadow: var(--shadow-xl);
  transform: rotate(-2deg);
  position: relative;
}
.wh-mag-teaser-body {
  padding: clamp(28px, 5vw, 56px);
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.wh-mag-teaser-body .wh-label { color: var(--accent-gold); }
.wh-mag-teaser-body h2 {
  font-family: var(--f-display);
  font-size: clamp(28px, 4vw, 48px);
  color: #fff;
  margin: var(--sp-2) 0 var(--sp-3);
  line-height: 1.1;
}
.wh-mag-teaser-body p {
  color: rgba(255,255,255,.7);
  font-size: var(--fs-md);
  line-height: 1.6;
  margin-bottom: var(--sp-5);
}
.wh-mag-teaser-cta {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  align-self: flex-start;
}
@media (max-width: 767px) {
  .wh-mag-teaser { grid-template-columns: 1fr; }
  .wh-mag-teaser-cover { padding: var(--sp-7); }
  .wh-mag-teaser-cover img { max-height: 280px; }
}

/* Newsletter inline CTA (anywhere on page) */
.wh-cta-newsletter {
  background:
    linear-gradient(135deg, var(--ink) 0%, #2a2a2a 100%);
  color: #fff;
  border-radius: var(--r-4);
  padding: clamp(32px, 5vw, 64px);
  text-align: center;
  position: relative;
  overflow: hidden;
  margin-bottom: var(--sp-9);
}
.wh-cta-newsletter::before {
  content: '';
  position: absolute;
  top: -50%; left: -10%;
  width: 400px; height: 400px;
  background: radial-gradient(circle, rgba(215,0,0,.18) 0%, transparent 70%);
  pointer-events: none;
}
.wh-cta-newsletter > * { position: relative; z-index: 1; }
.wh-cta-newsletter h2 {
  font-family: var(--f-display);
  font-size: clamp(28px, 4vw, 42px);
  color: #fff;
  margin-bottom: var(--sp-3);
}
.wh-cta-newsletter p {
  color: rgba(255,255,255,.7);
  font-size: var(--fs-md);
  max-width: 540px;
  margin: 0 auto var(--sp-5);
}
.wh-cta-newsletter-form {
  display: flex;
  gap: var(--sp-2);
  max-width: 480px;
  margin: 0 auto;
}
.wh-cta-newsletter-form input {
  flex: 1;
  padding: 14px 20px;
  border: 0;
  border-radius: var(--r-full);
  font-size: var(--fs-base);
  font-family: var(--f-ui);
  background: rgba(255,255,255,.08);
  color: #fff;
}
.wh-cta-newsletter-form input::placeholder { color: rgba(255,255,255,.4); }
.wh-cta-newsletter-form input:focus {
  outline: none;
  background: rgba(255,255,255,.12);
  box-shadow: 0 0 0 3px rgba(215,0,0,.3);
}
.wh-cta-newsletter-form button {
  padding: 14px 28px;
  background: var(--brand);
  color: #fff;
  border: 0;
  border-radius: var(--r-full);
  font-weight: 600;
  cursor: pointer;
  transition: all var(--t-fast);
  font-family: var(--f-ui);
  white-space: nowrap;
}
.wh-cta-newsletter-form button:hover { background: var(--brand-700); }
@media (max-width: 575px) {
  .wh-cta-newsletter-form { flex-direction: column; }
}

/* Sidebar widget shell (used in homepage + listing pages) */
.wh-widget {
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
  padding: var(--sp-5);
  margin-bottom: var(--sp-5);
}
.wh-widget-title {
  font-family: var(--f-serif);
  font-size: var(--fs-md);
  font-weight: 700;
  margin: 0 0 var(--sp-4);
  padding-bottom: var(--sp-3);
  border-bottom: 2px solid var(--ink);
  display: flex;
  align-items: center;
  gap: var(--sp-2);
}
.wh-widget-title i { color: var(--brand); }

/* Phase 15.2.55 — enhanced "Latest" widget design + tighter vertical spacing.
   - Tighter padding (16px instead of 20px) so widget doesn't bleed into
     the next section
   - Title row with "All →" link aligned right
   - Mini cards inside the widget get reduced gap so 5 items fit cleanly
   - Subtle hover lift on mini cards inside the latest widget */
.wh-widget--latest {
  padding: 16px;
  margin-bottom: 16px;
}
.wh-widget--latest .wh-widget-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 0 0 12px;
  padding-bottom: 10px;
  border-bottom: 2px solid var(--ink);
}
.wh-widget--latest .wh-widget-header .wh-widget-title {
  margin: 0;
  padding: 0;
  border-bottom: 0;
  font-size: 18px;
}
.wh-widget--latest .wh-widget-link {
  font-size: 12px;
  font-weight: 600;
  color: var(--brand);
  text-transform: uppercase;
  letter-spacing: .04em;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  transition: gap .15s;
}
.wh-widget--latest .wh-widget-link:hover { gap: 6px; }
.wh-widget--latest .wh-widget-link i { font-size: 14px; }
.wh-widget--latest .wh-article-mini {
  margin-bottom: 10px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--line);
  transition: opacity .15s;
}
.wh-widget--latest .wh-article-mini:last-child {
  margin-bottom: 0;
  padding-bottom: 0;
  border-bottom: 0;
}
.wh-widget--latest .wh-article-mini:hover { opacity: .75; }

/* ============================================================================
   §9  ARTICLE DETAIL
============================================================================ */

.wh-article-page {
  padding-block: var(--sp-7) var(--sp-9);
}

/* Hero: title + meta + featured image */
.wh-article-hero {
  max-width: 820px;
  margin: 0 auto var(--sp-7);
  text-align: left;
}
.wh-article-hero .wh-cat-tag {
  margin-bottom: var(--sp-4);
}
.wh-article-hero h1 {
  font-family: var(--f-serif);
  font-size: clamp(28px, 5vw, var(--fs-3xl));
  line-height: 1.15;
  margin-bottom: var(--sp-4);
  letter-spacing: -0.015em;
}
.wh-article-hero .wh-article-summary-lg {
  font-family: var(--f-serif-2);
  font-style: italic;
  font-size: var(--fs-lg);
  line-height: 1.55;
  color: var(--ink-3);
  margin-bottom: var(--sp-5);
  padding-left: var(--sp-4);
  border-left: 3px solid var(--brand);
}
.wh-article-hero .wh-meta {
  font-size: var(--fs-sm);
  padding: var(--sp-4) 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

.wh-article-featured-image {
  max-width: var(--article-col, 1140px);   /* Phase 15.2.85 — match the wider reading column */
  margin: 0 auto var(--sp-7);
  border-radius: var(--r-img, 8px);
  overflow: hidden;
}

/* Phase 15.2.85 — the article reading column is now wider so it fills the
   container area (no big blank gutters between the content and the side rails).
   Headline, image and body all share this width and stay aligned. */
.wh-article-page .wh-container-narrow,
.wh-article-page .wh-article-hero,
.wh-article-page .wh-article-featured-image,
.wh-article-page .wh-article-hero-video {
  max-width: var(--article-col, 1140px);
}
.wh-article-featured-image img { width: 100%; height: auto; display: block; }
/* Phase 15.2.32 — promoted hero video (replaces featured image when the article
   has an embedded video). Responsive 16:9. */
.wh-article-hero-video {
  max-width: 100%;
  margin: 0 auto var(--sp-7);
}
.wh-article-hero-video-wrap {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  border-radius: var(--r-3);
  overflow: hidden;
  background: #000;
}
.wh-article-hero-video-wrap iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}
.wh-article-featured-image-caption {
  font-size: var(--fs-xs);
  color: var(--muted);
  font-style: italic;
  padding: var(--sp-2) var(--sp-2) 0;
  text-align: center;
}

/* Reading column */
.wh-article-layout {
  display: grid;
  grid-template-columns: 1fr;
  max-width: 820px;
  margin: 0 auto;
  gap: var(--sp-7);
}
.wh-article-layout-with-rail {
  max-width: 1200px;
  grid-template-columns: minmax(0, 1fr) 320px;
}
@media (max-width: 991px) {
  .wh-article-layout-with-rail { grid-template-columns: 1fr; }
}

/* Article body typography */
.wh-prose {
  font-family: var(--f-serif);
  font-size: var(--fs-md);
  line-height: 1.75;
  color: var(--ink-2);
}
/* Phase 15.2.85 — drop-cap restored: big drop-cut first letter on the article. */
.wh-prose > p:first-of-type::first-letter {
  font-family: var(--f-display);
  font-size: 4em;
  float: left;
  line-height: .85;
  margin: 4px 12px 0 0;
  color: var(--brand);    /* Phase 15.2.85 — drop-cap in brand red to match the UI */
}
.wh-prose p { margin-bottom: var(--sp-5); }

/* Phase 15.2.85 — centre the "article below" ad slot (was left-aligned). */
.wh-article-below-ad { display: flex; justify-content: center; }
.wh-article-below-ad .wh-ad-slot { margin: 0; }
.wh-prose h2 {
  font-size: var(--fs-2xl);
  margin: var(--sp-7) 0 var(--sp-4);
  letter-spacing: -0.01em;
}
.wh-prose h3 {
  font-size: var(--fs-xl);
  margin: var(--sp-6) 0 var(--sp-3);
}
.wh-prose h4, .wh-prose h5 {
  font-size: var(--fs-lg);
  margin: var(--sp-5) 0 var(--sp-3);
}
.wh-prose img {
  border-radius: var(--r-2);
  margin: var(--sp-5) 0;
  width: 100%;
  height: auto;
}
/* Phase 15.2.31 — embedded video (Quill inserts .ql-video iframe for YouTube).
   Make it responsive 16:9 so it scales on every screen. */
.wh-prose iframe,
.wh-prose .ql-video {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  height: auto;
  min-height: 0;
  border: 0;
  border-radius: var(--r-2);
  margin: var(--sp-5) 0;
}
.wh-prose figure { margin: var(--sp-5) 0; }
.wh-prose figcaption {
  font-size: var(--fs-xs);
  color: var(--muted);
  font-style: italic;
  text-align: center;
  margin-top: var(--sp-2);
}
.wh-prose blockquote {
  border-left: 4px solid var(--brand);
  background: var(--paper-2);
  padding: var(--sp-5) var(--sp-6);
  margin: var(--sp-6) 0;
  font-family: var(--f-serif-2);
  font-size: var(--fs-lg);
  font-style: italic;
  color: var(--ink-2);
  border-radius: 0 var(--r-2) var(--r-2) 0;
}
.wh-prose blockquote p:last-child { margin-bottom: 0; }
.wh-prose ul, .wh-prose ol { margin-bottom: var(--sp-5); padding-left: var(--sp-6); }
.wh-prose li { margin-bottom: var(--sp-2); }
.wh-prose a {
  color: var(--brand);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
.wh-prose a:hover { color: var(--brand-700); }
.wh-prose hr {
  border: 0;
  text-align: center;
  margin: var(--sp-7) 0;
  position: relative;
  height: 1px;
}
.wh-prose hr::after {
  content: '· · ·';
  position: absolute;
  left: 50%; top: -10px;
  transform: translateX(-50%);
  background: var(--paper);
  padding: 0 var(--sp-4);
  color: var(--muted);
  letter-spacing: 0.4em;
  font-size: 18px;
}

/* Phase 15.2.55 — article tag chips, shown above Share */
.wh-article-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  margin: var(--sp-5, 20px) 0 var(--sp-3, 12px);
  padding-top: var(--sp-4, 16px);
  border-top: 1px solid var(--line, #e5e7eb);
}
.wh-article-tags-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--muted, #6b7280);
  margin-right: 6px;
}
.wh-article-tags-label .bi { margin-right: 4px; opacity: .8; }
.wh-article-tag {
  display: inline-flex;
  align-items: center;
  padding: 5px 12px;
  background: #f3f4f6;
  border: 1px solid #e5e7eb;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 500;
  color: #374151;
  text-decoration: none;
  transition: background .15s, color .15s, border-color .15s;
}
.wh-article-tag:hover {
  background: #d70000;
  border-color: #d70000;
  color: #fff;
}

/* Sticky share bar */
.wh-share {
  display: flex;
  gap: var(--sp-2);
  margin: var(--sp-6) 0;
  padding: var(--sp-4) 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
.wh-share-label {
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-weight: 600;
  color: var(--muted);
  align-self: center;
  margin-right: var(--sp-3);
}
/* Phase 15.2.88 — dark-gray circle + white icon (matches the footer social
   icons & the "Your Attention Please" share box). Was a near-white circle that
   looked invisible on the article page. */
.wh-share-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px; height: 36px;
  border-radius: 50%;
  background: #2f3238;
  border: 0;
  color: #fff;
  text-decoration: none;
  transition: all var(--t-fast);
}
.wh-share-btn i { color: #fff; }
.wh-share-btn:hover { background: var(--brand); border-color: var(--brand); color: #fff; transform: translateY(-2px); }

/* Byline block */
.wh-byline {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-5);
  background: var(--paper-2);
  border-radius: var(--r-3);
  margin: var(--sp-7) 0;
}
.wh-byline-avatar {
  width: 64px; height: 64px;
  border-radius: 50%;
  background: var(--paper-3);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--f-display);
  font-size: 28px;
  color: var(--ink);
  flex-shrink: 0;
  overflow: hidden;
}
.wh-byline-avatar img { width: 100%; height: 100%; object-fit: cover; }
.wh-byline-name {
  font-family: var(--f-serif);
  font-size: var(--fs-md);
  font-weight: 700;
  margin: 0 0 4px;
}
.wh-byline-name a { color: var(--ink); }
.wh-byline-name a:hover { color: var(--brand); }
.wh-byline-bio {
  font-size: var(--fs-sm);
  color: var(--muted);
  margin: 0;
}

/* Related articles */
.wh-related {
  margin-top: var(--sp-9);
  padding-top: var(--sp-7);
  border-top: 2px solid var(--ink);
}
.wh-related h2 {
  font-family: var(--f-display);
  font-size: var(--fs-2xl);
  margin-bottom: var(--sp-5);
}

/* Comments */
.wh-comments { margin-top: var(--sp-9); padding-top: var(--sp-7); border-top: 1px solid var(--line); }
.wh-comments-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: var(--sp-5);
}
.wh-comments-head h2 { font-family: var(--f-serif); font-size: var(--fs-xl); margin: 0; }
.wh-comment {
  display: flex;
  gap: var(--sp-3);
  padding: var(--sp-4) 0;
  border-bottom: 1px solid var(--line);
}
.wh-comment-avatar {
  width: 40px; height: 40px;
  border-radius: 50%;
  background: var(--paper-3);
  display: flex; align-items: center; justify-content: center;
  font-weight: 600;
  font-size: var(--fs-sm);
  color: var(--ink);
  flex-shrink: 0;
}
.wh-comment-body { flex: 1; min-width: 0; }
.wh-comment-meta { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-xs); color: var(--muted); margin-bottom: var(--sp-1); }
.wh-comment-author { font-weight: 600; color: var(--ink-2); }
.wh-comment-text { font-size: var(--fs-sm); color: var(--ink-2); line-height: 1.6; }

/* ============================================================================
   §10  LISTING + SEARCH
============================================================================ */

.wh-listing-head {
  background: var(--paper-2);
  padding: var(--sp-8) 0;
  margin-bottom: var(--sp-7);
  border-bottom: 1px solid var(--line);
}
.wh-listing-head h1 {
  font-family: var(--f-display);
  font-size: clamp(32px, 6vw, 64px);
  margin-bottom: var(--sp-3);
  line-height: 1;
  letter-spacing: -0.02em;
}
.wh-listing-head .wh-meta { font-size: var(--fs-sm); }

.wh-listing-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: var(--sp-7);
}
@media (max-width: 991px) {
  .wh-listing-grid { grid-template-columns: 1fr; }
}

.wh-listing-items {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-6);
}
/* Phase 15.2.35 — uniform 2-column grid, all cards the same size. The old
   first-child grid-column:span 2 + wh-article-lg hero treatment is gone. */
@media (max-width: 575px) {
  /* Phase 15.2.61 — keep 2 columns on phones (was 1 col). User requested
     all category news pages show 2 articles per row on mobile so the page
     reads denser and ~2× more headlines are visible per screen. Tighter
     gap so two cards fit on narrow phones (320-420px). */
  .wh-listing-items {
    grid-template-columns: repeat(2, 1fr);
    gap: var(--sp-4, 16px);
  }
}
@media (max-width: 420px) {
  .wh-listing-items { gap: 10px; }
}

.wh-empty {
  text-align: center;
  padding: var(--sp-9) var(--sp-5);
  color: var(--muted);
}
.wh-empty i { font-size: 48px; color: var(--muted-2); margin-bottom: var(--sp-3); display: block; }
.wh-empty h3 { font-family: var(--f-serif); margin-bottom: var(--sp-2); color: var(--ink-2); }

/* Search-specific */
.wh-search-box {
  display: flex;
  gap: var(--sp-2);
  max-width: 640px;
  width: 100%;
  margin: 0 auto var(--sp-5);
}
.wh-search-box input {
  flex: 1 1 auto;
  min-width: 0;          /* allow the input to shrink so the row never overflows */
  padding: 16px 20px;
  font-size: var(--fs-md);
  background: var(--paper);
  border: 2px solid var(--ink);
  border-radius: var(--r-full);
  font-family: var(--f-ui);
}
.wh-search-box button { flex: 0 0 auto; white-space: nowrap; }
@media (max-width: 575px) {
  .wh-search-box input { padding: 12px 16px; font-size: var(--fs-base); }
  .wh-search-box button { padding: 12px 16px; }
  .wh-search-box button .bi { margin: 0; }
}
.wh-search-box input:focus {
  outline: none;
  box-shadow: 0 0 0 3px rgba(15,15,15,.08);
}
.wh-search-box button {
  padding: 16px 28px;
  background: var(--ink);
  color: #fff;
  border: 0;
  border-radius: var(--r-full);
  font-weight: 600;
  cursor: pointer;
  font-family: var(--f-ui);
}
.wh-search-box button:hover { background: var(--brand); }

/* ============================================================================
   §11  MAGAZINE
============================================================================ */

/* Magazine landing hero */
.wh-mag-hero {
  background:
    radial-gradient(circle at 20% 20%, rgba(215,0,0,.08), transparent 50%),
    radial-gradient(circle at 80% 70%, rgba(201,163,65,.07), transparent 50%),
    var(--ink-bg);
  color: #fff;
  padding: var(--sp-10) 0 var(--sp-9);
  position: relative;
  overflow: hidden;
}
.wh-mag-hero-inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--sp-8);
  align-items: center;
}
.wh-mag-hero-eyebrow {
  display: inline-block;
  font-size: var(--fs-xs);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent-gold);
  margin-bottom: var(--sp-3);
  font-weight: 600;
}
.wh-mag-hero h1 {
  font-family: var(--f-display);
  font-size: clamp(36px, 6vw, 72px);
  line-height: 1;
  color: #fff;
  margin-bottom: var(--sp-4);
  letter-spacing: -0.02em;
}
.wh-mag-hero p {
  font-family: var(--f-serif-2);
  font-size: var(--fs-lg);
  line-height: 1.6;
  color: rgba(255,255,255,.75);
  margin-bottom: var(--sp-5);
  max-width: 540px;
}
.wh-mag-hero-actions { display: flex; gap: var(--sp-3); flex-wrap: wrap; }

.wh-mag-hero-stack {
  position: relative;
  height: 460px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.wh-mag-hero-stack img {
  position: absolute;
  width: 220px;
  height: auto;
  border-radius: var(--r-1);
  box-shadow: var(--shadow-xl);
  transition: transform var(--t-slow);
}
.wh-mag-hero-stack img:nth-child(1) { transform: translateX(-120px) translateY(20px) rotate(-8deg); z-index: 1; }
.wh-mag-hero-stack img:nth-child(2) { transform: translateY(-10px); z-index: 3; }
.wh-mag-hero-stack img:nth-child(3) { transform: translateX(120px) translateY(20px) rotate(8deg); z-index: 1; }
.wh-mag-hero-stack:hover img:nth-child(1) { transform: translateX(-140px) translateY(20px) rotate(-12deg); }
.wh-mag-hero-stack:hover img:nth-child(3) { transform: translateX(140px) translateY(20px) rotate(12deg); }
@media (max-width: 991px) {
  .wh-mag-hero-inner { grid-template-columns: 1fr; gap: var(--sp-6); }
  .wh-mag-hero-stack { height: 340px; }
  .wh-mag-hero-stack img { width: 160px; }
}

/* Phase 15.2.86 — cover-first magazine hero (pg 11): covers are the centrepiece,
   a big SUBSCRIBE NOW pill, then an "Already subscribed? Log in" line. */
.wh-mag-hero--cover { padding: var(--sp-8) 0 var(--sp-8); }
.wh-mag-hero-cover-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
.wh-mag-hero-cover-inner .wh-mag-hero-eyebrow { margin-bottom: var(--sp-2); }
.wh-mag-hero-cover-inner h1 {
  font-family: var(--f-display);
  font-size: clamp(32px, 5vw, 58px);
  line-height: 1.04;
  color: #fff;
  letter-spacing: -0.02em;
  margin: 0 0 var(--sp-4);
}
/* Constrain the coverflow so the prev/next arrows hug the covers instead of
   flying out to the container edges (cover-first hero is full-width). */
.wh-mag-hero--cover .wh-mag3d--hero { margin: 0 auto; width: min(560px, 92vw); max-width: 560px; }
.wh-mag-hero--cover .wh-mag3d-prev { left: 6px; }
.wh-mag-hero--cover .wh-mag3d-next { right: 6px; }
.wh-mag-hero--cover .wh-mag3d-arrow {
  background: rgba(255,255,255,.12);
  border-color: rgba(255,255,255,.35);
  color: #fff;
  backdrop-filter: blur(2px);
}
.wh-mag-hero--cover .wh-mag3d-arrow:hover {
  background: var(--brand, #d70000);
  border-color: var(--brand, #d70000);
  color: #fff;
}
.wh-mag-hero-cta {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-3);
  margin-top: var(--sp-4);
}
.wh-mag-subscribe-now {
  font-size: 19px;
  font-weight: 800;
  letter-spacing: .03em;
  text-transform: uppercase;
  padding: 15px 46px;
  border-radius: 999px;
  box-shadow: 0 14px 34px rgba(215,0,0,.45);
  animation: whMagPulse 2.6s ease-in-out infinite;
  transition: transform .18s ease, box-shadow .18s ease;
}
.wh-mag-subscribe-now:hover { transform: translateY(-2px); box-shadow: 0 18px 44px rgba(215,0,0,.6); }
@keyframes whMagPulse {
  0%, 100% { box-shadow: 0 14px 34px rgba(215,0,0,.42); }
  50%      { box-shadow: 0 16px 48px rgba(215,0,0,.72); }
}
.wh-mag-hero-login { color: rgba(255,255,255,.72); font-size: var(--fs-sm); margin: 0; }
.wh-mag-hero-login a { color: #fff; font-weight: 600; text-decoration: underline; text-underline-offset: 3px; }
#choose-language { scroll-margin-top: 88px; }
@media (prefers-reduced-motion: reduce) { .wh-mag-subscribe-now { animation: none; } }
@media (max-width: 991px) {
  .wh-mag-hero--cover { padding: var(--sp-6) 0; }
  .wh-mag-subscribe-now { font-size: 17px; padding: 13px 36px; }
}

/* Phase 15.2.86 — edition chip on the plan page (shows the chosen EN/HI funnel). */
.wh-edition-chip {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  justify-content: center;
  margin: calc(-1 * var(--sp-5)) auto var(--sp-6);
  font-size: var(--fs-sm);
}
.wh-edition-chip > span {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--brand, #d70000);
  color: #fff;
  font-weight: 700;
  padding: 6px 16px;
  border-radius: 999px;
}
.wh-edition-chip a { color: var(--ink-3); text-decoration: underline; text-underline-offset: 3px; }

/* Features grid (6-up icons + text) */
.wh-mag-features {
  background: var(--paper-2);
  padding: var(--sp-9) 0;
}
.wh-mag-features-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--sp-5);
}
.wh-mag-feature {
  display: flex;
  gap: var(--sp-3);
  align-items: start;
}
.wh-mag-feature-icon {
  width: 44px; height: 44px;
  border-radius: var(--r-2);
  background: var(--paper);
  border: 1px solid var(--line);
  display: flex; align-items: center; justify-content: center;
  color: var(--brand);
  flex-shrink: 0;
  font-size: 20px;
}
.wh-mag-feature-text {
  font-family: var(--f-serif);
  font-size: var(--fs-md);
  line-height: 1.5;
  color: var(--ink-2);
  margin: 6px 0 0;
}
@media (max-width: 767px) {
  .wh-mag-features-grid { grid-template-columns: 1fr; }
}

/* Language picker section */
.wh-mag-lang-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-6);
}
.wh-mag-lang-card {
  padding: var(--sp-7);
  border-radius: var(--r-3);
  background: var(--paper);
  border: 1px solid var(--line);
  text-align: center;
  transition: all var(--t-normal);
}
.wh-mag-lang-card:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
  border-color: var(--ink);
}
.wh-mag-lang-card-title {
  font-family: var(--f-display);
  font-size: var(--fs-2xl);
  margin-bottom: var(--sp-2);
}
@media (max-width: 575px) {
  .wh-mag-lang-grid { grid-template-columns: 1fr; }
}

/* Issue cover card */
.wh-issue-card {
  display: block;
  text-decoration: none;
  color: inherit;
  transition: all var(--t-normal);
}
.wh-issue-card-cover {
  aspect-ratio: 3 / 4;
  background: var(--paper-3);
  overflow: hidden;
  border-radius: var(--r-2);
  margin-bottom: var(--sp-3);
  position: relative;
  box-shadow: var(--shadow-sm);
  transition: all var(--t-normal);
}
.wh-issue-card:hover .wh-issue-card-cover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
}
.wh-issue-card-cover img {
  width: 100%; height: 100%;
  object-fit: cover;
}
.wh-issue-card-cover-fallback {
  width: 100%; height: 100%;
  background: linear-gradient(135deg, var(--brand), var(--brand-700));
  display: flex; align-items: center; justify-content: center;
  color: #fff;
  font-family: var(--f-display);
  font-size: 48px;
}
.wh-issue-card-title {
  font-family: var(--f-serif);
  font-size: var(--fs-md);
  font-weight: 700;
  margin: 0 0 4px;
  color: var(--ink);
  line-height: 1.3;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.wh-issue-card-meta {
  font-size: var(--fs-xs);
  color: var(--muted);
  display: flex;
  align-items: center;
  gap: 6px;
}
.wh-issue-card-badge {
  font-size: 10px;
  padding: 2px 6px;
  border-radius: 2px;
  background: var(--paper-3);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-weight: 700;
}
.wh-issue-card-badge-premium {
  background: var(--accent-gold);
  color: var(--ink);
}

/* FAQ accordion */
.wh-mag-faq {
  max-width: 720px;
  margin: 0 auto;
}
.wh-faq-item {
  border-bottom: 1px solid var(--line);
}
.wh-faq-item summary {
  list-style: none;
  cursor: pointer;
  padding: var(--sp-4) 0;
  font-family: var(--f-serif);
  font-size: var(--fs-md);
  font-weight: 700;
  color: var(--ink);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--sp-3);
}
.wh-faq-item summary::-webkit-details-marker { display: none; }
.wh-faq-item summary::after {
  content: '+';
  font-size: 24px;
  color: var(--brand);
  transition: transform var(--t-fast);
  font-family: var(--f-ui);
  font-weight: 400;
  flex-shrink: 0;
}
.wh-faq-item[open] summary::after { content: '−'; }
.wh-faq-body {
  padding: 0 0 var(--sp-4) 0;
  color: var(--ink-3);
  font-size: var(--fs-md);
  line-height: 1.7;
  font-family: var(--f-serif);
}

/* Package strip card */
.wh-package-card {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
  padding: var(--sp-6);
  text-align: center;
  transition: all var(--t-normal);
  display: flex;
  flex-direction: column;
  position: relative;
  height: 100%;
}
.wh-package-card:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
}
.wh-package-card.is-featured {
  border-color: var(--brand);
  background: var(--paper);
  box-shadow: var(--shadow-brand);
}
.wh-package-card-badge {
  position: absolute;
  top: -12px;
  left: 50%; transform: translateX(-50%);
  background: var(--brand);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 4px 12px;
  border-radius: var(--r-full);
}
.wh-package-card-name {
  font-family: var(--f-serif);
  font-size: var(--fs-lg);
  font-weight: 700;
  margin-bottom: var(--sp-3);
}
.wh-package-card-price {
  font-family: var(--f-display);
  font-size: 44px;
  line-height: 1;
  color: var(--ink);
  margin-bottom: var(--sp-2);
}
.wh-package-card-price small {
  font-family: var(--f-ui);
  font-size: var(--fs-sm);
  color: var(--muted);
  font-weight: 400;
}
.wh-package-card-duration {
  font-size: var(--fs-sm);
  color: var(--muted);
  margin-bottom: var(--sp-5);
}
.wh-package-card ul {
  list-style: none;
  padding: 0;
  margin: 0 0 var(--sp-5);
  font-size: var(--fs-sm);
  text-align: left;
}
.wh-package-card ul li {
  padding: var(--sp-2) 0;
  border-bottom: 1px solid var(--line-2);
  display: flex;
  align-items: start;
  gap: var(--sp-2);
}
.wh-package-card ul li::before {
  content: '✓';
  color: var(--brand);
  font-weight: 700;
  flex-shrink: 0;
}

/* ============================================================================
   §12  AUTHORS / WEB STORIES
============================================================================ */

/* Author card on directory */
.wh-author-card {
  display: block;
  padding: var(--sp-6);
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
  text-align: center;
  text-decoration: none;
  color: inherit;
  transition: all var(--t-normal);
  height: 100%;
}
.wh-author-card:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
  border-color: var(--ink);
}
.wh-author-avatar {
  width: 110px; height: 110px;
  margin: 0 auto var(--sp-4);
  border-radius: 50%;
  overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, var(--brand-100), var(--paper-3));
  color: var(--brand);
  font-family: var(--f-display);
  font-size: 44px;
  border: 4px solid var(--paper);
  box-shadow: var(--shadow-md);
}
.wh-author-avatar img { width: 100%; height: 100%; object-fit: cover; }
.wh-author-name {
  font-family: var(--f-serif);
  font-size: var(--fs-lg);
  font-weight: 700;
  margin: 0 0 var(--sp-2);
  color: var(--ink);
}
.wh-author-bio {
  font-size: var(--fs-sm);
  color: var(--ink-3);
  line-height: 1.6;
  margin-bottom: var(--sp-4);
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  min-height: 4.8em;
}
.wh-author-stats {
  display: flex;
  justify-content: center;
  gap: var(--sp-4);
  font-size: var(--fs-xs);
  color: var(--muted);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--line);
}
.wh-author-stat-num { font-weight: 700; color: var(--ink-2); }

/* Author profile hero */
.wh-author-hero {
  background:
    radial-gradient(circle at 30% 20%, rgba(215,0,0,.06), transparent 50%),
    var(--paper-2);
  padding: var(--sp-9) 0;
  margin-bottom: var(--sp-7);
  border-bottom: 1px solid var(--line);
}
.wh-author-hero-inner {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--sp-6);
  align-items: center;
  max-width: 920px;
  margin: 0 auto;
}
.wh-author-hero-avatar {
  width: 160px; height: 160px;
  border-radius: 50%;
  overflow: hidden;
  background: linear-gradient(135deg, var(--brand-100), var(--paper-3));
  display: flex; align-items: center; justify-content: center;
  font-family: var(--f-display);
  font-size: 64px;
  color: var(--brand);
  border: 5px solid var(--paper);
  box-shadow: var(--shadow-lg);
  flex-shrink: 0;
}
.wh-author-hero-avatar img { width: 100%; height: 100%; object-fit: cover; }
.wh-author-hero-name {
  font-family: var(--f-display);
  font-size: clamp(36px, 5vw, 56px);
  line-height: 1;
  margin-bottom: var(--sp-3);
  letter-spacing: -0.01em;
}
.wh-author-hero-bio {
  font-family: var(--f-serif-2);
  font-style: italic;
  font-size: var(--fs-md);
  line-height: 1.6;
  color: var(--ink-3);
  max-width: 560px;
  margin: 0 0 var(--sp-4);
}
.wh-author-hero-meta {
  display: flex;
  gap: var(--sp-4);
  flex-wrap: wrap;
  font-size: var(--fs-sm);
  color: var(--muted);
}
.wh-author-hero-meta a {
  color: var(--ink-2);
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-weight: 500;
}
.wh-author-hero-meta a:hover { color: var(--brand); }
@media (max-width: 575px) {
  .wh-author-hero-inner { grid-template-columns: 1fr; text-align: center; }
  .wh-author-hero-avatar { margin: 0 auto; }
  .wh-author-hero-meta { justify-content: center; }
}

/* Web Stories grid (3:4 covers) */
.wh-story-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--sp-4);
}
@media (max-width: 991px) { .wh-story-grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 575px) { .wh-story-grid { grid-template-columns: repeat(2, 1fr); } }
.wh-story-card {
  display: block;
  text-decoration: none;
  color: inherit;
  aspect-ratio: 3 / 4;
  border-radius: var(--r-3);
  overflow: hidden;
  position: relative;
  background: var(--ink-bg);
  transition: transform var(--t-normal);
}
.wh-story-card:hover { transform: translateY(-4px) scale(1.02); }
.wh-story-card img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform var(--t-slow);
}
.wh-story-card:hover img { transform: scale(1.05); }
.wh-story-card-fallback {
  position: absolute; inset: 0;
  background: linear-gradient(135deg, var(--brand), var(--brand-700));
  display: flex; align-items: center; justify-content: center;
  color: #fff;
  font-family: var(--f-display);
  font-size: 80px;
}
.wh-story-card-gradient {
  position: absolute; left: 0; right: 0; bottom: 0;
  height: 60%;
  background: linear-gradient(180deg, transparent 0%, rgba(0,0,0,.8) 100%);
}
.wh-story-card-body {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: var(--sp-4);
  color: #fff;
}
.wh-story-card-title {
  font-family: var(--f-serif);
  font-size: var(--fs-md);
  font-weight: 700;
  line-height: 1.3;
  margin: 0;
  color: #fff !important;   /* Phase 15.2.77 — was inheriting the global dark
                               heading colour; force white over the cover. */
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-shadow: 0 1px 4px rgba(0,0,0,.5);
}
.wh-story-card-icon {
  position: absolute;
  top: var(--sp-3); right: var(--sp-3);
  background: rgba(255,255,255,.2);
  backdrop-filter: blur(8px);
  width: 32px; height: 32px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  color: #fff;
  font-size: 14px;
}

/* ============================================================================
   §13  AUTH PAGES
============================================================================ */

.wh-auth-shell {
  min-height: 70vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-8) var(--sp-4);
  background:
    radial-gradient(circle at 20% 20%, rgba(215,0,0,.04), transparent 40%),
    radial-gradient(circle at 80% 80%, rgba(201,163,65,.03), transparent 40%),
    var(--paper-2);
}

.wh-auth-card {
  width: 100%;
  max-width: 980px;
  background: var(--paper);
  border-radius: var(--r-4);
  overflow: hidden;
  box-shadow: var(--shadow-xl);
  display: grid;
  grid-template-columns: 1fr 1fr;
}
.wh-auth-card-compact {
  max-width: 460px;
  grid-template-columns: 1fr;
}
@media (max-width: 767px) {
  .wh-auth-card { grid-template-columns: 1fr; max-width: 460px; }
}

/* Left brand pane (only shown in 2-col layout) */
.wh-auth-brand-pane {
  background: linear-gradient(135deg, var(--ink-bg) 0%, #2a0a0a 50%, var(--brand-700) 100%);
  color: #fff;
  padding: clamp(28px, 5vw, 56px);
  display: flex;
  flex-direction: column;
  position: relative;
  overflow: hidden;
}
.wh-auth-brand-pane::before {
  content: '';
  position: absolute;
  top: -20%; right: -20%;
  width: 400px; height: 400px;
  background: radial-gradient(circle, rgba(255,255,255,.05) 0%, transparent 70%);
  pointer-events: none;
}
.wh-auth-brand-pane > * { position: relative; z-index: 1; }
.wh-auth-brand-eyebrow {
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--accent-gold);
  font-weight: 600;
  margin-bottom: var(--sp-3);
}
.wh-auth-brand-pane h2 {
  font-family: var(--f-ui);        /* Phase 15.2.84 (D) — normal font (was Abril display) */
  font-weight: 700;
  font-size: clamp(28px, 4vw, 40px);
  color: #fff;
  margin-bottom: var(--sp-3);
  line-height: 1.15;
}
.wh-auth-brand-pane p {
  font-family: var(--f-serif-2);
  font-style: italic;
  font-size: var(--fs-md);
  line-height: 1.6;
  color: rgba(255,255,255,.8);
  margin-bottom: var(--sp-5);
}
.wh-auth-brand-points {
  list-style: none;
  padding: 0;
  margin: var(--sp-4) 0 0;
  font-family: var(--f-ui);
  font-size: var(--fs-sm);
}
.wh-auth-brand-points li {
  padding: var(--sp-2) 0;
  display: flex;
  align-items: start;
  gap: var(--sp-2);
  color: rgba(255,255,255,.85);
}
.wh-auth-brand-points li::before {
  content: '✓';
  color: var(--accent-gold);
  font-weight: 700;
  flex-shrink: 0;
}
.wh-auth-brand-bottom {
  margin-top: auto;
  padding-top: var(--sp-5);
  font-size: var(--fs-xs);
  color: rgba(255,255,255,.5);
}

/* Right form pane */
.wh-auth-form-pane {
  padding: clamp(28px, 4vw, 48px);
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.wh-auth-icon {
  width: 56px; height: 56px;
  border-radius: var(--r-3);
  background: var(--brand-100);
  color: var(--brand);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 24px;
  margin-bottom: var(--sp-3);
}
.wh-auth-form-pane h1 {
  font-family: var(--f-ui);        /* Phase 15.2.84 (D) — normal font (was Abril display) */
  font-weight: 700;
  font-size: var(--fs-2xl);
  margin-bottom: var(--sp-2);
}
.wh-auth-form-pane .lead {
  color: var(--muted);
  font-size: var(--fs-sm);
  margin-bottom: var(--sp-6);
}

.wh-auth-form .wh-form-group { margin-bottom: var(--sp-4); }

.wh-auth-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: var(--fs-sm);
  margin-bottom: var(--sp-4);
}
.wh-auth-row a { color: var(--ink-2); }
.wh-auth-row a:hover { color: var(--brand); }

.wh-auth-divider {
  text-align: center;
  margin: var(--sp-5) 0;
  position: relative;
  color: var(--muted);
  font-size: var(--fs-xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.wh-auth-divider::before,
.wh-auth-divider::after {
  content: '';
  position: absolute;
  top: 50%;
  width: calc(50% - 30px);
  height: 1px;
  background: var(--line);
}
.wh-auth-divider::before { left: 0; }
.wh-auth-divider::after  { right: 0; }

.wh-auth-social {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}
.wh-auth-social-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  padding: 12px 16px;
  border: 1px solid var(--line);
  border-radius: var(--r-2);
  background: var(--paper);
  color: var(--ink-2);
  font-size: var(--fs-sm);
  font-weight: 500;
  text-decoration: none;
  transition: all var(--t-fast);
}
.wh-auth-social-btn:hover { border-color: var(--ink); color: var(--ink); }
.wh-auth-social-btn img { width: 18px; height: 18px; }

.wh-auth-foot {
  text-align: center;
  font-size: var(--fs-sm);
  color: var(--muted);
  margin-top: var(--sp-5);
}
.wh-auth-foot a { color: var(--brand); font-weight: 600; }
.wh-auth-foot a:hover { text-decoration: underline; }

/* Result/status pages (verify_email, password reset confirmation) */
.wh-auth-status-icon {
  width: 80px; height: 80px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 40px;
  margin: 0 auto var(--sp-4);
  color: #fff;
}
.wh-auth-status-icon-success { background: var(--success); }
.wh-auth-status-icon-danger  { background: var(--danger); }
.wh-auth-status-icon-info    { background: var(--info); }

/* Password strength meter (signup) */
.wh-pw-meter {
  height: 4px;
  background: var(--line);
  border-radius: 2px;
  overflow: hidden;
  margin-top: var(--sp-1);
}
.wh-pw-meter-bar {
  height: 100%;
  width: 0%;
  background: var(--danger);
  transition: all var(--t-fast);
}
.wh-pw-meter-bar.is-weak    { width: 25%; background: var(--danger); }
.wh-pw-meter-bar.is-fair    { width: 50%; background: var(--warning); }
.wh-pw-meter-bar.is-good    { width: 75%; background: #10b981; }
.wh-pw-meter-bar.is-strong  { width: 100%; background: var(--success); }
.wh-pw-meter-label {
  font-size: var(--fs-xs);
  color: var(--muted);
  margin-top: var(--sp-1);
}

/* ============================================================================
   §14  ACCOUNT DASHBOARD
============================================================================ */

.wh-account-layout {
  display: grid;
  grid-template-columns: 240px minmax(0, 1fr);
  gap: var(--sp-7);
  padding-block: var(--sp-7);
}
@media (max-width: 991px) {
  .wh-account-layout { grid-template-columns: 1fr; gap: var(--sp-5); }
}

/* Sidebar nav */
.wh-account-side {
  position: sticky;
  top: var(--sp-5);
  align-self: start;
}
@media (max-width: 991px) {
  .wh-account-side { position: static; }
}
.wh-account-side-card {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
  padding: var(--sp-5);
  margin-bottom: var(--sp-4);
}
.wh-account-user {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding-bottom: var(--sp-4);
  margin-bottom: var(--sp-4);
  border-bottom: 1px solid var(--line);
}
.wh-account-user-avatar {
  width: 44px; height: 44px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--brand), var(--brand-700));
  color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--f-display);
  font-size: 18px;
  flex-shrink: 0;
}
.wh-account-user-name {
  font-family: var(--f-serif);
  font-weight: 700;
  font-size: var(--fs-sm);
  margin: 0;
  color: var(--ink);
  line-height: 1.2;
  word-break: break-word;
}
.wh-account-user-email {
  font-size: var(--fs-xs);
  color: var(--muted);
  margin: 2px 0 0;
  word-break: break-all;
}

.wh-account-nav {
  list-style: none;
  padding: 0;
  margin: 0;
}
.wh-account-nav li { margin: 0; }
.wh-account-nav a {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: 10px 12px;
  border-radius: var(--r-2);
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--ink-2);
  text-decoration: none;
  margin-bottom: 2px;
  transition: all var(--t-fast);
}
.wh-account-nav a:hover { background: var(--paper-2); color: var(--ink); }
.wh-account-nav a.is-active {
  background: var(--ink);
  color: #fff;
}
.wh-account-nav a.is-active i { color: var(--accent-gold); }
.wh-account-nav i { width: 16px; text-align: center; flex-shrink: 0; }
.wh-account-nav-sep {
  border-top: 1px solid var(--line);
  margin: var(--sp-3) -8px;
  padding-top: var(--sp-3);
  font-size: var(--fs-xxs);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  padding-left: 12px;
}

/* Main content */
.wh-account-main {
  min-width: 0;  /* prevent grid blowout */
}
.wh-account-head {
  padding-bottom: var(--sp-5);
  margin-bottom: var(--sp-6);
  border-bottom: 1px solid var(--line);
}
.wh-account-head h1 {
  font-family: var(--f-display);
  font-size: clamp(28px, 4vw, 40px);
  margin-bottom: var(--sp-2);
}
.wh-account-head .lead {
  color: var(--muted);
  font-size: var(--fs-md);
  margin: 0;
}

/* KPI cards (dashboard) */
.wh-kpi-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--sp-4);
  margin-bottom: var(--sp-6);
}
.wh-kpi {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
  padding: var(--sp-5);
  position: relative;
  overflow: hidden;
}
.wh-kpi::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 3px;
  background: var(--brand);
}
.wh-kpi-icon {
  width: 40px; height: 40px;
  border-radius: var(--r-2);
  background: var(--brand-100);
  color: var(--brand);
  display: flex; align-items: center; justify-content: center;
  margin-bottom: var(--sp-3);
  font-size: 18px;
}
.wh-kpi-value {
  font-family: var(--f-display);
  font-size: var(--fs-2xl);
  line-height: 1;
  color: var(--ink);
  margin-bottom: 4px;
}
.wh-kpi-label {
  font-size: var(--fs-xs);
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 600;
}
.wh-kpi a {
  color: var(--ink);
}

/* Data table */
.wh-table-wrap {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
  overflow: hidden;
}
.wh-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-sm);
}
.wh-table thead {
  background: var(--paper-2);
  border-bottom: 1px solid var(--line);
}
.wh-table th {
  text-align: left;
  padding: var(--sp-3) var(--sp-4);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 600;
  color: var(--muted);
}
.wh-table td {
  padding: var(--sp-4);
  border-bottom: 1px solid var(--line);
  color: var(--ink-2);
  vertical-align: top;
}
.wh-table tr:last-child td { border-bottom: 0; }
.wh-table tr:hover td { background: var(--paper-2); }
.wh-table-empty {
  padding: var(--sp-8) var(--sp-5);
  text-align: center;
  color: var(--muted);
}
.wh-table-empty i { font-size: 36px; color: var(--muted-2); display: block; margin-bottom: var(--sp-2); }

/* Section card on dashboard */
.wh-account-section {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
  padding: var(--sp-5);
  margin-bottom: var(--sp-5);
}
.wh-account-section-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-bottom: var(--sp-3);
  margin-bottom: var(--sp-4);
  border-bottom: 1px solid var(--line);
}
.wh-account-section-head h2 {
  font-family: var(--f-serif);
  font-size: var(--fs-lg);
  margin: 0;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
}
.wh-account-section-head h2 i { color: var(--brand); }

/* Address card */
.wh-address-card {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
  padding: var(--sp-5);
  position: relative;
}
.wh-address-card.is-default {
  border-color: var(--ink);
}
.wh-address-card.is-default::before {
  content: 'Default';
  position: absolute;
  top: 12px; right: 12px;
  background: var(--ink);
  color: #fff;
  font-size: 10px;
  padding: 3px 8px;
  border-radius: var(--r-1);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.wh-address-card-name {
  font-family: var(--f-serif);
  font-size: var(--fs-md);
  font-weight: 700;
  margin: 0 0 var(--sp-2);
}
.wh-address-card-lines {
  font-size: var(--fs-sm);
  color: var(--ink-3);
  line-height: 1.6;
  margin-bottom: var(--sp-3);
}
.wh-address-card-actions {
  display: flex;
  gap: var(--sp-2);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--line);
}

/* Invoice/order detail page */
.wh-invoice-page {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
  padding: clamp(28px, 4vw, 56px);
  max-width: 840px;
  margin: 0 auto;
}
.wh-invoice-head {
  display: flex;
  justify-content: space-between;
  align-items: start;
  padding-bottom: var(--sp-5);
  margin-bottom: var(--sp-5);
  border-bottom: 2px solid var(--ink);
}
.wh-invoice-brand {
  font-family: var(--f-display);
  font-size: var(--fs-xl);
  color: var(--ink);
  margin-bottom: var(--sp-1);
}
.wh-invoice-meta {
  font-size: var(--fs-sm);
  color: var(--ink-3);
}
.wh-invoice-meta dt {
  display: inline;
  font-weight: 600;
  color: var(--muted);
}
.wh-invoice-meta dd {
  display: inline;
  margin: 0 0 0 6px;
}
.wh-invoice-section {
  margin-bottom: var(--sp-5);
}
.wh-invoice-section-label {
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--muted);
  font-weight: 600;
  margin-bottom: var(--sp-2);
}
.wh-invoice-total {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding-top: var(--sp-4);
  border-top: 2px solid var(--ink);
  margin-top: var(--sp-4);
}
.wh-invoice-total-label {
  font-size: var(--fs-md);
  font-weight: 600;
  color: var(--muted);
}
.wh-invoice-total-value {
  font-family: var(--f-display);
  font-size: var(--fs-2xl);
  color: var(--ink);
}

@media print {
  .wh-account-side, .wh-back-top, .wh-ticker, .wh-header, .wh-footer { display: none !important; }
  .wh-account-layout { grid-template-columns: 1fr; }
  .wh-invoice-page { border: 0; padding: 0; max-width: 100%; }
}

/* ============================================================================
   §15  COMMERCE (subscriptions, order, checkout)
============================================================================ */

.wh-pricing-hero {
  background:
    radial-gradient(circle at 20% 20%, rgba(215,0,0,.05), transparent 50%),
    radial-gradient(circle at 80% 80%, rgba(201,163,65,.04), transparent 50%),
    var(--paper-2);
  padding: var(--sp-10) 0 var(--sp-8);
  text-align: center;
  border-bottom: 1px solid var(--line);
  margin-bottom: var(--sp-8);
}
.wh-pricing-hero h1 {
  font-family: var(--f-display);
  font-size: clamp(36px, 6vw, 64px);
  line-height: 1.05;
  margin-bottom: var(--sp-3);
  letter-spacing: -0.02em;
}
.wh-pricing-hero p {
  color: var(--ink-3);
  font-family: var(--f-serif-2);
  font-style: italic;
  font-size: var(--fs-lg);
  max-width: 540px;
  margin: 0 auto var(--sp-5);
  line-height: 1.6;
}

/* Order summary panel */
.wh-order-page {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: var(--sp-6);
  max-width: 980px;
  margin: 0 auto;
}
@media (max-width: 767px) {
  .wh-order-page { grid-template-columns: 1fr; }
}
.wh-order-status-banner {
  padding: var(--sp-5);
  border-radius: var(--r-3);
  margin-bottom: var(--sp-5);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  flex-wrap: wrap;
}
.wh-order-status-banner-pending {
  background: var(--warning-bg);
  border-left: 4px solid var(--warning);
}
.wh-order-status-banner-paid {
  background: var(--success-bg);
  border-left: 4px solid var(--success);
}
.wh-order-status-banner-cancelled {
  background: var(--paper-2);
  border-left: 4px solid var(--muted);
}
.wh-order-status-banner-title {
  font-family: var(--f-serif);
  font-weight: 700;
  font-size: var(--fs-md);
  margin: 0 0 4px;
}
.wh-order-status-banner-text {
  font-size: var(--fs-sm);
  color: var(--ink-3);
  margin: 0;
}

.wh-order-summary-list dt {
  font-size: var(--fs-xs);
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 600;
  margin-top: var(--sp-3);
  margin-bottom: 2px;
}
.wh-order-summary-list dt:first-child { margin-top: 0; }
.wh-order-summary-list dd {
  margin: 0;
  font-size: var(--fs-md);
  color: var(--ink);
  font-weight: 500;
}

/* Checkout page */
.wh-checkout-page {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 380px;
  gap: var(--sp-6);
  max-width: 1080px;
  margin: 0 auto;
  padding-block: var(--sp-8);
}
@media (max-width: 991px) {
  .wh-checkout-page { grid-template-columns: 1fr; }
}

.wh-checkout-panel {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
  padding: clamp(24px, 4vw, 40px);
}
.wh-checkout-panel-title {
  font-family: var(--f-display);
  font-size: var(--fs-xl);
  margin-bottom: var(--sp-3);
  padding-bottom: var(--sp-3);
  border-bottom: 2px solid var(--ink);
}

/* Gateway choice card */
.wh-gw-option {
  display: block;
  border: 2px solid var(--line);
  border-radius: var(--r-2);
  padding: var(--sp-4);
  margin-bottom: var(--sp-3);
  cursor: pointer;
  transition: all var(--t-fast);
  background: var(--paper);
}
.wh-gw-option:hover { border-color: var(--ink); }
.wh-gw-option.is-active { border-color: var(--brand); background: var(--brand-50); }
.wh-gw-option-title {
  font-family: var(--f-serif);
  font-weight: 700;
  font-size: var(--fs-md);
  margin: 0 0 4px;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
}
.wh-gw-option-title-pill {
  font-size: 10px;
  font-weight: 700;
  padding: 2px 8px;
  background: var(--ink);
  color: #fff;
  border-radius: var(--r-1);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.wh-gw-option-sub {
  font-size: var(--fs-xs);
  color: var(--muted);
  margin: 0;
}
.wh-gw-option-icon {
  width: 32px; height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  border-radius: var(--r-1);
}

.wh-checkout-secure {
  font-size: var(--fs-xs);
  color: var(--muted);
  text-align: center;
  margin-top: var(--sp-4);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}
.wh-checkout-secure i { color: var(--success); }

/* Summary side card */
.wh-checkout-summary {
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
  padding: var(--sp-5);
  position: sticky;
  top: var(--sp-5);
}
.wh-checkout-summary h3 {
  font-family: var(--f-serif);
  font-size: var(--fs-md);
  margin-bottom: var(--sp-4);
  padding-bottom: var(--sp-3);
  border-bottom: 1px solid var(--line);
}
.wh-checkout-summary-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: var(--sp-2) 0;
  font-size: var(--fs-sm);
}
.wh-checkout-summary-row strong { color: var(--ink); }
.wh-checkout-summary-row-muted { color: var(--muted); }
.wh-checkout-summary-total {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-top: var(--sp-3);
  padding-top: var(--sp-3);
  border-top: 2px solid var(--ink);
}
.wh-checkout-summary-total-label {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.wh-checkout-summary-total-value {
  font-family: var(--f-display);
  font-size: var(--fs-2xl);
  color: var(--brand);
}

/* ============================================================================
   §16  STATIC + CMS + ERRORS
============================================================================ */

/* Contact page */
.wh-contact-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  gap: var(--sp-7);
}
@media (max-width: 767px) { .wh-contact-grid { grid-template-columns: 1fr; } }

.wh-contact-info {
  background: var(--ink-bg);
  color: #fff;
  border-radius: var(--r-3);
  padding: var(--sp-6);
  position: sticky;
  top: var(--sp-5);
}
.wh-contact-info h2 {
  font-family: var(--f-display);
  font-size: var(--fs-xl);
  color: #fff;
  margin: 0 0 var(--sp-4);
}
.wh-contact-info-item {
  display: flex;
  align-items: start;
  gap: var(--sp-3);
  padding: var(--sp-3) 0;
  border-bottom: 1px solid rgba(255,255,255,.1);
  font-size: var(--fs-sm);
}
.wh-contact-info-item:last-of-type { border-bottom: 0; }
.wh-contact-info-icon {
  width: 36px; height: 36px;
  border-radius: 50%;
  background: rgba(255,255,255,.08);
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  color: var(--accent-gold);
}
.wh-contact-info-label {
  font-size: var(--fs-xxs);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: rgba(255,255,255,.5);
  margin: 0 0 2px;
  font-weight: 600;
}
.wh-contact-info-value {
  color: #fff;
  margin: 0;
  word-break: break-word;
}
.wh-contact-info-value a { color: #fff; }
.wh-contact-info-value a:hover { color: var(--accent-gold); }

/* CMS page (about, privacy, terms) */
.wh-cms-page {
  max-width: 760px;
  margin: 0 auto;
  padding-block: var(--sp-7) var(--sp-9);
}
.wh-cms-page > .wh-prose h2:first-child { margin-top: var(--sp-4); }

/* Newsletter status pages (confirm / unsubscribe) */
.wh-status-shell {
  min-height: 55vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-7) var(--sp-4);
}
.wh-status-card {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-4);
  padding: clamp(32px, 5vw, 56px);
  text-align: center;
  max-width: 480px;
  width: 100%;
  box-shadow: var(--shadow-md);
}
.wh-status-card-icon {
  width: 80px; height: 80px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 40px;
  margin: 0 auto var(--sp-4);
  color: #fff;
}
.wh-status-card-icon-success { background: var(--success); }
.wh-status-card-icon-danger  { background: var(--danger); }
.wh-status-card-icon-muted   { background: var(--muted); }
.wh-status-card-icon-info    { background: var(--info); }
.wh-status-card h1 {
  font-family: var(--f-display);
  font-size: clamp(24px, 4vw, 36px);
  margin-bottom: var(--sp-3);
}
.wh-status-card p {
  color: var(--ink-3);
  font-size: var(--fs-md);
  line-height: 1.6;
  margin-bottom: var(--sp-5);
}

/* Error page (404/500/419) */
.wh-error-shell {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-5);
  background:
    radial-gradient(circle at 20% 20%, rgba(215,0,0,.04), transparent 50%),
    radial-gradient(circle at 80% 80%, rgba(201,163,65,.03), transparent 50%),
    var(--paper);
}
.wh-error-content {
  text-align: center;
  max-width: 560px;
}
.wh-error-code {
  font-family: var(--f-display);
  font-size: clamp(96px, 22vw, 200px);
  line-height: 1;
  letter-spacing: -0.04em;
  color: var(--brand);
  margin: 0 0 var(--sp-3);
  position: relative;
  display: inline-block;
}
.wh-error-code::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 80px;
  height: 4px;
  background: var(--ink);
}
.wh-error-title {
  font-family: var(--f-serif);
  font-size: clamp(22px, 4vw, 32px);
  margin: var(--sp-5) 0 var(--sp-3);
  letter-spacing: -0.01em;
}
.wh-error-text {
  color: var(--ink-3);
  font-family: var(--f-serif-2);
  font-style: italic;
  font-size: var(--fs-md);
  line-height: 1.6;
  margin: 0 auto var(--sp-6);
  max-width: 420px;
}
.wh-error-actions {
  display: flex;
  justify-content: center;
  gap: var(--sp-2);
  flex-wrap: wrap;
}

/* ============================================================================
   §17  ADS + SKELETON LOADERS (Phase 15.2)
============================================================================ */

/* ---- Ad slot (inline, sidebar, sticky) ----
   The slot is empty by default and gets filled by ads.js once an ad is
   served from /api/ads/serve. If no ad is available, the slot collapses
   so it doesn't leave a visible gap. */
.wh-ad-slot {
  position: relative;
  display: block;
  text-align: center;
  margin: var(--sp-4) 0;
  background: transparent;
  min-height: 0;
}
.wh-ad-slot:empty { display: none; }       /* collapse if no ad served */
.wh-ad-slot a {
  display: inline-block;
  text-decoration: none;
  color: inherit;
  max-width: 100%;
  line-height: 0;
}
.wh-ad-slot img {
  max-width: 100%;
  height: auto;
  display: inline-block;
  border-radius: var(--r-2, 8px);
}
.wh-ad-slot::before {
  content: 'Ads';
  display: block;
  font-size: 7.5px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted, #9ca3af);
  margin-bottom: var(--sp-2, 8px);
  opacity: 0.6;
}
.wh-ad-slot:empty::before { display: none; }

/* Phase 15.2.56 — RESPONSIVE AD IMAGE SIZING.
   The user's mobile screenshot showed every in-flow ad slot rendering as
   a 400-500px tall banner (full screen height each), making the homepage
   feel like an ad gallery instead of a news site. Each ad creative was
   displayed at its native pixel dimensions, which is too big.

   Hard caps:
   - Desktop: max-height 250px (leaderboard-ish proportions)
   - Tablet (≤991px): max-height 200px
   - Phone (≤575px): max-height 140px (small enough that 1-2 fit per screen)
   - Tiny phone (≤420px): max-height 120px

   We use object-fit: contain so the creative isn't stretched/cropped — it
   shrinks to fit the cap while preserving its aspect ratio. */
.wh-ad-slot img {
  max-height: 250px;
  object-fit: contain;
}
@media (max-width: 991px) {
  .wh-ad-slot img { max-height: 200px; }
}
@media (max-width: 575px) {
  .wh-ad-slot img { max-height: 140px; }
  .wh-ad-slot { margin: 12px 0; }
}
@media (max-width: 420px) {
  /* Phase 15.2.62 — user requested: bump in-flow ad img cap to 480px on
     tiny phones so creatives (especially the sidebar `listing_sidebar`
     skyscraper-shaped ads on /politics, /bureaucracy etc.) read at a
     usable size. The v15.2.58 defensive `min-height: 0 !important` on
     ad slot containers is still in force, so the SLOT only grows to fit
     the image — no blank space below shrunken images.

     SCOPE: this is the GLOBAL .wh-ad-slot img rule, so it applies to
     every in-flow ad zone (listing_sidebar, article_top, article_middle,
     article_below, home_after_politics, home_after_corporate, etc.).
     Side-rail ads (.wh-ad-rail .wh-ad-slot img) and slider banner ads
     (.wh-slider-banner-ad .wh-ad-slot img !important) have their own
     more-specific rules and are unaffected. */
  .wh-ad-slot img { max-height: 480px; }
  .wh-ad-slot { margin: 10px 0; }
}

/* Sidebar variant — sticky inside the sidebar column */
.wh-ad-slot-sidebar {
  position: sticky;
  top: 96px;
  min-height: 250px;
}

/* Sticky bottom banner */
.wh-ad-sticky-bottom {
  position: fixed;
  inset: auto 0 0 0;
  background: rgba(255, 255, 255, 0.98);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  border-top: 1px solid var(--line, #e5e7eb);
  padding: 12px 16px;
  z-index: 90;
  display: none;
  align-items: center;
  justify-content: center;
  gap: 16px;
  box-shadow: 0 -4px 20px rgba(0,0,0,0.05);
}
.wh-ad-sticky-bottom.is-visible { display: flex; }
.wh-ad-sticky-bottom img { max-height: 90px; width: auto; }
.wh-ad-sticky-bottom-close {
  position: absolute;
  top: 6px; right: 10px;
  background: rgba(0,0,0,0.6);
  color: #fff;
  border: 0;
  width: 24px; height: 24px;
  border-radius: 50%;
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.wh-ad-sticky-bottom-close:hover { background: var(--brand, #d70000); }

/* Popup ad — modal overlay */
.wh-ad-popup-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.7);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  z-index: 200;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 20px;
  animation: wh-fade-in 0.25s ease;
}
.wh-ad-popup-backdrop.is-visible { display: flex; }
.wh-ad-popup {
  position: relative;
  background: #fff;
  border-radius: var(--r-3, 12px);
  max-width: 600px;
  width: 100%;
  max-height: 90vh;
  overflow: hidden;
  box-shadow: 0 24px 64px rgba(0,0,0,0.4);
  animation: wh-pop-in 0.3s ease;
}
.wh-ad-popup-close {
  position: absolute;
  top: 12px; right: 12px;
  background: rgba(0,0,0,0.6);
  color: #fff;
  border: 0;
  width: 32px; height: 32px;
  border-radius: 50%;
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  z-index: 2;
}
.wh-ad-popup-close:hover { background: var(--brand, #d70000); }
.wh-ad-popup a { display: block; line-height: 0; }
.wh-ad-popup img { width: 100%; height: auto; display: block; }
.wh-ad-popup-label {
  position: absolute;
  bottom: 12px; left: 12px;
  background: rgba(0,0,0,0.6);
  color: #fff;
  font-size: 7.5px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 4px 8px;
  border-radius: 4px;
}

@keyframes wh-fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes wh-pop-in {
  from { opacity: 0; transform: scale(0.92) translateY(20px); }
  to   { opacity: 1; transform: scale(1) translateY(0); }
}

/* ---- Skeleton loaders ----
   Drop on any element to get an animated shimmer placeholder. Common
   patterns: wrap images in a parent with wh-skel + an inner <img>;
   wh-skel-img sets the aspect ratio via inline style or modifier class. */
.wh-skel {
  position: relative;
  background: linear-gradient(
    90deg,
    rgba(0,0,0,0.04) 0%,
    rgba(0,0,0,0.08) 50%,
    rgba(0,0,0,0.04) 100%
  );
  background-size: 200% 100%;
  animation: wh-skel-shimmer 1.4s ease-in-out infinite;
  border-radius: var(--r-1, 4px);
  display: block;
  overflow: hidden;
}
.wh-skel-text   { height: 1em; margin-bottom: 0.4em; }
.wh-skel-text-lg { height: 1.4em; margin-bottom: 0.5em; }
.wh-skel-line { height: 12px; margin-bottom: 8px; }
.wh-skel-line-short { width: 60%; }
.wh-skel-img-16-9 { aspect-ratio: 16 / 9; width: 100%; }
.wh-skel-img-3-4  { aspect-ratio: 3 / 4;  width: 100%; }
.wh-skel-img-1-1  { aspect-ratio: 1 / 1;  width: 100%; }
.wh-skel-img-4-3  { aspect-ratio: 4 / 3;  width: 100%; }

@keyframes wh-skel-shimmer {
  0%   { background-position: 100% 0; }
  100% { background-position: -100% 0; }
}

/* Image with built-in skeleton — wraps the img in a parent that shows
   shimmer until [data-loaded] flips. ads.js / lazy-image.js does the flip. */
.wh-img-wrap {
  position: relative;
  display: block;
  background: rgba(0,0,0,0.04);
  overflow: hidden;
  border-radius: var(--r-1, 4px);
}
.wh-img-wrap::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    90deg,
    rgba(0,0,0,0.04) 0%,
    rgba(0,0,0,0.10) 50%,
    rgba(0,0,0,0.04) 100%
  );
  background-size: 200% 100%;
  animation: wh-skel-shimmer 1.4s ease-in-out infinite;
  z-index: 0;
}
.wh-img-wrap.is-loaded::before { display: none; }
.wh-img-wrap img {
  position: relative;
  z-index: 1;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 0.35s ease;
}
.wh-img-wrap.is-loaded img { opacity: 1; }

/* Aspect-ratio modifiers — picks the right placeholder shape */
.wh-img-wrap-16-9 { aspect-ratio: 16 / 9; }
.wh-img-wrap-3-4  { aspect-ratio: 3 / 4; }
.wh-img-wrap-1-1  { aspect-ratio: 1 / 1; }
.wh-img-wrap-4-3  { aspect-ratio: 4 / 3; }

/* ============================================================================
   §17.1  AD CAROUSEL + LIST (Phase 15.2.4)
============================================================================ */

/* Carousel — slides stack absolutely; only .is-active is visible */
.wh-ad-carousel {
  position: relative;
  width: 100%;
  min-height: 90px;
  overflow: hidden;
  border-radius: var(--r-2, 8px);
}
.wh-ad-carousel-slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 0.5s ease;
  pointer-events: none;
  text-align: center;
  line-height: 0;
}
.wh-ad-carousel-slide.is-active {
  position: relative;
  opacity: 1;
  pointer-events: auto;
}
.wh-ad-carousel-slide img {
  max-width: 100%;
  height: auto;
  display: inline-block;
}
.wh-ad-carousel-dots {
  position: absolute;
  bottom: 8px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 6px;
  z-index: 2;
}
.wh-ad-carousel-dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  border: 0;
  background: rgba(0,0,0,0.25);
  cursor: pointer;
  padding: 0;
  transition: background 0.2s;
}
.wh-ad-carousel-dot.is-active { background: var(--brand, #d70000); width: 24px; border-radius: 4px; }
.wh-ad-carousel-dot:hover { background: rgba(0,0,0,0.5); }

/* List — stacked vertically with gaps */
.wh-ad-list {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3, 12px);
  width: 100%;
}
.wh-ad-list-item {
  text-align: center;
  border-radius: var(--r-2, 8px);
  overflow: hidden;
  background: rgba(0,0,0,0.02);
  padding: 8px;
}
.wh-ad-list-item a { display: inline-block; line-height: 0; }
.wh-ad-list-item img { max-width: 100%; height: auto; }

/* ==========================================================================
 * Phase 15.2.11 — Responsive ad layouts
 *
 * 1. List zones (display_style='list') get smart column counts based on
 *    how many creatives are served:
 *      - 2 ads  → 2 columns (always, even on mobile)
 *      - 3 ads  → 1 col mobile, 3 cols tablet+
 *      - 4 ads  → 2×2 grid on mobile, 4 cols on desktop
 *      - 1 ad   → full width
 *
 * 2. Side-rail zones — fixed columns on left/right of viewport that only
 *    appear on screens wide enough that they don't overlap the content
 *    container. Below 1320px wide, they hide. Templates declare them via:
 *      <?= render_zones_at('home', 'left_rail') ?>
 *      <?= render_zones_at('home', 'right_rail') ?>
 * ==========================================================================
 */

/* === Responsive multi-creative grid === */
.wh-ad-list {
  display: grid;
  gap: var(--sp-3, 12px);
  width: 100%;
}
.wh-ad-list[data-count="1"] { grid-template-columns: 1fr; }
.wh-ad-list[data-count="2"] { grid-template-columns: 1fr 1fr; }
.wh-ad-list[data-count="3"] { grid-template-columns: 1fr; }
.wh-ad-list[data-count="4"] { grid-template-columns: 1fr 1fr; }
.wh-ad-list[data-count="5"],
.wh-ad-list[data-count="6"] { grid-template-columns: 1fr 1fr; }

@media (min-width: 768px) {
  .wh-ad-list[data-count="3"] { grid-template-columns: repeat(3, 1fr); }
  .wh-ad-list[data-count="4"] { grid-template-columns: repeat(4, 1fr); }
  .wh-ad-list[data-count="5"] { grid-template-columns: repeat(5, 1fr); }
  .wh-ad-list[data-count="6"] { grid-template-columns: repeat(6, 1fr); }
}

/* === Side-rail ad slots === */
/* Phase 15.2.57 — DUAL-MODE responsive side rails.
   The user wants ads visible on every screen size:
     - Desktop XL (≥1900px): rails fixed in side gutters, 200px wide
       (proper skyscraper proportions, not tiny 160px thumbnails)
     - Everything smaller: rails appear as an in-flow 2-column row at the
       very top of the page, ABOVE the hero/slider. Both rails sit
       side-by-side so they're prominent without dominating vertical space.

   Why ≥1900px for fixed mode? A 1440px container + 2×200px rails +
   2×24px gutters = 1888px minimum. Round up to 1900 for safety margin.

   The wrap div (.wh-ad-rails-wrap) lets us flex the two rails as a row
   on mobile while letting each be position:fixed on desktop XL.
   The wrap is harmless on desktop XL because position:fixed children
   escape their parent's box model. */

.wh-ad-rails-wrap {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  width: 100%;
  max-width: var(--container-max, 1440px);
  margin: 12px auto 16px;
  padding-inline: var(--container-pad, 16px);
}

/* Phase 15.2.65 — side-rail ads only make sense in the wide desktop gutters
   (≥1900px, fixed mode below). On phones/tablets/laptops they were rendering
   as two giant skyscraper banners stacked ABOVE the hero, eating the whole
   first screen with what read as blank space. Hide them entirely below the
   fixed-gutter breakpoint — the after-header carousel + in-content ad slots
   still serve ads on those widths. */
@media (max-width: 1899px) {
  .wh-ad-rails-wrap { display: none !important; }
}

.wh-ad-rail {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* In-flow rail slots (mobile + laptop default). Cap height so each ad
   stays banner-ish, not a wall of vertical real estate. */
.wh-ad-rail .wh-ad-slot {
  margin: 0;
  width: 100%;
  /* Phase 15.2.58 — defensive: zones set with skyscraper height (e.g. 600)
     in the DB inject inline `min-height: 600px` via render_one_zone_inline().
     We dropped that for server-served slots, but if any legacy code path
     still emits it, this override prevents the rail column from reserving
     huge blank space below a smaller responsive image. */
  min-height: 0 !important;
}
.wh-ad-rail .wh-ad-slot img {
  width: 100%;
  height: auto;
  max-height: 200px;
  object-fit: contain;
  display: block;
  margin: 0 auto;
}

/* Collapse if a rail has no creative — empty slot + empty rail */
.wh-ad-rail .wh-ad-slot:empty { display: none; }
.wh-ad-rail:empty { display: none; }
/* If BOTH rails are empty, collapse the wrap so we don't show a gap */
.wh-ad-rails-wrap:has(.wh-ad-rail-left:empty):has(.wh-ad-rail-right:empty) {
  display: none;
}

/* Tablet/phone: tighter spacing and image cap */
@media (max-width: 991px) {
  .wh-ad-rails-wrap { gap: 10px; margin: 10px auto 12px; }
  .wh-ad-rail .wh-ad-slot img { max-height: 160px; }
}
@media (max-width: 575px) {
  .wh-ad-rails-wrap { gap: 8px; margin: 8px auto 10px; }
  /* Phase 15.2.59 — user requested: bump mobile rail ad img cap to 480px
     so creatives (especially tall skyscraper-shaped ads) read at a usable
     size on phones. The defensive `min-height: 0 !important` on the slot
     container is still in place from v15.2.58, so even though the IMAGE
     can now be up to 480px tall, the SLOT only grows to fit the image —
     it doesn't reserve any extra blank space below it. */
  .wh-ad-rail .wh-ad-slot img { max-height: 480px; }
}
/* Very tiny phones (<360px): stack to single column since 2 ads would be
   too cramped at ~150px each */
@media (max-width: 359px) {
  .wh-ad-rails-wrap { grid-template-columns: 1fr; }
  .wh-ad-rail .wh-ad-slot img { max-height: 150px; }
}

/* === Desktop XL (≥1900px) === Fixed-position rails in side gutters.
   The wrap div becomes a no-op shell; each rail breaks out via
   position:fixed and the wrap's grid layout doesn't apply because we
   override display on the rails themselves. */
@media (min-width: 1900px) {
  /* Wrap stops being a grid — its children are fixed-positioned out */
  .wh-ad-rails-wrap {
    display: block;
    max-width: none;
    margin: 0;
    padding: 0;
    /* Don't take any vertical space */
    height: 0;
    overflow: visible;
  }
  .wh-ad-rail {
    position: fixed;
    top: 210px;            /* below utility + brand + nav + ticker */
    width: 200px;
    /* Phase 15.2.66 — anchor both rails to the viewport CENTRE (left:50%) and
       push them out by half the container width + a 16px gap. Because the
       centred .wh-container ALSO centres on 50%, the rails stay perfectly
       symmetric with the content — and unlike the old 100vw math this is
       immune to the vertical scrollbar (which made the right gap larger than
       the left). --rail-cw matches the live container width per breakpoint. */
    --rail-cw: 1440px;
    left: 50%;
    gap: 16px;
    z-index: 30;
    max-height: calc(100vh - 240px);
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: rgba(0,0,0,0.15) transparent;
    transition: opacity .25s ease, visibility 0s linear .25s;
    opacity: 1;
    visibility: visible;
  }
  .wh-ad-rail.is-hidden-by-footer {
    opacity: 0;
    visibility: hidden;
    transition: opacity .25s ease, visibility 0s linear .25s;
    pointer-events: none;
  }
  .wh-ad-rail::-webkit-scrollbar { width: 4px; }
  .wh-ad-rail::-webkit-scrollbar-thumb { background: rgba(0,0,0,0.15); border-radius: 4px; }
  /* Symmetric, scrollbar-proof placement: rail sits just outside the centred
     container (container half-width + 16px gap + its own 200px width). */
  .wh-ad-rail-left  { transform: translateX(calc(-1 * (var(--rail-cw) / 2 + 16px + 200px))); }
  .wh-ad-rail-right { transform: translateX(calc(var(--rail-cw) / 2 + 16px)); }
  /* Desktop rails: allow taller images (skyscraper proportions) */
  .wh-ad-rail .wh-ad-slot {
    min-height: 200px;
  }
  .wh-ad-rail .wh-ad-slot img {
    max-height: 600px;       /* full skyscraper height OK in side gutter */
  }
}

@media (min-width: 2000px) {
  /* At 2000+ the container grows to 1520; match the rail offset reference. */
  .wh-ad-rail { --rail-cw: 1520px; }
}

/* === Better in-flow sidebar slots (for article/category sidebar) === */
.wh-ad-slot-sidebar {
  position: sticky;
  top: 96px;
  margin-bottom: var(--sp-4, 16px);
}
@media (max-width: 991px) {
  .wh-ad-slot-sidebar { position: static; }
}

/* ==========================================================================
 * Phase 15.2.64 — Homepage refinements
 *   1. After-header carousel ad band
 *   2. Centered Bureaucracy section
 *   3. Latest widget spacing cleanup
 * ========================================================================== */

/* 1. After-header carousel ad band -------------------------------------- */
.wh-after-header-ad {
  margin: var(--sp-4, 16px) 0 var(--sp-2, 8px);
}
/* Phase 15.2.74 — fill the full container width (override the inline native
   1200px zone cap) so this band matches every other full-width ad band. */
.wh-after-header-ad .wh-ad-slot {
  margin: 0;
  width: 100%;
  max-width: 100% !important;
}
.wh-after-header-ad .wh-ad-slot a { display: block; width: 100%; }
.wh-after-header-ad .wh-ad-carousel,
.wh-after-header-ad .wh-ad-slot img {
  width: 100% !important;
  max-width: 100% !important;
  border-radius: var(--r-3, 12px);
}
.wh-after-header-ad .wh-ad-carousel-slide img {
  max-height: 200px;
  object-fit: contain;
}
/* Collapse the whole band (incl. its margins) when no creative is served */
.wh-after-header-ad:has(.wh-ad-slot:empty) { display: none; }
@media (max-width: 575px) {
  .wh-after-header-ad .wh-ad-carousel-slide img { max-height: 130px; }
}
/* Phase 15.3 — hide the ad-carousel indicator dots on MOBILE only (the slides
   still auto-rotate; dots stay on desktop). Requested: cleaner mobile band. */
@media (max-width: 991px) {
  .wh-ad-carousel-dots { display: none !important; }
}

/* 2. Centered Bureaucracy section --------------------------------------- */
/* The section header (label + title + "View all") stacks and centers, and the
   card grid centers its items so an under-filled final row is balanced rather
   than stuck to the left edge. */
.wh-cat-section--centered .wh-section-head {
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--sp-2, 8px);
}
.wh-cat-section--centered .wh-section-head > div { width: 100%; }
/* Phase 15.2.72 — HONOR the admin "Desktop columns" number exactly.
   The old rule forced grid-template-columns:auto-fit, which ignored the
   configured column count entirely (packing as many ~200px cards as the
   viewport allowed → e.g. 7 across) and left a ragged blank tail on the last
   row. Switch to flexbox: each item is sized to give exactly N per row from the
   data-cols value, and justify-content:center keeps an under-filled last row
   centred (no one-sided blank). */
.wh-cat-section--centered .wh-cat-uni-grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--sp-4, 16px);
  max-width: 100%;
}
.wh-cat-section--centered .wh-cat-uni-grid > .wh-cat-uni-item {
  flex: 0 1 auto;
  width: calc((100% - 3 * var(--sp-4, 16px)) / 4); /* default = 4 columns */
}
.wh-cat-section--centered .wh-cat-uni-grid[data-cols="2"] > .wh-cat-uni-item { width: calc((100% - 1 * var(--sp-4, 16px)) / 2); }
.wh-cat-section--centered .wh-cat-uni-grid[data-cols="3"] > .wh-cat-uni-item { width: calc((100% - 2 * var(--sp-4, 16px)) / 3); }
.wh-cat-section--centered .wh-cat-uni-grid[data-cols="4"] > .wh-cat-uni-item { width: calc((100% - 3 * var(--sp-4, 16px)) / 4); }
.wh-cat-section--centered .wh-cat-uni-grid[data-cols="5"] > .wh-cat-uni-item { width: calc((100% - 4 * var(--sp-4, 16px)) / 5); }
/* Tablet: 4/5-column configs fold to 3 across (matches the grid breakpoints). */
@media (max-width: 1199px) {
  .wh-cat-section--centered .wh-cat-uni-grid[data-cols="4"] > .wh-cat-uni-item,
  .wh-cat-section--centered .wh-cat-uni-grid[data-cols="5"] > .wh-cat-uni-item {
    width: calc((100% - 2 * var(--sp-4, 16px)) / 3);
  }
}

/* Phase 15.2.66 — Bureaucracy on mobile: 2-column grid with the FIRST story
   shown big (full width). Scoped to the Bureaucracy section only. */
@media (max-width: 767px) {
  .wh-cat-section[data-cat="bureaucracy"] .wh-cat-uni-grid {
    /* Phase 15.2.72 — the centered variant is flexbox on desktop; on mobile
       switch back to a 2-col grid so the first-card-spans-both rule works. */
    display: grid !important;
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
    gap: 12px;
  }
  .wh-cat-section--centered .wh-cat-uni-grid > .wh-cat-uni-item { width: auto !important; }
  /* Phase 15.2.73 — the "first card spans both columns" treatment must apply
     ONLY to the plain uniform grid (Large=0). When Large>=1 the big cards live
     in .wh-cat-hero-block, so the small grid (.wh-cat-hero-rest) must keep all
     its cards equal — don't blow up its first card. */
  .wh-cat-section[data-cat="bureaucracy"] .wh-cat-uni-grid:not(.wh-cat-hero-rest) .wh-cat-uni-item:first-child {
    grid-column: 1 / -1;
  }
  .wh-cat-section[data-cat="bureaucracy"] .wh-cat-uni-grid:not(.wh-cat-hero-rest) .wh-cat-uni-item:first-child .wh-article-media {
    aspect-ratio: 16 / 9;
  }
  .wh-cat-section[data-cat="bureaucracy"] .wh-cat-uni-grid:not(.wh-cat-hero-rest) .wh-cat-uni-item:first-child .wh-article-title {
    font-size: clamp(18px, 5vw, 22px);
  }
  /* the big card shows its summary (md cards hide it by default) */
  .wh-cat-section[data-cat="bureaucracy"] .wh-cat-uni-grid:not(.wh-cat-hero-rest) .wh-cat-uni-item:first-child .wh-article-summary {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
}

/* 3. Latest widget — remove the trailing gap -----------------------------
   When the sidebar ad zones below/above the Latest widget serve nothing they
   collapse, but the widget itself still carried a 16px bottom margin that left
   an uneven gap at the foot of the Politics sidebar. Zero it out so the sidebar
   ends flush with the main column. */
.wh-cat-strip-side > .wh-widget--latest:last-child { margin-bottom: 0; }
.wh-cat-strip-side .wh-ad-slot:empty { display: none; margin: 0; }
.wh-cat-strip-side { gap: var(--sp-4, 16px); }
.wh-cat-strip-side .wh-widget--latest { margin-bottom: 0; }

/* Phase 15.2.64 — "Read the magazine now" CTA on the order success page --- */
.wh-order-read-cta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--sp-4, 16px);
  max-width: 840px;
  margin: 0 auto var(--sp-5, 24px);
  padding: var(--sp-4, 18px) var(--sp-5, 22px);
  border-radius: var(--r-3, 14px);
  background: linear-gradient(120deg, var(--ink-bg, #14110f) 0%, #2a2320 100%);
  border: 1px solid rgba(255,255,255,.08);
  box-shadow: 0 10px 30px rgba(0,0,0,.18);
}
.wh-order-read-cta-text {
  display: flex;
  align-items: center;
  gap: var(--sp-3, 14px);
  color: #fff;
}
.wh-order-read-cta-text > i {
  font-size: 30px;
  color: var(--accent-gold, #d4af37);
  flex-shrink: 0;
}
.wh-order-read-cta-text strong {
  display: block;
  font-family: var(--f-serif, Georgia, serif);
  font-size: var(--fs-md, 18px);
  line-height: 1.2;
}
.wh-order-read-cta-text span {
  font-size: var(--fs-sm, 13.5px);
  color: rgba(255,255,255,.7);
}
@media (max-width: 575px) {
  .wh-order-read-cta { flex-direction: column; align-items: stretch; text-align: left; }
  .wh-order-read-cta .wh-btn { justify-content: center; }
}

/* Phase 15.2.64 — password show/hide eye toggle ------------------------- */
.wh-pw-wrap { position: relative; display: block; }
/* the .wh-input-group is already position:relative */
.wh-pw-wrap > .wh-input,
.wh-input-group.wh-has-pw-toggle > .wh-input {
  padding-right: 46px;            /* keep typed text clear of the eye button */
}
.wh-pw-toggle {
  position: absolute;
  right: 6px;
  top: 50%;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 0;
  border-radius: var(--r-2, 8px);
  background: transparent;
  color: var(--muted, #6b7280);
  cursor: pointer;
  font-size: 17px;
  line-height: 1;
  transition: color var(--t-fast, .15s), background var(--t-fast, .15s);
  z-index: 3;
}
.wh-pw-toggle:hover { color: var(--ink, #111); background: rgba(15,15,15,.06); }
.wh-pw-toggle:focus-visible {
  outline: none;
  color: var(--ink, #111);
  box-shadow: 0 0 0 3px rgba(15,15,15,.12);
}
.wh-pw-toggle[aria-pressed="true"] { color: var(--brand, #d70000); }

/* Phase 15.2.64 — OTP code input */
.wh-otp-input {
  letter-spacing: .5em;
  font-size: 22px;
  font-weight: 700;
  text-align: center;
  padding-left: 40px !important;
}
.wh-input-group > .wh-otp-input { text-indent: .5em; }
.wh-otp-timer {
  display: block;
  margin-top: 4px;
  font-size: 12.5px;
  color: var(--muted, #6b7280);
}
.wh-btn.is-disabled,
.wh-btn:disabled {
  opacity: .5;
  cursor: not-allowed;
  pointer-events: none;
}

/* Phase 15.2.65 — compact Create-account card (the signup form was too tall) */
.wh-auth-shell--dense { min-height: 0; padding-block: var(--sp-6, 28px); }
.wh-auth-card--dense .wh-auth-form-pane { padding: clamp(24px, 3vw, 40px); }
.wh-auth-card--dense .wh-auth-icon {
  width: 44px; height: 44px; font-size: 20px; margin-bottom: var(--sp-2, 8px);
}
.wh-auth-card--dense .wh-auth-form-pane h1 { font-size: var(--fs-xl, 26px); margin-bottom: 2px; }
.wh-auth-card--dense .wh-auth-form-pane .lead { margin-bottom: var(--sp-4, 16px); }
.wh-auth-card--dense .wh-auth-form .wh-form-group { margin-bottom: var(--sp-3, 12px); }
.wh-auth-card--dense .wh-input,
.wh-auth-card--dense .wh-input-group > .wh-input { padding-block: 10px; }
.wh-auth-card--dense .wh-pw-meter { margin-top: 6px; }
.wh-auth-card--dense .wh-pw-meter-label,
.wh-auth-card--dense .wh-help { margin-top: 4px; font-size: 11.5px; }
.wh-auth-card--dense .wh-auth-divider { margin-block: var(--sp-3, 12px); }
.wh-auth-card--dense .wh-auth-social { gap: 8px; }
.wh-auth-card--dense .wh-auth-social-btn { padding-block: 10px; }
.wh-auth-card--dense .wh-auth-foot { margin-top: var(--sp-3, 12px); }
/* brand pane: trim the bullet list breathing room so the two panes match height */
.wh-auth-card--dense .wh-auth-brand-points li { padding-block: 5px; }
.wh-auth-card--dense .wh-auth-brand-pane p { margin-bottom: var(--sp-3, 12px); }

/* ==========================================================================
 * Phase 15.2.65 — Politics: bespoke, tight editorial layout (no stretch gaps)
 * ========================================================================== */

.wh-politics { padding-block: var(--sp-6, 28px); }

/* Header with red accent bar + brand underline */
.wh-politics-head {
  border-bottom: 3px solid var(--brand, #d70000);
  align-items: center;
}
.wh-politics-head .wh-section-title {
  display: flex;
  align-items: center;
  margin: 0;
}
.wh-politics-head .wh-section-title::before {
  content: "";
  width: 6px;
  height: 1em;
  background: var(--brand, #d70000);
  border-radius: 3px;
  margin-right: 12px;
  flex: 0 0 auto;
}

/* Phase 15.6.4 — give the Bureaucracy section header the same RED line design
   as Politics (red 3px underline + red bar before the title). */
.wh-cat-section[data-cat="bureaucracy"] .wh-section-head {
  border-bottom: 3px solid var(--brand, #d70000);
  align-items: center;
}
.wh-cat-section[data-cat="bureaucracy"] .wh-section-head .wh-section-title {
  display: flex;
  align-items: center;
}
.wh-cat-section[data-cat="bureaucracy"] .wh-section-head .wh-section-title::before {
  content: "";
  width: 6px;
  height: 1em;
  background: var(--brand, #d70000);
  border-radius: 3px;
  margin-right: 12px;
  flex: 0 0 auto;
}

/* Phase 15.2.80 — Politics: LEFT column = big lead + a row of 2 small cards;
   RIGHT column = two square sponsor slots side-by-side, then the Latest list. */
.wh-politics-grid {
  display: grid;
  /* Phase 15.3 — sidebar locked to the shared rail width so it lines up with
     the in-content ad-rail used by the sections below (continuous right rail). */
  grid-template-columns: minmax(0, 1fr) var(--rail-w);
  gap: var(--rail-gap);
  align-items: start;
}
/* Phase 15.2.84 — the RIGHT column's Latest grows to fill the gap between the
   two ads so the column ends flush with the left (small hero + 2 small cards),
   keeping the cards their natural compact size. */

/* LEFT column — small lead card (image on top, title + description BELOW the
   image, like the Bureaucracy hero) + a row of 2 small cards. */
.wh-politics-main { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.wh-politics-lead { display: flex; min-width: 0; }
.wh-politics-lead > .wh-article { width: 100%; margin: 0; }
/* keep the lead image compact (~75% smaller than the old full-height overlay) */
.wh-politics-lead .wh-article-media {
  aspect-ratio: 16 / 9;
  border-radius: var(--r-img, 8px);
}
.wh-politics-lead .wh-article-title {
  font-family: var(--f-serif); /* Phase 15.2.88 — match the other section cards (was --f-display Abril) */
  /* Phase 15.6.2 — desktop hero title +4px (mobile keeps its own !important size). */
  font-size: clamp(24px, calc(2.1vw + 4px), 32px);
  line-height: 1.3;            /* more room so descenders aren't clipped at the bottom */
  margin-top: 10px;
}
.wh-politics-lead .wh-article-summary { color: var(--ink-3); }
/* Phase 15.2.84 — 2 small cards at their natural (compact) size. */
.wh-politics-subcards {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
}
.wh-politics-tile { min-width: 0; }
.wh-politics-tile > .wh-article {
  background: var(--paper-2, #f6f5f2);
  border: 1px solid var(--line, #e7e4de);
  border-radius: var(--r-3, 6px);
  padding: 10px;
  height: 100%;
  margin: 0;
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
.wh-politics-tile > .wh-article:hover {
  transform: translateY(-4px);
  box-shadow: 0 14px 26px rgba(0, 0, 0, .12);
  border-color: var(--brand, #d70000);
}
.wh-politics-tile .wh-article-media { border-radius: var(--r-img, 8px); aspect-ratio: 16 / 10; }
.wh-politics-tile .wh-article-title { font-size: calc(var(--fs-md, 18px) + 6px); } /* Phase 15.6.2 — desktop +6px (mobile keeps its own !important size) */

/* RIGHT column — bigger ad boxes on top, then the Latest list which GROWS to
   fill the rest of the column so it ends flush with the left column (no blank). */
.wh-politics-side { display: flex; flex-direction: column; gap: 18px; min-width: 0; }
.wh-politics-side-ads {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}
.wh-politics-ad { min-width: 0; }
/* Phase 15.2.84 — the ad slot shows ONLY the creative image: a fixed 3:2 box
   the image fills edge-to-edge (absolute fill so there's no leftover gap), with
   NO background colour and NO "Ads" label badge below it. */
.wh-politics-ad .wh-ad-slot {
  position: relative;
  margin: 0;
  width: 100%;
  max-width: 100% !important;
  min-height: 0 !important;
  aspect-ratio: 2 / 1;            /* Phase 15.2.84 — full-width banner, shorter so the
                                     right column matches the small-hero left (no blank) */
  overflow: hidden;
  border-radius: var(--r-img, 8px);
  background: transparent;
}
.wh-politics-ad .wh-ad-slot::before { display: none !important; }   /* no "Ads" badge */
.wh-politics-ad .wh-ad-slot:empty { display: none !important; }
.wh-politics-ad .wh-ad-slot a { position: absolute; inset: 0; display: block; }
.wh-politics-ad .wh-ad-slot img {
  position: absolute; inset: 0;
  width: 100% !important;
  height: 100% !important;
  max-height: none !important;   /* Phase 15.2.84 — override global 250px cap so the image fills the box (no blank below) */
  object-fit: cover;
  display: block;
}
.wh-politics-ad .wh-ad-slot > div { position: absolute; inset: 0; width: 100%; height: 100%; }
/* Latest widget grows to fill the remaining column height; its items spread to
   fill so the column ends flush with the left (no blank below the list). */
.wh-politics-side .wh-widget--latest {
  margin: 0;
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
}
.wh-politics-side .wh-widget--latest .wh-widget-latest-items {
  flex: 1 1 auto;
  justify-content: space-between;
}
/* Phase 15.2.83 — "Text button" at the bottom of the Latest container. */
.wh-widget-allbtn { margin-top: 14px; font-size: 13px; }

/* Latest list — simple, even item spacing (NO space-between voids) */
.wh-widget-latest-items {
  display: flex;
  flex-direction: column;
}
.wh-widget--latest .wh-widget-latest-items .wh-article-mini {
  margin: 0;
  padding: 11px 0;
  border-bottom: 1px solid var(--line, #e7e4de);
}
.wh-widget--latest .wh-widget-latest-items .wh-article-mini:first-child { padding-top: 0; }
.wh-widget--latest .wh-widget-latest-items .wh-article-mini:last-child {
  border-bottom: 0;
  padding-bottom: 0;
}

/* Tablet: stack the two columns; keep the 2 sub-cards and 2 ads side-by-side. */
@media (max-width: 991px) {
  .wh-politics-grid { grid-template-columns: 1fr; gap: 18px; }
  .wh-politics-lead .wh-article-overlay { min-height: 300px; aspect-ratio: 16 / 9; }
}
@media (max-width: 575px) {
  .wh-politics-subcards { gap: 10px; }
  .wh-politics-side-ads { gap: 10px; }
  .wh-politics-lead .wh-article-overlay { min-height: 220px; }
}

/* ==========================================================================
 * Phase 15.3 — Homepage in-content AD RAIL (section-wise)
 * Each major news section is a 2-col grid: content (left) + a rail cell
 * (right). Desktop ≥992px: rail = vertical stack of ad cards, lined up into
 * a continuous right column. Mobile ≤991px: the wrapper collapses to one
 * column and the rail becomes a horizontal swipe carousel under the section.
 * When a section has no eligible ad, :has() collapses the column so there is
 * NEVER an empty gutter.
 * ========================================================================== */
/* ==========================================================================
 * Phase 15.3 — Homepage 2-column layout.
 *   LEFT  (.wh-home-left) = all editorial content, flowing top→bottom.
 *   RIGHT (.wh-home-rail) = ONE continuous rail: Latest widget + a single
 *         stack of ad creatives shown at their NATURAL aspect ratio (no crop,
 *         like the reference design). Nothing is sticky — the whole page
 *         scrolls normally.
 * ========================================================================== */
.wh-home-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--rail-w);
  column-gap: var(--rail-gap);
  align-items: start;            /* columns are independent; both just scroll */
}
.wh-home-left { min-width: 0; }
.wh-home-left > .wh-section:first-child { padding-top: 0; }   /* align top with the rail */
.wh-home-left > .wh-ad-band   { margin: 22px 0; }
.wh-home-left > .wh-mag-teaser { margin: 22px 0; }

/* ---- The continuous right rail ---- */
.wh-home-rail { min-width: 0; }
.wh-rail-latest { margin: 0 0 18px; }

.wh-rail-ads {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.wh-rail-ads-label {
  display: block;
  font-size: 10px;
  letter-spacing: .16em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--muted, #9a958c);
}
/* render_rail() wraps a section's ads in a .wh-rail-track; flatten it so every
   ad is a direct, evenly-spaced item of the one rail. */
.wh-rail-track { display: contents; }

/* Each ad — shown at its NATIVE size (no stretch, no crop). A rail-width
   poster fills the column; a narrow skyscraper centres. This keeps the rail
   height honest so it tracks the article column (no giant blank gutter). */
.wh-rail-ad,
.wh-home-rail .wh-ad-slot {
  display: block;
  width: 100%;
  margin: 0;
  text-align: center;
  text-decoration: none;
}
.wh-home-rail .wh-ad-slot a { display: inline-block; max-width: 100%; }
.wh-rail-ad img,
.wh-home-rail .wh-ad-slot img {
  display: inline-block;
  width: auto;
  max-width: 100%;
  height: auto;                 /* native — the whole creative shows, undistorted */
  max-height: none !important;
  border-radius: var(--r-img, 8px);
  vertical-align: top;
}
.wh-home-rail .wh-ad-slot:empty { display: none; }
.wh-home-rail .wh-ad-slot::before { display: none !important; }   /* no per-slot badge */
.wh-rail-ad--html { padding: 0; }

/* Suppress the legacy ≥1900px skyscraper gutter rails on the homepage. */
.wh-page-home .wh-ad-rails-wrap { display: none !important; }

/* ---- Tablet / mobile: stack; the ad rail becomes a swipe carousel ---- */
@media (max-width: 991px) {
  .wh-home-grid { display: block; }
  .wh-home-rail { margin-top: 26px; }
  .wh-rail-ads {
    flex-direction: row;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    gap: 12px;
    padding-bottom: 4px;
  }
  .wh-rail-ads::-webkit-scrollbar { display: none; }
  .wh-rail-ads-label { position: absolute; transform: translateY(-20px); }
  .wh-home-rail { position: relative; padding-top: 20px; }
  /* every ad becomes a slide (the flattened tracks contribute their cards).
     Snap to START so the first card sits flush-left, aligned with the "ADS"
     label and the rest of the page content (no off-centre indent). */
  .wh-rail-ad,
  .wh-home-rail .wh-ad-slot {
    flex: 0 0 86%;
    max-width: 86%;
    scroll-snap-align: start;
  }
  .wh-rail-ad img,
  .wh-home-rail .wh-ad-slot img {
    height: 220px !important;   /* uniform in the carousel only */
    object-fit: cover;
  }
}
@media (max-width: 575px) {
  .wh-rail-ad,
  .wh-home-rail .wh-ad-slot { flex-basis: 86%; max-width: 86%; }
}

/* ==========================================================================
 * Phase 15.2.66 — Aesthetic full-width content ad bands
 * The after-section banner zones used to render at their native ~970px width,
 * left-aligned, floating in white. Now they stretch edge-to-edge across the
 * container as a clean banner band (image OR html creative), responsive, with
 * the "Ads" label centered. Collapses fully when nothing is served.
 * ========================================================================== */
/* Phase 15.3 — in-content ad band woven INTO a section's card grid (spans the
   full grid width after a row of cards). Only present when a creative serves. */
.wh-cat-inline-ad {
  grid-column: 1 / -1;
  margin: 6px 0;
  text-align: center;
}
.wh-cat-inline-ad .wh-ad-slot { width: 100%; max-width: 100% !important; margin: 0; }
.wh-cat-inline-ad .wh-ad-slot a { display: block; width: 100%; }
.wh-cat-inline-ad .wh-ad-slot img {
  width: 100%; height: auto; max-height: 160px;
  object-fit: contain; border-radius: var(--r-img, 8px);
}
.wh-cat-inline-ad .wh-ad-slot::before { display: none !important; }
@media (max-width: 575px) { .wh-cat-inline-ad .wh-ad-slot img { max-height: 120px; } }
/* Phase 15.6 — the every-2-rows band now emits a .wh-rail-ad card. */
.wh-cat-inline-ad .wh-rail-ad { display: block; width: 100%; margin: 0; text-decoration: none; }
.wh-cat-inline-ad .wh-rail-ad img {
  width: 100%; height: auto; max-height: 160px;
  object-fit: contain; border-radius: var(--r-img, 8px);
}
@media (max-width: 575px) { .wh-cat-inline-ad .wh-rail-ad img { max-height: 120px; } }

.wh-ad-band {
  margin: 22px 0;
  text-align: center;
}
.wh-ad-band .wh-ad-slot {
  width: 100%;
  max-width: 100% !important;   /* override the inline native-width cap */
  margin: 0;
}
.wh-ad-band .wh-ad-slot a { display: block; width: 100%; }
.wh-ad-band .wh-ad-slot img {
  width: 100%;
  height: auto;
  max-height: 200px;
  object-fit: cover;
  border-radius: 10px;
  display: block;
}
/* HTML creatives (e.g. the gradient "house ad" banners) also go full width */
.wh-ad-band .wh-ad-slot > div { width: 100%; }
.wh-ad-band:has(.wh-ad-slot:empty) { display: none; }
.wh-ad-band:has(.wh-ad-slot[data-prefilled]) .wh-ad-slot::before,
.wh-ad-band .wh-ad-slot::before { text-align: center; }

@media (max-width: 575px) {
  .wh-ad-band { margin: 16px 0; }
  .wh-ad-band .wh-ad-slot img { max-height: 130px; }
}

/* ==========================================================================
 * Phase 15.2.77 — Dashboard "Latest magazines" carousel (#8)
 * ========================================================================== */
.wh-dash-mag { margin: 8px 0 28px; }
.wh-dash-mag-head { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 12px; gap: 12px; }
.wh-dash-mag-title { font-family: var(--f-display, Georgia, serif); font-size: 20px; margin: 0; display: flex; align-items: center; gap: 8px; }
.wh-dash-mag-all { font-size: 13px; font-weight: 600; color: var(--brand, #d70000); text-decoration: none; white-space: nowrap; }
.wh-dash-mag-all:hover { text-decoration: underline; }
.wh-dash-mag-track {
  display: flex; gap: 16px; overflow-x: auto; scroll-snap-type: x mandatory;
  padding: 4px 2px 12px; scrollbar-width: thin;
}
.wh-dash-mag-track::-webkit-scrollbar { height: 6px; }
.wh-dash-mag-track::-webkit-scrollbar-thumb { background: var(--line, #ddd); border-radius: 99px; }
.wh-dash-mag-card {
  flex: 0 0 168px; width: 168px; scroll-snap-align: start; text-decoration: none; color: inherit;
  transition: transform .18s ease;
}
.wh-dash-mag-card:hover { transform: translateY(-4px); }
.wh-dash-mag-cover {
  aspect-ratio: 3 / 4; border-radius: var(--r-3, 6px); overflow: hidden;
  background: var(--ink-bg, #14110e); box-shadow: 0 8px 22px rgba(0,0,0,.16);
}
.wh-dash-mag-cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
.wh-dash-mag-fallback {
  width: 100%; height: 100%; display: flex; align-items: center; justify-content: center;
  color: #fff; font-family: var(--f-display, Georgia, serif); font-size: 48px;
  background: linear-gradient(135deg, var(--brand, #d70000), #7a0000);
}
.wh-dash-mag-cap { margin-top: 8px; line-height: 1.3; }
.wh-dash-mag-cap strong { display: block; font-size: 13.5px; font-weight: 700; }
.wh-dash-mag-cap span { display: block; font-size: 11.5px; color: var(--ink-3, #888); }
.wh-dash-mag-nav { display: flex; gap: 8px; justify-content: flex-end; }
.wh-dash-mag-btn {
  width: 36px; height: 36px; border-radius: 50%; border: 1px solid var(--line, #e5e7eb);
  background: #fff; cursor: pointer; display: inline-flex; align-items: center; justify-content: center;
  color: #333; transition: background .15s ease, border-color .15s ease;
}
.wh-dash-mag-btn:hover { background: var(--brand, #d70000); border-color: var(--brand, #d70000); color: #fff; }
@media (max-width: 575px) {
  .wh-dash-mag-card { flex-basis: 138px; width: 138px; }
}

/* ==========================================================================
 * Phase 15.2.77 (#2) — Magazine 3D coverflow carousel (homepage)
 * ========================================================================== */
.wh-mag3d-section { text-align: center; }
.wh-mag3d {
  position: relative;
  height: 440px;
  perspective: 1500px;
  margin: 8px auto 0;
  max-width: 980px;
}
.wh-mag3d-stage {
  position: absolute; inset: 0;
  transform-style: preserve-3d;
}
.wh-mag3d-card {
  position: absolute;
  top: 50%; left: 50%;
  width: 260px; height: 340px;
  margin: -170px 0 0 -130px;          /* center anchor */
  border-radius: var(--r-3, 6px);
  overflow: hidden;
  background: var(--ink-bg, #14110e);
  box-shadow: 0 20px 50px rgba(0,0,0,.35);
  transition: transform .55s cubic-bezier(.2,.7,.2,1), opacity .55s ease;
  will-change: transform, opacity;
  cursor: pointer;
  text-decoration: none;
}
.wh-mag3d-card img { width: 100%; height: 100%; object-fit: cover; display: block; }
.wh-mag3d-card::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg, transparent 55%, rgba(0,0,0,.35));
  opacity: 0; transition: opacity .4s ease;
}
.wh-mag3d-card.is-side::after { opacity: 1; }
.wh-mag3d-arrow {
  position: absolute; top: 50%; transform: translateY(-50%);
  z-index: 20; width: 44px; height: 44px; border-radius: 50%;
  border: 1px solid var(--line, #e5e7eb); background: #fff; color: #222;
  cursor: pointer; display: inline-flex; align-items: center; justify-content: center;
  font-size: 18px; box-shadow: 0 4px 14px rgba(0,0,0,.12); transition: background .15s, color .15s;
}
.wh-mag3d-arrow:hover { background: var(--brand, #d70000); border-color: var(--brand, #d70000); color: #fff; }
.wh-mag3d-prev { left: 4px; } .wh-mag3d-next { right: 4px; }
.wh-mag3d-dots { position: absolute; bottom: -6px; left: 0; right: 0; display: flex; gap: 8px; justify-content: center; z-index: 20; }
.wh-mag3d-dot { width: 9px; height: 9px; border-radius: 50%; border: 0; background: #cfcdc8; cursor: pointer; padding: 0; transition: background .2s, transform .2s; }
.wh-mag3d-dot.is-active { background: var(--brand, #d70000); transform: scale(1.25); }
@media (max-width: 680px) {
  .wh-mag3d { height: 360px; }
  .wh-mag3d-card { width: 200px; height: 264px; margin: -132px 0 0 -100px; }
}

/* Phase 15.2.78 — 3D coverflow inside the Magazines hero (dark, right column) */
.wh-mag3d--hero { height: 400px; margin: 0; max-width: 100%; }
.wh-mag3d--hero .wh-mag3d-card { width: 200px; height: 270px; margin: -135px 0 0 -100px; box-shadow: 0 24px 60px rgba(0,0,0,.5); }
.wh-mag3d--hero .wh-mag3d-dots { bottom: 2px; }
.wh-mag3d--hero .wh-mag3d-prev { left: -6px; }
.wh-mag3d--hero .wh-mag3d-next { right: -6px; }
@media (max-width: 991px) {
  .wh-mag3d--hero { height: 340px; }
  .wh-mag3d--hero .wh-mag3d-card { width: 168px; height: 226px; margin: -113px 0 0 -84px; }
}

/* ============================================================
   Phase 15.2.87 — Web Extras (hit counter / share box / disclaimer / forum)
   ============================================================ */
/* Phase 15.6.9 — Web Extras (Number of Hits / Your Attention Please) now show
   on mobile too (the old desktop-only hide is removed per request). */
/* @media (max-width: 768px) { .wh-webonly { display: none !important; } } */
@media (max-width: 991px) {
  /* Latest now sits above Corporate in the left column on mobile — hide the
     rail's own Latest widget so it isn't shown twice. */
  .wh-home-rail .wh-rail-latest { display: none !important; }
}

/* Phase 15.2.88 — counter + share box live as grid cells on footer row 2,
   filling what used to be blank space beside the Newsletter column. */
.wh-footer-cell { min-width: 0; display: flex; align-items: flex-end; }
.wh-footer-hits { justify-content: flex-start; }
.wh-footer-share { grid-column: span 2; }
.wh-footer-share .wh-share-box { max-width: none; width: 100%; }
@media (max-width: 1024px) { .wh-footer-share { grid-column: span 1; } }

/* Hit counter — refined split-flap odometer */
.wh-hitcounter { display: inline-flex; flex-direction: column; border-radius: 14px; overflow: hidden;
  box-shadow: 0 12px 30px rgba(215,0,0,.28); }
.wh-hitcounter-label {
  background: linear-gradient(180deg, #e10000, #ab0000); color: #fff; font-weight: 800; letter-spacing: .18em;
  text-transform: uppercase; font-size: 11px; text-align: center; padding: 9px 18px;
}
.wh-hitcounter-digits {
  display: flex; gap: 5px; background: linear-gradient(180deg, #c10000, #970000); padding: 12px 14px; justify-content: center;
}
.wh-hit-digit {
  position: relative; background: linear-gradient(180deg, #ffffff 0 50%, #e7e9ed 50% 100%); color: #16181d;
  font-family: var(--f-ui, system-ui); font-weight: 800; font-size: 28px; line-height: 1;
  width: 28px; padding: 11px 0; text-align: center; border-radius: 6px;
  box-shadow: 0 1px 0 rgba(255,255,255,.8) inset, 0 3px 5px rgba(0,0,0,.35);
}
.wh-hit-digit::after { content: ""; position: absolute; left: 0; right: 0; top: 50%; height: 1px; background: rgba(0,0,0,.13); }

/* Share-your-information box */
.wh-share-box { flex: 1 1 380px; max-width: 580px; background: #fff; border-radius: 14px; overflow: hidden;
  box-shadow: 0 12px 30px rgba(0,0,0,.34); }
.wh-share-box-head { background: linear-gradient(180deg, #fff, #fbe9e9); color: var(--brand, #d70000); font-weight: 800;
  font-size: 15px; padding: 12px 18px; border-bottom: 1px solid #f3dcdc; display: flex; align-items: center; gap: 9px; }
.wh-share-box-head i { font-size: 16px; }
.wh-share-box-body { padding: 14px 18px 16px; }
.wh-share-box-body p { margin: 0 0 14px; color: #2a2d34; font-size: 14.5px; line-height: 1.55; }
.wh-share-box-body a { color: var(--brand, #d70000); font-weight: 600; }
.wh-share-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
/* Phase 15.2.88 — uniform dark-gray circle + white icon (matches the footer
   social icons) instead of per-network brand colours. The two-class selector
   below also out-ranks ".wh-share-box-body a" so the icon stays white. */
.wh-share-box-body .wh-share-btn { width: 36px; height: 36px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center;
  background: #2f3238; color: #fff; font-size: 15px; text-decoration: none; font-weight: 400;
  transition: transform .15s ease, background .15s ease; }
.wh-share-box-body .wh-share-btn i { color: #fff; }
.wh-share-box-body .wh-share-btn:hover { background: var(--brand, #d70000); transform: translateY(-2px); }
.wh-share-feedback { margin-left: auto; display: inline-flex; align-items: center; gap: 6px; color: var(--brand, #d70000) !important;
  font-weight: 700; font-size: 13px; text-decoration: none; padding: 7px 15px; border: 1.5px solid var(--brand, #d70000);
  border-radius: 999px; transition: background .15s ease, color .15s ease; }
.wh-share-feedback:hover { background: var(--brand, #d70000); color: #fff !important; }

/* Disclaimer box */
.wh-disclaimer-box { margin-top: var(--sp-5); border-radius: 14px; overflow: hidden; box-shadow: 0 12px 32px rgba(0,0,0,.42); }
.wh-disclaimer-head { background: #fff; color: #16181d; font-weight: 800; letter-spacing: .02em; text-align: center; padding: 12px;
  font-size: 15px; display: flex; align-items: center; justify-content: center; gap: 9px; }
.wh-disclaimer-head i { color: var(--brand, #d70000); }
.wh-disclaimer-body { background: linear-gradient(180deg, #a90f0f, #7c0a0a); color: #fff; padding: 18px 24px; }
.wh-disclaimer-body p { margin: 0 auto; max-width: 1000px; font-size: 12.5px; line-height: 1.7; text-align: center; color: rgba(255,255,255,.92); }
.wh-disclaimer-copy { margin-top: 12px !important; font-weight: 700; color: #fff !important; letter-spacing: .02em; }

/* Whispers Forum (homepage, below Corporate) */
.wh-forum-section { margin-bottom: var(--sp-7); }
.wh-forum-head { background: linear-gradient(180deg, #e10000, #b80000); color: #fff; font-weight: 800; letter-spacing: .12em;
  text-transform: uppercase; font-size: 14px; text-align: center; padding: 12px; border-radius: 14px 14px 0 0; }
.wh-forum-grid { border: 1px solid #ecd9d9; border-top: 0; border-radius: 0 0 14px 14px; background: #fff;
  box-shadow: 0 12px 30px rgba(0,0,0,.06); overflow: hidden; }
.wh-forum-card { padding: 16px 20px; border-bottom: 1px solid #f1e6e6; transition: background .15s ease; }
.wh-forum-card:last-child { border-bottom: 0; }
.wh-forum-card:hover { background: #fdf6f6; }
.wh-forum-card-title { font-family: var(--f-serif, Georgia); font-size: var(--fs-md, 18px); color: var(--brand, #d70000);
  margin: 0 0 6px; display: flex; align-items: center; gap: 8px; }
.wh-forum-card-title i { font-size: 14px; opacity: .7; }
.wh-forum-card-body { color: #333; font-size: 14px; line-height: 1.6; }

/* ==========================================================================
 * Phase 15.3 — HOME page, MOBILE (≤575px) only: shrink NEWS CARD TITLES ~25%
 * (font-size × 0.75). Scoped to .wh-page-home so it never affects category /
 * article / other pages, and only to the article headline classes (not body,
 * section headings, buttons, etc.). !important so it wins over per-variant
 * sizes without touching them.
 * Phase 15.4.3 — bumped up from ×0.6 (40% smaller) to ×0.75 (25% smaller);
 * the earlier reduction read too small on phones.
 * ========================================================================== */
@media (max-width: 575px) {
  /* Phase 15.6.6 — small cards +3px (was ×0.75). */
  .wh-page-home .wh-article-md .wh-article-title,
  .wh-page-home .wh-politics-tile .wh-article-title {
    font-size: calc(var(--fs-md, 18px) * 0.75 + 3px) !important;
  }
  /* Top News (hero sidebar) rows +2px. */
  .wh-page-home .wh-article-row .wh-article-title {
    font-size: calc(var(--fs-md, 18px) * 0.75 + 2px) !important;
  }
  /* hero / lead / hero-overlay headlines +4px (was 17.5). */
  .wh-page-home .wh-article-lg .wh-article-title,
  .wh-page-home .wh-article-xl .wh-article-title,
  .wh-page-home .wh-politics-lead .wh-article-title,
  .wh-page-home .wh-article-overlay-body .wh-article-title {
    font-size: 21.5px !important;
    line-height: 1.25 !important;
  }
  /* small cards only. Phase 15.4.3 — the "Latest" mini list is intentionally
     NOT shrunk any more: it now renders at full size so the home rail "Latest"
     widget matches the category page's "Latest" widget exactly (per request). */
  .wh-page-home .wh-article-sm .wh-article-title {
    font-size: calc(var(--fs-sm, 14px) * 0.75) !important;
  }
}

/* ==========================================================================
 * Phase 15.3 — HOME page, MOBILE (≤991px) only: high-visibility, premium ads.
 * Desktop is untouched. Frames every homepage ad as a clean "sponsored" card
 * (rounded, soft shadow, subtle paper gradient) with a small red ADS pill, and
 * gives the images real height so ads stand out instead of getting squished.
 * ========================================================================== */
@media (max-width: 991px) {
  /* ---- shared "sponsored card" for content bands + in-grid inline ads ---- */
  .wh-page-home .wh-ad-band,
  .wh-page-home .wh-cat-inline-ad {
    position: relative;
    margin: 22px 0;
    padding: 24px 10px 10px;
    background: linear-gradient(180deg, #ffffff 0%, #f6f2ea 100%);
    border: 1px solid rgba(0,0,0,.07);
    border-radius: 18px;
    box-shadow: 0 10px 26px rgba(0,0,0,.09);
  }
  .wh-page-home .wh-ad-band::before,
  .wh-page-home .wh-cat-inline-ad::before {
    content: "ADS";
    position: absolute; top: 9px; left: 12px;
    font-size: 9px; font-weight: 700; letter-spacing: .16em;
    text-transform: uppercase; color: var(--muted, #9a958c);
    background: none; padding: 0; box-shadow: none;
  }
  .wh-page-home .wh-ad-band .wh-ad-slot,
  .wh-page-home .wh-cat-inline-ad .wh-ad-slot { width: 100%; max-width: 100% !important; margin: 0; }
  .wh-page-home .wh-ad-band .wh-ad-slot img,
  .wh-page-home .wh-cat-inline-ad .wh-ad-slot img {
    width: 100% !important; height: auto !important; max-height: 300px !important;
    object-fit: cover; border-radius: 12px; display: block;
  }
  .wh-page-home .wh-ad-band .wh-ad-slot::before,
  .wh-page-home .wh-cat-inline-ad .wh-ad-slot::before { display: none !important; }

  /* ---- right-rail → mobile swipe carousel: bigger rounded, shadowed cards.
       The rail also holds the Latest widget (content), so we DON'T frame the
       whole rail — only style the ADS label pill + the ad cards. ---- */
  /* rail "ADS" label stays the subtle muted style (no coloured pill) */
  .wh-page-home .wh-home-rail .wh-rail-ads-label {
    font-size: 10px; font-weight: 700; letter-spacing: .16em;
    text-transform: uppercase; color: var(--muted, #9a958c);
    background: none; padding: 0; box-shadow: none;
  }
  .wh-page-home .wh-rail-ad,
  .wh-page-home .wh-home-rail .wh-ad-slot {
    flex: 0 0 88% !important; max-width: 88% !important;
    border-radius: 14px; overflow: hidden;
    box-shadow: 0 6px 18px rgba(0,0,0,.16);
  }
  .wh-page-home .wh-rail-ad img,
  .wh-page-home .wh-home-rail .wh-ad-slot img { height: 250px !important; object-fit: cover; }

  /* ---- after-header sponsored banner: round + lift ---- */
  .wh-page-home .wh-after-header-ad { margin: 16px 0; }
  .wh-page-home .wh-after-header-ad .wh-ad-slot,
  .wh-page-home .wh-after-header-ad .wh-ad-carousel {
    border-radius: 16px; overflow: hidden; box-shadow: 0 8px 24px rgba(0,0,0,.14);
  }
}

/* ==========================================================================
 * Phase 15.4 — Homepage Side Ads (16-slot rail + per-section mobile carousels)
 *   Desktop: .wh-rail-ads.wh-only-desktop stacks all 16 slots down the rail
 *            (uses the existing .wh-rail-ad card styling — natural aspect).
 *   Mobile:  the desktop rail is hidden; each section instead shows a
 *            .wh-side-carousel (horizontal swipe of that section's 4 slots).
 * ========================================================================== */
.wh-only-mobile { display: none; }

@media (max-width: 991px) {
  .wh-only-desktop { display: none !important; }
  .wh-only-mobile  { display: block !important; }
}

/* Mobile per-section ad carousel */
.wh-side-carousel { margin: 14px 0 22px; }
.wh-side-carousel-label {
  display: block;
  font-size: 10px;
  letter-spacing: .16em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--muted, #9a958c);
  margin-bottom: 8px;
}
.wh-side-track {
  display: flex;
  flex-direction: row;
  align-items: stretch;   /* Phase 15.6.1 — all slides share one height */
  gap: 12px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  padding-bottom: 4px;
}
.wh-side-track::-webkit-scrollbar { display: none; }
/* Phase 15.6.1 — EQUAL height per carousel (site picks --side-ad-h from the
   ads in that section), images fit inside WITHOUT cropping and without going
   too wide (object-fit:contain, centred, letter-boxed on a clean card). */
.wh-side-track .wh-rail-ad {
  flex: 0 0 86%;
  max-width: 86%;
  scroll-snap-align: start;
  display: flex;
  align-items: center;
  justify-content: center;
  height: var(--side-ad-h, 200px);
  margin: 0;
  text-decoration: none;
  border-radius: 14px;
  overflow: hidden;
  box-shadow: 0 6px 18px rgba(0,0,0,.16);
  background: #fff;
}
.wh-side-track .wh-rail-ad img {
  display: block;
  width: 100%;
  height: 100% !important;
  max-height: none !important;
  object-fit: contain !important;   /* never crop */
  border-radius: 14px;
}
.wh-side-track .wh-rail-ad--html { padding: 0; border-radius: 14px; overflow: hidden; width: 100%; height: 100%; }
@media (max-width: 575px) {
  .wh-side-track .wh-rail-ad { flex-basis: 88%; max-width: 88%; }
}

/* Phase 15.4.3 — Category page ad slots (top banner + in-grid banner) */
.wh-category-top-ad { margin: 0 0 20px; }
.wh-listing-inline-ad {
  grid-column: 1 / -1;   /* span the full 2-column article grid */
  margin: 4px 0;
}
.wh-listing-inline-ad .wh-ad-slot img { width: 100%; height: auto; border-radius: 8px; }

/* ==========================================================================
 * Phase 15.5 — Category page sidebar ads (Side-Ads style: unlimited).
 *   Desktop: .wh-catside-stack = vertical stack at natural size.
 *   Mobile:  reuses .wh-side-carousel/.wh-side-track (swipe + 3s auto-rotate).
 * ========================================================================== */
.wh-catside-ads { margin: 0 0 16px; }
.wh-catside-stack { display: flex; flex-direction: column; gap: 14px; }
.wh-catside-stack .wh-rail-ad {
  display: block; width: 100%; margin: 0;
  text-decoration: none; border-radius: 8px; overflow: hidden;
  box-shadow: 0 2px 10px rgba(0,0,0,.08);
}
.wh-catside-stack .wh-rail-ad img {
  display: block; width: 100%; height: auto; border-radius: 8px;
}
.wh-catside-stack .wh-rail-ad--html { padding: 0; }

/* ==========================================================================
 * Phase 15.6.5 — Category / section page: bump the article-card TITLE +6px on
 * desktop (matches the homepage small-card bump). Scoped to .wh-listing-items
 * so only the category page is affected; mobile (<576px) keeps the base size.
 * ========================================================================== */
@media (min-width: 576px) {
  .wh-listing-items .wh-article-title { font-size: calc(var(--fs-md, 18px) + 6px); }
}

/* ==========================================================================
 * Phase 15.6.6 — NO "..." anywhere. Remove the multi-line ellipsis truncation
 * from all news-card text across the whole site (titles, summaries, excerpts,
 * the Latest mini list). Full headlines now show in full.
 * ========================================================================== */
.wh-article-title,
.wh-article-summary,
.wh-article-summary-lg,
.wh-article-mini-title,
.wh-article-excerpt,
.wh-article-overlay-body .wh-article-title,
.wh-cat-uni-item .wh-article-title,
.wh-listing-items .wh-article-title {
  -webkit-line-clamp: unset !important;
  overflow: visible !important;
  text-overflow: clip !important;
}

/* ==========================================================================
 * Phase 15.6.7 — Mobile drawer order: the account button + socials move UP,
 * so the order is now: [logo/close] → [My account + socials] → [Search] → [Nav].
 * ========================================================================== */
.wh-mobile-drawer-head   { order: 0; }
.wh-mobile-drawer-footer {
  order: 1;
  border-top: 0;
  border-bottom: 1px solid var(--line);
  padding-bottom: var(--sp-5);          /* it's no longer at the bottom */
}
.wh-mobile-drawer-search { order: 2; }
.wh-mobile-drawer-nav    {
  order: 3;
  padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 14px);  /* nav is last now */
}
