/* ==========================================================================
   Pengfeng site — news module styles
   Loaded after style.css on: news.html, news-detail.html, news-admin.html

   Kept in a separate file on purpose. style.css is the shared marketing
   shell at ~1700 lines; the news CMS has its own dense, form-heavy UI and
   mixing the two would make both harder to maintain.
   ========================================================================== */

/* The UA stylesheet implements [hidden] as `display:none`, but any author
   rule wins — and .nbtn / .nlogin__tab both set an explicit display. Without
   this, a hidden Cancel or Delete button is still visible. */
[hidden]{display:none !important}

/* --------------------------------------------------------------------------
   1. News list — states that only exist once data comes from the cloud
   -------------------------------------------------------------------------- */
/* Placeholder cards hold the layout while the cloud query is in flight, so
   the page does not jump when the real cards replace them. */
.nskeleton{
  background:#fff; border:1px solid var(--line); border-radius:var(--r-lg);
  overflow:hidden;
}
.nskeleton__thumb{aspect-ratio:16/9; background:var(--bg-soft)}
.nskeleton__body{padding:24px}
.nskeleton__line{
  height:13px; border-radius:6px; margin-bottom:12px;
  background:linear-gradient(90deg,var(--line-soft) 25%,#E8EEF6 50%,var(--line-soft) 75%);
  background-size:200% 100%;
  animation:nskeleton 1.3s linear infinite;
}
.nskeleton__line--title{height:19px; width:88%}
.nskeleton__line--short{width:58%}
@keyframes nskeleton{from{background-position:200% 0}to{background-position:-200% 0}}

/* The featured skeleton keeps the real .nfeat grid so the page does not
   reflow when the actual card replaces it. */
.nfeat--skeleton{pointer-events:none}
.nfeat--skeleton .nfeat__thumb{background:var(--bg-soft)}
.nfeat--skeleton .nfeat__body{padding:40px 38px}

/* Error / empty states. Hidden until the cloud query decides which one
   applies — never shown speculatively. */
.nstate{
  text-align:center; padding:64px 24px;
  border:1px dashed var(--line); border-radius:var(--r-lg);
  background:var(--bg-soft);
}
.nstate__ico{
  width:56px; height:56px; margin:0 auto 20px;
  display:grid; place-items:center; border-radius:var(--r-full);
  background:#fff; border:1px solid var(--line); color:var(--ink-400);
}
.nstate__ico svg{width:26px; height:26px}
.nstate h3{font-size:22px; color:var(--ink-900); margin-bottom:10px}
.nstate p{font-size:16.5px; color:var(--ink-500); max-width:52ch; margin:0 auto 22px}
.nstate--error .nstate__ico{color:#C0392B; border-color:#F0C4BE; background:#FDF3F2}

/* --------------------------------------------------------------------------
   2. News detail
   -------------------------------------------------------------------------- */
.narticle{padding:56px 0 72px}
.narticle__back{
  display:inline-flex; align-items:center; gap:8px;
  font-size:16px; font-weight:700; color:var(--ink-500);
  margin-bottom:28px; transition:color .18s;
}
.narticle__back:hover{color:var(--blue-600)}
.narticle__back svg{width:17px; height:17px; transform:rotate(180deg)}

.narticle__head{max-width:840px; margin-bottom:34px}
.narticle__head h1{
  font-size:42px; line-height:1.2; color:var(--ink-900);
  margin:16px 0 20px; letter-spacing:-.4px;
}
.narticle__meta{
  display:flex; align-items:center; gap:14px; flex-wrap:wrap;
  font-size:15px; font-weight:650; color:var(--ink-400);
  padding-top:18px; border-top:1px solid var(--line-soft);
}
/* Fixed 670×430 canvas rather than a full-bleed 16:9. The stored cover is
   already cropped to this exact ratio on upload, so stretching it to the
   container width only magnified it — on a 1200px screen a 670px image was
   being scaled up 1.8× and read soft. Pinning the box means the image is
   shown at the size it was compressed for, and the page keeps a stable
   layout before the image loads. */
.narticle__hero{
  border-radius:var(--r-xl); overflow:hidden; margin-bottom:38px;
  background:var(--bg-soft);
  width:670px; max-width:100%; aspect-ratio:670/430;
}
.narticle__hero img{width:100%; height:100%; object-fit:cover; display:block}

/* Body copy. Measure is capped at ~72ch — long-form industrial writing
   set any wider becomes hard to track back to the next line. */
.narticle__body{max-width:720px; font-size:18px; line-height:1.78; color:var(--ink-700)}
.narticle__body p{margin-bottom:22px}
.narticle__body p:last-child{margin-bottom:0}
.narticle__body a{color:var(--blue-600); text-decoration:underline}

.narticle__foot{
  max-width:720px; margin-top:48px; padding-top:28px;
  border-top:1px solid var(--line);
}
.narticle__footLabel{font-size:14px; font-weight:750; color:var(--ink-400); margin-bottom:14px}
.narticle__nav{display:flex; gap:14px; flex-wrap:wrap}
.narticle__nav a{
  flex:1 1 240px; min-width:0;
  padding:18px 20px; border:1px solid var(--line); border-radius:var(--r-md);
  background:#fff; transition:all .2s;
}
.narticle__nav a:hover{border-color:var(--blue-300); box-shadow:var(--sh-2)}
.narticle__nav span{
  display:block; font-size:13.5px; font-weight:700; color:var(--ink-400); margin-bottom:5px;
}
.narticle__nav b{
  display:block; font-size:16px; font-weight:700; color:var(--ink-900);
  line-height:1.4; overflow:hidden; text-overflow:ellipsis;
  display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical;
}

/* --------------------------------------------------------------------------
   3. Admin shell
   -------------------------------------------------------------------------- */
.nadmin{padding:40px 0 80px; background:var(--bg-soft); min-height:100vh}
.nadmin__bar{
  background:#fff; border:1px solid var(--line); border-radius:var(--r-lg);
  padding:22px 26px; margin-bottom:26px;
  display:flex; align-items:center; gap:20px; flex-wrap:wrap;
}
.nadmin__bar h1{font-size:23px; margin:0; flex:1; min-width:200px}
.nadmin__bar p{font-size:14.5px; color:var(--ink-500); margin-top:5px; font-weight:500}
.nadmin__who{
  display:flex; align-items:center; gap:11px;
  font-size:14.5px; color:var(--ink-500); font-weight:650;
}
.nadmin__who b{color:var(--ink-900); font-weight:750}

.nadmin__layout{display:grid; grid-template-columns:1fr 400px; gap:26px; align-items:start}

.npanel{
  background:#fff; border:1px solid var(--line); border-radius:var(--r-lg);
  overflow:hidden;
}
.npanel__head{
  padding:20px 24px; border-bottom:1px solid var(--line-soft);
  display:flex; align-items:center; gap:14px;
}
.npanel__head h2{font-size:18px; margin:0; flex:1}
.npanel__body{padding:24px}
.npanel__body--flush{padding:0}

/* ---- Login ---- */
.nlogin{max-width:520px; margin:56px auto}
.nlogin__tabs{display:flex; gap:6px; padding:6px; background:var(--bg-soft); border-radius:var(--r-md); margin-bottom:24px}
.nlogin__tab{
  flex:1; padding:11px 14px; border:none; background:transparent; cursor:pointer;
  border-radius:var(--r-sm); font-size:15px; font-weight:700; color:var(--ink-500);
  font-family:inherit; transition:all .16s;
}
.nlogin__tab.is-on{background:#fff; color:var(--navy-800); box-shadow:var(--sh-1)}

.nlogin__hint{
  background:var(--blue-50); border:1px solid var(--blue-100);
  border-radius:var(--r-md); padding:15px 17px; margin-bottom:22px;
  font-size:14.5px; color:var(--blue-700); line-height:1.6;
}
.nlogin__hint b{font-weight:750}
.nlogin__hint code{
  font-family:var(--mono); font-size:13px; background:#fff;
  padding:2px 6px; border-radius:4px; border:1px solid var(--blue-100);
}

/* ---- Form primitives ---- */
.nfld{margin-bottom:18px}
.nfld label{display:block; font-size:14.5px; font-weight:700; color:var(--ink-700); margin-bottom:8px}
.nfld label em{color:var(--accent); font-style:normal}
.nfld input[type=text],.nfld input[type=email],.nfld input[type=password],
.nfld input[type=date],.nfld textarea,.nfld select{
  width:100%; padding:12px 14px; border:1.5px solid var(--line);
  border-radius:var(--r-sm); font-family:inherit; font-size:15.5px;
  color:var(--ink-900); background:#fff; transition:border-color .16s;
}
.nfld textarea{resize:vertical; min-height:110px; line-height:1.65}
.nfld textarea.nfld__body{min-height:280px; font-size:15.5px}
.nfld input:focus,.nfld textarea:focus,.nfld select:focus{
  outline:none; border-color:var(--blue-500);
  box-shadow:0 0 0 3px rgba(43,130,245,.12);
}
.nfld small{display:block; font-size:13px; color:var(--ink-400); margin-top:6px; line-height:1.5}
.nfld--row{display:grid; grid-template-columns:1fr 1fr; gap:14px}

.ncheck{display:flex; align-items:flex-start; gap:11px; cursor:pointer; padding:14px 0}
.ncheck input{width:19px; height:19px; margin-top:1px; accent-color:var(--blue-600); flex:none; cursor:pointer}
.ncheck b{display:block; font-size:15px; font-weight:700; color:var(--ink-800)}
.ncheck span{display:block; font-size:13.5px; color:var(--ink-500); margin-top:3px; line-height:1.5}

/* ---- Buttons ---- */
.nbtn{
  display:inline-flex; align-items:center; justify-content:center; gap:8px;
  padding:12px 20px; border-radius:var(--r-sm); border:1.5px solid transparent;
  font-family:inherit; font-size:15px; font-weight:750; cursor:pointer;
  transition:all .16s; white-space:nowrap;
}
.nbtn svg{width:16px; height:16px}
.nbtn--primary{background:var(--blue-600); color:#fff}
.nbtn--primary:hover:not(:disabled){background:var(--blue-700)}
.nbtn--ghost{background:#fff; border-color:var(--line); color:var(--ink-700)}
.nbtn--ghost:hover:not(:disabled){border-color:var(--blue-300); color:var(--blue-700)}
.nbtn--danger{background:#fff; border-color:#F0C4BE; color:#C0392B}
.nbtn--danger:hover:not(:disabled){background:#FDF3F2; border-color:#C0392B}
.nbtn--sm{padding:8px 13px; font-size:13.5px}
.nbtn--block{width:100%}
.nbtn:disabled{opacity:.5; cursor:not-allowed}
.nbtn__row{display:flex; gap:10px; flex-wrap:wrap}
.nbtn__row .nbtn{flex:1}

/* ---- Status banner ---- */
.nmsg{
  padding:14px 16px; border-radius:var(--r-sm); font-size:14.5px;
  font-weight:650; margin-bottom:18px; line-height:1.55;
  display:none; align-items:flex-start; gap:10px;
}
.nmsg svg{width:18px; height:18px; flex:none; margin-top:1px}
.nmsg.is-on{display:flex}
.nmsg--ok{background:var(--green-50); color:#0A6E4C; border:1px solid #B6E6D4}
.nmsg--err{background:#FDF3F2; color:#9B2C1F; border:1px solid #F0C4BE}
.nmsg--busy{background:var(--blue-50); color:var(--blue-700); border:1px solid var(--blue-100)}

/* ---- Editor row list ---- */
.nlist{display:flex; flex-direction:column}
.nrow{
  display:flex; gap:16px; align-items:center;
  padding:16px 24px; border-bottom:1px solid var(--line-soft);
  transition:background .14s;
}
.nrow:last-child{border-bottom:none}
.nrow:hover{background:var(--bg-soft)}
.nrow.is-editing{background:var(--blue-50); box-shadow:inset 3px 0 0 var(--blue-600)}
.nrow__thumb{
  width:88px; height:60px; border-radius:var(--r-xs); flex:none;
  background:var(--bg-soft); object-fit:cover; overflow:hidden;
  border:1px solid var(--line);
}
.nrow__thumb img{width:100%; height:100%; object-fit:cover; display:block}
.nrow__main{flex:1; min-width:0}
.nrow__title{
  font-size:15.5px; font-weight:700; color:var(--ink-900);
  margin-bottom:5px; line-height:1.4;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.nrow__meta{display:flex; align-items:center; gap:10px; flex-wrap:wrap; font-size:13px; color:var(--ink-400); font-weight:600}
.nrow__acts{display:flex; gap:7px; flex:none}

.nbadge{
  padding:3px 9px; border-radius:var(--r-full);
  font-size:11.5px; font-weight:800; letter-spacing:.2px;
}
.nbadge--published{background:var(--green-50); color:#0A6E4C}
.nbadge--draft{background:var(--bg-soft); color:var(--ink-500); box-shadow:inset 0 0 0 1px var(--line)}
.nbadge--featured{background:var(--accent-50); color:var(--accent-600)}

.nlist__empty{padding:52px 24px; text-align:center; color:var(--ink-400); font-size:15px}

/* ---- News pager ----
   The pager classes themselves live in style.css, where the product
   catalogue already uses them. Only the two news-specific pieces are added
   here: the ellipsis that stands in for a skipped run of page numbers, and
   the spacing between the grid and the pager. */
.pager__gap{
  display:inline-flex; align-items:center; justify-content:center;
  min-width:28px; height:46px;
  font-size:14.5px; font-weight:700; color:var(--ink-400);
}
#pfNewsPager{margin-top:40px}
#pfNewsPager[hidden]{display:none !important}

/* ---- Category filter ----
   The pills themselves are styled in style.css, where the public News page
   uses them. The admin panel gets the same look at a smaller scale: it
   sits inside a column that is half the width of the page and holds a
   150-row list, so the public size would eat the panel's width and pull
   the attention away from the rows.

   news.css is loaded after style.css, so these rules win at equal
   specificity without needing !important. */
.nfilters--admin{
  justify-content:flex-start; flex-wrap:wrap; gap:8px;
  margin:0; padding:14px 20px;
  border-bottom:1px solid var(--line-soft); background:#fff;
}
.nfilters--admin .nfilter{
  padding:8px 14px; font-size:13.5px; gap:7px; border-width:1px;
}
.nfilters--admin .nfilter svg{width:15px; height:15px}
.nfilters--admin .nfilter b{font-size:11.5px}

/* ---- Bulk selection toolbar ----
   The select-all checkbox and the "Delete selected" button sit in their own
   bar above the rows rather than inside the panel head, because they only
   mean anything while rows are on screen and the head also carries the
   article count. */
.nbulk{
  display:flex; align-items:center; gap:14px; flex-wrap:wrap;
  padding:12px 24px; border-bottom:1px solid var(--line-soft);
  background:var(--bg-soft);
}
.nbulk__label{
  display:inline-flex; align-items:center; gap:9px;
  font-size:13.5px; font-weight:700; color:var(--ink-700); cursor:pointer;
  user-select:none;
}
.nbulk__count{font-size:13.5px; font-weight:650; color:var(--ink-400)}
.nbulk__spacer{flex:1}
.nbulk[hidden]{display:none !important}

/* The checkbox itself is styled rather than left to the browser default,
   so a 16px tick at this density is still visible against a 60px thumbnail. */
.ncheck{
  width:18px; height:18px; margin:0; flex:none;
  accent-color:var(--blue-600); cursor:pointer;
}
.nrow__pick{
  display:flex; align-items:center; justify-content:center; flex:none;
  padding-right:2px;
}
.nrow.is-picked{background:var(--blue-50)}

/* ---- Image picker ---- */
.ndrop{
  border:2px dashed var(--line); border-radius:var(--r-md);
  padding:28px 20px; text-align:center; cursor:pointer;
  transition:all .16s; background:var(--bg-soft);
}
.ndrop:hover,.ndrop.is-over{border-color:var(--blue-500); background:var(--blue-50)}
.ndrop__ico{width:38px; height:38px; margin:0 auto 12px; color:var(--ink-400)}
.ndrop b{display:block; font-size:15px; color:var(--ink-700); margin-bottom:5px}
.ndrop span{font-size:13.5px; color:var(--ink-400)}
.ndrop input{display:none}

.npreview{
  margin-top:14px; border-radius:var(--r-md); overflow:hidden;
  border:1px solid var(--line); background:var(--bg-soft); display:none;
}
.npreview.is-on{display:block}
/* Matches the stored 670×430 cover and the .narticle__hero box, so what the
   editor approves in this preview is the crop the reader will see. */
.npreview img{width:100%; display:block; aspect-ratio:670/430; object-fit:cover}
.npreview__bar{
  padding:10px 14px; font-size:13px; color:var(--ink-500);
  display:flex; align-items:center; justify-content:space-between; gap:12px;
  border-top:1px solid var(--line-soft); background:#fff;
}
.nclear{
  background:none; border:none; padding:0; cursor:pointer;
  font-family:inherit; font-size:13px; font-weight:700; color:#C0392B;
}
.nclear:hover{text-decoration:underline}

/* ---- Character counter ---- */
.ncount{
  display:flex; justify-content:flex-end; gap:10px;
  font-size:12.5px; color:var(--ink-400); font-weight:650;
  margin-top:6px; font-family:var(--mono);
}
.ncount.is-warn{color:var(--accent-600)}

/* --------------------------------------------------------------------------
   4. Responsive
   -------------------------------------------------------------------------- */
@media (max-width:1080px){
  .nadmin__layout{grid-template-columns:1fr}
  .narticle__head h1{font-size:36px}
}

@media (max-width:760px){
  .narticle{padding:32px 0 48px}
  .narticle__head h1{font-size:29px; line-height:1.25}
  .narticle__hero{margin-bottom:28px; border-radius:var(--r-lg)}
  .narticle__body{font-size:17px; line-height:1.72}
  .nadmin{padding:24px 0 56px}
  .nadmin__bar{padding:18px 20px; gap:14px}
  .nadmin__bar h1{font-size:20px}
  .nfld--row{grid-template-columns:1fr; gap:0}
  .nlogin{margin:32px auto}
  .nrow{padding:14px 18px; gap:12px}
  .nrow__thumb{width:64px; height:46px}
  .nrow__acts{flex-direction:column}
  .nrow__acts .nbtn{width:100%}
  .npanel__body{padding:18px}
  .npanel__head{padding:16px 18px}
}
/* --------------------------------------------------------------------------
   4b. Article body content

   The body can now carry headings, lists, quotes, tables and images. Only
   paragraph spacing existed before, so everything else renders with the
   browser's defaults — which means a table inside an article sits flush
   against the text with no breathing room and an <h2> breaks the vertical
   rhythm of the page. These rules restore it, using the site's own spacing
   scale so an article reads like the rest of the site.
   ------------------------------------------------------------------------ */

.narticle__body{overflow-wrap:break-word}
.narticle__body h2{
  font-size:26px; font-weight:780; line-height:1.3;
  color:var(--ink-900); margin:38px 0 14px;
}
.narticle__body h3{
  font-size:21px; font-weight:750; line-height:1.36;
  color:var(--ink-900); margin:32px 0 12px;
}
.narticle__body h4{
  font-size:18.5px; font-weight:730; line-height:1.4;
  color:var(--ink-800); margin:26px 0 10px;
}
/* A reader who clicks a heading link or an in-page anchor should not land
   under the sticky header, so the first heading gets its natural spacing back. */
.narticle__body > h2:first-child,
.narticle__body > h3:first-child,
.narticle__body > h4:first-child{margin-top:0}

.narticle__body h2,.narticle__body h3,.narticle__body h4{scroll-margin-top:88px}

.narticle__body ul,.narticle__body ol{margin:0 0 22px; padding-left:26px}
.narticle__body li{margin-bottom:9px}
.narticle__body li::marker{color:var(--blue-600)}

.narticle__body blockquote{
  margin:28px 0; padding:18px 24px;
  border-left:3px solid var(--blue-500);
  background:var(--blue-50,#eff6ff);
  border-radius:0 var(--r-md) var(--r-md) 0;
  color:var(--ink-700); font-size:17.5px;
}
.narticle__body blockquote p:last-child{margin-bottom:0}

.narticle__body code{
  font-family:var(--mono,ui-monospace,monospace);
  font-size:.86em; background:var(--ink-100,#eef2f6);
  padding:2px 7px; border-radius:4px; color:var(--ink-800);
}
.narticle__body pre{
  margin:26px 0; padding:20px 22px;
  background:var(--ink-900); color:#e2e8f0;
  border-radius:var(--r-md); overflow-x:auto;
  font-size:14.5px; line-height:1.6;
}
.narticle__body pre code{background:none; color:inherit; padding:0; font-size:inherit}

.narticle__body hr{margin:38px 0; border:0; border-top:1px solid var(--line)}

.narticle__body figure{margin:30px 0}
.narticle__body figure img{
  width:100%; height:auto; display:block;
  border-radius:var(--r-md);
}
.narticle__body figcaption{
  margin-top:11px; font-size:14.5px; color:var(--ink-400);
  text-align:center; line-height:1.55;
}

.narticle__body table{
  width:100%; border-collapse:collapse; margin:26px 0;
  font-size:15.5px; display:block; overflow-x:auto;
}
.narticle__body th,.narticle__body td{
  border:1px solid var(--line); padding:11px 15px;
  text-align:left; vertical-align:top;
}
.narticle__body th{
  background:var(--ink-50,#f8fafc);
  font-weight:730; color:var(--ink-800); white-space:nowrap;
}
.narticle__body tbody tr:nth-child(even){background:#fcfdfe}

.narticle__body a[target=_blank]::after{
  content:' ↗'; font-size:.82em; opacity:.6;
}

@media (max-width:640px){
  .narticle__body h2{font-size:22px; margin-top:30px}
  .narticle__body h3{font-size:19px; margin-top:26px}
  .narticle__body blockquote{padding:15px 18px; font-size:16.5px}
  .narticle__body table{font-size:14.5px}
}

/* --------------------------------------------------------------------------
   5. Rich-text editor

   The article body is a contenteditable surface rather than a textarea, so
   the editor sees the text laid out as it will appear on the article. The
   styles below therefore have two jobs: make the editing surface readable, and
   make it look like the article page — because an editor that looks different
   from the result cannot tell whether their formatting worked.
   ------------------------------------------------------------------------ */

.nrich{
  border:1.5px solid var(--line);
  border-radius:var(--r-sm);
  background:#fff;
  overflow:hidden;
  transition:border-color .16s, box-shadow .16s;
}
.nrich:focus-within{
  border-color:var(--blue-500);
  box-shadow:0 0 0 3px rgba(43,130,245,.12);
}

/* ---- Toolbar ---- */
.nrich__bar{
  display:flex; align-items:center; flex-wrap:wrap; gap:2px;
  padding:7px 8px;
  background:var(--ink-50,#f8fafc);
  border-bottom:1px solid var(--line);
  /* The toolbar must stay visible while the editor is scrolled: an editor who
     has to scroll back up to reach Bold stops using it. */
  position:sticky; top:0; z-index:3;
}
.nrich__bar.is-off{opacity:.4; pointer-events:none}

.nrich__btn{
  min-width:31px; height:31px; padding:0 7px;
  display:inline-flex; align-items:center; justify-content:center;
  border:1px solid transparent; border-radius:var(--r-sm);
  background:transparent; color:var(--ink-600);
  font-family:inherit; font-size:13.5px; font-weight:700;
  cursor:pointer; transition:background .13s, color .13s;
}
.nrich__btn:hover{background:#fff; border-color:var(--line); color:var(--ink-900)}
.nrich__btn.is-on{background:var(--blue-600); border-color:var(--blue-600); color:#fff}

/* The B/I/U/S buttons are letters, so each needs its own typographic voice or
   four of them read as four identical buttons. */
.nrich__btn.is-b{font-weight:850}
.nrich__btn.is-i{font-style:italic; font-family:var(--serif,Georgia,serif)}
.nrich__btn.is-u{text-decoration:underline}
.nrich__btn.is-s{text-decoration:line-through}

.nrich__sep{
  width:1px; height:19px; margin:0 5px;
  background:var(--line);
}

/* ---- Editing surface ---- */
.nrich__surface{
  min-height:340px; max-height:64vh; overflow-y:auto;
  padding:20px 22px;
  font-size:16px; line-height:1.72; color:var(--ink-800);
  outline:none;
}
/* Placeholder via :empty rather than a real placeholder attribute, which a
   contenteditable element does not show once it has been clicked into even
   when emptied again. */
.nrich__surface:empty::before{
  content:attr(data-placeholder);
  color:var(--ink-300,#cbd5e1);
  pointer-events:none;
}
.nrich__surface.is-raw{
  font-family:var(--mono,ui-monospace,monospace);
  font-size:13.5px; line-height:1.7;
  white-space:pre-wrap; word-break:break-word;
  background:#fbfcfd;
}
.nrich__surface.is-drop{background:var(--blue-50,#eff6ff)}

/* The source textarea. Visually hidden but still a real form control, so the
   field stays in the POST body and the required attribute still works. It is
   not display:none — a display:none textarea is barred from constraint
   validation, which would silently drop the required-field check. */
.nrich__source{
  position:absolute; width:1px; height:1px;
  padding:0; margin:-1px; overflow:hidden;
  clip:rect(0 0 0 0); white-space:nowrap; border:0;
}

/* ---- Content inside the editing surface ----
   These mirror .narticle__body on the article page, so what the editor sees
   is what a reader gets. */
.nrich__surface p{margin:0 0 14px}
.nrich__surface p:last-child{margin-bottom:0}
.nrich__surface h2{font-size:22px; font-weight:780; margin:26px 0 11px; color:var(--ink-900); line-height:1.32}
.nrich__surface h3{font-size:18.5px; font-weight:750; margin:22px 0 9px; color:var(--ink-900); line-height:1.36}
.nrich__surface h4{font-size:16.5px; font-weight:730; margin:18px 0 8px; color:var(--ink-800)}
.nrich__surface h2:first-child,.nrich__surface h3:first-child{margin-top:0}
.nrich__surface ul,.nrich__surface ol{margin:0 0 14px; padding-left:26px}
.nrich__surface li{margin-bottom:6px}
.nrich__surface blockquote{
  margin:18px 0; padding:12px 18px;
  border-left:3px solid var(--blue-500);
  background:var(--blue-50,#eff6ff);
  color:var(--ink-700); border-radius:0 var(--r-sm) var(--r-sm) 0;
}
.nrich__surface blockquote p:last-child{margin-bottom:0}
.nrich__surface code{
  font-family:var(--mono,ui-monospace,monospace);
  font-size:.88em; background:var(--ink-100,#eef2f6);
  padding:2px 6px; border-radius:4px;
}
.nrich__surface pre{
  margin:16px 0; padding:15px 17px;
  background:var(--ink-900); color:#e2e8f0;
  border-radius:var(--r-sm); overflow-x:auto;
}
.nrich__surface pre code{background:none; color:inherit; padding:0}
.nrich__surface a{color:var(--blue-600); text-decoration:underline}
.nrich__surface hr{margin:26px 0; border:0; border-top:1px solid var(--line)}
.nrich__surface img{max-width:100%; height:auto; border-radius:var(--r-sm); display:block}
.nrich__surface img.is-dragging{opacity:.4; outline:2px dashed var(--blue-500)}
.nrich__surface figure{margin:22px 0}
.nrich__surface figcaption{
  margin-top:8px; font-size:13.5px; color:var(--ink-400);
  line-height:1.5; text-align:center;
}
.nrich__surface figcaption:focus{
  outline:2px solid var(--blue-500); outline-offset:3px;
  border-radius:3px; color:var(--ink-600);
}
.nrich__surface table{
  width:100%; border-collapse:collapse; margin:18px 0; font-size:14.5px;
}
.nrich__surface th,.nrich__surface td{
  border:1px solid var(--line); padding:9px 12px; text-align:left;
}
.nrich__surface th{background:var(--ink-50,#f8fafc); font-weight:730}

/* ---- Footer: word count and status ---- */
.nrich__foot{
  display:flex; align-items:center; justify-content:space-between;
  gap:14px; flex-wrap:wrap;
  padding:9px 12px;
  border-top:1px solid var(--line);
  background:var(--ink-50,#f8fafc);
}
.nrich__foot .ncount{margin-top:0}
.nrich__status{
  font-size:12.5px; font-weight:650; color:var(--ink-400);
}
.nrich__status.is-busy{color:var(--blue-600)}
.nrich__status.is-err{color:var(--accent-600)}

/* On a phone the toolbar wraps to two rows, which is fine; the editing surface
   is shortened instead, because a 64vh box on a small screen leaves almost no
   room above the keyboard. */
@media (max-width:640px){
  .nrich__surface{min-height:260px; max-height:52vh; padding:16px}
  .nrich__btn{min-width:29px; height:29px; font-size:13px}
  .nrich__sep{margin:0 3px}
}

/* The delete button is the only irreversible action on a row, so it is set
   apart from the status buttons rather than sitting beside them. A row of
   random text is easy to delete by accident, and the gap is what stops the
   tap from landing there. */
.iqrow__acts .iqrow__del{margin-left:auto}

/* ==========================================================================
   Per-article SEO fields

   A block of its own rather than three loose inputs at the bottom of a long
   form: it is optional, and optional fields that look like required ones get
   filled in badly. The tinted background and its own heading mark it as the
   section that changes how the page ranks rather than what it says.
   ========================================================================== */
.nseo{
  background:var(--blue-50, #f5f8fd);
  border:1px solid var(--blue-100, #dfe8f6);
  border-radius:14px;
  padding:18px 18px 6px;
  margin-top:24px;
}
.nseo__head{
  display:flex; align-items:baseline; gap:10px; flex-wrap:wrap;
  margin-bottom:16px;
}
.nseo__head b{font-size:15px; color:var(--ink-800, #16233a)}
.nseo__head span{font-size:13px; color:var(--ink-400)}

.nseo .nfld{margin-bottom:14px}

/* A mock search result, sized and coloured the way Google renders one. The
   point is that the editor sees the same line lengths, the same truncation and
   the same colour split as the real thing — a preview that does not look like
   the result it is previewing teaches the wrong length. */
.nseo__preview{margin:4px 0 16px}
.nseo__previewLabel{
  font-size:12px; font-weight:700; letter-spacing:.04em; text-transform:uppercase;
  color:var(--ink-400); margin-bottom:8px;
}
.nserp{
  background:#fff;
  border:1px solid var(--line, #e6e9ef);
  border-radius:12px;
  padding:16px 18px;
}
.nserp__url{
  font-size:13px; color:#3c7a3c; line-height:1.4;
  word-break:break-all; margin-bottom:5px;
}
.nserp__title{
  font-size:19px; line-height:1.3; color:#1a0dab;
  margin-bottom:5px; font-weight:500;
}
.nserp__desc{
  font-size:14px; line-height:1.58; color:#4d5156;
}
.nserp__title.is-cut,.nserp__desc.is-cut{text-decoration:none}

@media (max-width:640px){
  .nseo{padding:14px 13px 4px}
  .nserp__title{font-size:17px}
}
