/* ==========================================================================
   Vertwo Premium — News Single (/news/{slug}/)
   --------------------------------------------------------------------------
   v0.20.1 — verbatim port of (then) 07-news-details.html style block
             (lines 19-1147), filtered down to news-detail-only rules.
   v0.29.0 — re-pointed at current /html/08-news-details.html (Vic renumbered
             the prototype after the original port). Three structural deltas
             vs v0.28.x:
               • Added the full .nd-gslide / .nd-gslide-bg / .nd-gslide-portrait
                 / .nd-gslide-overlay / .nd-gslide-cap / .nd-gslide-cap-tag /
                 .nd-gslide-cap-title family (9 rules, ~70 lines) which were
                 silently missing — news-single.js renders these classes on
                 gallery slides but no CSS existed for them, so slides
                 rendered unstyled and the parallax/letterbox effects didn't
                 work for real-image galleries.
               • Filtered to news-detail-only rules; nav, footer, back-to-top,
                 and page-hero CSS still come from components.css / page-hero.css.
   Loaded only when is_singular('vertwo_news') via conditional enqueue
   in functions.php → vertwo_enqueue_news_single_assets().

   Loaded only when is_singular('vertwo_news') via conditional enqueue
   in functions.php → vertwo_enqueue_news_single_assets().

   Coverage:
     - #nd-progress      reading-progress bar at the very top of the page
     - #nd-hero          small dark hero with .ah-bg / .ah-blob*** blobs
     - #nd-main          3-col desktop / 1-col mobile layout
     - .nd-gallery-col   sticky gallery + thumb strip + pills + share +
                         topics rail (left column on desktop)
     - .nd-gslide*       gallery slide internals (v0.29.0)
     - .nd-body-col      article body (right column on desktop)
     - .nd-author-card   "From the studio" card pinned at end of body
     - #nd-paging        prev/current/next paging
     - .nd-lightbox      fullscreen gallery viewer
     - responsive @media 768/600/1023/860/520 + reduced-motion

   NOT in this file (already provided elsewhere):
     - .nd-section-eyebrow, .nd-cinemaquote → news-blocks.css (v0.20.0)
     - nav, hamburger, mobile menu, pause button → components.css
     - footer, #backToTop                          → components.css

   Theme-global variables provided by design-system.css:
     --orange, --gold, --black, --white, --off, --line, --font-title,
     --font-body, --hairline (defined here if missing).
   Local variables defined here:
     --cat-* (mirrors news.css for chip colors, scoped to :root for the
              --cat-news /-events /-careers /-announcement chip backdrops).
     --ease, --ease-io (motion tokens used inline by .nd-* rules).
   ========================================================================== */

/* ─── Local variables — keep in sync with news.css :root ─── */
:root {
	--cat-announcement: #F27A0F;
	--cat-news:         #2D7EF7;
	--cat-events:       #8A3FFC;
	--cat-careers:      #11B981;

	/* hairline mirrors prototype --hairline (mid-gray rule used by .nd-hairline) */
	--hairline: rgba(0,0,0,0.08);

	/* easing tokens used by .nd-* rules */
	--ease:    cubic-bezier(.16,1,.3,1);
	--ease-io: cubic-bezier(.7,0,.3,1);
}

/* v0.29.2 — flip page bg to white on news single only. Theme default body
   bg is #1d1d1f (matches footer to remove the tonal seam), but the news
   body content uses near-black text intended for a light surface. Without
   this override the body paragraphs are dark-on-dark and invisible
   (Vic's "details still broken" screenshot, second one). Scoped to the
   WP body class so other pages keep their dark bg. The #nd-hero and
   #ndLightbox have their own dark backgrounds so they're unaffected. */
body.single-vertwo_news {
  background: var(--white);
}

#nd-progress{
  position:fixed;left:0;top:0;height:2px;width:0%;
  background:linear-gradient(90deg,var(--orange) 0%,var(--gold) 100%);
  z-index:299;pointer-events:none;
  transition:width .12s linear;
}

#nd-hero{
  position:relative;
  min-height:28vh;height:auto;
  display:flex;align-items:flex-end;
  overflow:hidden;background:#0a0a0c;isolation:isolate;
  padding:110px 24px 40px;
}

.ah-bg{position:absolute;inset:-10% -5%;z-index:0;pointer-events:none;filter:blur(70px) saturate(140%);opacity:.85;will-change:transform}

.ah-blob{position:absolute;border-radius:50%;mix-blend-mode:screen}

