/* ==========================================================================
   Pryme Research — reset, typography, layout primitives
   ========================================================================== */

/* --- Reset ---------------------------------------------------------------- */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

/* --- Scrollbar -------------------------------------------------------------
   The one piece of chrome the browser draws for us, and the default is a grey
   trough with hard edges that belongs to no design system at all.

   Drawn to the same rules as everything else here: no track, a fully rounded
   thumb in the palette's own faint ink, and nothing visible until there is
   something to scroll. The thumb is inset from the gutter by a transparent
   border rather than by making the bar narrow, so the grab target stays the
   full 12px while the mark reads as 6px.

   Width is declared rather than left to the platform because the head script
   publishes --scrollbar from the measured difference between 100vw and the
   content width, and every full-bleed section pads itself back in by it. A
   value that changes between browsers is fine — it is measured, not assumed —
   but it does have to be a real, reserved bar, which is why this deliberately
   does not use overlay scrollbars.

   .pills and the compound rail opt out on their own further down; their
   narrower rules win on specificity. */

html {
  scrollbar-width: thin;
  scrollbar-color: var(--ink-faint) transparent;
  /* Reserve the gutter whether or not there is anything to scroll.

     It fixes two things at once. The head script publishes --scrollbar from
     the difference between 100vw and the content width, and every full-bleed
     section pads itself back in by it; with the gutter reserved, that
     difference is a constant the script can measure before the page has any
     content in it. And because the gutter survives an overlay locking the
     page, opening the gate, the cart drawer or the offer no longer yanks the
     whole page sideways by the width of a disappearing scrollbar. */
  scrollbar-gutter: stable;
}

::-webkit-scrollbar {
  width: 12px;
  height: 12px;
}

::-webkit-scrollbar-track {
  background: transparent;
}

::-webkit-scrollbar-thumb {
  background-color: var(--ink-faint);
  border-radius: var(--radius-control);
  /* Transparent border plus content-box clipping is what insets the thumb
     without shrinking the area the pointer can grab. */
  border: 3px solid transparent;
  background-clip: content-box;
}

::-webkit-scrollbar-thumb:hover {
  background-color: var(--ink-soft);
}

::-webkit-scrollbar-corner {
  background: transparent;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
}

body {
  margin: 0;
  background-color: var(--paper);
  color: var(--ink);
  font-family: var(--font-text);
  font-size: var(--size-base);
  line-height: var(--leading-normal);
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

h1,
h2,
h3,
h4,
h5,
h6,
p,
figure,
blockquote,
dl,
dd {
  margin: 0;
}

/* Wrapped in :where() so the whole selector carries zero specificity. As
   `ul[role='list']` it was (0,1,1) and quietly outranked every component class
   that tried to give a list a margin — .feature__list asked for 36px above it
   and silently got 0, which is why the blend's bullets sat jammed under its
   lede. A reset should never win a specificity contest with a component. */
:where(ul[role='list'], ol[role='list']) {
  list-style: none;
  margin: 0;
  padding: 0;
}

img,
picture,
svg,
video {
  display: block;
  max-width: 100%;
}

/* Components set display explicitly, which otherwise beats the UA rule for
   [hidden] and leaves things like an empty cart badge showing a 0. */
[hidden] {
  display: none !important;
}

input,
button,
textarea,
select {
  font: inherit;
  color: inherit;
}

button {
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}

a {
  color: inherit;
}

table {
  border-collapse: collapse;
  width: 100%;
}

/* --- Focus ----------------------------------------------------------------
   Always visible for keyboard users, never a removed outline. */

:focus-visible {
  outline: var(--focus-ring);
  outline-offset: var(--focus-offset);
  border-radius: 2px;
}

:focus:not(:focus-visible) {
  outline: none;
}

.skip-link {
  position: absolute;
  top: var(--space-2xs);
  left: var(--space-2xs);
  z-index: calc(var(--z-gate) + 10);
  padding: var(--space-2xs) var(--space-sm);
  background: var(--ink);
  color: var(--paper);
  border-radius: var(--radius-surface);
  transform: translateY(-200%);
  transition: transform var(--dur-fast) var(--ease-out);
}

.skip-link:focus {
  transform: translateY(0);
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* --- Display voice --------------------------------------------------------
   Wide, tight, and left-aligned. The width axis is the signature. */

.display,
.h1,
.h2,
.h3 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  text-wrap: balance;
}

/* Tighter than the other two, and only here. Leading is a ratio, so the 1.12
   that sets a comfortable two lines on an h2 opens into a visible gap at the
   h1's clamp ceiling — the same proportion is simply worth more pixels. A
   display headline should read as one object; at 68px, 1.12 was letting its
   lines drift apart into two. */
.h1 {
  font-size: clamp(var(--size-2xl), 6vw, var(--size-4xl));
  line-height: 1.04;
}

.h2 {
  font-size: clamp(var(--size-xl), 4vw, var(--size-3xl));
}

.h3 {
  font-size: clamp(var(--size-lg), 2.5vw, var(--size-xl));
}

/* Emphasis.

   The pill that used to sit behind an emphasised word is gone — a coloured
   shape behind a headline fought the headline. What replaced it is the change
   of voice the layout comment had been promising for a while without any font
   behind it: one word set in Newsreader italic, a serif dropped into a line of
   grotesque.

   It is a quieter mark than a fill and a more particular one. A colour says
   "look here" about anything it is applied to; a change of face says the word
   itself is of a different kind — the aside, the qualification, the one the
   sentence turns on.

   Strictly one word per headline. Two is a font pairing exercise rather than
   an emphasis, and the effect dies the second it repeats.

   Sized up a touch because it has to be: at equal font-size a serif italic
   sits optically smaller than the grotesque around it, its x-height is lower,
   and it leans away from the word that follows, so it needs the size and the
   sliver of space after it to sit on the same line rather than in front of
   it.

   Set a step back from the heading's ink rather than in it. The face change
   already marks the word; taking it to full display black as well made it
   compete with the line it belongs to. --ink-soft is the same grey the site
   uses for secondary text, so the mark is a recession rather than a new
   colour, and at headline size it clears AA against paper several times
   over. */
.em {
  font-family: var(--font-emphasis);
  font-style: italic;
  font-weight: 400;
  font-size: 1.06em;
  letter-spacing: 0;
  padding-inline-end: 0.06em;
  color: var(--ink-soft);
}

/* The same idea inverted. Without this the word takes the light ground's grey
   onto a near-black panel and disappears into it. */
.section--ink .em {
  color: var(--ink-ground-soft);
}

.h4 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--size-md);
  line-height: var(--leading-snug);
  letter-spacing: var(--tracking-tight);
}

