/* ==========================================================================
   New Niguro — Naver-style homepage (page-newniguro.php)
   --------------------------------------------------------------------------
   Mobile first: one column of white cards, 2-up at >=900px, 3-column board at
   >=1024px. Every surface is built from the theme's own design tokens
   (hsl(var(--card)) / --foreground / --muted-foreground / --primary …) so the
   board reads correctly in the light theme and in dark mode alike.
   All classes are .nn-* scoped (plus the #home-* ids the homepage JS expects).
   ========================================================================== */

/* ── Chrome: this page is board-first, the old left rail is not part of it ── */
body.newniguro-template #left-sidebar { display: none !important; }
/* Header content lines up with the page content (1150px), and the bar itself is
   transparent — same as index.php, where the hero owns the top of the page. */
body.newniguro-template #site-header {
  /* Not sticky on this page: the hero and the board scroll, the bar goes with
     them (m.naver does the same — the search hero owns the top of the page). */
  position: absolute;
  max-width: 1150px;
  margin-inline: auto;
  background: transparent;
  box-shadow: none;
  /* Same gutters as .nn-wrap, so the hamburger and the account/theme buttons
     line up with the edge of the board instead of floating outside it. */
  padding-inline: 12px;
}
@media (min-width: 640px) {
  body.newniguro-template #site-header { padding-inline: 16px; }
}
/* Keep the header offset (header.php's inline padding-top) — only the sidebar
   gutter and the mobile side padding are overridden; .nn-wrap supplies the
   gutters so the board can use the full 1150px column. */
body.newniguro-template #main-content {
  margin-left: 0 !important;
  width: 100% !important;
  max-width: 100% !important;
  padding-left: 0 !important;
  padding-right: 0 !important;
}

.nn-wrap { width: 100%; max-width: 1150px; margin-inline: auto; padding-inline: 12px; }
@media (min-width: 640px) { .nn-wrap { padding-inline: 16px; } }

/* ==========================================================================
   1. Hero — index.php's own geometry: banner (65% of the search field wide)
   above the search form, the pair centred on their own, generous whitespace
   around.
   Nothing else lives in here, which is what makes the search stand alone.
   ========================================================================== */
.nn-hero {
  background: hsl(var(--background));
}
.nn-hero-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  width: 100%;
  max-width: 1150px;
  margin-inline: auto;
  padding: 6px 10px 14px;
}
@media (min-width: 640px) { .nn-hero-inner { padding-inline: 24px; } }
/* Desktop: the banner + search stand on their own, the way index.php centres
   them, with the rail and board waiting below the fold. The block is kept
   short so the search form sits high, close under the header. */
@media (min-width: 768px) {
  /* Top-aligned, tight under the header — the banner + search sit high on the
     page with a small gap and the board follows straight after (no 100vh
     centring, so nothing is pushed down any more). */
  .nn-hero-inner { min-height: 0; padding-block: 10px 18px; }
}

/* Banner / logo block — the same width index.php gives it: 65% of the *visible*
   search field, not of the column. The field is the column minus the form
   wrapper's md:px-2 (8px a side), so the width is written as (column - 16px) *
   0.65 — exact even if the share is retuned. Keep in step with index.php. */
.nn-hero .home-banner-link { display: block; width: calc((100% - 16px) * 0.65); margin: 0 auto; }
.nn-hero .home-banner-link img { display: block; width: 100%; height: auto; }
/* Logo fallback (no banner / no bloom banner): the brand sits directly above
   the search form, so its bottom margin *is* the gap the reader sees — the
   search section itself carries no top margin. Keep it tight, closer to the way
   a banner sits on the form. */
.nn-hero-logo { margin-bottom: 20px; }
/* No display here on purpose: the light / dark logos are toggled by
   .nn-logo-light / .nn-logo-dark below, and a display rule would outrank it. */
.nn-hero-logo img { max-height: 64px; width: auto; }

/* One logo per colour scheme, never both. */
.nn-logo-dark { display: none !important; }
.dark .nn-logo-light { display: none !important; }
.dark .nn-logo-dark { display: block !important; }
@media (max-width: 767px) {
  /* Phones: the form wrapper is px-0, so the field IS the column. */
  .nn-hero .home-banner-link { width: 65%; }
  .nn-hero-logo { margin-bottom: 10px; }
}

/* The search column itself — index.php's own box, narrowed to a 570px field on
   desktop. It is the container of the banner and the focus strip, so the
   banner's (100% - 16px) * 0.65 measures 65% of that 570px field exactly as it
   does on the homepage. */
.nn-search-section {
  position: relative;
  width: 98%;
  /* 586, not 570: the form's own wrapper carries md:px-2 (8px each side), so
     the rounded field the reader sees measures exactly 570px from 768px up. */
  max-width: 586px;
  margin-inline: auto;
  /* No negative pull any more: the hero is already tight under the header, so
     the old -32px would slide the banner up behind the bar. On desktop the
     search stands alone with a wide band of space under it before the rail;
     phones keep a tighter one. With a promo row below the form that band closes
     up instead — see .nn-page.has-promo further down.

     Why 172px: the old 120px band plus the hero's 18px bottom padding came to
     138px — almost exactly the footprint the promo row occupies when it is on
     (46px of gap + ~84px of row + 18px of margin = 148px). So switching the
     promo on and off changed the layout by only ~10px and read as "the same
     margin either way". The empty band is now deliberately *larger* than the
     promo row it replaces, so the two states are visibly different: 172 + 18 =
     190px of space under the form with no promo, against 148px total with one. */
  margin-top: 0;
  margin-bottom: 172px;
}
/* Phones: the search is a centred 95% of the viewport with real room below it
   before the rail (76 + the hero's 14px = 90px with no promo). */
@media (max-width: 767px) {
  .nn-search-section { width: 95%; margin-bottom: 76px; }
}

/* With a promo row under the search form that band is empty twice over — the
   form does not need to push the reader past it to reach the rail any more, so
   it closes up and the promo takes the slot. The gap that remains is this
   margin plus .nn-hero-inner's own bottom padding (18px from 768px up, 14px
   below it): 38 + 18 = 56px on desktop, 20 + 14 = 34px on phones. */
.nn-page.has-promo .nn-search-section { margin-bottom: 38px; }
@media (max-width: 767px) {
  .nn-page.has-promo .nn-search-section { margin-bottom: 20px; }
}

/* Search: same geometry + behaviour as the theme homepage (index.php) */
#main-search-input::placeholder { color: transparent; }
#main-search-input:placeholder-shown ~ #main-search-placeholder { display: flex !important; }

/* The rotating hint is pinned across the field's own box instead of being
   shrink-to-fit. It used to size itself to its text, and because the hint is
   nowrap it simply spilled out of that box — the tail ran off the right edge
   and under the sparkles / submit buttons. Pinned between the search glyph and
   the right-hand controls, the hint now truncates with an ellipsis the moment
   it runs out of room, on phones and on desktop alike. */
#main-search-placeholder {
  left: 0;
  right: 88px;          /* the visible right controls: 10 + 36 + 4 + 36 + 2 */
  padding-right: 0;     /* this id outranks the pr-5 utility — no double inset */
  overflow: hidden;
}
#main-search-placeholder-text {
  display: block;
  min-width: 0;         /* let the flex item shrink below its text width … */
  max-width: 100%;      /* … and stop at the label's own box */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 16px;
  font-weight: 400;
}

/* Focus reveal — index.php's strip, same 40px (mb-10) gap above the form and
   now the same 570px as the field it swaps with, so the strip's edges line up
   with the rounded box. Anchored to the bottom of the banner slot so the strip
   lands exactly where the banner's baseline is: the gap between the strip and
   the search form is identical whether the banner or the services show. */
