:root {
  /* Lab-report palette: deep navy ink on white, cool gray panels. */
  --ink: #16233d;
  --ink-soft: #3d4c66;
  --muted: #6b7890;
  --navy: #12213f;
  --navy-2: #1f3156;
  --link: #2f5fa3;
  --panel: #f4f6f9;
  --panel-line: #dde3ec;
  --line: #e3e8f0;
  --track: #dbe4f0;
  --fill: #16233d;
  --page: #ffffff;
  --serif: Georgia, "Times New Roman", serif;

  /* Brand blue ramp, built from #0e08ae by holding its hue and
     saturation (hsl 242, 91%) and walking the lightness. Everything
     blue on the page — the aurora wash, the canvas tint, the headline
     gradient, the button glow — is drawn from these five stops, so the
     whole background reads as one colour rather than a set of
     near-misses. */
  --blue-700: #0e08ae; /* the brand shade, as given */
  --blue-600: #130bf4;
  --blue-500: #423cf6;
  --blue-400: #726df8;
  --blue-300: #a19efa;

  /* The page canvas is a whisper of the brand blue rather than pure
     white. It is deliberately NOT --page: that token is also the fill
     for the checker card and every white panel, and tinting it would
     dissolve those cards into the background they are meant to sit on. */
  --canvas: #f6f5ff;

  /* Per-ingredient rating colors */
  --safe: #256e46;
  --safe-bg: #e7f5ec;
  --safe-line: #c2e3cf;
  --moderate: #b07a10;
  --moderate-bg: #fdf6e0;
  --moderate-line: #ecdca3;
  --unclear: #3f6ea6;
  --unclear-bg: #edf3fa;
  --unclear-line: #cfe0f1;
  --hazardous: #b3402f;
  --hazardous-bg: #fcefec;
  --hazardous-line: #f2cfc8;

  /* Score band (neutral until a report renders) */
  --band-fg: #6b7890;
  --band-bg: #f4f6f9;
  --band-line: #dde3ec;
}

* { box-sizing: border-box; }
/* display rules like `.divider { display: flex }` would otherwise beat
   the hidden attribute the JS toggles */
[hidden] { display: none !important; }
body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  color: var(--ink-soft);
  background: var(--canvas);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  /* Any stray element wider than a phone screen would let the page pan
     sideways into blank space; clip instead of scrolling into it. */
  overflow-x: clip;
}

/* ---------- Masthead: sticky glass band ----------
   Translucent navy over the aurora rather than a flat slab, so the colour
   field drifts through it and the bar reads as part of the page. It is
   sticky because a long report otherwise leaves the user with no wordmark
   and no way back to the form. */
/* Absolutely positioned, not in flow: as a 1px block element above the
   sticky bar it rendered a 1px band of the light canvas across the very
   top of the page — a hairline white line over the navy masthead. Out of
   flow it still sits at scroll origin, so the observer test is unchanged. */
.mast-sentinel { position: absolute; top: 0; left: 0; width: 1px; height: 1px; }
.masthead {
  position: sticky; top: 0; z-index: 60;
  color: #fff;
  background: rgba(18, 33, 63, 0.82);
  -webkit-backdrop-filter: saturate(160%) blur(14px);
  backdrop-filter: saturate(160%) blur(14px);
  transition: background var(--dur-mid, 0.36s) ease, box-shadow var(--dur-mid, 0.36s) ease;
}
/* Browsers without backdrop-filter would show the aurora straight through
   82% navy and turn the wordmark to mush — give them the solid band. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .masthead { background: var(--navy); }
}
/* The 3px near-black slab is replaced by a 2px brand rail. ::after rather
   than a border so it can hold a gradient — and so motion.css can run a
   highlight along it. The old ramp ended on #a19efa, and that pale violet
   over navy read as a muddy purple smear; the rail stays in the teal→indigo
   half of the brand and returns to teal. (It no longer echoes the mark now
   that the logo is a green flask — the accents were left alone on purpose.) */
.masthead::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -2px; height: 2px;
  background: linear-gradient(90deg, #2dd4bf, var(--blue-500, #423cf6) 55%, #2dd4bf);
  opacity: 0.85;
}
/* Set by app.js once the page has scrolled past the top: denser backing and
   a lift, so the bar separates from the content sliding under it. */
.masthead.stuck {
  background: rgba(12, 22, 44, 0.93);
  box-shadow: 0 8px 30px rgba(9, 16, 34, 0.28);
}
.mast-inner {
  max-width: 1180px; margin: 0 auto; padding: 14px 24px;
  display: flex; align-items: center; gap: 12px;
  transition: padding var(--dur-mid, 0.36s) var(--ease-out-expo, ease);
}
.masthead.stuck .mast-inner { padding-top: 9px; padding-bottom: 9px; }
/* Anchors and every scrollIntoView in app.js land under a sticky bar unless
   the scrollport reserves room for it. */
html { scroll-padding-top: 84px; }
.mast-inner .brand {
  display: flex; align-items: center; gap: 12px;
  color: inherit; text-decoration: none;
}
/* Flat mark, no tile: the flask is its own silhouette and the gradient
   chip it used to sit in only competed with it. */
