/* ═══════════════════════════════════════════════════════════
   NS theme — Reviews page (frontend/ns/feedback.php, served at /feedback).

   Loaded only on that page (head.php checks $ns_page), so none of this
   costs anything anywhere else. It leans on the theme's own primitives —
   .phero, .pagesec, .sectitle, .tpbar, .tpsearch, .btn, .reveal — and only
   adds what the wall itself needs.
   ═══════════════════════════════════════════════════════════ */

/* ───────────────────────────────────────────────
   0. TURN THE THEME'S SCROLL-REVEAL BACK ON

   ns-theme.css carries the reveal animation as `.ns-theme .js .reveal`, but
   `js` is set on <html> and `ns-theme` on <body> — so `.js` is an ANCESTOR of
   `.ns-theme`, never a descendant, and the rule has never matched on any page.
   The correct nesting is `.js` then `.ns-theme`. Scoped to .rvpage here so it
   only switches on for this page; the same two lines without `.rvpage` would
   enable it site-wide.
   ─────────────────────────────────────────────── */
.js .ns-theme .rvpage .reveal{
  opacity:0;
  transform:translateY(26px);
  filter:blur(7px);
  transition:opacity .95s var(--ease),transform .95s var(--ease),filter .95s var(--ease);
}
.js .ns-theme .rvpage .reveal.in{opacity:1;transform:none;filter:none}

@media (prefers-reduced-motion:reduce){
  .js .ns-theme .rvpage .reveal,
  .js .ns-theme .rvpage .reveal.in{opacity:1;transform:none;filter:none;transition:none}
}


/* ───────────────────────────────────────────────
   0b. A TIGHTER HEADER FOR THIS PAGE

   The shared .phero is sized for pages whose header IS the content. Here it
   is just the way in to 278 reviews, so it gives up height: at 1900x950 the
   wall used to start 851px down, below the fold on most laptops. Everything
   is scoped to .rvpage — .phero is shared with Courses, Books, Top Scorers
   and the rest, which keep their original proportions.

   The top padding still has to clear the fixed header (about 90px tall before
   it shrinks on scroll), so it comes down only as far as 104px.
   ─────────────────────────────────────────────── */
.ns-theme .rvpage .phero{padding:104px 0 26px}
.ns-theme .rvpage .crumb{margin-bottom:11px}
.ns-theme .rvpage .phero h1{font-size:clamp(29px,3.3vw,43px)}
.ns-theme .rvpage .phero__lede{
  margin-top:11px;
  max-width:62ch;
  font-size:15px;
  line-height:1.62;
}
.ns-theme .rvpage .pmeta div{padding:9px 14px;min-width:92px}
.ns-theme .rvpage .pmeta b{font-size:22px}
.ns-theme .rvpage .pmeta span{font-size:9px}


/* ───────────────────────────────────────────────
   1. STARS
   ─────────────────────────────────────────────── */
.ns-theme .rvstars{display:inline-flex;gap:2px;line-height:1}
.ns-theme .rvstars i{font-style:normal;font-size:13px;color:var(--gold-2)}
.ns-theme .rvstars i.is-off{color:var(--line-2)}
.ns-theme .rvstars--lg i{font-size:22px;letter-spacing:1px}


/* ───────────────────────────────────────────────
   2. THE RATING BAR

   The score used to have a full-width band to itself. For a handful of
   figures that pushed the reviews off the screen, so it now shares the
   wall's toolbar row: average and stars on the left, the distribution
   beside them, the running count on the right.
   ─────────────────────────────────────────────── */
.ns-theme .rvbar{
  gap:clamp(14px,2vw,32px);
  padding:14px 18px;
  border-radius:var(--r-md);
  background:linear-gradient(158deg,var(--surface),var(--surface-2));
  border:1px solid var(--line);
  box-shadow:var(--sh-sm);
}

.ns-theme .rvsum{
  display:flex;
  align-items:center;
  gap:clamp(12px,1.6vw,24px);
  flex-wrap:wrap;
  min-width:0;
}
.ns-theme .rvsum__avg{
  font-family:var(--display);
  font-size:clamp(30px,3vw,40px);
  font-weight:700;
  line-height:1;
  letter-spacing:-.035em;
  font-variant-numeric:tabular-nums;
  background:var(--accent-text);
  -webkit-background-clip:text;background-clip:text;color:transparent;
}
.ns-theme .rvsum__of{display:flex;flex-direction:column;gap:3px}
.ns-theme .rvsum__cap{
  font-family:var(--label);
  font-size:10px;font-weight:600;line-height:1.3;
  letter-spacing:.13em;text-transform:uppercase;
  color:var(--faint);
}

