/* RIPPLES — product reviews section.
 * Loaded only on product pages. Uses the Nocturne tokens, adds no new colours.
 *
 * Sits between "what it does" and "goes well with", so it has to hold its own
 * against those sections rather than read as a footnote under them: a real score
 * panel, cards with some weight, and the form open by default.
 */

/* ---------------- SCORE PANEL ---------------- */
.rev-score{
  display:flex;flex-wrap:wrap;align-items:center;gap:32px 56px;
  margin-top:30px;padding:26px 28px;
  border:1px solid var(--line);border-radius:10px;
  background:
    radial-gradient(120% 180% at 0% 0%, rgba(194,74,44,.10), transparent 60%),
    var(--surface);
}
.rev-score-figure{display:flex;flex-direction:column;gap:8px;min-width:132px}
.rev-avg{
  font-size:clamp(2.6rem,6vw,3.4rem);line-height:.9;font-weight:700;
  color:var(--cream);letter-spacing:-.02em;
}
.rev-count{font-size:.85rem;color:var(--cream-faint)}

/* The spread. Kept visible on purpose: an average with the distribution hidden is
   a marketing number, and two threes among seven fives is useful information. */
.rev-dist{display:grid;gap:6px;flex:1 1 260px;max-width:420px}
.rev-dist-row{display:grid;grid-template-columns:14px 1fr 22px;align-items:center;gap:10px}
.rev-dist-n,.rev-dist-c{font-size:.78rem;color:var(--cream-faint);font-variant-numeric:tabular-nums}
.rev-dist-c{text-align:right}
.rev-dist-track{height:6px;border-radius:999px;background:rgba(241,235,222,.07);overflow:hidden}
.rev-dist-fill{display:block;height:100%;border-radius:999px;background:var(--accent-deep)}

/* ---------------- STARS ---------------- */
.rev-stars{display:inline-flex;gap:3px;line-height:1}
.rev-stars svg{width:17px;height:17px}
/* The same .on/.off stars are used twice: read-only in .rev-stars, and as the
   interactive control in .rev-rate. Both containers need the rule - without it an
   SVG falls back to its default black fill and vanishes against the card. */
.rev-stars .on,.rev-rate .on{fill:var(--accent-bright);stroke:var(--accent-bright)}
.rev-stars .off,.rev-rate .off{fill:none;stroke:var(--cream-faint)}

/* ---------------- LIST ---------------- */
.rev-list{display:grid;gap:16px;margin-top:26px}
@media(min-width:900px){ .rev-list{grid-template-columns:repeat(2,1fr)} }

.rev-item{
  position:relative;
  border:1px solid var(--line);border-radius:10px;
  background:var(--surface);padding:24px 26px;
  transition:border-color .2s var(--ease,ease),transform .2s var(--ease,ease);
}
.rev-item:hover{border-color:var(--line-strong);transform:translateY(-1px)}
/* A quote mark set behind the text rather than in the flow, so a card reads as
   somebody speaking without stealing a line of space. */
.rev-item::before{
  content:"”";position:absolute;top:6px;right:18px;
  font-size:3.4rem;line-height:1;
  color:var(--cream);opacity:.07;pointer-events:none;
}
.rev-item-head{display:flex;justify-content:space-between;align-items:flex-start;gap:14px}
.rev-title{font-size:1.06rem;font-weight:600;margin-bottom:8px;letter-spacing:-.01em}
.rev-body{
  font-size:.97rem;line-height:1.7;color:var(--cream-dim);
  white-space:pre-wrap;overflow-wrap:anywhere;margin-top:12px;
}
.rev-meta{
  display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  margin-top:18px;padding-top:14px;border-top:1px solid var(--line);
  font-size:.82rem;color:var(--cream-faint);
}
.rev-author{color:var(--cream);font-weight:600}

.rev-badge{
  display:inline-block;font-size:.72rem;letter-spacing:.02em;
  padding:3px 9px;border-radius:999px;
  border:1px solid var(--line-strong);color:var(--cream-faint);
}
.rev-badge.is-verified{
  border-color:rgba(194,74,44,.4);color:var(--accent-bright);
  background:var(--accent-soft);
}

/* ---------------- FORM ---------------- */
/* Open when the product has no reviews - the ask is the whole section then. Once
   reviews exist the form collapses in behind this disclosure, because ~700px of
   form under them buries what people came to read. Matches .win-setup so the two
   disclosures on a product page behave the same way. */
/* Collapsed, this bar has to read as "there is more here" on its own - it is the
   only route to the form on a product that already has reviews. Hence the accent
   border and the chevron rather than a quiet grey +. */
.rev-disclose{
  margin-top:26px;border:1px solid rgba(194,74,44,.38);border-radius:10px;
  background:var(--surface);max-width:760px;
  transition:border-color .2s var(--ease,ease),background-color .2s var(--ease,ease);
}
.rev-disclose:hover{border-color:var(--accent);background:var(--accent-soft)}
.rev-disclose[hidden]{display:none}
.rev-disclose-sum{
  list-style:none;cursor:pointer;padding:15px 20px;
  display:flex;align-items:center;gap:12px;
  font-size:.95rem;font-weight:600;color:var(--cream);
}
.rev-disclose-sum::-webkit-details-marker{display:none}
.rev-disclose-sum:focus-visible{outline:2px solid var(--accent);outline-offset:-2px;border-radius:10px}
.rev-disclose-chev{
  margin-left:auto;width:20px;height:20px;flex:none;color:var(--accent-bright);
  transition:transform .2s var(--ease,ease);
}
.rev-disclose[open]{border-color:var(--line);background:var(--surface)}
.rev-disclose[open] .rev-disclose-sum{border-bottom:1px solid var(--line)}
.rev-disclose[open] .rev-disclose-chev{transform:rotate(180deg)}
@media(prefers-reduced-motion:reduce){
  .rev-disclose,.rev-disclose-chev{transition:none}
}
/* Inside the disclosure the form is already framed by it, so drop the second
   border and the gap that would stack under the summary. */