.mast-inner .logo {
  width: 34px; height: 34px; flex: none;
  display: grid; place-items: center;
  transition: transform var(--dur-mid, 0.36s) var(--ease-spring, ease);
}
.mast-inner .brand:hover .logo { transform: rotate(-6deg) scale(1.06); }
.mast-inner b { display: block; font-size: 16px; color: #fff; line-height: 1.2; letter-spacing: 0.01em; }
/* Lightened from the mockup's #4E9E7A, which sits at ~2.6:1 on the navy bar. */
.wm-accent { color: #7FC8A9; }
.mast-inner small { display: block; color: #b9c6dd; font-size: 11.5px; }
/* The brand owns the auto margin, so everything after it sits together at
   the right edge in DOM order. (Putting `margin-left:auto` on BOTH the
   tagline and the Admin link split the free space between them and left
   the Admin pill stranded in the middle of the bar.) */
.mast-inner .brand { margin-right: auto; }
.mast-admin {
  flex: none; font-size: 12px; color: #b9c6dd;
  letter-spacing: 0.08em; text-transform: uppercase; text-decoration: none;
  border: 1px solid #35507f; border-radius: 999px; padding: 7px 14px;
}
.mast-admin:hover { background: #1c2f52; color: #fff; }
.mast-admin[hidden] { display: none; }
/* On a phone the bar holds the wordmark plus whichever links are present. */
@media (max-width: 640px) {
  .mast-inner { padding: 12px 16px; gap: 8px; }
  .mast-inner small { display: none; }
}

.wrap { max-width: 1180px; margin: 0 auto; padding: 36px 24px 80px; }
.eyebrow {
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-size: 12px;
  font-weight: 700;
  color: #5b6b8c;
  margin: 0 0 6px;
}
h1 {
  font-family: var(--serif);
  font-size: 30px; line-height: 1.15; margin: 0 0 10px;
  color: var(--ink); font-weight: 700; letter-spacing: 0;
}
.lede { max-width: 640px; margin: 0; color: var(--ink-soft); }
.lede .accent { color: var(--navy-2); font-weight: 600; }

/* Standing claims about what this is, carried out of the masthead tagline. */
/* Plain text, deliberately not pills: bordered rounded chips read as
   buttons and people tried to click claims that go nowhere. */
.trust-line {
  margin: 0 0 32px;
  font-size: 12.5px; font-weight: 600; letter-spacing: 0.03em;
  color: var(--muted);
}

/* ---------- Checker form ---------- */
.checker {
  margin: 28px 0 40px;
  background: var(--page);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 24px;
  box-shadow: 0 1px 3px rgba(18, 33, 63, 0.06), 0 10px 30px rgba(18, 33, 63, 0.05);
}
.checker h2 { font-family: var(--serif); font-size: 20px; margin: 0 0 20px; color: var(--ink); }
.grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; }
@media (max-width: 820px) { .grid2 { grid-template-columns: 1fr; } }
.field { margin-bottom: 16px; }
/* Deliberately `.lbl`, not `label.lbl`: "Who is this for?" and "Or upload
   a label photo" label a GROUP of controls, not one input, so they are
   <span class="lbl"> — an element-scoped rule left them with no bottom
   margin and visibly tighter than every real <label> around them. */
.lbl { display: block; font-size: 13px; font-weight: 600; color: var(--ink); margin-bottom: 6px; }
textarea, select, input[type="text"], input[type="email"], input[type="tel"] {
  width: 100%;
  border: 1px solid var(--panel-line);
  border-radius: 10px;
  padding: 10px 12px;
  font: inherit;
  color: var(--ink);
  background: #fff;
}
/* The native control is drawn by the platform, and Chrome paints its own
   box over ours — the bottom edge of the border went missing on the
   Product type / Focus dropdowns. Owning the arrow means owning the whole
   box, so all four sides match the text inputs beside them. */
select {
  appearance: none; -webkit-appearance: none;
  padding-right: 34px;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='none'%3E%3Cpath d='M1.5 1.75 6 6.25l4.5-4.5' stroke='%234a5b78' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 12px 8px;
}
textarea { min-height: 160px; resize: vertical; }
/* The ingredients box is the centerpiece of the form — a fixed minimum of
   rows keeps the layout stable, and the drag handle is removed so users
   can't stretch it over the rest of the page. */
#ingredients { resize: none; min-height: 0; }
select:focus, textarea:focus, input:focus { outline: 2px solid var(--track); border-color: var(--navy-2); }
/* A two-up grid rather than a wrapping flex row. Content-width pills left
   four ragged chips of four different widths ("General adult" beside
   "Pregnant or postpartum"), which read as an accident rather than as one
   set of equal options. The grid makes every pill the same width, and the
   stretched rows make the pair in each row the same height even when the
   longer label wraps. */
.choices {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}
/* min-height 44px: these chips are the main interaction on the form and
   were 36px, under the minimum comfortable touch target. */
.choice {
  border: 1px solid var(--panel-line);
  background: #fff;
  border-radius: 999px;
  padding: 7px 14px;
  min-height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  font-size: 13px;
  line-height: 1.25;
  cursor: pointer;
  color: var(--ink-soft);
  user-select: none;
}
.choice.active { background: var(--fill); border-color: var(--fill); color: #fff; }
/* Scoped to #choices so the feedback widget's reuse of .choice is untouched. */
#choices .choice { gap: 8px; justify-content: flex-start; padding: 7px 14px 7px 12px; }
#choices .c-ico { width: 20px; height: 20px; flex: none; opacity: 0.75; }
#choices .choice.active .c-ico { opacity: 1; }
#choices .choice .pregnant-choice-ico .badge-bg { fill: #ffffff; transition: fill 0.2s ease; }
#choices .choice.active .pregnant-choice-ico .badge-bg { fill: var(--fill); }
#choices .choice .pregnant-choice-ico .badge-check { stroke: var(--ink-soft); transition: stroke 0.2s ease; }
#choices .choice.active .pregnant-choice-ico .badge-check { stroke: #ffffff; }
.upload {
  display: inline-flex; align-items: center; gap: 8px;
  border: 1px dashed var(--panel-line); border-radius: 10px; padding: 10px 14px;
  min-height: 44px; box-sizing: border-box;
  cursor: pointer; font-size: 14px; color: var(--navy-2); font-weight: 600;
}
.upload input { display: none; }
.u-ico { width: 18px; height: 18px; flex: none; }
.upload-row { display: flex; flex-wrap: wrap; gap: 8px; }
.photo-preview { display: flex; align-items: center; gap: 10px; margin-top: 8px; }
.photo-thumb {
  width: 64px; height: 64px; object-fit: cover; border-radius: 8px;
  border: 1px solid var(--panel-line); cursor: zoom-in; flex: none;
}
.file-name { display: none; font-size: 13px; color: var(--muted); }
.lightbox {
  position: fixed; inset: 0; z-index: 100; display: none;
  align-items: center; justify-content: center; padding: 24px;
  background: rgba(18, 33, 63, 0.85); cursor: zoom-out;
}
.lightbox.show { display: flex; }
.lightbox img { max-width: 100%; max-height: 100%; border-radius: 10px; box-shadow: 0 12px 48px rgba(0, 0, 0, 0.4); }
.actions { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 8px; }
.btn {
  border: 0; border-radius: 10px; padding: 11px 20px; font: inherit; font-weight: 600;
  cursor: pointer; background: var(--fill); color: #fff;
}
.btn:hover { background: var(--navy-2); }
a.btn { display: inline-flex; align-items: center; text-decoration: none; }
.btn.ghost { background: #fff; color: var(--navy-2); border: 1px solid var(--panel-line); }
.btn.ghost:hover { background: var(--panel); }
.form-message { display: none; margin-top: 12px; font-size: 14px; color: var(--navy-2); }
.form-message.show { display: block; }
.form-message.error { color: var(--hazardous); }
.dym-row { display: block; margin-top: 8px; color: var(--navy-2); }
.dym-btn { border: 1px solid var(--navy-2); background: none; border-radius: 999px; padding: 3px 12px; margin: 0 2px; font-size: 13px; font-weight: 600; color: var(--navy-2); cursor: pointer; }
.dym-btn:hover { background: var(--navy-2); color: #fff; }

/* Phones: the desktop hero (serif h1 + 36/24px page padding + 24px card
   padding) pushed the textarea — the whole point of the page — most of a
   screen down, and the submit button roughly two screens down. */
@media (max-width: 640px) {
  .wrap { padding: 24px 16px 80px; }
  h1 { font-size: 24px; }
  .eyebrow { font-size: 11px; }
  .checker { margin: 20px 0 32px; padding: 18px 16px; }
}
/* The page has no footer — it just ends after the last "about" card — so
   the desktop 80px tail reads as the page having failed to load something
   rather than as breathing room once the cards go full-bleed. */
@media (max-width: 900px) { .wrap { padding-bottom: 80px; } }

.hint { font-size: 12px; color: var(--muted); }
.product-search { background: var(--panel); border: 1px solid var(--panel-line); border-radius: 12px; padding: 16px; margin-bottom: 4px; }
.replay-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 14px 0 0; padding: 10px 14px; border: 1px dashed var(--line); border-radius: 10px; font-size: 13px; color: var(--muted); background: var(--panel); }
.replay-bar .run-pill { border: 1px solid var(--line); background: none; border-radius: 999px; padding: 3px 10px; font-size: 12px; color: var(--navy-2); cursor: pointer; }
.replay-bar .run-pill.active { background: var(--navy-2); color: #fff; border-color: var(--navy-2); }
.replay-bar .run-count { font-size: 12px; color: var(--muted); }
.replay-bar a { color: var(--link); }
.replay-bar .replay-runs { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; }

.divider { display: flex; align-items: center; text-align: center; color: var(--muted); font-size: 12px; margin: 18px 0; }
.divider::before, .divider::after { content: ""; flex: 1; border-top: 1px solid var(--line); }
.divider span { padding: 0 12px; }

/* Autocomplete */
.ac-wrap { position: relative; }
.ac-menu {
  position: absolute; left: 0; right: 0; top: calc(100% + 4px); z-index: 20;
  background: #fff; border: 1px solid var(--line); border-radius: 10px;
  box-shadow: 0 8px 24px rgba(18, 33, 63, 0.12); overflow: hidden; max-height: 300px; overflow-y: auto;
}
.ac-item { display: flex; align-items: baseline; gap: 8px; padding: 10px 12px; cursor: pointer; border-bottom: 1px solid var(--line); }
.ac-item:last-child { border-bottom: none; }
.ac-item.active, .ac-item:hover { background: var(--panel); }
.ac-name { color: var(--ink); font-size: 14px; font-weight: 600; }
.ac-host { margin-left: auto; color: var(--muted); font-size: 11px; white-space: nowrap; }
.ac-loading { padding: 10px 12px; font-size: 13px; color: var(--muted); display: flex; align-items: center; gap: 8px; }
.ac-loading .spin { width: 12px; height: 12px; border: 2px solid var(--track); border-top-color: var(--fill); border-radius: 50%; animation: spin 0.8s linear infinite; }
.meta-row .v a { color: var(--link); text-decoration: none; }
.meta-row .v a:hover { text-decoration: underline; }

/* ---------- Report ---------- */
.report-head { margin: 8px 0 18px; }
/* Names the thing the cards below add up to, and dates it. */
.letterhead {
  display: flex; align-items: center; gap: 14px;
  margin: 0 0 18px; padding-bottom: 16px;
  border-bottom: 1px solid var(--line);
}
.lh-mark { width: 42px; height: 42px; flex: none; }
.lh-title {
  margin: 0; font-family: var(--serif); font-size: 20px;
  font-weight: 700; color: var(--ink); line-height: 1.2;
}
.lh-date { margin: 3px 0 0; font-size: 12.5px; color: var(--muted); }
.state { display: none; }
.state.show { display: block; }
.loading, .error-box {
  border: 1px solid var(--line); border-radius: 16px; padding: 40px; text-align: center; color: var(--muted);
}
/* The spinner stays centered, but an error is a sentence to READ — centering
   it wrapped to seven ragged lines on a phone. Left-aligned, narrower padding. */
.error-box {
  color: var(--hazardous); border-color: var(--hazardous-line); background: var(--hazardous-bg);
  text-align: left; padding: 22px 24px;
}
.spinner {
  width: 28px; height: 28px; border: 3px solid var(--track); border-top-color: var(--fill);
  border-radius: 50%; margin: 0 auto 14px; animation: spin 0.8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.report {
  display: grid; grid-template-columns: 270px 1fr; gap: 22px; align-items: start;
}
@media (max-width: 900px) { .report { grid-template-columns: 1fr; } }

/* Score card — the whole card tints to the score band (see .band-N below). */
.score-card {
  background: var(--band-bg);
  border: 1px solid var(--band-line);
  border-radius: 16px;
  padding: 22px;
  box-shadow: 0 1px 3px rgba(18, 33, 63, 0.07);
}
.score-card .cap {
  font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase; font-weight: 700;
  color: var(--muted); margin: 0 0 12px;
}

/* Ring gauge */
.gauge { position: relative; width: 156px; margin: 0 0 14px; }
/* Once .report collapses to one column (900px) the score card is full
   width, and a 156px ring pinned left leaves a ~165px empty gutter beside
   the headline number of the whole report. Center the hero block there. */
@media (max-width: 900px) {
  .gauge { margin-left: auto; margin-right: auto; }
  .score-card { text-align: center; }
  .score-card .score-note { text-align: left; }
  .score-card .meta-row { text-align: left; }
}
.gauge svg { display: block; width: 100%; height: auto; }
.g-track { fill: none; stroke: rgba(18, 33, 63, 0.09); stroke-width: 10; }
.g-fill {
  fill: none; stroke: var(--band-fg); stroke-width: 10; stroke-linecap: round;
  stroke-dasharray: 326.7; stroke-dashoffset: 326.7;
  transform: rotate(-90deg); transform-origin: 60px 60px;
  transition: stroke-dashoffset 0.6s ease;
}
.g-center {
  position: absolute; inset: 0; display: grid; place-content: center; text-align: center;
}
.g-center .num {
  font-size: 40px; font-weight: 800; line-height: 1; color: var(--band-fg);
  font-variant-numeric: tabular-nums;
}
.g-center small { font-size: 12px; font-weight: 600; color: var(--muted); }

.overall {
  display: inline-block; font-size: 13px; font-weight: 700; padding: 8px 14px; border-radius: 10px;
  background: var(--band-fg); color: #fff; margin-bottom: 12px; letter-spacing: 0.02em;
}
.score-note { font-size: 13px; color: var(--ink-soft); margin: 0 0 16px; }

/* Dynamic report badges styling */
.badges-row {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 0 0 16px;
  text-align: left;
}
.r-badge {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  border-radius: 10px;
  font-size: 13px;
  font-weight: 600;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.02);
  animation: fadeInBadge 0.4s cubic-bezier(0.16, 1, 0.3, 1) both;
}
.r-badge .b-ico {
  width: 20px;
  height: 20px;
  flex: none;
}
.badge-pregnancy-safe {
  color: var(--unclear);
  border-color: var(--unclear-line);
  background: var(--unclear-bg);
  border: 1px solid var(--unclear-line);
}
.badge-clean-ingredients {
  color: var(--safe);
  border-color: var(--safe-line);
  background: var(--safe-bg);
  border: 1px solid var(--safe-line);
}
.badge-clinically-proven {
  color: var(--link);
  border-color: var(--panel-line);
  background: #ffffff;
  border: 1px solid var(--panel-line);
}

@keyframes fadeInBadge {
  from {
    opacity: 0;
    transform: translateY(4px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
/* "What this means for me" — the effect on hair/scalp (or skin) and who the
   product suits. Sits directly under the score, because the number is the
   question people arrive with and this is the answer they actually wanted.
   Boxed and left-aligned so it survives the centred phone layout above. */
.outcome {
  text-align: left; margin: 0 0 16px; padding: 12px 14px; border-radius: 12px;
  background: rgba(255, 255, 255, 0.72); border: 1px solid var(--band-line);
  display: grid; gap: 8px;
}
.outcome-line {
  margin: 0; display: grid; grid-template-columns: 18px 1fr; gap: 8px;
  font-size: 13px; line-height: 1.5; color: var(--ink);
}
.outcome-line .o-icon { font-size: 13px; line-height: 1.5; }
.meta-row { display: flex; justify-content: space-between; font-size: 13px; padding: 10px 0; border-top: 1px solid var(--band-line); }
.meta-row .k { color: var(--muted); }
.meta-row .v { color: var(--ink); font-weight: 600; }

/* Score bands: <50 red, 50–65 orange, 65–80 amber, 80–90 light green, 90+ green.
   The band colors the gauge, the number, the Overall pill, and tints the card. */
.score-card.band-1 { --band-fg: #b3362b; --band-bg: #fdeeec; --band-line: #f0cbc5; }
.score-card.band-2 { --band-fg: #c2610c; --band-bg: #fdf1e4; --band-line: #f2d4b3; }
.score-card.band-3 { --band-fg: #a8830a; --band-bg: #fbf5dd; --band-line: #eadfad; }
.score-card.band-4 { --band-fg: #4f8f3b; --band-bg: #eff7ea; --band-line: #d2e6c6; }
.score-card.band-5 { --band-fg: #1e7d46; --band-bg: #e7f5ec; --band-line: #c2e3cf; }
/* No assessable ingredient at all — the gauge has nothing to show. */
.score-card.band-none { --band-fg: #6b6b6b; --band-bg: #f4f4f4; --band-line: #dcdcdc; }

/* Label clarity / compliance band. Deliberately sits ABOVE the ingredient
   table, not in a footnote: the Safety Score now answers only "is anything
   here hazardous", so "this declaration is non-compliant or unassessable"
   has to be visible on its own or it isn't being said at all. */
.free-note { margin: 0 0 18px; border: 1px solid #bfe3c8; background: #f0faf2; border-radius: 12px; padding: 12px 16px; font-size: 14px; line-height: 1.5; color: var(--ink-soft); }
.free-note b { color: var(--ink); }
.clarity { margin: 0 0 18px; border: 1px solid #f0d9a8; background: #fdf8ec; border-radius: 12px; padding: 14px 16px; }
.clarity h3 { margin: 0 0 10px; font-size: 13px; letter-spacing: .04em; text-transform: uppercase; color: #8a6a12; }
.clarity .flag { padding: 10px 0; border-top: 1px solid #f0e2c2; }
.clarity .flag:first-of-type { border-top: 0; padding-top: 0; }
.clarity .flag b { display: block; font-size: 14px; color: var(--ink); margin-bottom: 3px; }
.clarity .flag p { margin: 0 0 6px; font-size: 13px; line-height: 1.5; color: var(--ink-soft); }
.clarity .flag ul { margin: 0 0 6px; padding-left: 18px; }
.clarity .flag li { font-size: 13px; line-height: 1.5; color: var(--ink); word-break: break-word; }
.clarity .basis { font-size: 11px; color: var(--muted); letter-spacing: .02em; }

/* Trust callout — the independence/reproducibility statement, promoted. */
.trust {
  margin-top: 14px; background: #fff;
  border: 1px solid var(--panel-line); border-left: 4px solid var(--navy);
  border-radius: 12px; padding: 14px 16px;
}
.trust-head {
  font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase;
  font-weight: 800; color: var(--navy); margin-bottom: 6px;
}
.trust p { margin: 0; font-size: 13px; line-height: 1.55; color: #2b3a55; }

.report-main {}
.tiles { display: grid; grid-template-columns: repeat(5, 1fr); gap: 14px; margin-bottom: 18px; }
.tile { border: 1px solid var(--line); border-radius: 14px; padding: 16px; background: #fff; }
.tile .t-label { font-size: 12px; color: var(--muted); margin-bottom: 8px; }
.tile .t-num { font-size: 26px; font-weight: 800; color: var(--ink); line-height: 1; font-variant-numeric: tabular-nums; }
.tile.safe .t-num { color: var(--safe); }
.tile.moderate .t-num { color: var(--moderate); }
.tile.unclear .t-num { color: var(--unclear); }
.tile.hazardous .t-num { color: var(--hazardous); }
/* Three columns, not two: with five tiles a 2-col grid orphans "Hazardous" —
   the tile that matters most — alone on a half-width row. 3-col fills as
   Total/Safe/Moderate + Unclear/Hazardous, and the tighter padding keeps the
   counts from eating a whole phone screen before the first ingredient.
   Declared after the base .tile rules so the compact padding wins. */
@media (max-width: 720px) {
  .tiles { grid-template-columns: repeat(3, 1fr); gap: 10px; }
  .tile { padding: 12px 10px; }
  .tile .t-label { font-size: 11px; margin-bottom: 5px; }
  .tile .t-num { font-size: 22px; }
}

.table { border: 1px solid var(--line); border-radius: 14px; overflow: hidden; background: #fff; }
.thead {
  display: grid; grid-template-columns: 1.4fr 0.7fr 2fr; gap: 12px; padding: 12px 18px;
  background: var(--panel); font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); font-weight: 700;
}
.ingredient-row {
  display: grid; grid-template-columns: 1.4fr 0.7fr 2fr; gap: 12px; padding: 16px 18px;
  border-top: 1px solid var(--line); align-items: start;
}
.ingredient-row:nth-child(even) { background: #f8fafc; }
.ingredient-name { font-weight: 700; color: var(--ink); font-size: 14px; word-break: break-word; }
.reason { font-size: 13px; color: var(--ink-soft); }
/* Flagged rows carry two more lines under the reason: what the ingredient can
   do, and whose hair/skin type it suits. Full ink (the reason above it is
   softened) so the part people came for isn't the faintest text in the row. */
.r-outcome { display: grid; gap: 5px; margin-top: 8px; }
.r-line {
  display: grid; grid-template-columns: 16px 1fr; gap: 7px;
  font-size: 13px; line-height: 1.45; color: var(--ink);
}
.r-line.r-suits { color: var(--ink-soft); }
.tag {
  display: inline-block; font-size: 12px; font-weight: 700; padding: 5px 12px; border-radius: 999px;
  border: 1px solid transparent; letter-spacing: 0.02em;
}
.tag.safe { background: var(--safe); border-color: var(--safe); color: #fff; }
.tag.moderate { background: var(--moderate); border-color: var(--moderate); color: #fff; }
.tag.unclear { background: var(--unclear); border-color: var(--unclear); color: #fff; }
.tag.hazardous { background: var(--hazardous); border-color: var(--hazardous); color: #fff; }
/* Every row gets a wash of its rating color plus a solid left edge,
   so the verdict is scannable without reading. Declared after the
   nth-child zebra rule so the tint wins on even rows too. */
.ingredient-row.r-safe { background: var(--safe-bg); box-shadow: inset 3px 0 0 var(--safe); }
.ingredient-row.r-moderate { background: var(--moderate-bg); box-shadow: inset 3px 0 0 var(--moderate); }
.ingredient-row.r-unclear { background: var(--unclear-bg); box-shadow: inset 3px 0 0 var(--unclear); }
.ingredient-row.r-hazardous { background: var(--hazardous-bg); box-shadow: inset 3px 0 0 var(--hazardous); }
/* Phones: three skinny columns squeeze long INCI names into vertical
   letter-stacks, so stack each row — name + tag on one line, reason under. */
@media (max-width: 640px) {
  .thead { display: none; }
  .ingredient-row { grid-template-columns: 1fr auto; gap: 6px 12px; }
  .ingredient-row .reason { grid-column: 1 / -1; }
}

/* ---------- Report gate: blurred tail of the table + the unlock card ----------
   The teaser (score card, tiles, first rows) stays sharp; the remaining rows
   render as blurred PLACEHOLDERS (the real ratings/reasons never reach the
   DOM while locked) behind a white veil carrying the beta-access card. */
.gate-zone { position: relative; border-top: 1px solid var(--line); }
.gate-blur {
  position: absolute; inset: 0; overflow: hidden;
  filter: blur(5px); pointer-events: none; user-select: none;
}
.gate-veil {
  position: relative;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.35), rgba(255, 255, 255, 0.94) 130px, rgba(255, 255, 255, 0.97));
  padding: 46px 18px 40px;
  display: flex; justify-content: center;
}
.gate-card {
  background: #fff; max-width: 620px; width: 100%;
  border: 1px solid var(--panel-line); border-top: 4px solid var(--navy);
  border-radius: 16px; padding: 26px 28px;
  box-shadow: 0 1px 3px rgba(18, 33, 63, 0.08), 0 16px 44px rgba(18, 33, 63, 0.14);
}
@media (max-width: 640px) { .gate-card { padding: 20px 18px; } }
.gate-card .eyebrow { color: var(--navy); }
.gate-card h3 { font-family: var(--serif); font-size: 24px; line-height: 1.2; margin: 0 0 10px; color: var(--ink); }
.gate-card .vision { margin: 0 0 18px; font-size: 14px; line-height: 1.6; color: var(--ink-soft); }
.gate-card .vision b { color: var(--ink); }
.g-road-head {
  font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase;
  font-weight: 800; color: var(--navy); margin: 0 0 10px;
}
.g-roadmap { list-style: none; counter-reset: gstep; margin: 0 0 18px; padding: 0; display: flex; flex-direction: column; gap: 9px; }
.g-roadmap li {
  counter-increment: gstep; position: relative; padding-left: 34px;
  font-size: 13px; line-height: 1.5; color: var(--ink-soft);
}
.g-roadmap li::before {
  content: counter(gstep); position: absolute; left: 0; top: 1px; width: 22px; height: 22px; border-radius: 50%;
  background: #e6ecf5; color: var(--navy); font-weight: 800; font-size: 11px;
  display: grid; place-items: center; border: 1px solid #b9c9e2;
}
.g-roadmap b { color: var(--ink); }
.gate-pledge {
  background: var(--panel); border: 1px solid var(--panel-line); border-left: 4px solid var(--navy);
  border-radius: 12px; padding: 12px 14px; margin: 0 0 20px;
  font-size: 12.5px; line-height: 1.55; color: var(--ink-soft);
}
.gate-pledge b { color: var(--navy); }
.gate-form .row2 { display: grid; grid-template-columns: 1.2fr 1fr; gap: 12px; }
@media (max-width: 560px) { .gate-form .row2 { grid-template-columns: 1fr; } }
.gate-form .field { margin-bottom: 14px; }
.gate-msg { display: none; margin-top: 12px; font-size: 13px; color: var(--navy-2); }
.gate-msg.show { display: block; }
.gate-msg.error { color: var(--hazardous); }
.gate-sent { font-size: 13px; color: var(--ink-soft); margin: 0 0 14px; }
.gate-sent b { color: var(--ink); }
/* One box per digit. The boxes flex down on narrow screens rather than
   wrapping to a second line — six on one row is the whole point of the
   pattern, and a 2x3 grid reads as two separate fields. */
.otp-boxes { display: flex; gap: 8px; max-width: 320px; }
.otp-box {
  /* Beats the shared `width: 100%` on text inputs further up. */
  width: auto !important;
  flex: 1 1 0;
  min-width: 0;
  aspect-ratio: 1 / 1;
  max-height: 56px;
  padding: 0 !important;
  text-align: center;
  font-size: 22px; font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  caret-color: var(--navy-2);
}
.otp-box:focus {
  border-color: var(--navy-2);
  outline: 2px solid var(--track);
  outline-offset: 0;
}
/* A filled box reads as done at a glance, so a half-entered code is
   obvious without counting. */
.otp-box.filled { border-color: var(--navy-2); background: var(--panel); }
@media (max-width: 380px) { .otp-boxes { gap: 6px; } }
.gate-links { margin-top: 12px; font-size: 12.5px; }
.gate-links a { color: var(--link); text-decoration: none; cursor: pointer; }
.gate-links a:hover { text-decoration: underline; }
.gate-links span { color: var(--muted); padding: 0 8px; }
.btn[disabled] { opacity: 0.6; cursor: default; }

.followups { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-top: 18px; }
@media (max-width: 720px) { .followups { grid-template-columns: 1fr; } }
.followup { border: 1px solid var(--line); border-radius: 14px; padding: 16px; background: #fff; }
.followup .f-label { font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); font-weight: 700; margin-bottom: 6px; }
.followup p { margin: 0; font-size: 14px; color: var(--ink-soft); }

/* ---------- About us — redesigned (two-tone hero, pledge card,
   illustrated step cards, icon value grid) ---------- */
.about { margin: 56px auto 0; border-top: 1px solid var(--line); padding-top: 40px; }
.about-chip {
  display: inline-block; font-size: 11px; font-weight: 800; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--link); background: #edf3fb;
  border: 1px solid #cfe0f1; border-radius: 999px; padding: 5px 14px; margin: 0 0 16px;
}
.about-hero { display: grid; grid-template-columns: 1.2fr 0.8fr; gap: 32px; align-items: center; }
@media (max-width: 820px) { .about-hero { grid-template-columns: 1fr; } .about-hero .hero-art { display: none; } }
.about-hero h2 {
  font-family: var(--serif); font-size: 38px; line-height: 1.12;
  margin: 0 0 14px; color: var(--ink); font-weight: 700;
}
.about-hero h2 .alt { display: block; color: var(--link); }
@media (max-width: 640px) { .about-hero h2 { font-size: 30px; } }
.about-hero .lead { color: var(--ink-soft); font-size: 15px; line-height: 1.6; margin: 0; max-width: 560px; }
.about b { color: var(--ink); }
.about .lead .accent { color: var(--link); font-weight: 700; }
.hero-art svg { display: block; width: 100%; max-width: 340px; height: auto; margin: 0 auto; }

/* Pledge: the trust statement, promoted to a full-width tinted card. */
.pledge {
  margin-top: 28px; background: #f3f7fd;
  border: 1px solid #d6e3f5; border-radius: 16px; padding: 20px 22px;
  display: flex; gap: 16px; align-items: flex-start;
}
.pledge .p-ico { flex: none; width: 44px; height: 44px; }
.pledge .p-ico svg { display: block; width: 100%; height: 100%; }
.pledge .p-head { display: block; color: var(--navy); font-size: 15px; margin-bottom: 4px; }
.pledge p { color: var(--ink-soft); font-size: 13.5px; line-height: 1.6; margin: 0; }
@media (max-width: 560px) { .pledge { flex-direction: column; padding: 18px 16px; } }

.hiw-head {
  text-align: center;
  margin: 40px 0 22px; font-family: var(--serif); font-size: 22px; color: var(--ink); font-weight: 700;
}

/* Step cards: a compact horizontal stepper. Each card shows only an icon
   and a 1-2 word label; the full title + description lives in a popover
   revealed on hover / keyboard focus / tap. */
.steps { list-style: none; margin: 0; padding: 8px 0 0; display: grid; grid-template-columns: repeat(5, 1fr); gap: 18px; position: relative; }
.steps li { position: relative; }
/* height:100% + align-content:start, so a card whose label wraps to two
   lines ("Open formula" does between ~390px and ~430px) doesn't leave its
   single-line neighbours visibly shorter — the grid row already stretches
   the <li>, the card just has to fill it, with the icons still aligned. */
.steps li .s-card {
  position: relative; width: 100%; height: 100%; display: grid;
  justify-items: center; align-content: start; gap: 8px;
  background: #fff; border: 1px solid var(--line); border-radius: 16px;
  padding: 18px 8px 14px; cursor: pointer; font: inherit; color: var(--ink);
  box-shadow: 0 1px 3px rgba(18, 33, 63, 0.05);
  transition: border-color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease;
}
.steps li .s-card:hover,
.steps li.open .s-card,
.steps li .s-card:focus-visible {
  border-color: #9db8dd; box-shadow: 0 4px 14px rgba(18, 33, 63, 0.12);
  transform: translateY(-2px);
}
.steps li .s-card:focus-visible { outline: 2px solid var(--link); outline-offset: 2px; }
.steps li .s-art {
  width: 56px; height: 56px; border-radius: 14px;
  background: var(--panel); border: 1px solid var(--panel-line);
  display: grid; place-items: center;
}
.steps li .s-art svg { width: 36px; height: 36px; }
.steps li .s-label { font-size: 12.5px; font-weight: 700; color: var(--ink); line-height: 1.25; text-align: center; }
/* Step detail panel. This used to be an absolutely positioned popover
   floating under whichever card was open, which meant it painted straight
   over the About cards below the section — on a phone it covered
   "Evidence over marketing" entirely. It now sits in normal flow after
   the stepper and expands, pushing what follows down instead.

   The open/close is animated with grid-template-rows 0fr -> 1fr, which
   gets a real transition to the content's natural height without anyone
   having to guess a max-height that later goes stale. */
.s-pops {
  display: grid;
  grid-template-rows: 0fr;
  margin-top: 0;
  position: relative;
  /* No overflow clip here on purpose: .s-pop below does the clipping, and
     the arrow has to straddle the panel's top edge to point at the card. */
  transition: grid-template-rows 0.32s ease, margin-top 0.32s ease;
}
.s-pops.open { grid-template-rows: 1fr; margin-top: 16px; }
.s-pops .s-pop {
  /* All five details share ONE grid cell. Without this they would land in
     implicit rows, which are auto-sized and so would never collapse —
     only the first row is the 0fr/1fr one being animated. */
  grid-area: 1 / 1;
  /* This box is deliberately bare: no padding, no border. A grid item's
     automatic minimum size still counts its padding and border even with
     min-height:0 and overflow:hidden, so styling it directly left 30px of
     empty card under the stepper when nothing was open. The visible card
     is .s-pop-in inside it; this element only clips. */
  min-height: 0;
  overflow: hidden;
}
.s-pops .s-pop-in {
  text-align: left;
  background: #fff; border: 1px solid #d6e3f5; border-radius: 14px;
  padding: 14px 16px;
  font-size: 13px; line-height: 1.55; color: var(--ink-soft);
}
.s-pops .s-pop-in .s-title { display: block; font-size: 13.5px; color: var(--ink); margin-bottom: 3px; }
/* The arrow keeps the panel tied to the step that opened it. app.js sets
   --arrow-x to that card's centre; without JS it simply never shows. */
.s-pops::before {
  content: "";
  position: absolute;
  top: -6px;
  left: var(--arrow-x, 50%);
  width: 12px; height: 12px;
  margin-left: -6px;
  background: #fff;
  border-left: 1px solid #d6e3f5; border-top: 1px solid #d6e3f5;
  transform: rotate(45deg) scale(0);
  transition: left 0.28s ease, transform 0.2s ease;
  z-index: 1;
}
.s-pops.open::before { transform: rotate(45deg) scale(1); }

/* (The open card's highlight is already handled by the .s-card rule
   further up, which covers :hover, .open and :focus-visible together.) */
@media (max-width: 900px) {
  .steps { grid-template-columns: repeat(5, 1fr); gap: 8px; }
  .steps li .s-card { padding: 14px 4px 10px; border-radius: 12px; }
  .steps li .s-art { width: 44px; height: 44px; border-radius: 11px; }
  .steps li .s-art svg { width: 28px; height: 28px; }
  .steps li .s-label { font-size: 11px; }
  /* The phone-specific popover rules that used to live here (li goes
     static, popover stretched edge to edge) are gone: the panel is
     full-width and in flow at every size now, so there is nothing left
     to special-case. */
}

/* Value cards: icon chip left, copy right. */
.aboutgrid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 14px; margin: 32px 0 0; }
@media (max-width: 720px) { .aboutgrid { grid-template-columns: 1fr; } }
.acard {
  position: relative;
  background: #fff; border: 1px solid var(--line); border-radius: 16px; padding: 16px 18px;
  display: flex; gap: 14px; align-items: flex-start;
  box-shadow: 0 1px 3px rgba(18, 33, 63, 0.05);
}
.acard .ico {
  position: relative;
  flex: none; width: 44px; height: 44px; border-radius: 12px;
  display: grid; place-items: center;
}
/* z-index keeps the glyph above the chase ring motion.css paints behind it. */
.acard .ico svg { position: relative; z-index: 2; width: 26px; height: 26px; }
.acard .ico.i-1 { background: #fdf1f5; --ico-accent: #c2477e; }
.acard .ico.i-2 { background: #eef7ef; --ico-accent: #2fa36b; }
.acard .ico.i-3 { background: #eef3fc; --ico-accent: #2f5fa3; }
.acard .ico.i-4 { background: #fdf6e8; --ico-accent: #b07a10; }

.acard b { display: block; font-size: 13.5px; margin-bottom: 4px; color: var(--ink); }
.acard p { color: var(--ink-soft); font-size: 12.5px; line-height: 1.5; margin: 0; }

/* ---------- AI-powered badge + footer ---------- */
.ai-badge {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 12px; font-weight: 700; color: var(--navy-2);
  background: #edf3fb; border: 1px solid #cfe0f1; border-radius: 999px; padding: 6px 14px;
}
.ai-badge svg { width: 14px; height: 14px; flex: none; }
.trust .ai-badge { margin-top: 10px; }
.site-footer { border-top: 1px solid var(--line); margin-top: 44px; padding: 22px 0 0; text-align: center; }
.site-footer .f-line { font-size: 12.5px; color: var(--muted); margin: 10px 0 0; }

/* ---------- Feedback widget: floating button + panel ---------- */
.fb-fab {
  position: fixed; right: 18px; bottom: 18px; z-index: 60;
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--navy); color: #fff; border: none; border-radius: 999px;
  padding: 12px 18px; font: inherit; font-size: 13.5px; font-weight: 700; cursor: pointer;
  box-shadow: 0 6px 24px rgba(18, 33, 63, 0.35);
}
.fb-fab:hover { background: var(--navy-2); }
@media (max-width: 640px) {
  .fb-fab {
    padding: 0;
    width: 44px;
    height: 44px;
    justify-content: center;
    border-radius: 50%;
    font-size: 16px;
  }
  .fb-fab .fb-text {
    display: none;
  }
}
.fb-panel {
  position: fixed; right: 18px; bottom: 76px; z-index: 61;
  width: min(380px, calc(100vw - 36px));
  max-height: calc(100vh - 110px); overflow-y: auto;
  background: #fff; border: 1px solid var(--line); border-radius: 14px; padding: 18px;
  box-shadow: 0 4px 16px rgba(18, 33, 63, 0.12), 0 18px 56px rgba(18, 33, 63, 0.28);
}
.fb-head { display: flex; align-items: baseline; gap: 10px; }
.fb-head b { font-family: var(--serif); font-size: 17px; color: var(--ink); }
.fb-close {
  margin-left: auto; border: none; background: none; cursor: pointer;
  color: var(--muted); font-size: 22px; line-height: 1; padding: 2px 6px;
}
.fb-close:hover { color: var(--ink); }
.fb-sub { margin: 4px 0 12px; font-size: 12.5px; color: var(--muted); }
.fb-panel textarea { min-height: 96px; }
.fb-msg { display: none; margin-top: 10px; font-size: 13px; color: var(--safe); }
.fb-msg.show { display: block; }
.fb-msg.error { color: var(--hazardous); }
.fb-done {
  position: fixed; inset: 0; z-index: 70; padding: 24px;
  display: flex; align-items: center; justify-content: center;
  background: rgba(18, 33, 63, 0.45);
}
.fb-done-card {
  background: #fff; border-radius: 14px; padding: 26px 22px; width: min(360px, 100%);
  text-align: center; box-shadow: 0 18px 56px rgba(18, 33, 63, 0.28);
}
.fb-done-ico { width: 52px; height: 52px; margin: 0 auto 12px; }
.fb-done-ico svg { display: block; width: 100%; height: 100%; }
.fb-done-card b { display: block; font-family: var(--serif); font-size: 19px; color: var(--ink); }
.fb-done-card p { margin: 8px 0 18px; font-size: 13.5px; color: var(--muted); }