/* --- Text voice ----------------------------------------------------------- */

.prose {
  max-width: var(--measure);
  line-height: var(--leading-loose);
  color: var(--ink-soft);
}

.prose > * + * {
  margin-top: var(--space-sm);
}

.prose a {
  color: var(--peptide-deep);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}

.lede {
  font-size: var(--size-md);
  line-height: var(--leading-normal);
  color: var(--ink-soft);
  max-width: 52ch;
}

.text-sm {
  font-size: var(--size-sm);
}

.text-soft {
  color: var(--ink-soft);
}

.text-faint {
  color: var(--ink-faint);
}

/* --- Data voice -----------------------------------------------------------
   Monospace is reserved for values a researcher would read off a
   certificate: lot numbers, CAS, formulae, mass, purity. */

.data {
  font-family: var(--font-data);
  font-size: var(--size-xs);
  font-weight: 400;
  letter-spacing: var(--tracking-normal);
  font-variant-numeric: tabular-nums;
}

/* --- Layout --------------------------------------------------------------- */

.container {
  width: 100%;
  max-width: var(--measure-page);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.container--narrow {
  max-width: 58rem;
}

/* Wider than the page measure. The header reads better spanning more than the
   body text does — it is chrome, not content. */
.container--wide {
  max-width: var(--measure-wide);
}

/* Vertical rhythm.

   Was 9vw capped at 8rem, which put 128px above and below every section and so
   256px between any two — the page read as a string of isolated slabs with the
   eye travelling through emptiness between them. The reference site runs 48 to
   64px at this width. 88px is the considered step between the two: more air
   than theirs, because our headings are larger and our sections carry fewer
   elements, but half the void we had.

   The seam, not the section, is the thing to size: two abutting sections each
   contribute their padding, so the number that matters is always the doubled
   one. */
.section {
  padding-block: clamp(var(--space-xl), 4.6vw, var(--space-2xl));
}

.section--tight {
  padding-block: clamp(var(--space-lg), 3vw, var(--space-xl));
}

/* Explicit so "paper" is a real choice in the editor rather than the absence
   of one. */
.section--paper {
  background: var(--paper);
}

.section--sunk {
  background: var(--paper-sunk);
}

/* Pastel grounds, one per palette hue. This is where the brand's multi-colour
   identity does its work at page scale: scrolling steps through the same hues
   the compounds are coloured by, instead of through six panels of white.

   Named rather than free-form, so the set stays closed and every ground keeps
   its verified text pairing. See --ground-* in pryme-tokens.css. */
.section--apricot {
  background: var(--ground-apricot);
}

.section--butter {
  background: var(--ground-butter);
}

.section--coral {
  background: var(--ground-coral);
}

.section--sage {
  background: var(--ground-sage);
}

.section--sky {
  background: var(--ground-sky);
}

.section--lilac {
  background: var(--ground-lilac);
}

.section--mint {
  background: var(--ground-mint);
}

/* Same-ground seam collapse.

   When two neighbouring sections share a ground there is no edge between them,
   so their two paddings read as one enormous gap rather than as two sections —
   184px of unbroken white sat between the assurance cards and the catalogue
   heading, and 256px between the standard and the FAQ. Where the ground does
   change, the colour edge does the separating and both paddings are legible as
   the sections' own.

   Written against every ground so it holds however the client reorders
   sections in the editor, which is the only way this stays fixed. The lower
   section keeps its padding and the upper drops its bottom, so a heading still
   clears whatever sits above it. */
.pryme-section:has(> .section--paper) + .pryme-section:has(> .section--paper) > .section,
.pryme-section:has(> .section--sunk) + .pryme-section:has(> .section--sunk) > .section,
.pryme-section:has(> .section--apricot) + .pryme-section:has(> .section--apricot) > .section,
.pryme-section:has(> .section--butter) + .pryme-section:has(> .section--butter) > .section,
.pryme-section:has(> .section--coral) + .pryme-section:has(> .section--coral) > .section,
.pryme-section:has(> .section--sage) + .pryme-section:has(> .section--sage) > .section,
.pryme-section:has(> .section--sky) + .pryme-section:has(> .section--sky) > .section,
.pryme-section:has(> .section--lilac) + .pryme-section:has(> .section--lilac) > .section,
.pryme-section:has(> .section--mint) + .pryme-section:has(> .section--mint) > .section,
.pryme-section:has(> .section--ink) + .pryme-section:has(> .section--ink) > .section {
  padding-top: 0;
}

/* --- Section grounds ------------------------------------------------------
   A long page needs its sections to differ. These are full-bleed bands: the
   colour runs to the viewport edge while the content stays in the container. */

.section--ink {
  background: var(--ink-ground);
  color: #fff;
}

.section--ink .text-soft,
.section--ink .lede,
.section--ink .standard__eyebrow {
  color: var(--ink-ground-soft);
}

.section--ink .rule,
.section--ink .section-head {
  border-color: var(--ink-ground-rule);
}

.section--ink .btn--quiet {
  --btn-fg: #fff;
  --btn-edge: var(--ink-ground-rule);
}

.section--ink .btn--quiet:hover {
  --btn-bg: var(--ink-ground-rule);
  --btn-edge: #fff;
}

.section--ink .link-action {
  color: #fff;
  border-color: var(--ink-ground-rule);
}

.section--ink .link-action:hover {
  border-color: #fff;
}

/* A whisper of the compound spectrum, for a band that needs to feel warm
   without carrying a single product's colour. */
.section--spectrum {
  background-image: linear-gradient(
    112deg,
    #fdf6ec 0%,
    #f6faf3 26%,
    #f1f7fb 52%,
    #f5f2fa 76%,
    #fdf3f3 100%
  );
}

/* --- Split sections -------------------------------------------------------
   The signature layout device: two full-bleed halves with a hard edge between
   them. The copy half pads itself by --edge so its text still lines up with
   every contained section above and below it; the panel half runs clean to the
   viewport edge.

   Below the breakpoint the halves stack and the panel becomes a band. */

.split {
  display: grid;
}

.split__copy {
  display: flex;
  flex-direction: column;
  justify-content: center;
  /* Was clamp(xl, 6vw, 3xl), which put 115px above and below the copy and made
     the hero row taller than the viewport. */
  padding-block: clamp(var(--space-lg), 3.4vw, var(--space-2xl));
  padding-inline: var(--edge);
}

.split__panel {
  position: relative;
  overflow: hidden;
  background: var(--split-panel, var(--paper-sunk));
  min-height: 22rem;
}

@media (min-width: 56rem) {
  .split {
    grid-template-columns: 1fr 1fr;
    align-items: stretch;
  }

  /* Inside a split, the copy only needs the container gutter on the side that
     meets the panel, not the full page edge. */
  .split__copy {
    padding-inline: var(--edge) clamp(var(--space-md), 2.2vw, var(--space-xl));
  }

  /* Panel on the left: the padding mirrors. */
  .split--reverse .split__copy {
    order: 2;
    padding-inline: clamp(var(--space-md), 2.2vw, var(--space-xl)) var(--edge);
  }

  .split--reverse .split__panel {
    order: 1;
  }

  .split__panel {
    min-height: min(80vh, 40rem);
  }
}

.split__panel > img,
.split__panel picture img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* A section header: heading plus optional supporting line and action.
   No eyebrow label — the heading carries itself. */
.section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  justify-content: space-between;
  gap: var(--space-md);
  padding-bottom: var(--space-md);
  margin-bottom: clamp(var(--space-lg), 4vw, var(--space-xl));
  border-bottom: 1px solid var(--rule);
}

