/* ============================================================================
   Nouri Narie 2.0 — the six content pages

   Loads after components.css and adds only what the shared system does not
   already provide. Anything that could be a .card, a .note, an .acc, a .tbl,
   a .meter, a .step or a .grid-* is one of those and is absent from this file.

   Three things here are behavioural rather than decorative and are commented
   as such: the .quiz-step / .quiz-result display toggle (js/quiz.js switches
   .is-active and nothing else makes a step appear), the .field.is-invalid
   state (js/contact.js sets it), and the .form-msg tones the same script
   assigns by className.

   No glass effects. No --shadow-3 — every one of these pages already spends
   Rhode's rose float once, on the primary button's hover in components.css.
   Disabled is --ink-disabled and cursor:not-allowed, never opacity; base.css
   already owns that and nothing below overrides it.
   ========================================================================= */

/* ── shared across the six ─────────────────────────────────────────────── */

/* The closing CTA pair. Wraps to a column below 480 so neither button is
   squeezed under its own label. */
.cta-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
  margin-top: var(--s-10);
}
@media (max-width: 479px) {
  .cta-row { flex-direction: column; align-items: stretch; }
}

/* The heading/body statement card used by story's promise band and shipping's
   returns list. Deliberately rule-and-ground rather than a bordered .card:
   these are prose, not products, and a four-up of bordered boxes on an
   editorial page reads as a spec sheet. */
.stmt {
  padding-top: var(--s-5);
  border-top: 2px solid var(--sage);
}
.stmt h3 { font-size: var(--t-h4); }
.stmt p { margin-top: var(--s-3); color: var(--ink-soft); }

/* A list that separates on a hairline rather than a bullet — Rhode's habit,
   and it keeps a long ingredient list legible at the reading measure. */
.rule-list {
  list-style: none;
  margin: var(--s-5) 0 0;
  padding: 0;
}
.rule-list li {
  padding-block: var(--s-4);
  border-top: 1px solid var(--rule-hair);
  color: var(--ink-soft);
}
.rule-list li:last-child { border-bottom: 1px solid var(--rule-hair); }
.rule-list b { color: var(--ink); }

/* Cautions and supplier caveats. --ink-muted is 5.7:1 on --paper; the left
   rule is what actually marks it as an aside. */
.caution {
  margin-top: var(--s-5);
  padding-left: var(--s-4);
  border-left: 2px solid var(--rule-soft);
}

/* Accordion bodies on these pages hold multiple paragraphs — the FAQ answers
   and the ingredient notes. components.css sets the body's padding but not the
   rhythm between paragraphs inside it. */
.acc-body > * + * { margin-top: var(--s-4); }

/* ── story ─────────────────────────────────────────────────────────────── */

/* Image first on mobile, image left from 1024. The visual is the entry point
   to the argument, so it leads on both. */
.story-grid { align-items: start; }
.story-visual { position: relative; }

/* Kylie's badge language, at panel size. --alu-light behind --ink is 11.79:1.
   Sits on the frame's lower corner rather than over the subject. */
.story-badge {
  position: absolute;
  left: var(--s-5);
  bottom: var(--s-5);
  display: flex;
  flex-direction: column;
  padding: var(--s-4) var(--s-5);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  background: var(--alu-light);
}
.story-badge strong {
  font-family: var(--font-display);
  font-variation-settings: 'wght' 800, 'wdth' 88;
  font-size: var(--t-h3);
  line-height: var(--lh-tight);
}
.story-badge span {
  font-family: var(--font-mono);
  font-size: var(--t-micro);
  letter-spacing: var(--ls-micro);
  text-transform: uppercase;
  color: var(--ink-muted);
}

@media (max-width: 767px) {
  .story-badge { left: var(--s-3); bottom: var(--s-3); padding: var(--s-3) var(--s-4); }
}

/* ── ritual ────────────────────────────────────────────────────────────── */

/* The chapter thumbnail rides inside the step body, above the position line.
   4:3 rather than the source 3:2 so three of them sit level with the ladder's
   text without pushing the rules apart. */
.ritual-thumb {
  display: block;
  margin-bottom: var(--s-4);
  border-radius: var(--r-sm);
  overflow: hidden;
  text-decoration: none;
  color: inherit;
  position: relative;
  background: var(--mist);
}
.ritual-thumb img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  transition: transform var(--d-slow) var(--ease-out);
}
.ritual-thumb:hover img { transform: scale(1.03); }
.ritual-thumb span {
  position: absolute;
  left: var(--s-3);
  bottom: var(--s-3);
  padding: var(--s-1) var(--s-2);
  border-radius: var(--r-xs);
  background: var(--graphite);
  color: var(--on-dark);
}