.rev-disclose .rev-form{
  margin-top:0;border:none;border-radius:0;background:none;max-width:none;
}

.rev-form{
  margin-top:30px;border:1px solid var(--line-strong);border-radius:10px;
  background:linear-gradient(180deg,rgba(241,235,222,.02),transparent 40%),var(--surface);
  padding:28px 26px;max-width:760px;
}
.rev-form[hidden]{display:none}
.rev-form-head{margin-bottom:22px}
.rev-form-head h3{font-size:1.18rem;letter-spacing:-.01em}
.rev-form-note{margin-top:7px;font-size:.88rem;color:var(--accent-bright)}
.rev-row{margin-bottom:18px}
.rev-row label{display:block;font-size:.82rem;color:var(--cream-dim);margin-bottom:7px}
.rev-opt{opacity:.6}
@media(min-width:640px){
  .rev-grid{display:grid;grid-template-columns:1fr 1fr;gap:0 18px}
}
.rev-form input[type=text],
.rev-form input[type=email],
.rev-form textarea{
  width:100%;background:var(--bg-2);color:var(--cream);
  border:1px solid var(--line-strong);border-radius:6px;
  padding:12px 14px;font:inherit;font-size:.95rem;
  transition:border-color .15s var(--ease,ease),box-shadow .15s var(--ease,ease);
}
.rev-form textarea{min-height:132px;resize:vertical}
.rev-form input::placeholder,.rev-form textarea::placeholder{color:var(--cream-faint)}
.rev-form input:focus,.rev-form textarea:focus{
  border-color:var(--accent);outline:none;box-shadow:0 0 0 3px var(--accent-soft);
}

/* Honeypot. Off-screen rather than display:none, which some bots skip. */
.rev-hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

/* The rating control, deliberately large: it is the only required field with no
   text in it, and "pressed Post without picking a rating" was the single biggest
   point of loss once we started measuring it. */
.rev-row-rate{display:flex;align-items:center;flex-wrap:wrap;gap:6px 16px}
.rev-row-rate label{width:100%;margin-bottom:2px}
.rev-rate{display:flex;gap:4px;border-radius:8px;padding:4px 6px;margin-left:-6px}
.rev-rate:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.rev-rate button{
  background:none;border:none;cursor:pointer;padding:2px;line-height:0;color:inherit;
}
.rev-rate svg{width:32px;height:32px;transition:transform .12s var(--ease,ease)}
.rev-rate button:hover svg{transform:scale(1.12)}
.rev-rate-read{font-size:.86rem;color:var(--cream-dim);font-variant-numeric:tabular-nums}
.rev-rate-read.is-preview{color:var(--cream-faint)}

/* Shown when someone presses Post with no rating chosen. */
.rev-rate.is-missing{
  background:var(--accent-soft);
  box-shadow:0 0 0 1px rgba(194,74,44,.45);
  animation:rev-nudge .35s var(--ease,ease);
}
@keyframes rev-nudge{
  0%,100%{transform:translateX(0)}
  25%{transform:translateX(-4px)}
  75%{transform:translateX(4px)}
}
@media(prefers-reduced-motion:reduce){
  .rev-rate.is-missing{animation:none}
  .rev-item{transition:none}
}

.rev-note{font-size:.82rem;color:var(--cream-faint);margin:-4px 0 20px}
.rev-submit-row{display:flex;align-items:center;gap:16px;flex-wrap:wrap}
.rev-fineprint{font-size:.78rem;color:var(--cream-faint)}

/* Live length hint under the review body. Counts down while they are short. */
.rev-hint{font-size:.78rem;color:var(--cream-faint);margin-top:7px}
.rev-hint.ok{color:var(--cream-dim)}

.rev-msg{margin-top:14px;font-size:.9rem}
.rev-msg.err{color:var(--accent-bright)}
.rev-msg.ok{color:var(--cream)}

.rev-thanks{
  margin-top:28px;border:1px solid rgba(194,74,44,.4);background:var(--accent-soft);
  border-radius:10px;padding:24px 26px;max-width:760px;
}
.rev-thanks h3{font-size:1.1rem;margin-bottom:8px}
.rev-thanks p{font-size:.95rem;color:var(--cream-dim)}

/* Few reviews: a compact score line rather than a wide panel with empty rows, and
   a single review spanning the row instead of leaving a hole beside it. Sparse data
   should look deliberate, not broken. */
.rev-score.is-compact{gap:20px 28px;padding:22px 26px}
.rev-score.is-compact .rev-score-figure{flex-direction:row;align-items:baseline;gap:14px;min-width:0;flex-wrap:wrap}
.rev-score.is-compact .rev-avg{font-size:2.2rem}
@media(min-width:900px){ .rev-list.is-single{grid-template-columns:1fr} }
.rev-list.is-single .rev-item{max-width:860px}