/* Wider than a reading measure on purpose: at 44ch the supporting line left the
   trailing link stranded in the middle of a very wide empty row. */
.section-head__text {
  max-width: 52ch;
}

/* space-md, matching the heading-to-lede gap in the split sections. At
   space-xs a section heading sat 12px above its supporting line while every
   split heading sat 24px above its own, so the same pair of elements was
   spaced two different ways depending on which layout it landed in. The
   eyebrow pairing rule above still overrides this for the label. */
/* Centred variant. justify-content alone is not enough: the text block itself
   needs its own centring, or a wrapped heading stays ragged-right inside a
   centred box. */
.section-head--center {
  justify-content: center;
  text-align: center;
}

.section-head__text > * + * {
  margin-top: var(--space-md);
}

/* --- Section eyebrow -----------------------------------------------------
   A tinted pill above a section heading, a different colour per section, so
   the page steps through the compound palette as you scroll. */

/* A label, not a badge. It was a tinted pill through three versions — filled,
   outlined, gradient-filled — and each read as an object in its own right when
   its whole job is to name the section under it. The per-section colour moved
   to the heading's full stop; see .stop below. */
.eyebrow {
  display: inline-flex;
  align-items: center;
  /* The copy column is a column flex container, so an inline-flex child would
     otherwise stretch to its full width. */
  align-self: flex-start;
  width: fit-content;
  /* No bottom margin of its own. Every layout that holds an eyebrow is an owl
     stack (`> * + *`), and in a flex container a sibling margin does not
     collapse into the stack's own — the two add. That is how a nominal 8px
     turned into a 32px box gap, and 54px optically once the heading's leading
     and cap offset were counted. The gap belongs to the stack; the rule below
     tightens it for this one pair. */
  margin-bottom: 0;
  color: var(--ink-faint);
}