.ah-blob--a{width:55vw;height:55vw;left:-10%;top:-10%;background:radial-gradient(circle at 30% 30%,#1E3A8A 0%,rgba(30,58,138,0) 60%);animation:ahDriftA 22s ease-in-out infinite alternate}

.ah-blob--b{width:50vw;height:50vw;right:-12%;top:8%;background:radial-gradient(circle at 70% 50%,#5B21B6 0%,rgba(91,33,182,0) 60%);animation:ahDriftB 28s ease-in-out infinite alternate}

.ah-blob--c{width:62vw;height:62vw;left:18%;bottom:-22%;background:radial-gradient(circle at 50% 50%,#F59E0B 0%,rgba(245,158,11,0) 60%);animation:ahDriftC 34s ease-in-out infinite alternate}

@keyframes ahDriftA{0%{transform:translate3d(0,0,0) scale(1)}100%{transform:translate3d(8vw,4vh,0) scale(1.12)}}

@keyframes ahDriftB{0%{transform:translate3d(0,0,0) scale(1.05)}100%{transform:translate3d(-6vw,5vh,0) scale(1)}}

@keyframes ahDriftC{0%{transform:translate3d(0,0,0) scale(1)}100%{transform:translate3d(-4vw,-6vh,0) scale(1.15)}}

.ah-grain{position:absolute;inset:0;z-index:1;pointer-events:none;opacity:.08;background-image:url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' /%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");background-size:200px 200px;mix-blend-mode:overlay}

.ah-veil{position:absolute;inset:0;z-index:2;pointer-events:none;background:radial-gradient(ellipse at 30% 90%,rgba(0,0,0,0.55) 0%,rgba(0,0,0,0) 60%),linear-gradient(180deg,rgba(10,10,12,0.0) 0%,rgba(10,10,12,0.45) 100%)}

.nd-hero-inner{position:relative;z-index:3;width:100%;max-width:1200px;margin:0 auto;color:#fff;text-align:left}

/* v0.32.111 — eyebrow + leading dash → solid white (was orange / orange-0.7).
   Matches the universal .vw-hero-eyebrow change in page-hero.css this round. */
.nd-hero-eyebrow{display:inline-flex;align-items:center;gap:8px;font-size:0.66rem;font-weight:700;letter-spacing:0.18em;text-transform:uppercase;color:#fff;margin-bottom:14px}

.nd-hero-eyebrow::before{content:"";display:inline-block;width:18px;height:1px;background:#fff;opacity:1}

.nd-hero-title{
  /* v0.32.59 — weight 900 → 700 (NHG Black → NHG Bold). Need
     !important because typography-system.css's shared small-hero
     rule (.pd-hero-title + .nd-hero-title + .vw-hero--small) sets
     900 and loads LAST in the cascade. Scope the bump to
     .nd-hero-title only — work-detail hero (.pd-hero-title) stays
     at 900. */
  font-family:var(--font-title);font-weight:700 !important;
  font-size:clamp(1.6rem,2.8vw,2.8rem);
  letter-spacing:-0.045em;line-height:1.04;color:#fff;
  max-width:880px;
}

.nd-hero-title em{font-style:normal;color:var(--orange)}

.nd-breadcrumb{
  display:inline-flex;align-items:center;gap:0;
  max-width:100%;
  margin-top:18px;padding:6px 6px 6px 14px;
  background:rgba(255,255,255,0.08);
  border:1px solid rgba(255,255,255,0.14);
  border-radius:980px;
  backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);
  font-size:0.74rem;font-weight:500;letter-spacing:-0.005em;
  color:rgba(255,255,255,0.62);
  transition:background .3s ease,border-color .3s ease,color .3s ease;
  min-width:0;
}

.nd-breadcrumb:hover{background:rgba(242,122,15,0.16);border-color:rgba(242,122,15,0.4);color:#fff}

.nd-breadcrumb-back{display:inline-flex;align-items:center;gap:6px;color:rgba(255,255,255,0.85);font-weight:700;transition:color .25s ease;flex-shrink:0}

.nd-breadcrumb-back svg{width:11px;height:11px;transition:transform .35s var(--ease)}

.nd-breadcrumb:hover .nd-breadcrumb-back svg{transform:translateX(-3px)}

.nd-breadcrumb-sep{display:inline-block;margin:0 10px;width:3px;height:3px;border-radius:50%;background:rgba(255,255,255,0.30);flex-shrink:0}

.nd-breadcrumb-current{
  display:inline-block;padding:5px 12px;border-radius:980px;
  background:rgba(255,255,255,0.06);border:1px solid rgba(255,255,255,0.10);
  color:rgba(255,255,255,0.92);font-weight:600;
  margin-left:2px;
  max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;
}

#nd-main{
  position:relative;
  max-width:1240px;margin:0 auto;
  padding:80px 48px 110px;
  display:grid;
  grid-template-columns:minmax(0,2fr) minmax(0,3fr);
  gap:64px;align-items:start;
}

.nd-body-col{
  display:flex;flex-direction:column;gap:26px;min-width:0;
  /* v0.32.49 — relative positioning so the .nd-mascot bubble (which
     uses position:absolute) anchors to this column rather than to a
     more distant ancestor. */
  position:relative;
}

.nd-gallery-col{
  display:flex;flex-direction:column;gap:32px;min-width:0;
  position:sticky;top:108px;
}

.nd-title{
  /* v0.32.53 — Use the SAME CSS variables that .nd-hero-title pulls
     from typography-system.css (small-hero rule, line 185) so the
     letter-spacing, font-size and line-height match the hero EXACTLY
     instead of approximately. Hardcoded values in v0.32.48 (-0.045em
     etc.) were the visible-but-subtle kerning drift Vic spotted —
     hero used --vw-title-letter-spacing (= -0.02em), body was tighter
     at -0.045em.
     v0.32.59 — weight 900 → 700 (NHG Black → NHG Bold). Matches the
     .nd-hero-title weight bump above. */
  font-family:var(--font-title);font-weight:700;
  font-size:var(--vw-hero-sm-fs);
  letter-spacing:var(--vw-title-letter-spacing);
  line-height:var(--vw-title-line-height);
  color:var(--black);
  max-width:880px;
}

.nd-title em{font-style:normal;color:var(--orange)}

.nd-cat{
  display:inline-flex;align-items:center;
  padding:7px 14px;border-radius:980px;
  background:var(--cat-announcement);color:#fff;
  font-size:0.7rem;font-weight:700;letter-spacing:0.04em;
}

.nd-cat[data-cat="News"]         { background:var(--cat-news); }

.nd-cat[data-cat="Announcement"] { background:var(--cat-announcement); }

.nd-cat[data-cat="Events"]       { background:var(--cat-events); }

.nd-cat[data-cat="Careers"]      { background:var(--cat-careers); }

.nd-meta{
  display:flex;align-items:center;gap:14px;flex-wrap:wrap;
  font-size:0.78rem;font-weight:500;color:var(--mid);letter-spacing:0.02em;
}

.nd-meta-dot{width:3px;height:3px;border-radius:50%;background:var(--line);flex-shrink:0}

.nd-hairline{height:1px;background:linear-gradient(90deg,var(--orange) 0%,rgba(242,122,15,0.20) 30%,var(--hairline) 100%);margin:6px 0 4px}

.nd-body{
  font-family:var(--font-body);
  font-size:1.02rem;font-weight:300;line-height:1.85;
  color:rgba(26,26,26,0.82);
}

/* v0.32.48 — Vic flagged that <strong> wasn't rendering bold inside
   article bodies. The parent .nd-body is font-weight:300, so the
   browser default `font-weight: bolder` on <strong> should compute
   to 700 — but it wasn't reading consistently in his screenshot.
   Force it explicitly here, plus add <b> as a safety net in case
   the Block Editor or an older WP version emits <b> instead of
   <strong>. Color also goes to solid var(--black) so bold runs read
   as a high-contrast emphasis against the .82-opacity body text. */
.nd-body strong,
.nd-body b {
  font-weight: 700;
  color: var(--black);
}

.nd-body p+p{margin-top:18px}

.nd-body > p:first-of-type::first-letter{
  font-family:var(--font-title);font-weight:900;
  float:left;font-size:3.6em;line-height:0.86;
  color:var(--orange);
  margin:6px 10px 0 0;letter-spacing:-0.04em;
}

.nd-body h3{
  font-family:var(--font-title);font-weight:900;letter-spacing:-0.025em;
  font-size:clamp(1.2rem,1.6vw,1.45rem);line-height:1.2;
  color:var(--black);margin:36px 0 12px;
}

.nd-body blockquote{
  margin:30px 0;padding:18px 22px;
  border-left:3px solid var(--orange);
  background:linear-gradient(90deg,rgba(242,122,15,0.07) 0%,rgba(242,122,15,0.02) 60%,transparent 100%);
  border-radius:0 12px 12px 0;
  font-family:var(--font-body);font-style:italic;font-weight:400;
  font-size:1.02rem;line-height:1.7;color:rgba(26,26,26,0.78);
}

.nd-tags-rail{
  display:flex;align-items:center;flex-wrap:wrap;gap:8px;
  padding-top:24px;border-top:1px solid var(--hairline);
}

.nd-tags-label{
  font-size:0.62rem;font-weight:700;letter-spacing:0.18em;text-transform:uppercase;
  color:var(--mid);margin-right:6px;
}

.nd-tag{
  display:inline-flex;align-items:center;
  padding:6px 14px;border-radius:980px;
  border:1px solid var(--line);background:var(--white);
  font-size:0.78rem;font-weight:600;color:var(--black);
  letter-spacing:-0.005em;
  transition:background .25s ease,border-color .25s ease,color .25s ease,transform .35s var(--ease),box-shadow .35s ease;
}

.nd-tag:hover{
  background:rgba(242,122,15,0.10);border-color:rgba(242,122,15,0.45);
  color:var(--orange);transform:translateY(-1px);
  box-shadow:0 6px 14px rgba(242,122,15,0.18);
}

.nd-tag-cta{
  display:inline-flex;align-items:center;gap:6px;
  margin-left:6px;
  font-size:0.78rem;font-weight:700;color:var(--orange);
  letter-spacing:-0.005em;
}

.nd-tag-cta svg{width:13px;height:13px;transition:transform .3s var(--ease)}

.nd-tag-cta:hover svg{transform:translateX(3px)}

.nd-author-card{
  display:flex;gap:18px;align-items:flex-start;
  margin-top:36px;padding:22px 24px;
  background:var(--off);border:1px solid var(--hairline);border-radius:16px;
}

.nd-author-card-avatar{
  flex-shrink:0;width:56px;height:56px;border-radius:50%;
  background:linear-gradient(135deg,var(--orange),var(--gold));
  display:flex;align-items:center;justify-content:center;
  color:#fff;font-family:var(--font-title);font-weight:900;
  font-size:1.25rem;letter-spacing:-0.02em;
  box-shadow:0 8px 22px rgba(242,122,15,0.28);
}
/* v0.32.49 — Photo-avatar variant. Renders the uploaded profile photo
   (typically the vermin mascot head). The letter badge below is
   replaced by this when the user has a `vertwo_user_avatar_id` set.
   v0.32.73 — Vic ask: "remove the circular mask and just let the vermin
   head freely shown there." So this variant now:
     • drops border-radius (no more circle crop)
     • drops the gray placeholder fill (PNG transparency carries it)
     • drops the box-shadow (no shape to cast a shadow from)
     • uses background-size:contain instead of cover so the full
       head is visible — ears, body, all of it
     • bumps to 72×72 (60×60 mobile) since contain shrinks the rendered
       head to fit, and at the old 56px it looked too small. The CSS
       cascade lets the inline `background-image:url(...)` win against
       the `background:` shorthand below.

   To override the base .nd-author-card-avatar's orange gradient +
   flex-centering (which would draw the gradient AND show the image),
   we set `background:` shorthand to none — which would also erase the
   inline-style background-image, EXCEPT inline styles win by
   specificity. Net effect: image renders alone on transparent. */
.nd-author-card-avatar--photo{
  width:72px;height:72px;
  border-radius:0;
  background:transparent center/contain no-repeat;
  box-shadow:none;
  /* Belt-and-suspenders for inline-style override scenarios. */
  background-size:contain !important;
  background-color:transparent !important;
}

.nd-author-card-meta{display:flex;flex-direction:column;gap:6px;min-width:0}

.nd-author-card-eyebrow{font-size:0.6rem;font-weight:700;letter-spacing:0.18em;text-transform:uppercase;color:var(--orange)}

.nd-author-card-name{font-family:var(--font-title);font-weight:900;font-size:1.05rem;letter-spacing:-0.025em;color:var(--black)}

.nd-author-card-role{font-size:0.78rem;font-weight:500;color:var(--mid);margin-top:-2px}

.nd-author-card-bio{font-size:0.86rem;font-weight:300;line-height:1.65;color:rgba(26,26,26,0.72);margin-top:4px}

.nd-gallery{
  display:flex;flex-direction:column;gap:18px;
  width:100%;
  /* v0.32.50 — relative anchor so the .nd-mascot--mobile bubble
     (rendered as the first child) can absolutely-position itself to
     this container's top-right corner, overlapping the gallery card
     on mobile/tablet. .nd-gallery stays a flex block on all
     breakpoints (unlike .nd-gallery-col which becomes
     display:contents on ≤1023px and would otherwise leave the mascot
     anchorless). */
  position:relative;
}

.nd-gallery-head{
  display:flex;align-items:center;justify-content:space-between;
  gap:12px;margin-bottom:2px;
}

.nd-gallery-eyebrow{
  font-size:0.62rem;font-weight:700;letter-spacing:0.18em;text-transform:uppercase;
  color:var(--orange);
}

.nd-gv{
  position:relative;width:100%;
  aspect-ratio:16/9;
  border-radius:18px;overflow:hidden;
  background:#0d0d0d;isolation:isolate;
  box-shadow:0 6px 24px rgba(0,0,0,0.10);
  cursor:zoom-in;
  transform:translateZ(0);
  transition:transform .5s var(--ease),box-shadow .5s var(--ease);
}

.nd-gv:hover{
  transform:translateY(-3px);
  /* Stronger orange outline per Vic spec — 2px ring + glow */
  box-shadow:0 10px 28px rgba(242,122,15,0.50),0 0 0 2px rgba(242,122,15,0.55);
}

.nd-gtrack{
  position:absolute;inset:0;display:flex;
  will-change:transform;
  /* Slower + smoother transition per Vic's spec — matches About's tc-track
     (0.9s with the slow-in/slow-out ease-io curve), so the parallax shift
     during the slide reads cinematic instead of clipped. */
  transition:transform .95s var(--ease-io);
}

/* v0.29.5 — .pd-share-* family ported from work-detail.css (lines 882-936)
   because v0.29.4 reused the .pd-share-btn / .pd-share-inner classes in
   single-vertwo_news.php for visual consistency with the Work Details share
   row — but work-detail.css is conditionally enqueued only on single-vertwo_work
   pages, so news single rendered the SVG icons unstyled (browser default
   300x150 box) and produced the giant Facebook glyph Vic flagged.
   These rules are copied verbatim (modulo the dropped #pd-share wrapper
   rule, since news single has no #pd-share container) so styling stays
   identical across the two page types — if work-detail.css's share row
   is updated later, mirror the changes here. */
.pd-share-inner{
  /* prototype v0.1.2: full-width to align visually with the synopsis
     above. */
  max-width:none;margin:0;
  display:flex;align-items:center;gap:14px;
  flex-wrap:wrap;
  padding:18px 22px;
  border:1px solid var(--hairline);border-radius:14px;
  background:var(--off);
}

/* v0.29.6 / v0.29.7 — within the news single's narrow left aside on DESKTOP,
   force the share box into title-on-top / buttons-below layout (Vic spec).
   The Work Details page has a full-width #pd-share container where the
   default row layout looks right, but in the news aside (~480px wide on
   desktop), the row form pushes the label into a vertical tight strip +
   buttons wrap awkwardly.

   v0.29.7 — scope this to `@media (min-width:1024px)` ONLY. On tablet
   (<=1023px) the aside collapses to single-column flow via the
   `display:contents` rule below, and at that point Vic wants the share
   box to use the SAME layout as the Work Details page (horizontal row at
   tablet widths, column-stretch at mobile <=720px). Both rules live in
   .pd-share-inner / `@media (max-width:720px) { .pd-share-inner }` above
   and apply transparently to news single now that this overlay is
   desktop-scoped. */
@media (min-width: 1024px){
.nd-gallery-col .pd-share-inner{
  flex-direction:column;align-items:stretch;gap:14px;
}
.nd-gallery-col .pd-share-label{align-self:flex-start}
.nd-gallery-col .pd-share-buttons{
  display:flex;flex-wrap:wrap;gap:8px;width:100%;
}
.nd-gallery-col .pd-share-btn{
  flex:1 1 calc(50% - 4px);
  justify-content:center;padding:10px 14px;
}
}
.pd-share-label{
  font-family:var(--font-title);font-weight:700;font-size:0.66rem;
  letter-spacing:0.14em;text-transform:uppercase;color:var(--mid);
  flex-shrink:0;
}
.pd-share-buttons{display:flex;gap:8px;flex-wrap:wrap;flex:1;min-width:0}
.pd-share-btn{
  display:inline-flex;align-items:center;gap:8px;
  padding:8px 14px;border-radius:980px;
  background:#fff;border:1px solid var(--hairline);
  font-family:var(--font-title);font-weight:600;font-size:0.78rem;color:var(--black);
  transition:border-color .25s ease,color .25s ease,background .25s ease,transform .35s var(--ease);
  cursor:pointer;
  white-space:nowrap;
  text-decoration:none;
}
.pd-share-btn:hover{
  border-color:var(--orange);color:var(--orange);
  background:rgba(242,122,15,0.04);
  transform:translateY(-1px);
}
.pd-share-btn svg{width:14px;height:14px;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;fill:none;stroke:currentColor}
.pd-share-btn.copy-link.is-copied{
  border-color:#1a8e3d;color:#1a8e3d;background:rgba(52,199,89,0.06);
}

@media (max-width: 720px){
  .pd-share-inner{
    flex-direction:column;align-items:stretch;
    gap:12px;padding:16px 18px;
  }
  .pd-share-label{align-self:flex-start}
  .pd-share-buttons{display:flex;flex-wrap:wrap;gap:8px;width:100%}
  .pd-share-btn{
    flex:1 1 calc(50% - 4px);
    justify-content:center;padding:10px 12px;
  }
}
/* v0.29.10 — keep the 2-up grid down to the smallest mobile size for news.
   The work-detail.css ships `@media (max-width:420px) { .pd-share-btn { flex:1 1 100% }}`
   which collapses to single-column on very narrow phones. Vic wants the
   news single's share buttons to stay 2-up (matches tablet portrait look)
   even at iPhone widths because the 5 stacked full-width buttons felt too
   chunky compared to the tablet layout. Override that rule back to 2-up.
   The Work Details page's #pd-share retains the 1-column-at-420px behavior
   because this override is scoped to a news-only selector. */
@media (max-width: 420px){
  body.single-vertwo_news .pd-share-btn{flex:1 1 calc(50% - 4px)}
}

/* v0.29.0 — .nd-gslide family ported verbatim from 08-news-details.html
   (proto lines 519-585). These rules were silently missing from v0.28.x
   so the JS-rendered gallery slides (built in news-single.js around
   "s.className = 'nd-gslide'") rendered as zero-width flex children with
   no background sizing, no overlay gradient, no caption layout. Two
   slide modes:
     • LANDSCAPE (default) — uses .nd-gslide-bg with -25% inset, parallax
       shifts horizontally inside the viewport.
     • PORTRAIT — .nd-gslide.is-portrait wraps a centered .nd-gslide-portrait
       poster that letterboxes against a blurred .nd-gslide-bg backdrop. */
.nd-gslide{
  flex:0 0 100%;width:100%;height:100%;
  position:relative;overflow:hidden;
  isolation:isolate;
}
/* v0.32.69 — .nd-gslide-bg is now a passive parallax WRAP that contains
   an <img class="nd-gslide-img">. Was previously a div with background-
   image. The bug class it solves: iPad Safari's compositor produced edge-
   clipping on portrait viewports when background-image + transform stacks
   were promoted to their own layer. <img> + object-fit:cover routes
   through the image-element renderer, which doesn't hit that bug.

   Layout: bg wrap at inset:-25% (50% wider than slide on each axis) gives
   the parallax shift room. The <img> inside fills the wrap (100% w/h) and
   object-fit:cover crops the image to the wrap's box. Slide is overflow:
   hidden so only the center 67% of the wrap is visible at rest. Parallax
   transform on the wrap reveals up to ±25% travel. */
.nd-gslide-bg{
  position:absolute;inset:-25%;
  overflow:hidden;
  /* Layer promotion (verbatim About defensive pattern) — prevents caption
     flicker on mobile during the rAF parallax loop's rapid transform writes. */
  will-change:transform;
  transform:translate3d(0,0,0);
  backface-visibility:hidden;
  -webkit-backface-visibility:hidden;
}
.nd-gslide-img{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;object-position:center;
  display:block;
  /* Subtle saturation match for the about-page tc-track tonal pop. */
  filter:saturate(1.02) contrast(1.02);
}
.nd-gslide.is-portrait .nd-gslide-bg{
  /* Soft blurred backdrop fill — blur applies to the <img> inside. */
  filter:blur(28px) saturate(140%);opacity:0.65;
}
.nd-gslide-portrait{
  position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
  height:92%;aspect-ratio:3/4;
  border-radius:8px;overflow:hidden;
  box-shadow:0 16px 40px rgba(0,0,0,0.45);
  z-index:1;
  will-change:transform;
  backface-visibility:hidden;
  -webkit-backface-visibility:hidden;
}
.nd-gslide-portrait-img{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;object-position:center;
  display:block;
}
.nd-gslide.ph .nd-gslide-bg{
  display:flex;align-items:center;justify-content:center;
  font-family:serif;font-size:5rem;color:rgba(255,255,255,0.10);
}
.nd-gslide-overlay{
  position:absolute;inset:0;z-index:2;
  background:linear-gradient(180deg,rgba(0,0,0,0) 35%,rgba(0,0,0,0.78) 100%);
  pointer-events:none;
  /* Layer promotion — stops the gradient flickering when the bg shifts rapidly */
  transform:translate3d(0,0,0);
  backface-visibility:hidden;
  -webkit-backface-visibility:hidden;
  will-change:transform;
}
.nd-gslide-cap{
  position:absolute;left:24px;right:24px;bottom:20px;z-index:3;color:#fff;pointer-events:none;
  /* Layer promotion — keeps caption text rendering stable during transitions.
     Without this, mobile browsers can briefly re-compose the caption mid-slide,
     which Vic flagged as "rough" text animation. */
  transform:translate3d(0,0,0);
  backface-visibility:hidden;
  -webkit-backface-visibility:hidden;
  will-change:transform;
}
.nd-gslide-cap-tag{
  display:inline-block;font-size:0.66rem;font-weight:700;letter-spacing:0.18em;
  text-transform:uppercase;color:var(--orange);margin-bottom:6px;
}
.nd-gslide-cap-title{
  font-family:var(--font-title);font-weight:900;letter-spacing:-0.02em;
  font-size:clamp(0.98rem,1.25vw,1.2rem);line-height:1.25;color:#fff;
}

.nd-gv-zoom{
  position:absolute;top:16px;right:16px;z-index:4;
  width:38px;height:38px;border-radius:50%;
  background:rgba(0,0,0,0.45);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);
  border:1px solid rgba(255,255,255,0.22);
  display:flex;align-items:center;justify-content:center;
  color:rgba(255,255,255,0.86);
  opacity:0;transition:opacity .25s ease,background .2s ease,transform .25s var(--ease);
  pointer-events:none;
}

.nd-gv:hover .nd-gv-zoom{opacity:1}

.nd-gv-zoom svg{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}

.nd-gv-arrows{display:flex;gap:8px;flex-shrink:0}

.nd-gv-arrow{
  width:46px;height:46px;border-radius:14px;
  background:var(--white);border:1px solid var(--line);
  display:flex;align-items:center;justify-content:center;
  color:var(--black);
  transition:background .25s ease,border-color .25s ease,color .25s ease,
             transform .35s var(--ease),box-shadow .35s ease;
}

.nd-gv-arrow:hover{background:var(--orange);border-color:var(--orange);color:#fff;transform:translateY(-2px);box-shadow:0 10px 24px rgba(242,122,15,0.35)}

.nd-gv-arrow svg{width:18px;height:18px;stroke:currentColor;fill:none;stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round}

.nd-gv-pills-row{
  display:flex;align-items:center;justify-content:flex-end;
  gap:18px;margin-top:6px;
}

.nd-gv-paging{
  display:flex;align-items:center;gap:8px;flex-wrap:wrap;justify-content:flex-end;
}

.nd-gv-pill{
  width:32px;height:6px;border-radius:980px;
  background:rgba(0,0,0,0.12);transition:width .45s var(--ease),background .35s ease;
  cursor:pointer;border:none;padding:0;
}

.nd-gv-pill:hover:not(.active){background:rgba(0,0,0,0.28)}

.nd-gv-pill.active{width:64px;background:var(--orange)}

.nd-thumbs-wrap{position:relative;display:flex;flex-direction:column;gap:8px;margin-top:8px}

.nd-thumbs{
  position:relative;
  width:100%;overflow:hidden;
  scrollbar-width:none;
  -webkit-overflow-scrolling:touch;
}

.nd-thumbs::-webkit-scrollbar{display:none}

.nd-thumbs-content{
  display:flex;gap:8px;
  padding:2px 0;
  width:max-content;
}

.nd-thumb{
  flex-shrink:0;width:104px;height:64px;
  border-radius:8px;overflow:hidden;
  cursor:pointer;position:relative;
  border:2px solid transparent;
  transition:border-color .25s ease,opacity .25s ease,
             transform .35s var(--ease),box-shadow .35s ease;
  opacity:0.6;
  isolation:isolate;
}

.nd-thumb-bg{
  position:absolute;inset:-15%;
  background-size:cover;background-position:center;
  will-change:transform;
  transform:translate3d(0,0,0);
  backface-visibility:hidden;
  -webkit-backface-visibility:hidden;
}

/* v0.32.60 — Video-thumb ▶ overlay. The .is-video class is added by
   news-single.js to thumbs whose slide has an uploaded video. The
   poster image still shows underneath; a centered ▶ glyph sits on
   top so editors / readers can tell at a glance which slides open
   a video in the lightbox. */
.nd-thumb.is-video::after{
  content:"";
  position:absolute;inset:0;
  display:flex;align-items:center;justify-content:center;
  background:
    radial-gradient(circle at center, rgba(0,0,0,0.45) 0%, rgba(0,0,0,0.15) 30%, transparent 55%);
  pointer-events:none;
  z-index:1;
}
.nd-thumb.is-video::before{
  content:"";
  position:absolute;
  top:50%;left:50%;
  width:0;height:0;
  /* Triangle pointing right — 12px wide × 14px tall, white. */
  border-top:7px solid transparent;
  border-bottom:7px solid transparent;
  border-left:12px solid #fff;
  transform:translate(-40%,-50%);
  filter:drop-shadow(0 2px 4px rgba(0,0,0,0.5));
  pointer-events:none;
  z-index:2;
}

.nd-thumb:hover{
  opacity:0.95;transform:translateY(-2px);
  border-color:rgba(242,122,15,0.55);
  box-shadow:0 4px 14px rgba(242,122,15,0.30);
}

.nd-thumb.active{
  border-color:var(--orange);opacity:1;transform:none;
  box-shadow:0 4px 14px rgba(242,122,15,0.40);
}

.nd-thumb-ph{
  width:100%;height:100%;display:flex;align-items:center;justify-content:center;
  font-size:0.7rem;font-weight:700;color:rgba(255,255,255,0.22);letter-spacing:0.06em;
  position:relative;z-index:1;
}

.nd-share-inline{
  display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  padding-top:24px;border-top:1px solid var(--hairline);
}

.nd-share-inline .nd-share-label{
  font-size:0.62rem;font-weight:700;letter-spacing:0.18em;text-transform:uppercase;color:var(--mid);
  margin-right:4px;
}

.nd-share-btn{
  position:relative;
  display:inline-flex;align-items:center;
  height:38px;padding:0 10px;
  border:1px solid var(--line);border-radius:980px;
  color:var(--mid);background:var(--white);
  text-decoration:none;overflow:hidden;
  transition:
    color .55s cubic-bezier(.22,0.61,0.36,1),
    border-color .55s cubic-bezier(.22,0.61,0.36,1),
    background .55s cubic-bezier(.22,0.61,0.36,1),
    padding .75s cubic-bezier(.22,0.61,0.36,1);
}

.nd-share-btn .nd-share-btn-icon{
  display:inline-flex;align-items:center;justify-content:center;
  width:18px;height:18px;flex-shrink:0;
}

.nd-share-btn .nd-share-btn-icon svg{width:16px;height:16px;fill:currentColor}

.nd-share-btn .nd-share-btn-label{
  display:inline-block;
  max-width:0;margin-left:0;
  overflow:hidden;white-space:nowrap;
  font-size:13px;font-weight:600;letter-spacing:-0.005em;
  opacity:0;transform:translateX(-4px);
  transition:
    max-width .75s cubic-bezier(.22,0.61,0.36,1),
    margin-left .75s cubic-bezier(.22,0.61,0.36,1),
    opacity .55s cubic-bezier(.22,0.61,0.36,1),
    transform .75s cubic-bezier(.22,0.61,0.36,1);
}

.nd-share-btn:hover{
  color:var(--orange);
  border-color:rgba(242,122,15,0.55);
  background:rgba(242,122,15,0.10);
  padding:0 14px;
}

.nd-share-btn:hover .nd-share-btn-label{
  max-width:120px;margin-left:8px;
  opacity:1;transform:translateX(0);
}

@media (max-width:768px){
.nd-share-btn{
    width:38px;height:38px;padding:0;justify-content:center;
  }
.nd-share-btn .nd-share-btn-label{display:none}
.nd-share-btn:hover{
    padding:0;
    color:var(--orange);
    border-color:rgba(242,122,15,0.50);
    background:rgba(242,122,15,0.08);
  }
}

.nd-share-btn.copied::after{
  content:"copied!";position:absolute;left:50%;top:-32px;transform:translateX(-50%);
  font-size:0.7rem;font-weight:700;color:var(--orange);
  background:var(--white);padding:4px 10px;border-radius:6px;border:1px solid var(--line);
  white-space:nowrap;animation:fadePop 1.2s ease forwards;
  pointer-events:none;
}

@keyframes fadePop{0%{opacity:0;transform:translateX(-50%) translateY(4px)}30%{opacity:1;transform:translateX(-50%) translateY(0)}80%{opacity:1}100%{opacity:0}}

.nd-lightbox{
  position:fixed;inset:0;
  background:rgba(10,10,12,0.94);
  backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);
  display:flex;align-items:center;justify-content:center;
  z-index:1000;opacity:0;pointer-events:none;
  transition:opacity 260ms var(--ease);
}

.nd-lightbox.is-open{opacity:1;pointer-events:auto}

.nd-lightbox:not(.is-open),.nd-lightbox:not(.is-open) *{pointer-events:none!important}

.nd-lb-viewport{position:relative;width:92vw;height:84vh;overflow:hidden}

.nd-lb-track{
  position:absolute;top:0;left:0;height:100%;display:flex;
  will-change:transform;
  /* Match the main gallery + About Team rail's slow-in/slow-out feel.
     .55s ease was too snappy — Vic asked for the smoother About-rail timing. */
  transition:transform .95s var(--ease-io);
}

.nd-lb-slide{
  flex:0 0 92vw;width:92vw;height:84vh;
  display:flex;align-items:center;justify-content:center;
  /* v0.32.61 — relative anchor for the .nd-lb-tag pill (bottom-center
     of each slide). */
  position:relative;
}

.nd-lb-image{
  display:block;max-width:92vw;max-height:84vh;width:auto;height:auto;
  object-fit:contain;user-select:none;-webkit-user-drag:none;cursor:pointer;
  border-radius:8px;box-shadow:0 30px 80px rgba(0,0,0,0.5);
}

/* v0.32.60 — Lightbox <video> sibling of .nd-lb-image. Same size /
   shadow / radius treatment so videos sit in the lightbox at the same
   visual weight as images. Cursor stays default so the native video
   controls hit-test cleanly (no "this is clickable" pointer over the
   timeline scrubber). */
.nd-lb-video{
  display:block;max-width:92vw;max-height:84vh;width:auto;height:auto;
  background:#000;
  border-radius:8px;box-shadow:0 30px 80px rgba(0,0,0,0.5);
  outline:none;
}

/* v0.32.61 — Tag pill floating at the bottom of each lightbox slide.
   Surfaces the editor-supplied "Tag (short kicker)" string from the
   gallery row (e.g. "afternoon tea break"). Centered horizontally,
   anchored above the lightbox footer (pills + counter); cushioned
   above the bottom edge so it doesn't crowd the footer chrome.
   pointer-events:none so it doesn't catch clicks meant for the
   image-advance / dim-area-close handlers. */
.nd-lb-tag{
  position:absolute;
  bottom:24px;left:50%;
  transform:translateX(-50%);
  font-family:var(--font-title);
  font-size:0.66rem;font-weight:700;letter-spacing:0.18em;
  text-transform:uppercase;
  color:var(--orange);
  background:rgba(0,0,0,0.55);
  -webkit-backdrop-filter:blur(8px) saturate(140%);
          backdrop-filter:blur(8px) saturate(140%);
  padding:8px 16px;
  border-radius:980px;
  white-space:nowrap;
  pointer-events:none;
  z-index:3;
}

.nd-lb-block{
  width:min(680px,80vw);aspect-ratio:4/5;
  border-radius:12px;display:flex;align-items:center;justify-content:center;
  font-family:var(--font-title);font-weight:900;font-size:6rem;
  color:rgba(255,255,255,0.10);letter-spacing:-0.04em;
  box-shadow:0 30px 80px rgba(0,0,0,0.5);
  position:relative;overflow:hidden;
}

.nd-lb-close,.nd-lb-nav{
  position:absolute;width:48px;height:48px;border-radius:50%;
  background:transparent;border:1px solid rgba(255,255,255,0.24);color:#fff;
  display:inline-flex;align-items:center;justify-content:center;
  cursor:pointer;z-index:2;
  transition:background .3s ease,border-color .3s ease,transform .3s ease,box-shadow .35s ease;
}

.nd-lb-close{top:24px;right:24px}

.nd-lb-close svg{width:20px;height:20px}

.nd-lb-close:hover{
  background:var(--orange);border-color:var(--orange);
  transform:rotate(90deg);
  box-shadow:0 10px 30px -6px rgba(242,122,15,0.6);
}

.nd-lb-nav{top:50%;width:52px;height:52px;border-radius:14px;transform:translateY(-50%)}

.nd-lb-nav svg{width:22px;height:22px}

.nd-lb-prev{left:24px}

.nd-lb-next{right:24px}

.nd-lb-nav:hover{
  background:var(--orange);border-color:var(--orange);
  box-shadow:0 10px 30px -6px rgba(242,122,15,0.6);
}

.nd-lb-prev:hover{transform:translateY(-50%) translateX(-3px)}

.nd-lb-next:hover{transform:translateY(-50%) translateX(3px)}

.nd-lb-footer{
  position:absolute;left:50%;bottom:24px;transform:translateX(-50%);
  display:flex;align-items:center;gap:16px;z-index:2;
}

.nd-lb-pills{display:flex;gap:6px}

.nd-lb-pill{
  width:28px;height:4px;background:rgba(255,255,255,0.22);
  border-radius:2px;cursor:pointer;border:none;padding:0;
  transition:background .3s ease,width .3s ease;
}

.nd-lb-pill.is-active{background:var(--orange);width:40px}

.nd-lb-pill:hover{background:rgba(242,122,15,0.75)}

.nd-lb-counter{
  color:rgba(255,255,255,0.7);font-size:12px;font-weight:600;letter-spacing:0.06em;
  font-variant-numeric:tabular-nums;
}

#nd-paging{
  background:var(--off);
  border-top:1px solid var(--hairline);
  border-bottom:1px solid var(--hairline);
}

.nd-paging-inner{
  max-width:1200px;margin:0 auto;
  padding:28px 48px;
  display:grid;grid-template-columns:1fr auto 1fr;
  align-items:center;gap:20px;
}

.nd-page-link{
  display:inline-flex;align-items:center;gap:14px;
  padding:8px;border-radius:14px;
  min-width:0;max-width:100%;
}

.nd-page-link.next{justify-self:end;flex-direction:row-reverse}

.nd-page-link.prev{justify-self:start}

.nd-page-arrow{
  flex-shrink:0;width:48px;height:48px;
  border-radius:12px;
  background:var(--white);border:1px solid var(--hairline);
  display:flex;align-items:center;justify-content:center;
  color:var(--black);
  transition:background .3s ease,border-color .3s ease,color .3s ease,transform .4s var(--ease),box-shadow .35s var(--ease);
}

.nd-page-arrow svg{width:18px;height:18px;stroke:currentColor;fill:none;stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round}

.nd-page-link:hover .nd-page-arrow{background:var(--orange);border-color:var(--orange);color:#fff;box-shadow:0 6px 18px rgba(242,122,15,0.32)}

.nd-page-link.prev:hover .nd-page-arrow{transform:translateX(-3px)}

.nd-page-link.next:hover .nd-page-arrow{transform:translateX(3px)}

.nd-page-text{display:flex;flex-direction:column;gap:2px;min-width:0}

.nd-page-link.next .nd-page-text{text-align:right}

.nd-page-dir{
  font-size:0.62rem;font-weight:700;letter-spacing:0.14em;
  text-transform:uppercase;color:var(--mid);
}

.nd-page-title{
  font-family:var(--font-title);font-weight:700;letter-spacing:-0.015em;
  font-size:0.95rem;color:var(--black);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:280px;
  transition:color .3s ease;
}

.nd-page-link:hover .nd-page-title{color:var(--orange)}

.nd-page-current{
  font-family:var(--font-title);font-weight:700;letter-spacing:0.06em;
  font-size:0.7rem;text-transform:uppercase;color:var(--mid);
  text-align:center;padding:0 8px;
}

.nd-page-current span{
  display:block;color:var(--black);letter-spacing:-0.02em;
  font-size:0.92rem;text-transform:none;margin-top:3px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:240px;
}

.nd-page-empty{visibility:hidden;pointer-events:none}

.r{opacity:0;transform:translateY(22px);transition:opacity .7s var(--ease),transform .7s var(--ease)}

.r.in{opacity:1;transform:none}

.d1{transition-delay:.08s}

.d2{transition-delay:.18s}

.d3{transition-delay:.28s}

@media(max-width:1023px){
#nd-main{
    display:flex;flex-direction:column;gap:32px;padding:60px 32px 88px;
  }
.nd-gallery-col,
  .nd-body-col{ display:contents; }
.nd-gallery-col{position:static;top:auto}
.nd-body-col    > .nd-title       { order:1; }
.nd-body-col    > .nd-meta        { order:2; }
.nd-body-col    > .nd-hairline    { order:3; }
.nd-gallery-col > .nd-gallery     { order:4; }
.nd-body-col    > .nd-body        { order:5; }
.nd-body-col    > .nd-author-card { order:6; }
/* v0.29.6 — share box (now .pd-share-inner after the v0.29.4 work-detail
   markup port) goes at the very bottom on mobile/tablet per Vic spec
   ("on mobile and tablet, put it on the bottom, after the article"). */
.nd-gallery-col > .pd-share-inner { order:9; }
}

@media(max-width:860px){
#nd-hero{padding:110px 24px 36px;min-height:24vh}
.nd-hero-title{font-size:clamp(1.5rem,4.6vw,2rem)}
/* v0.32.48 — synced to .nd-hero-title size for visual parity. */
.nd-title{font-size:clamp(1.5rem,4.6vw,2rem)}
.nd-meta{font-size:0.74rem;gap:10px}
#nd-main{padding:48px 24px 72px}
.nd-gv{aspect-ratio:16/10}
.nd-gv-arrow{width:42px;height:42px;border-radius:12px}
.nd-gv-arrow svg{width:16px;height:16px}
.nd-gv-pill{width:24px;height:5px}
.nd-gv-pill.active{width:48px}
.nd-thumb{width:88px;height:54px}
.nd-paging-inner{padding:24px 24px;gap:14px}
.nd-page-arrow{width:44px;height:44px}
.nd-page-title{max-width:140px;font-size:0.85rem}
}

@media(max-width:520px){
#nd-hero{padding:96px 18px 28px}
.nd-hero-eyebrow{font-size:0.62rem}
.nd-hero-title{font-size:clamp(1.35rem,5.4vw,1.7rem)}
.nd-breadcrumb-current{display:none}
#nd-main{padding:36px 18px 60px}
/* v0.32.48 — synced to .nd-hero-title size for visual parity. */
.nd-title{font-size:clamp(1.35rem,5.4vw,1.7rem)}
.nd-body{font-size:0.95rem;line-height:1.78}
.nd-body > p:first-of-type::first-letter{font-size:3rem;margin:5px 8px 0 0}
.nd-body h3{font-size:1.1rem;margin:30px 0 10px}
.nd-author-card{flex-direction:column;align-items:flex-start;padding:18px 18px;gap:12px}
.nd-author-card-avatar{width:48px;height:48px;font-size:1.1rem}
/* v0.32.73 — Photo variant mobile size. Without this override, the
   selector above (single-class specificity, later in source) would
   shrink the vermin head to 48px on mobile too. Keep it at 60px so
   the head stays visible at phone widths. */
.nd-author-card-avatar--photo{width:60px;height:60px}
.nd-gv{aspect-ratio:5/4}
.nd-gv-pills-row{justify-content:center}
.nd-gv-paging{justify-content:center;width:100%}
.nd-thumbs{display:none}
.nd-paging-inner{padding:20px 16px;gap:8px;grid-template-columns:auto auto auto}
.nd-page-arrow{width:38px;height:38px}
.nd-page-arrow svg{width:14px;height:14px}
.nd-page-text{display:none}
.nd-page-current{font-size:0.62rem}
.nd-page-current span{font-size:0.78rem;max-width:140px}
}

@media (prefers-reduced-motion: reduce){
.ah-blob,.ah-blob--a,.ah-blob--b,.ah-blob--c{animation:none}
.r{transition:opacity .3s ease}
.nd-gtrack{transition:transform .3s ease}
.nd-lb-track{transition:transform .3s ease}
}

/* ═══════════════════════════════════════════════════════════════════
   v0.32.69 — iPad portrait: drop parallax cushion + use plain inset 0
   ───────────────────────────────────────────────────────────────────
   With the bg-image → <img> refactor, the parallax wrap (.nd-gslide-bg)
   doesn't NEED inset:-25% on iPad portrait — there's no parallax
   transform happening there (skipped in JS via isTabletPortrait()),
   so the 50% overshoot just zooms the image 1.5× for no reason. On
   iPad portrait specifically, force the wrap to inset:0 so the <img>
   inside renders at 1× scale, edge-to-edge with the slide.

   This is the cleanest possible fix for the long-running iPad portrait
   edge-clipping bug. The combo of (a) <img> + object-fit:cover routing
   through Safari's image-element renderer instead of the bg-image
   renderer + (b) no parallax overshoot on portrait should give Vic
   exactly what he wanted: image fills the gallery viewport, no edge
   clipping, no compositor artifacts. */
@media (max-width: 1023px) and (orientation: portrait) {
  .nd-gslide-bg {
    inset: 0;
    transform: none;
    will-change: auto;
    -webkit-backface-visibility: visible;
            backface-visibility: visible;
  }
  .nd-gslide-portrait {
    will-change: auto;
    -webkit-backface-visibility: visible;
            backface-visibility: visible;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   v0.32.45 — Single news hero + breadcrumb keep editor case
   ───────────────────────────────────────────────────────────────────
   Vic's request: editorial article titles should render in the case
   the editor typed them (e.g. "Breaking Fast & Talking Shop: Vertwo's
   Ramadan Iftar 2025"), not the brand-locked lowercase. Same idea as
   the .ft-title override on the news archive.

   .nd-hero-title is otherwise in typography-system.css's small-hero
   group (~line 193) alongside .pd-hero-title (work detail). We
   override here so news goes editorial while work-detail keeps the
   brand lowercase.

   .nd-breadcrumb-current echoes the post title in the breadcrumb
   trail, so it gets the same treatment for visual consistency.
   ═══════════════════════════════════════════════════════════════════ */
.nd-hero-title,
.nd-breadcrumb-current,
.nd-title {
  text-transform: none !important;
}


/* ═══════════════════════════════════════════════════════════════════
   v0.32.50 — Vermin mascot bubble (with ears popping above)
   ───────────────────────────────────────────────────────────────────
   New bubble SVG (uploads/bubble_001.svg) — bigger main circle, white
   fill, darker stroke. Head PNG (118×118) sits ON TOP of the bubble
   so its ears can pop above the bubble outline naturally (no circle
   mask — the PNG's own transparency carries the silhouette). The
   wrapper gets a stronger layered drop-shadow that traces both the
   bubble outline AND the ear shapes, so the shadow falls from the
   ears too.

   Two rendered variants share these rules — the desktop variant
   anchors top-right of .nd-body-col on ≥1024px; the mobile variant
   anchors top-right of .nd-gallery-col on ≤1023px so it overlaps the
   gallery card.

   Container math (for the new bubble SVG):
     SVG viewBox  : 164.4 × 149.7
     SVG main-circle center : (94.5, 68.3),  radius 61
     Rendered at  : 155px wide
       → bubble height       = 155 × 149.7/164.4 ≈ 141px
       → circle diameter CSS = 61 × 2 × (155/164.4) ≈ 115px
     Container    : 155 × 176px (35px of "ear room" above bubble top)
       → bubble bottom-aligned, head 118×118 top-aligned
       → head's vertical center ≈ y=59 in container; bubble circle
         center ≈ y=99.4 → face sits in the UPPER portion of the
         bubble circle, ears extend 35px above bubble outline.
   ═══════════════════════════════════════════════════════════════════ */

/* v0.32.53 — Head sits INSIDE the bubble (Vic's reference image).
   The head is fully positioned WITHIN the bubble's main circle —
   ears tucked just under the bubble's top edge with only a tiny
   peek above. No mask needed: the PNG's natural transparency
   carries the silhouette, and once positioned correctly the head
   fits cleanly inside the bubble's circular space.

   Geometry (container 128×148):
     bubble bottom-aligned, height 117 → bubble top at y=31
     bubble main-circle (in SVG coords): center (~88, 75), radius ~62
     scaled to CSS (factor 128/164.4 = 0.779):
       center in bubble-local: (68.5, 58.4), radius 48.3
       center in container:    (68.5, 89.4)
     head 100×100 centered on bubble main-circle center:
       head top  = 89.4 − 50 = 39.4 → 39
       head left = 68.5 − 50 = 18.5

   With head center at the bubble center, the head's top edge (y=39)
   sits just 2px above the bubble's main-circle top (y=41.1), so only
   the very tips of the ears peek above the outline — matches Vic's
   reference. */
.nd-mascot {
  position: absolute;
  width: 128px;
  height: 148px;
  pointer-events: none;
  z-index: 5;
  /* v0.32.54 — Shadow tuned per Vic:
       • Tighter (blur 18px / 8px instead of 32 / 12).
       • Offset toward lower-RIGHT (positive x, positive y) instead of
         straight-down.
       • Tinted with the bubble's stroke color #4b1d40 (= rgb 75 29 64),
         the deep wine-purple that lives in the bubble outline AND the
         darker tonal range of vermin's mauve hair — gives the cast
         shadow a subtle warm-purple bias instead of a generic black. */
  filter:
    drop-shadow(8px 12px 18px rgba(75, 29, 64, 0.30))
    drop-shadow(3px 5px 8px rgba(75, 29, 64, 0.22));
  animation: vw-vermin-bob 9.4s cubic-bezier(.4,.0,.2,1) infinite;
  transform-origin: 50% 60%;
}

.nd-mascot__bubble {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 128px;
  /* Bubble aspect 164.4/149.7 → height = 128 × 149.7/164.4 ≈ 117px. */
  height: 117px;
  display: block;
}

.nd-mascot__head {
  position: absolute;
  /* v0.32.56 — Head bumped from 100→110 on desktop + tablet (Vic ask).
     Bubble container/dimensions stay the same — only the head grows,
     so vermin's face becomes a bit more prominent and his body extends
     slightly past the bubble outline on the sides (~7px each side),
     matching Vic's reference image 3 where the body breaks the bubble
     edge slightly. Phone override (≤520px) keeps head at 94×94 since
     Vic asked for desktop + tablet only.
     v0.32.57 — head nudged right (Vic ask): left 13.5 → 17. */
  width: 110px;
  height: 110px;
  left: 17px;
  top: 34px;
  display: block;
}

/* ─── Per-variant placement (desktop / mobile) ──────────────────── */

/* Desktop variant — anchored top-right of .nd-body-col with bigger
   right offset so it sits clearly inside the column instead of flush
   to the right edge. */
.nd-mascot--desktop {
  top: -24px;
  right: 24px;
}
@media (max-width: 1023px) {
  .nd-mascot--desktop { display: none; }
}

/* Mobile/tablet variant — anchored to the LEFT but offset further
   IN so it sits to the RIGHT of the "GALLERY" eyebrow with a clear
   gap (v0.32.58 — Vic flagged that left:16 had the bubble's lower-
   left tail overlapping the GALLERY text). At left:130 the tail tip
   (container x≈14) lands at .nd-gallery x≈144 — well past the
   GALLERY eyebrow which typically ends around x=100, giving a ~30px
   visual gap. Still well clear of the prev/next arrows at the
   right edge. */
.nd-mascot--mobile {
  top: -100px;
  left: 130px;
}
@media (min-width: 1024px) {
  .nd-mascot--mobile { display: none; }
}

/* ─── Title clear-space (desktop only) ──────────────────────────── */
/* Reserve room beside the bubble so long titles don't underlap.
   128 bubble + 24 right offset + small margin = 160. */
@media (min-width: 1024px) {
  .nd-title { padding-right: 160px; }
}

/* ─── Phone (≤520px) ────────────────────────────────────────────── */
/* v0.32.55 — bigger on phone (120×138 / head 94×94) + anchored over
   the gallery image. v0.32.56 — lifted UP so only ~30% of the bottom
   overlaps the gallery image (Vic ask). Container 138 tall × 0.7 =
   ~97px above gallery card; top:-97 puts ~41px (~30%) inside.
   Phone bubble math (scale 120/164.4 = 0.730): main-circle center
   (88×0.730, 75×0.730) = (64.2, 54.8) in bubble-local; container
   coord (bubble top y=28): center (64.2, 82.8), radius 45.3.
   Head 94×94 centered on bubble center:
     head left = 64.2 − 47 = 17.2 → 17
     head top  = 82.8 − 47 = 35.8 → 36 */
@media (max-width: 520px) {
  /* v0.32.58 — phone shifted further right (left:16→120) so the
     bubble's tail clears the GALLERY eyebrow with a ~20px gap. */
  .nd-mascot--mobile { width: 120px; height: 138px; top: -97px; left: 120px; right: auto; }
  .nd-mascot--mobile .nd-mascot__bubble { width: 120px; height: 110px; }
  .nd-mascot--mobile .nd-mascot__head { width: 94px; height: 94px; left: 21px; top: 36px; }
}

/* v0.32.51 — Idle bob with a subtle LEFT lean (Vic ask).
   Rotation values shifted negative across the cycle so the average
   tilt is a bit leftward (rotate-left is the dominant pose, with
   small right-tilt only as a momentary kick). Translations slightly
   reduced from v0.32.49 since the smaller bubble doesn't need as
   much sway to feel alive. Total cycle still 9.4s. */
@keyframes vw-vermin-bob {
  0%   { transform: translate(0, 0)       rotate(-1deg); }
  17%  { transform: translate(1px, -3px)  rotate(-3deg); }
  34%  { transform: translate(-2px, -1px) rotate(-2deg); }
  51%  { transform: translate(1px, -5px)  rotate(-4deg); }
  68%  { transform: translate(2px, 1px)   rotate(0.5deg); }
  85%  { transform: translate(-1px, -2px) rotate(-1.5deg); }
  100% { transform: translate(0, 0)       rotate(-1deg); }
}

@media (prefers-reduced-motion: reduce) {
  .nd-mascot { animation: none; transform: rotate(-1deg); }
}