/* The caption for the full-bleed chapter band. media_band()'s own caption slot
   sets --t-display, which belongs to index.html and story.html alone, so the
   chapter is titled underneath at the interior scale instead. */
.chapter-note {
  padding-top: var(--s-8);
  padding-bottom: var(--s-8);
}
.chapter-note p { max-width: 56ch; }
.chapter-note .btn { margin-top: var(--s-6); }

.ampm {
  display: grid;
  gap: var(--s-8);
  grid-template-columns: 1fr;
  margin-top: var(--s-6);
}
@media (min-width: 768px) { .ampm { grid-template-columns: 1fr 1fr; gap: var(--s-12); } }

.ampm-col ol {
  margin: var(--s-4) 0 0;
  padding: 0;
  list-style: none;
  counter-reset: ampm;
}
.ampm-col li {
  counter-increment: ampm;
  padding: var(--s-3) 0 var(--s-3) var(--s-8);
  border-top: 1px solid var(--rule-hair);
  color: var(--ink-soft);
  position: relative;
}
.ampm-col li::before {
  content: counter(ampm, decimal-leading-zero);
  position: absolute;
  left: 0;
  top: var(--s-3);
  font-family: var(--font-mono);
  font-size: var(--t-micro);
  letter-spacing: var(--ls-micro);
  color: var(--sage-deep);
}

/* ── ingredients ───────────────────────────────────────────────────────── */

/* The five featured ingredients. Same rule-over-heading treatment as .stmt so
   the two lists on this page read as one family. */
.active-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s-3);
  padding-top: var(--s-5);
  border-top: 2px solid var(--sage);
}
.active-card h3 { font-size: var(--t-h4); }
.active-card p { color: var(--ink-soft); }
.active-card .t-caption { margin-top: auto; }

.formulas > * + * {
  margin-top: var(--s-16);
  padding-top: var(--s-16);
  border-top: 1px solid var(--rule-soft);
}
.formula h3 { font-size: var(--t-h3); }
.formula h3 a { text-decoration: none; }
.formula h3 a:hover { text-decoration: underline; text-underline-offset: 0.18em; }
.formula h4 {
  margin-top: var(--s-10);
  font-family: var(--font-mono);
  font-variation-settings: normal;
  font-size: var(--t-micro);
  font-weight: 500;
  letter-spacing: var(--ls-micro);
  text-transform: uppercase;
  color: var(--ink-muted);
}
.formula h4 + p { margin-top: var(--s-4); }
.formula p + p { margin-top: var(--s-4); }
.formula p { color: var(--ink-soft); }
.formula .acc { margin-top: var(--s-8); }

/* The supplier list itself. Long, comma-separated, and not prose — the mono
   face and the loosened leading make it scannable for one word. */
.inci {
  font-family: var(--font-mono);
  font-size: var(--t-caption);
  line-height: var(--lh-prose);
  color: var(--ink-soft);
}

/* ── shipping ──────────────────────────────────────────────────────────── */

/* The rates table has no <thead> — content.py carries no column labels and the
   service name is the row header instead. No zebra striping; .tbl's 1px rule
   already separates the rows. */
.tbl-wrap { overflow-x: auto; }
.tbl th[scope='row'] {
  font-family: var(--font-display);
  font-variation-settings: 'wght' 800, 'wdth' 88;
  font-size: var(--t-body);
  letter-spacing: var(--ls-head);
  text-transform: none;
  color: var(--ink);
  white-space: nowrap;
}
.rate-note { display: block; margin-top: var(--s-1); }

/* ── contact ───────────────────────────────────────────────────────────── */

.contact-grid { align-items: start; }
@media (min-width: 1024px) { .contact-grid { grid-template-columns: 1.35fr 1fr; } }

.contact-form { display: flex; flex-direction: column; gap: var(--s-5); }
.contact-form h2 { font-size: var(--t-h3); margin-bottom: var(--s-2); }
.contact-form .btn { align-self: flex-start; }

/* js/contact.js toggles this on the input's closest .field. Not decoration —
   it is the only visual difference between a field that failed validation and
   one that did not, and the .field-error text alone sits below the fold of a
   long form. */