.nn-hero-services {
  position: absolute;
  left: 50%;
  bottom: 40px;
  z-index: 2;
  width: 100%;
  max-width: 570px;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transform: translateX(-50%) translateY(15px);
  transition: opacity 0.4s ease, transform 0.4s ease, visibility 0.4s ease;
}
.nn-hero-services.show {
  opacity: 1 !important;
  visibility: visible !important;
  pointer-events: auto !important;
  transform: translateX(-50%) translateY(0) !important;
}
#home-hero-content { transition: opacity 0.25s ease; }
#home-hero-content.hide { opacity: 0 !important; pointer-events: none !important; }

@keyframes nn-magic-burst {
  0%   { transform: scale(1);    opacity: 1;   filter: blur(0); }
  50%  { transform: scale(1.25); opacity: 0.5; filter: blur(2px); }
  100% { transform: scale(1.6);  opacity: 0;   filter: blur(5px); }
}
.home-svc-link.burst { animation: nn-magic-burst 0.45s ease-out forwards; }

/* ==========================================================================
   2. Service rail — Niriv-style white pill bar, 5 most-viewed / admin picks
   ========================================================================== */
.nn-rail {
  display: flex;
  align-items: center;
  gap: 2px;
  margin-top: 14px;
  padding: 8px 8px;
  border-radius: 12px;
  background: hsl(var(--card));
  box-shadow: 0 2px 4px 0 rgb(0 0 0 / 0.04);
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.nn-rail::-webkit-scrollbar { display: none; }
.nn-rail-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 8px;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 600;
  color: hsl(var(--foreground));
  white-space: nowrap;
  text-decoration: none;
  transition: background 0.15s ease;
}
.nn-rail-item:hover { background: hsl(var(--muted)); }
.nn-rail-ico {
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 7px;
  background: hsl(var(--primary) / 0.12);
  color: hsl(var(--primary));
  flex: 0 0 22px;
}
.nn-rail-ico i, .nn-rail-ico svg { width: 13px; height: 13px; }
.nn-rail-item.is-text { font-weight: 500; color: hsl(var(--foreground) / 0.78); }
.nn-rail-sep {
  flex: 0 0 auto;
  width: 1px;
  height: 18px;
  margin: 0 5px;
  background: hsl(var(--border));
}
/* Rail → board gap. This collapses with the board's own 8px top margin (the
   two are adjacent siblings in a block wrapper), so 8px here is the gap you
   actually see — 18px read as a hole under the rail. Keep the two numbers equal
   or the larger one silently wins. */
.nn-rail { margin-bottom: 8px; }
.nn-rail-grow { flex: 1 0 12px; }
/* Phones: the rail is a card like every other section — it sits inside the same
   12px gutter and keeps its radius and hairline, rather than bleeding to the
   screen edges. It still scrolls sideways when the links outrun the width. */
@media (min-width: 1024px) { .nn-rail { flex-wrap: wrap; gap: 4px; } }

/* ==========================================================================
   2b. Promo row — the admin's image + text between the search form and the rail
   Laid out the way m.naver puts its promo under the search box: a small rounded
   thumbnail, two lines of copy beside it, the whole row centred with no card
   surface of its own, so it reads as part of the page rather than as a widget.
   Text-only and image-only both render sensibly (see page-newniguro.php).
   ========================================================================== */