/* the distribution — one row per rating that actually occurs */
.ns-theme .rvbars{
  display:grid;gap:5px;margin:0;padding:0;list-style:none;
  padding-left:clamp(12px,1.6vw,24px);
  border-left:1px solid var(--line);
}
.ns-theme .rvbars li{display:grid;grid-template-columns:34px clamp(90px,11vw,190px) 34px;gap:10px;align-items:center}
.ns-theme .rvbars__k{
  font-family:var(--num);font-size:11.5px;font-weight:600;
  color:var(--muted);white-space:nowrap;
}
.ns-theme .rvbars__k i{font-style:normal;color:var(--gold-2)}
.ns-theme .rvbars__track{
  position:relative;display:block;height:7px;border-radius:100px;
  background:rgba(15,39,69,.09);overflow:hidden;
}
.ns-theme .rvbars__track i{
  position:absolute;inset:0 auto 0 0;display:block;
  width:0;                       /* animates to --w when the bar reveals */
  border-radius:100px;
  background:var(--gold-fill);
  transition:width 1.15s var(--ease) .25s;
}
.ns-theme .rvbars__n{
  font-family:var(--num);font-size:11.5px;font-weight:600;
  color:var(--text);text-align:right;font-variant-numeric:tabular-nums;
}
/* the bars fill once the row has scrolled in. min-width keeps a rating that
   only one student gave (0.4% of the total) from rendering as nothing at all —
   only ratings with at least one review get a row, so this never shows a
   sliver for a count of zero. */
.ns-theme .rvbar.in .rvbars__track i{width:var(--w);min-width:5px}
/* no JS, or motion turned down: show them filled straight away */
html:not(.js) .ns-theme .rvbars__track i{width:var(--w)}
@media (prefers-reduced-motion:reduce){
  .ns-theme .rvbars__track i{width:var(--w);transition:none}
}


/* ───────────────────────────────────────────────
   3. THE WALL

   CSS columns rather than a grid: the reviews run from 50 to 1500 characters,
   so fixed rows would leave big holes. Columns also collapse to 2 and then 1
   on their own, and keep document order — which a hand-built column split
   (like the homepage marquee) does not.
   ─────────────────────────────────────────────── */
.ns-theme .rvwall{
  column-count:3;
  column-gap:18px;
  margin-top:4px;
}
/* Each card is tinted in one of the theme's four supporting hues, cycling in
   document order, so a wall of 278 reviews reads as a mosaic instead of 278
   identical boxes. Same device the offerings grid (.svc) and the About
   promises (.pledge) already use — done here with :nth-child rather than an
   inline --accent, so the view stays free of presentation detail and the
   cards revealed by "Show more" pick up their colour automatically. */