.field.is-invalid input,
.field.is-invalid textarea,
.field.is-invalid select { border-color: var(--danger); }

/* The honeypot. Off-screen to people, in the DOM for bots; the API answers a
   filled value with a silent 200. Never display:none — a field that is not
   rendered is not filled. */
.field-hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* js/contact.js writes className directly: 'form-msg', 'form-msg is-ok' or
   'form-msg is-err'. All three have to exist here. */
.form-msg { font-size: var(--t-sm); min-height: 1.5em; }
.form-msg.is-ok  { color: var(--ok); }
.form-msg.is-err { color: var(--danger); }
.form-msg a { color: inherit; }
.form-note { font-size: var(--t-caption); color: var(--ink-muted); }

.reach {
  padding: var(--s-6);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  background: var(--mist);
}
.reach h2 { font-size: var(--t-h4); }
.reach-item { margin-top: var(--s-6); }
.reach-item h3 {
  font-family: var(--font-mono);
  font-variation-settings: normal;
  font-size: var(--t-micro);
  font-weight: 500;
  letter-spacing: var(--ls-micro);
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-bottom: var(--s-2);
}
.reach-item p { font-size: var(--t-sm); color: var(--ink-soft); }

/* ── quiz ──────────────────────────────────────────────────────────────────
   Kylie's half of the fusion: a progress bar, card-shaped answers and a bold
   full-width CTA. The class names below are read by js/quiz.js and asserted by
   build/check.py — .quiz-step, .quiz-result, .quiz-progress and .quiz-q are
   behaviour, not style. */

.quiz {
  padding-top: var(--s-8);
  padding-bottom: var(--s-8);
}

.quiz-progress {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  margin-bottom: var(--s-12);
}

/* BEHAVIOURAL. js/quiz.js toggles .is-active and nothing else; without this
   pair every question and every result is on screen at once. */
.quiz-step,
.quiz-result { display: none; }
.quiz-step.is-active,
.quiz-result.is-active { display: block; }

.quiz-q { font-size: var(--t-h2); }
.quiz-hint { margin-top: var(--s-3); font-size: var(--t-sm); color: var(--ink-muted); }

.quiz-options {
  list-style: none;
  margin: var(--s-8) 0 0;
  padding: 0;
  display: grid;
  gap: var(--s-3);
}
@media (min-width: 768px) { .quiz-options { grid-template-columns: 1fr 1fr; } }

.quiz-option {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  padding: var(--s-4) var(--s-5);
  border: 1px solid var(--rule);
  border-radius: var(--r-sm);
  background: var(--shell);
  font-size: var(--t-sm);
  cursor: pointer;
  transition: border-color var(--d-fast) var(--ease), background var(--d-fast) var(--ease);
}
.quiz-option:hover { background: var(--sage-wash); }

/* The native input is the accessible control and keeps focus; the dot is its
   visible form. Clipped rather than display:none so it stays focusable. */
.quiz-option input {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
}
.quiz-dot {
  flex: none;
  width: 18px; height: 18px;
  border: 1px solid var(--rule);
  border-radius: var(--r-pill);
  background: var(--shell);
  transition: border-color var(--d-fast) var(--ease), box-shadow var(--d-fast) var(--ease);
}
.quiz-option input:checked ~ .quiz-dot {
  border-color: var(--sage-deep);
  border-width: 5px;
}
.quiz-option:has(input:checked) {
  border-color: var(--sage-deep);
  background: var(--sage-wash);
}
.quiz-option:has(input:focus-visible) {
  outline: 2px solid var(--sage-deep);
  outline-offset: 3px;
}

.quiz-nav {
  display: flex;
  gap: var(--s-3);
  margin-top: var(--s-10);
}
.quiz-nav [data-next] { margin-left: auto; }
@media (max-width: 479px) {
  .quiz-nav { flex-direction: column-reverse; }
  .quiz-nav [data-next] { margin-left: 0; }
}

.result-card {
  padding: var(--s-8);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  background: var(--shell);
}
.result-card h2 { font-size: var(--t-h2); }
.result-card > .t-lede { margin-top: var(--s-4); max-width: 56ch; }
.result-card .grid-3 { margin-top: var(--s-10); }

@media (max-width: 767px) {
  .result-card { padding: var(--s-5); }
}