.nn-promo {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  max-width: 1150px;
  margin: 0 auto 18px;
  padding-inline: 12px;
}
.nn-promo-media {
  display: block;
  flex: 0 0 auto;
  width: 76px;
  height: 76px;
  border-radius: 14px;
  overflow: hidden;
  /* No surface behind the artwork on purpose: it is just the admin's image,
     so a transparent or cut-out PNG sits straight on the page instead of on an
     accent-coloured card. The radius + overflow still clip it to the row's
     rounded shape. */
  background: transparent;
}
.nn-promo-media img { display: block; width: 100%; height: 100%; object-fit: cover; }
.nn-promo-body {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.nn-promo-title {
  font-size: 15px;
  font-weight: 700;
  letter-spacing: -0.2px;
  color: hsl(var(--foreground));
  text-decoration: none;
}
a.nn-promo-title:hover { text-decoration: underline; }
.nn-promo-sub {
  font-size: 13px;
  color: hsl(var(--muted-foreground));
}
@media (min-width: 640px) {
  .nn-promo { gap: 14px; margin-bottom: 22px; }
  .nn-promo-media { width: 84px; height: 84px; }
  .nn-promo-title { font-size: 16px; }
}

/* ==========================================================================
   3. The board — 1 column on phones, 2 at >=900px, 3 at >=1024px
   ========================================================================== */
.nn-board { display: flex; flex-direction: column; gap: 8px; margin: 8px 0 32px; }
.nn-col { display: contents; }
@media (min-width: 900px) {
  .nn-board {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px;
    align-items: start;
  }
  .nn-col { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
  .nn-col:nth-child(3) { grid-column: 1 / -1; }
  .nn-col:nth-child(3) > .nn-card { max-width: none; }
}
@media (min-width: 1024px) {
  .nn-board { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .nn-col:nth-child(3) { grid-column: auto; }
}

/* ── Card shell: the "whitest card" surface ───────────────────────────────── */
.nn-card {
  background: hsl(var(--card));
  border-radius: 14px;
  box-shadow: 0 2px 4px 0 rgb(0 0 0 / 0.04);
  overflow: hidden;
  min-width: 0;
}
.nn-card + .nn-card { margin-top: 0; }
.nn-card-body { padding: 12px 13px 14px; }

.nn-chead {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 11px 13px;
  border-bottom: 1px solid hsl(var(--border) / 0.75);
}
.nn-chead h3 {
  margin: 0;
  font-size: 14.5px;
  font-weight: 800;
  letter-spacing: -0.2px;
  color: hsl(var(--foreground));
}
.nn-chead h3 .nn-hi { color: hsl(var(--primary)); }
.nn-chead-ico { display: grid; place-items: center; width: 18px; height: 18px; color: hsl(var(--primary)); flex: 0 0 18px; }
.nn-chead-ico i, .nn-chead-ico svg { width: 15px; height: 15px; }
.nn-see {
  margin-left: auto;
  font-size: 11.5px;
  font-weight: 700;
  color: hsl(var(--primary));
  text-decoration: none;
  white-space: nowrap;
}
.nn-see:hover { text-decoration: underline; }

/* ── Variant: 2×2 tile grid (image + author chip + title) ─────────────────── */
.nn-tiles { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; padding: 12px 13px 14px; }
.nn-tile { display: flex; flex-direction: column; min-width: 0; text-decoration: none; }
/* Every media / label box below is a <span> in the markup: without an explicit
   display they stay inline, and inline boxes ignore aspect-ratio, width and the
   border-radius clipping — which is exactly how the actor / movie / tile media
   lost their rounding and their titles lost their spacing. */
.nn-tile-media {
  display: block;
  position: relative;
  aspect-ratio: 1 / 1;
  border-radius: 12px;
  overflow: hidden;
  background: hsl(var(--muted));
}
.nn-tile-media img { display: block; width: 100%; height: 100%; object-fit: cover; }
.nn-tile-scrim {
  position: absolute;
  inset: auto 0 0 0;
  height: 46%;
  background: linear-gradient(to top, rgb(0 0 0 / 0.72), rgb(0 0 0 / 0));
  pointer-events: none;
}
.nn-tile-title {
  margin-top: 7px;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.36;
  color: hsl(var(--foreground));
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.nn-tile:hover .nn-tile-title { color: hsl(var(--primary)); }
.nn-tile-excerpt {
  margin-top: 4px;
  font-size: 11.5px;
  line-height: 1.4;
  color: hsl(var(--muted-foreground));
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.nn-badge-play {
  position: absolute;
  top: 6px;
  right: 6px;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 3px 6px;
  border-radius: 999px;
  background: rgb(0 0 0 / 0.62);
  color: #fff;
  font-size: 9px;
  font-weight: 700;
}
.nn-badge-play i, .nn-badge-play svg { width: 10px; height: 10px; }

/* ── Variant: TOP ranking (numbered, 2 per row) ───────────────────────────── */
.nn-rank { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; padding: 12px 13px 14px; }
.nn-rank-item {
  position: relative;
  display: block;
  aspect-ratio: 3 / 4;
  border-radius: 12px;
  overflow: hidden;
  background: hsl(var(--muted));
  text-decoration: none;
}
.nn-rank-item img { display: block; width: 100%; height: 100%; object-fit: cover; }
.nn-rank-scrim {
  position: absolute;
  inset: auto 0 0 0;
  padding: 34px 8px 8px;
  background: linear-gradient(to top, rgb(0 0 0 / 0.9), rgb(0 0 0 / 0.45) 55%, rgb(0 0 0 / 0));
}
.nn-rank-num {
  position: absolute;
  top: 2px;
  left: 8px;
  font-size: 30px;
  font-weight: 900;
  font-style: italic;
  line-height: 1.1;
  color: #fff;
  text-shadow: 0 2px 10px rgb(0 0 0 / 0.6);
}
.nn-rank-title {
  font-size: 12.5px;
  font-weight: 700;
  line-height: 1.34;
  color: #fff;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ── Variant: surging (the numbered card, fed by the view stream) ────────────
   Same numbered tiles as TOP ranking, marked as the surging card: amber zap in
   the header (the colour /surging gives its surging chip) and a small view
   count on each tile so "surging" has a number behind it. */
.nn-card-surging .nn-chead-ico { color: hsl(35 92% 50%); }
.nn-card-surging .nn-chead-ico svg { fill: hsl(35 92% 50%); }
.nn-surging-views {
  position: absolute;
  top: 6px;
  right: 6px;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 3px 7px;
  border-radius: 999px;
  background: rgb(0 0 0 / 0.62);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
}
.nn-surging-views i, .nn-surging-views svg {
  width: 11px;
  height: 11px;
  fill: hsl(35 92% 50%);
  color: hsl(35 92% 50%);
}
/* A surging post with no image of its own: the accent wash the /surging page
   uses for its image-less blooms, so the tile still reads as a card. */
/* ── Picture-less stand-in ───────────────────────────────────────────────────
   A post with nothing to show keeps its box: the accent wash below, with the
   community's mark in the middle — its icon (an upload or its emoji), else the
   post kind's own glyph. The card stays a card instead of a hole in the
   column, and nothing in the grid shifts when a text-only post lands. */
.nn-rank-ph,
.nn-ph {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  overflow: hidden;
  background: radial-gradient(circle at 28% 22%, hsl(var(--primary) / 0.55), transparent 62%),
              linear-gradient(135deg, hsl(var(--primary)) 0%, hsl(var(--primary) / 0.85) 55%, hsl(var(--primary) / 0.65) 100%);
}
.nn-ph .nn-ph-emoji {
  font-size: 24px;
  line-height: 1;
  filter: drop-shadow(0 1px 3px rgb(0 0 0 / 0.45));
}
.nn-ph .nn-ph-icon {
  display: grid;
  place-items: center;
  color: hsl(var(--primary-foreground));
  opacity: 0.9;
}
.nn-ph .nn-ph-icon svg { width: 26px; height: 26px; stroke-width: 1.6; }
.nn-ph .nn-ph-img {
  width: 42%;
  height: auto;   /* the media boxes set height:100% on every img inside them */
  max-width: 96px;
  aspect-ratio: 1;
  border-radius: 999px;
  object-fit: cover;
  box-shadow: 0 0 0 2px hsl(var(--primary-foreground) / 0.55);
}
/* The tall cards carry the mark at a size a reader can read across the card;
   the 66px row thumb keeps it small, and the wide clip keeps it large. */
.nn-single-media .nn-ph .nn-ph-emoji,
.nn-photo .nn-ph .nn-ph-emoji,
.nn-video .nn-ph .nn-ph-emoji { font-size: 34px; }
.nn-single-media .nn-ph .nn-ph-icon svg,
.nn-photo .nn-ph .nn-ph-icon svg,
.nn-video .nn-ph .nn-ph-icon svg { width: 36px; height: 36px; }
.nn-row-media .nn-ph .nn-ph-emoji { font-size: 15px; }
.nn-row-media .nn-ph .nn-ph-icon svg { width: 16px; height: 16px; }
.nn-row-media .nn-ph .nn-ph-img { width: 34px; max-width: none; box-shadow: none; }

/* ── Author / meta rows ───────────────────────────────────────────────────── */
/* A member with no photo gets their initial in an accent circle. Defined here
   (not per context) so it keeps its circle and centring in the video chip, the
   story tile and anywhere else the avatar is dropped in. */
.nn-av-initial {
  display: grid;
  place-items: center;
  border-radius: 50%;
  font-weight: 800;
  line-height: 1;
  user-select: none;
  overflow: hidden;
}
.nn-arow { display: flex; align-items: center; gap: 8px; min-width: 0; }
.nn-arow-av { display: inline-flex; flex: 0 0 auto; border-radius: 50%; }
/* The name and its verified badge now live inside one link, so the flex row and
   its gap move to the anchor (the badge would otherwise lose the 4px spacing). */
.nn-arow-name a {
  display: flex;
  align-items: center;
  gap: 4px;
  min-width: 0;
  color: inherit;
  text-decoration: none;
}
.nn-arow-name a:hover { color: hsl(var(--primary)); }
.nn-arow .nn-av {
  width: 30px; height: 30px; border-radius: 50%; flex: 0 0 30px; object-fit: cover;
  background: hsl(var(--primary) / 0.14); color: hsl(var(--primary));
  display: grid; place-items: center; font-size: 12px; font-weight: 800;
}
.nn-arow-info { min-width: 0; flex: 1 1 auto; }
.nn-arow-name {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 12.5px;
  font-weight: 700;
  color: hsl(var(--foreground));
  line-height: 1.25;
}
.nn-arow-name span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nn-arow-name i, .nn-arow-name svg { width: 13px; height: 13px; flex: 0 0 13px; }
.nn-arow-meta { font-size: 11px; color: hsl(var(--muted-foreground)); line-height: 1.3; }

/* Reaction row — the theme's flame (upvote) + message-circle (comments) */
.nn-reactions { display: flex; align-items: center; gap: 14px; margin-top: 10px; font-size: 11.5px; color: hsl(var(--muted-foreground)); }
/* The news single card's flame / comment are the reader's own controls, so they
   get a step up from the 15px default. */
.nn-reactions.is-lg { gap: 20px; margin-top: 12px; font-size: 13.5px; }
.nn-reactions.is-lg .nn-react { gap: 7px; }
.nn-reactions.is-lg .nn-react i, .nn-reactions.is-lg .nn-react svg { width: 19px; height: 19px; }
.nn-reactions.is-lg .nn-react-flame i, .nn-reactions.is-lg .nn-react-flame svg { width: 21px; height: 21px; }
/* Vote button: a real .vote-btn for theme.js, styled as a plain icon + score. */
.nn-react-flame { background: none; border: 0; padding: 0; cursor: pointer; font: inherit; color: inherit; }
.nn-react-flame .nn-flame { color: hsl(var(--muted-foreground)); fill: hsl(var(--muted-foreground) / 0.2); transition: color 0.15s ease, fill 0.15s ease; }
.nn-react-flame:hover .nn-flame { color: hsl(var(--primary)); fill: hsl(var(--primary) / 0.35); }
.nn-reactions[data-user-vote="up"] .nn-react-flame .nn-flame { color: hsl(var(--primary)); fill: hsl(var(--primary)); }
.nn-reactions[data-user-vote="up"] .nn-react-flame .vote-score { color: hsl(var(--primary)); font-weight: 800; }
.nn-react-comments { text-decoration: none; }
.nn-react-comments:hover { color: hsl(var(--foreground)); }
.nn-react { display: inline-flex; align-items: center; gap: 5px; font-weight: 600; }
.nn-react i, .nn-react svg { width: 15px; height: 15px; }
.nn-react-flame i, .nn-react-flame svg { color: hsl(var(--primary)); fill: hsl(var(--primary) / 0.16); }
.nn-react-views { margin-left: auto; display: inline-flex; align-items: center; gap: 4px; }
.nn-react-views i, .nn-react-views svg { width: 13px; height: 13px; }

/* ── Post options menu (single-article card only) ─────────────────────────── */
.nn-opt-wrap { position: relative; flex: 0 0 auto; }
.nn-opt-btn {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: hsl(var(--muted-foreground));
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}
.nn-opt-btn:hover { background: hsl(var(--muted)); color: hsl(var(--foreground)); }
.nn-opt-btn i, .nn-opt-btn svg { width: 18px; height: 18px; }
.nn-opt-menu {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  z-index: 40;
  min-width: 176px;
  padding: 5px;
  border: 1px solid hsl(var(--border));
  border-radius: 10px;
  background: hsl(var(--card));
  box-shadow: 0 10px 24px rgb(0 0 0 / 0.12);
}
.nn-opt-menu[hidden] { display: none; }
.nn-opt-row {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  padding: 8px 9px;
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: hsl(var(--foreground));
  font-size: 12.5px;
  font-weight: 500;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}
.nn-opt-row:hover { background: hsl(var(--muted)); }
.nn-opt-row i, .nn-opt-row svg { width: 15px; height: 15px; }
/* The single.php share dropdown (desktop dropdown / native sheet on mobile)
   rendered as one row of this menu. */
.nn-opt-menu .nn-share-slot [data-share-toggle] {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  padding: 8px 9px;
  border-radius: 7px;
  font-size: 12.5px;
  font-weight: 500;
  color: hsl(var(--foreground));
}
.nn-opt-menu .nn-share-slot [data-share-toggle]:hover { background: hsl(var(--muted)); color: hsl(var(--foreground)); }
.nn-opt-menu .nn-share-slot [data-share-toggle]::after { content: "Share"; }
.nn-opt-menu .nn-share-slot [data-share-toggle] i,
.nn-opt-menu .nn-share-slot [data-share-toggle] svg { width: 15px; height: 15px; }
.nn-opt-menu .report-btn {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  padding: 8px 9px;
  border-radius: 7px;
  font-size: 12.5px;
  font-weight: 500;
  color: hsl(var(--foreground));
  text-align: left;
}
.nn-opt-menu .report-btn:hover { background: hsl(var(--muted)); color: hsl(var(--destructive)); }
.nn-opt-menu .report-btn i, .nn-opt-menu .report-btn svg { width: 15px; height: 15px; }

/* ── Variant: single article (excerpt + details + options) ────────────────── */
.nn-single-media {
  display: block;
  position: relative;
  margin-top: 10px;
  /* Portrait, and the shortest it has been: 8/9 of the body width (~437px at
     the phone measurement, down from 443px at 7/8). The clip card next to it is
     the tall one, so a story and a clip no longer compete for height — and the
     shorter the crop, the less the landscape source has to be stretched. */
  aspect-ratio: 8 / 9;
  border-radius: 12px;
  background: hsl(var(--muted));
  overflow: hidden;
}
.nn-single-media img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* "+3" when the post carries more gallery images than the one on show, the way
   a photo post counts its extras. */
.nn-media-more {
  position: absolute;
  top: 8px;
  right: 8px;
  display: inline-flex;
  align-items: center;
  padding: 3px 8px;
  border-radius: 999px;
  background: rgb(0 0 0 / 0.62);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  line-height: 1.2;
}
.nn-single-title {
  display: block;
  margin: 9px 0 5px;
  font-size: 16.5px;
  font-weight: 800;
  line-height: 1.32;
  letter-spacing: -0.3px;
  color: hsl(var(--foreground));
  text-decoration: none;
}
.nn-single-title:hover { color: hsl(var(--primary)); }
/* The single-story card carries no headline: the excerpt is the story text —
   two lines, hard ellipsis, a step larger than the same excerpt under a title. */
.nn-card-single .nn-single-text {
  display: -webkit-box;
  margin: 9px 0 0;
  font-size: 15px;
  font-weight: 400;
  line-height: 1.38;
  letter-spacing: -0.2px;
  color: hsl(var(--foreground));
  text-decoration: none;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
}
.nn-card-single .nn-single-text:hover { color: hsl(var(--primary)); }
/* The cafe photo card keeps its title but drops the excerpt, and the title is
   not emphasised — the two-up pictures are what the card is for. */
.nn-card-photos .nn-single-title { font-size: 15.5px; font-weight: 400; margin: 9px 0 0; }
.nn-single-excerpt {
  margin: 0;
  font-size: 12.5px;
  line-height: 1.5;
  color: hsl(var(--muted-foreground));
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.nn-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 7px;
  border-radius: 999px;
  background: hsl(var(--muted));
  color: hsl(var(--foreground) / 0.8);
  font-size: 10.5px;
  font-weight: 700;
}
.nn-single-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 9px; }

/* ── Variant: cafe photo post (2-up images, +N, dots) ─────────────────────── */
.nn-photos { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; margin-top: 10px; }
.nn-photos.is-single { grid-template-columns: 1fr; }
.nn-photo {
  position: relative;
  display: block;
  /* Taller tiles: cafe photo posts read like a Naver feed, not a square grid.
     2/3 is a step up from 5/7 (itself a step up from the 3/4 the actors and
     poster grids keep) — taller than them, but not the height of the clip
     card, and still short enough not to outrun the source images. */
  aspect-ratio: 2 / 3;
  border-radius: 12px;
  overflow: hidden;
  background: hsl(var(--muted));
}
.nn-photos.is-single .nn-photo { aspect-ratio: 16 / 9; }
.nn-photo img { display: block; width: 100%; height: 100%; object-fit: cover; }
.nn-photo-more {
  position: absolute;
  top: 6px;
  right: 6px;
  padding: 2px 7px;
  border-radius: 999px;
  background: rgb(0 0 0 / 0.6);
  color: #fff;
  font-size: 10.5px;
  font-weight: 700;
}
.nn-dots { display: flex; align-items: center; justify-content: center; gap: 5px; margin-top: 8px; }
.nn-dot { width: 5px; height: 5px; border-radius: 50%; background: hsl(var(--muted-foreground) / 0.28); }
.nn-dot.is-on { background: hsl(var(--foreground) / 0.55); }

/* ── Variant: cafe video (YouTube autoplay, muted) ────────────────────────── */
.nn-video {
  display: block; /* an <a>: without this the aspect-ratio box collapses */
  position: relative;
  margin-top: 0;
  width: 100%;
  /* The tall clip card — the tallest thing in a column, and now a clear step
     above the news single's image (~580px vs ~443px at the phone measurement).
     Vertical (Shorts) clips go taller still. */
  aspect-ratio: 5 / 7;
  border-radius: 12px;
  overflow: hidden;
  background: hsl(var(--muted));
}
.nn-video.is-wide { aspect-ratio: 16 / 9; }
.nn-video.is-portrait { aspect-ratio: 2 / 3; }
/* Direct child only: this is the poster still that fills the clip box. A bare
   `.nn-video img` also caught the author avatar inside the chip and pinned it
   absolute/inset:0, which dropped it out of the flex row and made it overlap
   the name. The poster is the only <img> directly inside .nn-video. */
.nn-video > img, .nn-video .nn-video-frame {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border: 0;
}
/* The player is a picture, not a control surface: nothing inside it can be
   hovered or clicked, so YouTube's title / channel / watch-later chrome never
   opens up. Sound is ours (the Sound on button above the frame). */
.nn-video .nn-video-frame { pointer-events: none !important; }
/* YouTube paints its own title / channel bar over the first frames of an embed
   and no parameter removes it, so the frame is scaled a little past the card and
   clipped by it — that strip falls outside the visible box. It also drops
   YouTube's edge padding, so the picture fills the card. */
.nn-video .nn-video-frame {
  transform: scale(1.25);
  transform-origin: center center;
}
/* The clip *is* the card: the media fills it edge to edge. */
.nn-card-video { padding: 0; }
.nn-card-video .nn-video { border-radius: inherit; }
/* While the embed plays, the poster must get out of the way — otherwise the
   <img> (later in the DOM) paints over the iframe and only the sound is heard. */
.nn-video.is-playing > img { opacity: 0; visibility: hidden; }
.nn-video .nn-video-frame { z-index: 1; }
.nn-video-play, .nn-video-sound, .nn-video-author, .nn-video-scrim { z-index: 2; }

/* Avatar + author name over the media, top-left. No time row: the clip shows a
   name while the board's other cards carry the age.

   The chip (and the Sound button) are siblings of the card's <a>, not children
   of it: the whole clip is one link to the post, so a profile link could not be
   nested inside. They resolve against .nn-card-video, which is the same box as
   .nn-video because the clip card has no padding. */
.nn-card-video { position: relative; }
.nn-video-author {
  position: absolute;
  top: 10px;
  left: 10px;
  right: 96px;
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  z-index: 3;
  text-decoration: none;
}
/* Decoration as a plain span; a real tap target once it is a link (it used to
   sit inside the card's link, which is why it never had to catch its own). */
span.nn-video-author { pointer-events: none; }
a.nn-video-author { pointer-events: auto; }
a.nn-video-author:hover .nn-video-author-name { text-decoration: underline; }
/* display:grid + place-items is what gives the avatar its box: without it a
   coloured-initial <span> stays inline, so width/height are ignored and the
   name slides under it. Same treatment as .nn-arow .nn-av. */
.nn-video-author .nn-av {
  width: 26px;
  height: 26px;
  min-width: 26px;
  border-radius: 50%;
  flex: 0 0 26px;
  object-fit: cover;
  display: grid;
  place-items: center;
  font-weight: 800;
  box-shadow: 0 1px 6px rgb(0 0 0 / 0.35);
}
.nn-video-author-info {
  display: flex;
  min-width: 0;
  flex: 1 1 0;
}
.nn-video-author-name {
  display: flex;
  align-items: center;
  gap: 4px;
  min-width: 0;
  font-size: 12.5px;
  font-weight: 700;
  color: #fff;
  text-shadow: 0 1px 6px rgb(0 0 0 / 0.55);
  line-height: 1.2;
}
.nn-video-author-name span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}
.nn-video-play {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: rgb(0 0 0 / 0.18);
  pointer-events: none;
}
.nn-video-play span {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: rgb(255 255 255 / 0.92);
  color: #111;
}
.nn-video-play i, .nn-video-play svg { width: 20px; height: 20px; margin-left: 2px; }
.nn-video.is-playing .nn-video-play { display: none; }
/* Sound control: hidden until the card is hovered (or the reader already turned
   sound on), so the clip stays clean. Touch devices have no hover, so there it
   is always visible. */
/* The button rides beside the card's link rather than inside it, so the hover
   root is the card and the state attribute is read off its sibling anchor. */
.nn-card-video .nn-video-sound { opacity: 0; pointer-events: none; transition: opacity 0.18s ease; }
.nn-card-video:hover .nn-video-sound,
.nn-card-video:focus-within .nn-video-sound,
.nn-video[data-nn-sound="on"] + .nn-video-sound { opacity: 1; pointer-events: auto; }
/* A device that cannot hover at all (a phone), and any device that has a touch
   screen at all (a laptop with a touch panel), shows it outright: on those the
   first tap comes with no hover to arm it, and the button would eat that tap. */
@media (hover: none), (any-pointer: coarse) {
  .nn-card-video .nn-video-sound { opacity: 1; pointer-events: auto; }
}
/* One label at a time: "Sound on" while muted, "Sound off" once it is playing
   with audio. */
.nn-video-sound .nn-snd-on { display: none; }
.nn-video[data-nn-sound="on"] + .nn-video-sound .nn-snd-off { display: none; }
.nn-video[data-nn-sound="on"] + .nn-video-sound .nn-snd-on { display: inline-flex; }
/* TikTok hands the host page no mute control, so the card's Sound button would
   be a lie on a TikTok clip. Its embed autoplays muted; sound belongs to the
   post view, which renders the full player. */
.nn-video[data-video-kind="tiktok"] + .nn-video-sound { display: none !important; }
.nn-video-scrim {
  position: absolute;
  inset: auto 0 0 0;
  padding: 40px 10px 11px;
  background: linear-gradient(to top, rgb(0 0 0 / 0.86), rgb(0 0 0 / 0.4) 55%, rgb(0 0 0 / 0));
  pointer-events: none;
}
.nn-video-title {
  font-size: 14px;
  font-weight: 800;
  line-height: 1.35;
  color: #fff;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.nn-video-sound {
  position: absolute;
  top: 8px;
  right: 8px;
  z-index: 3;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 9px;
  border: 0;
  border-radius: 999px;
  background: rgb(0 0 0 / 0.62);
  color: #fff;
  font-size: 10.5px;
  font-weight: 700;
  cursor: pointer;
}
.nn-video-sound i, .nn-video-sound svg { width: 12px; height: 12px; }
.nn-video-sound .nn-snd-off, .nn-video-sound .nn-snd-on {
  align-items: center;
  gap: 5px;
}
.nn-video-sound[hidden] { display: none; }

/* ── Variant: weather + market pill (the board's opening card) ─────────────── */
/* Same corner radius as every other card on the board (14px) — the pill's
   content is what makes it read as a pill, not a 999px radius. */
.nn-card-pill { border-radius: 14px; }
.nn-wpill {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 56px;
  padding: 9px 16px;
  overflow: hidden;
}

.nn-wpill.is-swap { opacity: 0.35; transition: opacity 0.2s ease; }
.nn-wpill-w {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  flex: 1 1 auto;
  text-decoration: none;
}
.nn-wpill-ico {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  flex: 0 0 26px;
  color: hsl(var(--primary));
}
.nn-wpill-ico svg, .nn-wpill-ico i { width: 22px; height: 22px; }
.nn-wpill-now {
  display: flex;
  align-items: baseline;
  gap: 5px;
  min-width: 0;
  font-size: 13.5px;
  color: hsl(var(--foreground));
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.nn-wpill-now b { font-size: 16px; font-weight: 800; letter-spacing: -0.2px; }
.nn-wpill-now span { font-weight: 600; }
.nn-wpill-sep {
  flex: 0 0 1px;
  width: 1px;
  align-self: stretch;
  margin-block: 8px;
  background: hsl(var(--border));
}
.nn-wpill-idx {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: 0 0 auto;
  text-decoration: none;
  color: hsl(var(--muted-foreground));
  white-space: nowrap;
}

.nn-wpill-idxname { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.4px; }
.nn-wpill-idxval { font-size: 15px; font-weight: 800; color: hsl(var(--foreground)); }
.nn-wpill-chg { font-size: 12px; font-weight: 700; }
.nn-wpill-chg.is-up { color: hsl(var(--primary)); }
.nn-wpill-chg.is-down { color: hsl(var(--destructive)); }
@media (max-width: 420px) {
  .nn-wpill { padding: 9px 12px; gap: 8px; }
  .nn-wpill-idxname { display: none; }
  .nn-wpill-now b { font-size: 15px; }

}

/* ── Variant: compact list rows (updates / blooms fallback) ───────────────── */
.nn-rows { display: flex; flex-direction: column; }
.nn-row {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 11px 13px;
  text-decoration: none;
  border-bottom: 1px solid hsl(var(--border) / 0.6);
}
.nn-row:last-child { border-bottom: 0; }
.nn-row:hover { background: hsl(var(--muted) / 0.5); }
.nn-row-media {
  display: block;
  position: relative;
  flex: 0 0 66px;
  width: 66px;
  height: 66px;
  border-radius: 9px;
  overflow: hidden;
  background: hsl(var(--muted));
}
.nn-row-media img { display: block; width: 100%; height: 100%; object-fit: cover; }
.nn-row-body { min-width: 0; flex: 1 1 auto; }
.nn-row-title {
  font-size: 13px;
  font-weight: 700;
  line-height: 1.36;
  color: hsl(var(--foreground));
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.nn-row:hover .nn-row-title { color: hsl(var(--primary)); }
.nn-row-meta { display: flex; align-items: center; gap: 8px; margin-top: 5px; font-size: 10.5px; color: hsl(var(--muted-foreground)); }
.nn-row-meta .nn-react { font-size: 10.5px; }
.nn-row-meta .nn-react i, .nn-row-meta .nn-react svg { width: 12px; height: 12px; }

/* ── Widget cards (Niriv homepage widget style, theme tokens) ───────────────
   Data reads as 2-column tiles, the way Naver's dashboard chips do: label on
   top, big value under it, unit beneath that. One column under 360px only. */
.nn-wrows { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; padding: 11px 13px 13px; }
.nn-wrow {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1px;
  min-width: 0;
  padding: 8px 10px 9px;
  border-radius: 10px;
  background: hsl(var(--muted) / 0.55);
}
.nn-wrow-label {
  font-size: 11px;
  font-weight: 600;
  line-height: 1.25;
  color: hsl(var(--muted-foreground));
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 100%;
}
.nn-wrow-value {
  font-size: 15px;
  font-weight: 800;
  line-height: 1.2;
  letter-spacing: -0.2px;
  color: hsl(var(--foreground));
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}
.nn-wrow-sub { display: block; font-size: 9.5px; font-weight: 500; color: hsl(var(--muted-foreground)); text-align: left; }
/* Fuel prices: two tiles (petrol, diesel) side by side and a full step taller
   than a normal widget row — there is room for it, since the card holds two
   numbers instead of three. */
.nn-card-fuel .nn-wrows { gap: 10px; padding: 12px 13px 14px; }
.nn-card-fuel .nn-wrow {
  justify-content: center;
  gap: 3px;
  min-height: 68px;
  padding: 14px 13px 15px;
  border-radius: 12px;
}
.nn-card-fuel .nn-wrow-label { font-size: 11.5px; }
.nn-card-fuel .nn-wrow-value { font-size: 17px; }
.nn-card-fuel .nn-wrow-sub { font-size: 10px; }
@media (max-width: 359px) {
  .nn-wrows { grid-template-columns: minmax(0, 1fr); }
}

/* ── Variant: the dated list (Nepal cricket fixtures, upcoming events) ─────
   Shared by the two cards whose rows are "a date on the left, what happens on
   the right". A list, not a 2-column tile grid: a fixture is two team names and
   an event is a festival name, neither of which survives being halved into a
   160px chip. Rows stay quiet so the card reads as part of the feed, and the
   date column is a fixed width so the titles line up down the card. */
.nn-wlist { display: flex; flex-direction: column; padding: 4px 6px 5px; }
.nn-wlist-row {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  padding: 8px 7px;
  border-radius: 10px;
  text-decoration: none;
  color: inherit;
}
.nn-wlist-row + .nn-wlist-row { box-shadow: inset 0 1px 0 0 hsl(var(--border) / 0.6); }
.nn-wlist-row:hover { background: hsl(var(--muted) / 0.55); }
.dark .nn-wlist-row:hover { background: hsl(var(--muted) / 0.38); }
.nn-wlist-when {
  flex: 0 0 56px;
  display: flex;
  flex-direction: column;
  gap: 0;
  min-width: 0;
}
/* The fixtures and events cards put the date and its qualifier on one line, so a
   row reads "date left, what it is right" as a single band instead of two short
   columns: a two-line date block over two lines of fixture is taller than the
   fixture needs, and on a phone that is most of a card. The band then sizes to
   its own text (`flex: 0 0 auto`) rather than to the 56px stacked version.

   The qualifier is the kick-off time on a fixture and the countdown (Today /
   in 31 days) on an event — in both cases it is date information, so it belongs
   with the date rather than under the event. */
.nn-card-fixtures .nn-wlist-when,
.nn-card-events .nn-wlist-when {
  flex: 0 0 auto;
  flex-direction: row;
  align-items: baseline;
  gap: 0;
  white-space: nowrap;
}
.nn-card-fixtures .nn-wlist-when b,
.nn-card-events .nn-wlist-when b { font-size: 11.5px; }
.nn-card-fixtures .nn-wlist-when b::after,
.nn-card-events .nn-wlist-when b::after {
  content: '\00b7';
  margin: 0 4px;
  color: hsl(var(--muted-foreground));
}
/* …but only when a second line actually followed: a fixture with no announced
   time would otherwise sit there with a stray separator after its date. */
.nn-wlist-when b:last-child::after { content: none; margin: 0; }
.nn-card-fixtures .nn-wlist-when span,
.nn-card-events .nn-wlist-when span { font-size: 11px; font-weight: 600; }

/* Both bands hold a minimum width, so every row's title starts at the same x.
   Without it "Mar 26 · 1:00 PM" and "Mar 28 · 12:00 PM" push their fixture text
   6px apart, and an events row carrying "Today" instead of "in 31 days" pulls
   its title 25px left of its neighbours — a list where the second column moves
   line by line reads as broken. The minimum is a floor, not a cap: a longer
   date ("Tomorrow · 12:00 PM") widens its own row. */
.nn-card-fixtures .nn-wlist-when { min-width: 104px; }
.nn-card-events .nn-wlist-when { min-width: 112px; }
.nn-wlist-when b {
  font-size: 12px;
  font-weight: 800;
  line-height: 1.25;
  color: hsl(var(--foreground));
  white-space: nowrap;
}
.nn-wlist-when span {
  font-size: 10px;
  font-weight: 600;
  line-height: 1.3;
  color: hsl(var(--muted-foreground));
  white-space: nowrap;
}
.nn-wlist-main { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1 1 auto; }
.nn-wlist-line {
  display: flex;
  align-items: baseline;
  gap: 5px;
  min-width: 0;
  font-size: 12.5px;
  font-weight: 700;
  line-height: 1.3;
  color: hsl(var(--foreground));
}
.nn-wlist-txt { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nn-wlist-line em {
  flex: 0 0 auto;
  font-style: normal;
  font-size: 10px;
  font-weight: 600;
  color: hsl(var(--muted-foreground));
  text-transform: lowercase;
}
.nn-wlist-sub {
  font-size: 10.5px;
  font-weight: 500;
  line-height: 1.3;
  color: hsl(var(--muted-foreground));
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.nn-wlist-foot {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 9px 13px 11px;
  border-top: 1px solid hsl(var(--border) / 0.75);
  font-size: 11.5px;
  font-weight: 700;
  color: hsl(var(--primary));
  text-decoration: none;
}
.nn-wlist-foot i, .nn-wlist-foot svg { width: 13px; height: 13px; }
.nn-wlist-foot:hover { text-decoration: underline; }

.nn-trends { display: flex; flex-direction: column; }
.nn-trend {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 13px;
  text-decoration: none;
  border-bottom: 1px solid hsl(var(--border) / 0.6);
}
.nn-trend:last-child { border-bottom: 0; }
.nn-trend:hover { background: hsl(var(--muted) / 0.5); }
.nn-trend-rank {
  flex: 0 0 18px;
  font-size: 13px;
  font-weight: 900;
  font-style: italic;
  color: hsl(var(--primary));
}
.nn-trend-kw { flex: 1 1 auto; min-width: 0; font-size: 13px; font-weight: 600; color: hsl(var(--foreground)); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nn-trend i, .nn-trend svg { width: 14px; height: 14px; color: hsl(var(--primary)); flex: 0 0 14px; }

.nn-signs { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 2px; padding: 8px 8px 11px; }
.nn-sign {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  padding: 8px 4px;
  border-radius: 9px;
  text-decoration: none;
  transition: background 0.15s ease;
}
.nn-sign:hover { background: hsl(var(--muted)); }
.nn-sign-ico { font-size: 17px; line-height: 1; color: hsl(var(--primary)); }
.nn-sign-name { font-size: 11.5px; font-weight: 700; color: hsl(var(--foreground)); }
.nn-sign-rashi { font-size: 10px; color: hsl(var(--muted-foreground)); }

/* ── Cinema: actors 2-up, posters 3-up ────────────────────────────────────── */
.nn-actors { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; padding: 12px 13px 14px; }
.nn-actors { align-items: start; }
.nn-actor { display: flex; flex-direction: column; text-decoration: none; min-width: 0; }
.nn-actor-media { display: block; position: relative; aspect-ratio: 3 / 4; border-radius: 12px; overflow: hidden; background: hsl(var(--muted)); }
.nn-actor-media img { display: block; width: 100%; height: 100%; object-fit: cover; }
.nn-actor-name { display: block; margin-top: 8px; font-size: 12.5px; font-weight: 700; line-height: 1.35; color: hsl(var(--foreground)); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nn-actor-known { display: block; margin-top: 2px; font-size: 10.5px; line-height: 1.35; color: hsl(var(--muted-foreground)); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nn-actor:hover .nn-actor-name { color: hsl(var(--primary)); }

/* Movies / cinema: 2×2, taller posters than the 3-up grid it used to be. */
.nn-posters { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; padding: 12px 13px 14px; align-items: start; }
.nn-poster { display: flex; flex-direction: column; text-decoration: none; min-width: 0; }
.nn-poster-media { display: block; position: relative; aspect-ratio: 3 / 4; border-radius: 12px; overflow: hidden; background: hsl(var(--muted)); }
.nn-poster-media img { display: block; width: 100%; height: 100%; object-fit: cover; }
.nn-poster-rate {
  position: absolute;
  left: 5px;
  bottom: 5px;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 2px 5px;
  border-radius: 5px;
  background: rgb(0 0 0 / 0.66);
  color: #fff;
  font-size: 9.5px;
  font-weight: 700;
}
.nn-poster-rate i, .nn-poster-rate svg { width: 9px; height: 9px; fill: currentColor; }
/* Dated poster tiles — Upcoming / New plus the date it refers to. The two sit in
   one absolutely-positioned row, so the tag can never drift away from its date
   or push past the tile's edge. */
.nn-poster-stamp {
  position: absolute;
  left: 5px;
  bottom: 5px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  max-width: calc(100% - 10px);
}
.nn-poster-tag {
  padding: 2px 5px;
  border-radius: 5px;
  background: hsl(var(--accent));
  color: hsl(var(--accent-foreground));
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  white-space: nowrap;
}
.nn-poster-date {
  padding: 2px 5px;
  border-radius: 5px;
  background: rgb(0 0 0 / 0.66);
  color: #fff;
  font-size: 9.5px;
  font-weight: 700;
  white-space: nowrap;
}
.nn-poster-title {
  display: block;
  margin-top: 8px;
  font-size: 12px;
  line-height: 1.35;
  font-weight: 600;
  line-height: 1.3;
  color: hsl(var(--foreground));
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.nn-poster:hover .nn-poster-title { color: hsl(var(--primary)); }

/* ── Dark theme: the "white card" model becomes a hairline surface ──────────
   Tokens already flip the fill (--card, --foreground, --border); only the
   soft light-theme drop shadow is meaningless on a dark page, so it is
   swapped for the theme's border token. Bright image overlays stay as they
   are — they sit on photos, not on the page background. */
.dark .nn-card,
.dark .nn-rail {
  box-shadow: none;
  border: 1px solid hsl(var(--border) / 0.7);
}
.dark .nn-tile-media,
.dark .nn-photo img,
.dark .nn-video,
.dark .nn-rank-media,
.dark .nn-actor-media,
.dark .nn-poster-media { background: hsl(var(--muted)); }
.dark .nn-wrow { background: hsl(var(--muted) / 0.38); }

/* ── Column auto-load indicator (three dots while a column fetches) ───────── */
/* Kept in flow (never display:none) so its position stays measurable even
   while the dots are invisible — a hidden element reports a zero rect and
   would otherwise trigger loads that the reader never asked for. */
/* Column end marker. Idle it is invisible but keeps a real box (the scroll
   observer needs a measurable rect); while a request is in flight it pulses and
   says so, and once the column is spent it keeps the end note on screen. */
.nn-more {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 14px 0 6px;
  min-height: 34px;
  opacity: 0;
  transition: opacity 0.2s ease;
}
.nn-more.is-on, .nn-more.is-error { opacity: 1; }
.nn-more.is-done { display: none; }
.nn-more-dots { display: inline-flex; align-items: center; gap: 5px; }
.nn-more.is-error .nn-more-dots { display: none; }
.nn-more.is-error .nn-more-txt { color: hsl(var(--destructive)); }
.nn-more-txt { font-size: 12px; font-weight: 600; text-align: center; color: hsl(var(--muted-foreground)); }

/* End of the feed: one note under the three columns, revealed by the loader
   once every column has stopped. */
.nn-end {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin: 24px 0 6px;
  padding-top: 18px;
  border-top: 1px solid hsl(var(--border) / 0.6);
  font-size: 12.5px;
  font-weight: 600;
  color: hsl(var(--muted-foreground));
}
.nn-end[hidden] { display: none; }
.nn-end-ico { display: inline-flex; }
.nn-end-ico i, .nn-end-ico svg { width: 16px; height: 16px; color: hsl(var(--primary)); }
.nn-more-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: hsl(var(--muted-foreground) / 0.45);
  animation: nn-more-pulse 1s ease-in-out infinite;
}
.nn-more-dot:nth-child(2) { animation-delay: 0.15s; }
.nn-more-dot:nth-child(3) { animation-delay: 0.3s; }
@keyframes nn-more-pulse {
  0%, 100% { opacity: 0.35; transform: translateY(0); }
  50%      { opacity: 1;    transform: translateY(-3px); }
}

/* Phones: the board is one stacked flow, so a column's end marker no longer
   marks the end of anything — it sits under the whole flow. Idle markers are
   taken out of the flow entirely, because three invisible 34px boxes would
   leave a gap before the end note for no reason. (The measurable box the
   scroll observer relies on only matters on desktop, and stays.) */
@media (max-width: 899.98px) {
  .nn-more { order: 999000; }
  .nn-more:not(.is-on):not(.is-error) { display: none; }
}

/* ── Empty-state helper ───────────────────────────────────────────────────── */
.nn-empty { padding: 18px 13px; text-align: center; font-size: 12.5px; color: hsl(var(--muted-foreground)); }

/* ── Live Now: an active live blog as one board card ─────────────────────── */
.nn-card-live { padding-bottom: 4px; }
.nn-live-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 11px 13px;
  border-bottom: 1px solid hsl(var(--border) / 0.75);
}
.nn-live-flag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex: 0 0 auto;
  padding: 4px 9px;
  border-radius: 999px;
  background: hsl(0 84% 60% / 0.12);
  color: hsl(0 84% 60%);
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.nn-live-pulse {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: currentColor;
  animation: nn-live-pulse 1.9s ease-out infinite;
}
@keyframes nn-live-pulse {
  0%   { box-shadow: 0 0 0 0 hsl(0 84% 60% / 0.5); }
  70%  { box-shadow: 0 0 0 8px hsl(0 84% 60% / 0); }
  100% { box-shadow: 0 0 0 0 hsl(0 84% 60% / 0); }
}
@media (prefers-reduced-motion: reduce) {
  .nn-live-pulse { animation: none; }
}
.nn-live-counts {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 11.5px;
  color: hsl(var(--muted-foreground));
}
.nn-live-media {
  position: relative;
  display: block;
  margin: 10px 12px 0;
  border-radius: 12px;
  overflow: hidden;
  background: hsl(var(--muted));
}
.nn-live-media img { display: block; width: 100%; aspect-ratio: 16 / 9; object-fit: cover; }
/* No featured picture on any live blog: keep the slot's shape rather than
   letting the card collapse into pure text. */
.nn-live-media-ph {
  display: flex;
  align-items: center;
  justify-content: center;
  /* A placeholder should not take a photograph's height: this is a band, not a
     picture, so the card stays a card when no live blog has an image. */
  height: 104px;
  background: linear-gradient(135deg, hsl(var(--primary) / 0.18), hsl(var(--muted)));
}
.nn-live-ph-lbl {
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: hsl(var(--muted-foreground));
}
.nn-live-media-badge {
  position: absolute;
  top: 8px;
  left: 8px;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 8px;
  border-radius: 999px;
  background: hsl(0 84% 60%);
  color: #fff;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.nn-live-media-badge .nn-live-pulse { background: #fff; animation: none; }
.nn-live-title {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin: 11px 12px 0;
  font-size: 15.5px;
  font-weight: 700;
  line-height: 1.32;
  color: hsl(var(--foreground));
  text-decoration: none;
}
.nn-live-excerpt {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin: 6px 12px 0;
  font-size: 13px;
  line-height: 1.5;
  color: hsl(var(--muted-foreground));
}

/* The updates timeline: a dot per event, coloured by its type. */
.nn-live-tl { margin: 11px 12px 0; border-top: 1px solid hsl(var(--border) / 0.75); }
.nn-live-ev {
  display: flex;
  gap: 9px;
  padding: 10px 0;
  border-bottom: 1px solid hsl(var(--border) / 0.6);
  color: inherit;
  text-decoration: none;
}
.nn-live-ev:last-child { border-bottom: 0; }
.nn-live-ev-dot {
  flex: 0 0 auto;
  width: 9px;
  height: 9px;
  margin-top: 5px;
  border-radius: 50%;
  background: hsl(var(--primary));
  box-shadow: 0 0 0 3px hsl(var(--primary) / 0.14);
}
.nn-live-ev.type-alert .nn-live-ev-dot { background: hsl(0 84% 60%); box-shadow: 0 0 0 3px hsl(0 84% 60% / 0.16); }
.nn-live-ev.type-photo .nn-live-ev-dot,
.nn-live-ev.type-video .nn-live-ev-dot { background: hsl(212 90% 58%); box-shadow: 0 0 0 3px hsl(212 90% 58% / 0.16); }
.nn-live-ev.type-quote .nn-live-ev-dot { background: hsl(280 70% 60%); box-shadow: 0 0 0 3px hsl(280 70% 60% / 0.16); }
.nn-live-ev.type-result .nn-live-ev-dot { background: hsl(142 62% 45%); box-shadow: 0 0 0 3px hsl(142 62% 45% / 0.16); }
.nn-live-ev-body { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.nn-live-ev-meta {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: hsl(var(--muted-foreground));
}
.nn-live-ev-meta b { font-weight: 800; }
.nn-live-ev-title { font-size: 14px; font-weight: 600; line-height: 1.35; color: hsl(var(--foreground)); }
.nn-live-ev-text { font-size: 12.5px; line-height: 1.5; color: hsl(var(--muted-foreground)); }
.nn-live-ev-media { display: flex; gap: 4px; margin-top: 6px; }
.nn-live-ev-shot { position: relative; display: block; }
.nn-live-ev-media img { display: block; width: 62px; height: 46px; border-radius: 8px; object-fit: cover; }
/* An update with more pictures than we show keeps the board's "+N" promise. */
.nn-live-ev-more {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  background: hsl(0 0% 0% / 0.55);
  color: #fff;
  font-size: 12px;
  font-weight: 800;
}
.nn-live-ev.is-newest .nn-live-ev-title { font-weight: 700; }

/* Arrives from the poll: the reader taps it rather than having the column jump. */
.nn-live-new {
  display: block;
  width: 100%;
  margin: 10px 0 0;
  padding: 8px 10px;
  border: 0;
  border-radius: 10px;
  background: hsl(var(--primary) / 0.12);
  color: hsl(var(--primary));
  font: inherit;
  font-size: 12px;
  font-weight: 700;
  cursor: pointer;
}
.nn-live-new[hidden] { display: none; }
.nn-live-more {
  display: flex;
  align-items: center;
  gap: 5px;
  margin: 0 12px;
  padding: 11px 0 12px;
  font-size: 12.5px;
  font-weight: 700;
  color: hsl(var(--primary));
  text-decoration: none;
}
.nn-live-more i, .nn-live-more svg { width: 14px; height: 14px; }
.nn-live-also { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; padding: 0 12px 12px; }
.nn-live-also-lbl {
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: hsl(var(--muted-foreground));
}
.nn-live-also a {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding: 3px 8px;
  border-radius: 999px;
  background: hsl(var(--accent));
  color: hsl(var(--foreground));
  font-size: 11.5px;
  text-decoration: none;
}
.nn-live-empty { margin: 0; padding: 12px 0; font-size: 12.5px; color: hsl(var(--muted-foreground)); }

/* ── Stories from Nigurians ──────────────────────────────────────────────── */
.nn-stories { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; padding: 10px 12px 12px; }
.nn-story {
  display: flex;
  flex-direction: column;
  min-width: 0;
  overflow: hidden;
  border-radius: 12px;
  background: hsl(var(--muted) / 0.32);
  color: inherit;
  text-decoration: none;
}
.nn-story-media { display: block; background: hsl(var(--muted)); }
.nn-story-media img { display: block; width: 100%; aspect-ratio: 4 / 3; object-fit: cover; }
.nn-story-media-ph {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 4 / 3;
  background: linear-gradient(135deg, hsl(var(--muted)), hsl(var(--accent)));
}
/* The cover-less story tile keeps its shape: a glyph, then the /Story label. */
.nn-story-media-ph { flex-direction: column; gap: 5px; }
.nn-story-media-ph .nn-story-ph-ico {
  display: grid;
  place-items: center;
  color: hsl(var(--muted-foreground) / 0.75);
}
.nn-story-media-ph .nn-story-ph-ico svg { width: 20px; height: 20px; stroke-width: 1.6; }
.nn-story-media-ph span {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: hsl(var(--muted-foreground) / 0.7);
}
.nn-story-body { display: flex; flex-direction: column; gap: 7px; padding: 9px 10px 11px; }
.nn-story-title {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.38;
  color: hsl(var(--foreground));
}
.nn-story-author { display: flex; align-items: center; gap: 5px; font-size: 11px; color: hsl(var(--muted-foreground)); }
.nn-story-author b { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.nn-story-author .nn-av { flex: 0 0 auto; width: 18px; height: 18px; border-radius: 50%; }
.nn-story-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  padding: 10px 12px 12px;
  border-top: 1px solid hsl(var(--border) / 0.7);
}
.nn-story-foot-lbl {
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: hsl(var(--muted-foreground));
}
.nn-story-avs { display: flex; }
.nn-story-avs a { display: inline-flex; margin-left: -6px; border-radius: 50%; }
.nn-story-avs a:first-child { margin-left: 0; }
/* niriv_user_avatar() emits an inline-sized div or img, so the pair overlaps
   on the avatar itself rather than on a class the helper does not add. */
.nn-story-avs a > * { border-radius: 50%; border: 2px solid hsl(var(--card)); }
.nn-story-write { margin-left: auto; font-size: 11.5px; font-weight: 700; color: hsl(var(--primary)); text-decoration: none; white-space: nowrap; }