.ns-theme .rvcard{
  --accent:#1B4B96;
  position:relative;
  display:block;
  break-inside:avoid;
  page-break-inside:avoid;      /* older engines */
  width:100%;
  margin:0 0 18px;
  padding:30px 24px 20px;
  border-radius:var(--r-lg);
  overflow:hidden;              /* keeps the top edge and the bloom on the radius */
  background:
    linear-gradient(158deg,
      color-mix(in srgb,var(--accent) 7%,#fff) 0%,
      color-mix(in srgb,var(--accent) 2%,#fff) 46%,
      var(--surface) 100%);
  border:1px solid color-mix(in srgb,var(--accent) 16%,var(--line));
  box-shadow:var(--sh-sm);
  transition:transform .5s var(--ease),box-shadow .5s var(--ease),border-color .4s;
}
.ns-theme .rvcard:nth-child(4n+2){--accent:#C2451F}
.ns-theme .rvcard:nth-child(4n+3){--accent:#0F6E75}
.ns-theme .rvcard:nth-child(4n+4){--accent:#9A7420}

/* the accent edge — a hairline at rest, full weight when the card is hovered */
.ns-theme .rvcard::before{
  content:"";position:absolute;left:0;right:0;top:0;height:3px;
  background:linear-gradient(90deg,var(--accent),color-mix(in srgb,var(--accent) 25%,transparent));
  transform:scaleX(1);transform-origin:left;
  opacity:.5;transition:opacity .45s var(--ease);
}
/* a soft bloom in the top-right, so the tint has somewhere to come from */
.ns-theme .rvcard::after{
  content:"";position:absolute;right:-30%;top:-46%;width:88%;aspect-ratio:1;
  pointer-events:none;border-radius:50%;
  background:radial-gradient(circle,color-mix(in srgb,var(--accent) 16%,transparent),transparent 66%);
  opacity:.6;transition:opacity .45s var(--ease);
}
.ns-theme .rvcard:hover{
  transform:translateY(-6px);
  border-color:color-mix(in srgb,var(--accent) 42%,transparent);
  box-shadow:0 26px 54px -28px color-mix(in srgb,var(--accent) 55%,transparent),
             0 4px 14px rgba(12,31,61,.07);
}
.ns-theme .rvcard:hover::before{opacity:1}
.ns-theme .rvcard:hover::after{opacity:1}

/* The quote mark sits behind the text as a watermark rather than beside it —
   bigger, softer, and out of the reading line. */
/* top:4px, not a negative offset — the card clips its overflow now, and the
   glyph's ink starts right at the top of its line box, so anything negative
   shears the tops off the two commas. */
.ns-theme .rvcard__mark{
  position:absolute;top:4px;right:18px;z-index:0;
  font-family:var(--display);font-size:96px;line-height:1;
  color:color-mix(in srgb,var(--accent) 17%,transparent);
  pointer-events:none;user-select:none;
}
/* lift the real content above the bloom and the watermark — but not the mark
   itself, which must keep its own absolute position */
.ns-theme .rvcard > *:not(.rvcard__mark){position:relative;z-index:1}

.ns-theme .rvcard .rvstars{
  margin-bottom:13px;
  padding:5px 10px;border-radius:100px;
  background:color-mix(in srgb,var(--accent) 8%,transparent);
  border:1px solid color-mix(in srgb,var(--accent) 15%,transparent);
}

.ns-theme .rvcard__body{position:relative}
.ns-theme .rvcard__body p{
  margin:0;
  font-size:14.8px;
  line-height:1.72;
  letter-spacing:.002em;
  color:var(--text);
  /* long reviews are clamped until "Read the full review" is pressed */
  display:-webkit-box;
  -webkit-line-clamp:10;
  -webkit-box-orient:vertical;
  overflow:hidden;
}
.ns-theme .rvcard.is-open .rvcard__body p{-webkit-line-clamp:unset;overflow:visible}
.ns-theme .rvcard__body em,
.ns-theme .rvcard__body i{font-style:italic;color:var(--blue-2)}
.ns-theme .rvcard__body b,
.ns-theme .rvcard__body strong{font-weight:600;color:var(--ink-900)}

.ns-theme .rvcard__more{
  margin-top:9px;padding:0;border:0;background:none;
  font-family:var(--label);
  font-weight:600;font-size:10.5px;letter-spacing:.15em;text-transform:uppercase;
  color:var(--blue-2);cursor:pointer;
  display:inline-flex;align-items:center;gap:7px;
  transition:gap .3s var(--ease);
}
.ns-theme .rvcard__more::after{content:"";width:14px;height:1px;background:currentColor;transition:width .3s var(--ease)}
.ns-theme .rvcard__more:hover{gap:10px}
.ns-theme .rvcard__more:hover::after{width:20px}

.ns-theme .rvcard__by{
  display:flex;align-items:center;gap:13px;
  margin-top:18px;padding-top:15px;
  border-top:1px solid color-mix(in srgb,var(--accent) 14%,var(--line));
}
/* gold disc, a white gap, then a thin ring in the card's accent */
.ns-theme .rvcard__av{
  position:relative;
  display:grid;place-items:center;
  width:44px;height:44px;flex:none;
  border-radius:50%;overflow:hidden;
  background:var(--gold-fill);
  border:2px solid #fff;
  box-shadow:0 0 0 1.5px color-mix(in srgb,var(--accent) 45%,transparent),
             0 4px 10px -4px rgba(12,31,61,.35);
  transition:box-shadow .45s var(--ease),transform .45s var(--ease);
}
.ns-theme .rvcard:hover .rvcard__av{
  transform:scale(1.06);
  box-shadow:0 0 0 2px var(--accent),0 6px 14px -5px rgba(12,31,61,.4);
}
/* the photograph covers the initials; if it 404s it removes itself and the
   initials underneath show through */
.ns-theme .rvcard__av img{
  position:absolute;inset:0;
  width:100%;height:100%;object-fit:cover;
}
.ns-theme .rvcard__av b{
  font-family:var(--display);font-size:15px;font-weight:700;font-style:italic;color:#241A05;
}
.ns-theme .rvcard__who{display:flex;flex-direction:column;min-width:0}
.ns-theme .rvcard__who b{
  font-family:var(--display);font-size:15.5px;font-weight:600;letter-spacing:-.014em;color:var(--text);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
/* the role picks up the card's accent, which ties the byline to the edge */
.ns-theme .rvcard__who span{
  font-family:var(--label);font-weight:700;font-size:9.5px;
  letter-spacing:.15em;text-transform:uppercase;margin-top:3px;
  color:color-mix(in srgb,var(--accent) 72%,var(--ink-900));
}

/* cards brought in by "Show more" fade up rather than snapping in */
@keyframes ns-rv-in{from{opacity:0;transform:translateY(16px)}to{opacity:1;transform:none}}
.ns-theme .rvcard.is-new{animation:ns-rv-in .6s var(--ease) both}
@media (prefers-reduced-motion:reduce){
  .ns-theme .rvcard.is-new{animation:none}
  .ns-theme .rvcard:hover{transform:none}
}

/* The marker the wall watches to load its next batch. It needs real height —
   a zero-height element sitting exactly on the boundary can fail to register
   as intersecting — but no visible presence. */
.ns-theme .rvsentinel{width:100%;height:1px;margin:0;pointer-events:none}

.ns-theme .rvmorewrap{display:flex;justify-content:center;margin-top:26px}
.ns-theme .rvmorewrap .btn svg{transition:transform .4s var(--ease)}
.ns-theme .rvmorewrap .btn:hover svg{transform:translateY(3px) translateX(0)}

.ns-theme .rvnone{
  padding:60px 0;text-align:center;color:var(--muted);font-size:16px;
}


/* ───────────────────────────────────────────────
   4. CTA
   ─────────────────────────────────────────────── */
.ns-theme .rvcta{
  display:flex;align-items:center;justify-content:space-between;
  gap:clamp(18px,3vw,40px);flex-wrap:wrap;
  padding:clamp(24px,3vw,38px);
  border-radius:var(--r-lg);
  background:linear-gradient(120deg,var(--cream),var(--surface) 62%);
  border:1px solid rgba(217,180,92,.4);
  box-shadow:var(--sh-sm);
}
.ns-theme .rvcta h2{
  font-family:var(--display);
  font-size:clamp(22px,2.5vw,32px);font-weight:600;letter-spacing:-.018em;color:var(--text);
}
.ns-theme .rvcta h2 em{
  font-style:italic;font-weight:700;
  background:var(--accent-text);-webkit-background-clip:text;background-clip:text;color:transparent;
}
.ns-theme .rvcta p{margin-top:9px;max-width:52ch;color:var(--muted);font-size:15px;line-height:1.7}
.ns-theme .rvcta__btns{display:flex;gap:12px;flex-wrap:wrap}


/* ───────────────────────────────────────────────
   5. RESPONSIVE
   ─────────────────────────────────────────────── */
@media (max-width:1100px){
}
@media (max-width:980px){
  .ns-theme .rvwall{column-count:2}
  /* score, distribution and count no longer fit one line */
  .ns-theme .rvbar{flex-direction:column;align-items:flex-start;gap:12px}
  .ns-theme .rvbars{padding-left:0;border-left:0}
}
@media (max-width:720px){
  /* On a phone the header is pure preamble before the reviews, so it gives up
     more again: measured at 390px the wall started 1029px down. */
  .ns-theme .rvpage .phero{padding:88px 0 18px}
  .ns-theme .rvpage .phero__lede{font-size:14.5px;line-height:1.55;margin-top:9px}
  .ns-theme .rvpage .pmeta{gap:7px;justify-content:flex-start}
  .ns-theme .rvpage .pmeta div{flex:1 1 0;min-width:0;padding:8px 10px}
  .ns-theme .rvpage .pmeta b{font-size:19px}
  .ns-theme .rvstars--lg i{font-size:18px}

  .ns-theme .rvwall{column-count:1}
  .ns-theme .rvcta{flex-direction:column;align-items:flex-start}
  .ns-theme .rvcta__btns{width:100%}
  .ns-theme .rvcta__btns .btn{flex:1 1 auto;justify-content:center}
}