/* An eyebrow labels the heading directly beneath it, so it sits against that
   heading rather than at the stack's default gap.

   Restoring a rule my own rewrite of the block above deleted, and the page had
   been running in two minds since: the three stacks with an owl (`> * + *`)
   fell back to its 24px, giving a 56px gap from the label's baseline to the
   heading's cap line, while the three without any such rule sat at 0 and gave
   27px. Twice the space in half the sections.

   Zero, not a small positive value: the heading already carries its own
   leading plus the distance from its line-box top to its cap line — 22px at
   the hero's 68px — so the visible gap lands at about 27px on its own, which
   is what the tight half of the page was already doing correctly. */
.eyebrow + :is(h1, h2, h3, .h1, .h2, .h3) {
  margin-top: 0;
}

.section--ink .eyebrow {
  color: var(--ink-ground-soft);
}

/* Plain ink. This mark carried the section's colour for a long time — one
   tinted full stop, at the largest size on the page, a different hue per
   section — and it was the third attempt at putting the per-section colour
   somewhere after the eyebrow pill was cut. It is the last of them: a coloured
   period reads as a dot that has landed on the sentence rather than as
   punctuation, and at headline size there is nowhere for it to hide.

   The span stays. It costs nothing, it is a hook if a future treatment wants
   the terminal mark, and removing it would mean touching every headline in the
   theme to gain nothing. --accent still reaches the section root and still
   colours what it colours elsewhere. */
.stop {
  color: inherit;
}

.grid {
  display: grid;
  gap: var(--space-md);
}

.rule {
  height: 1px;
  background: var(--rule);
  border: 0;
  margin: 0;
}

/* --- Stack utility --------------------------------------------------------
   Owl selector so vertical rhythm is set once by the parent rather than by
   margins scattered across children. */

.stack > * + * {
  margin-top: var(--flow, var(--space-sm));
}

/* A hairline separator between inline facts, replacing the middle dot. Same
   job, no dot — the theme uses no round marks anywhere. */
.sep {
  display: inline-block;
  width: 1px;
  height: 0.85em;
  margin-inline: 0.5em;
  vertical-align: -0.08em;
  background: var(--rule-strong);
}
