/* ==========================================================================
   Starfish Group — surimi.css
   The raw-material page: introduction, species index, four species panels, and
   the gel-strength material that follows them.

   This is the sober page. Surimi-based products get illustration; surimi is
   what a buyer writes a specification against, so the register here is a
   materials sheet — real photography, one type system, rules instead of fills,
   and the same layout four times so two species can be compared without first
   working out where the grades went.

   NOTHING ALTERNATES. Every panel is identical, in the same order, at the same
   sizes. That is the whole argument of the page.
   ========================================================================== */

/* --------------------------------------------------------------------------
   THE PAGE'S OWN TONES
   Named in the brief, scoped here because nothing else on the site paints with
   them. --rm-coral is the accent as specified; --rm-coral-ink is the same hue
   carried down far enough to set 12px type on ivory, which the accent itself
   cannot — measured, it comes out at 2.9.
   -------------------------------------------------------------------------- */
/* A WIDER MEASURE THAN THE REST OF THE SITE, on instruction: the brief asks
   for 1180-1240 of content and the shell caps at 1120. It is scoped to this
   page's own sections so nothing else moves. */
.rm-intro > .shell,
.sx__inner,
.sp-list > .shell { max-width: 1300px; }

body {
  --rm-coral:     #D87552;
  --rm-coral-ink: #A94A2E;
  --rm-sage:      #9EB58A;
  --rm-rule:      rgba(120, 112, 106, 0.26);
  --rm-panel:     #FBFAF7;
}

/* --------------------------------------------------------------------------
   1. INTRODUCTION
   Compact, left, and over before the fold. No photograph behind it.
   -------------------------------------------------------------------------- */
.rm-intro {
  background: var(--ivory);
  padding-top: calc(var(--header-h) + clamp(40px, 6vh, 76px));
  padding-bottom: clamp(28px, 4vh, 44px);
}

.rm-intro__eyebrow {
  font-family: var(--font-body);
  font-size: var(--text-micro);
  font-weight: 600;
  letter-spacing: var(--track-micro);
  text-transform: uppercase;
  /* The brand red, which is what the same line does on the products page.
     Grey read as a caption rather than as the label of the page, and this is
     this page's single use of the red. */
  color: var(--red);
}

.rm-intro__heading {
  margin-top: var(--s-12);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(34px, 3.4vw, 50px);
  line-height: 1.04;
  letter-spacing: var(--track-headline);
  color: var(--ink);
}

.rm-intro__lede {
  margin-top: var(--s-16);
  max-width: 62ch;
  font-size: var(--text-body);
  line-height: var(--leading-body);
  color: var(--ink-soft);
}

/* --------------------------------------------------------------------------
   2. THE SPECIES INDEX
   Sticky under the header. Four real links to four real sections; the active
   one is a coral rule and a darker word, and nothing else.
   -------------------------------------------------------------------------- */
.sx {
  position: sticky;
  top: var(--header-h);
  z-index: 40;
  background: var(--ivory);
  border-bottom: 1px solid var(--rm-rule);
  /* the phone scrolls this sideways; the bar itself never wraps */
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
}
.sx::-webkit-scrollbar { display: none; }

.sx__inner {
  display: flex;
  gap: clamp(28px, 5vw, 88px);
  align-items: stretch;
}

.sx__item {
  display: flex;
  flex-direction: column;
  gap: 2px;
  /* 44px of target at the smallest size the bar ever is */
  min-height: 58px;
  padding-block: var(--s-12);
  white-space: nowrap;
  border-bottom: 2px solid transparent;
  transition: border-color 200ms var(--ease-out);
}
.sx__jp {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-subheading);
  letter-spacing: var(--track-headline);
  line-height: 1.1;
  color: var(--ink-meta);
  transition: color 200ms var(--ease-out);
}
.sx__en {
  font-family: var(--font-body);
  font-size: var(--text-micro);
  color: var(--ink-meta);
}
.sx__item:hover .sx__jp { color: var(--ink); }
.sx__item.is-active { border-bottom-color: var(--rm-coral); }
.sx__item.is-active .sx__jp { color: var(--ink); }
.sx__item:focus-visible { outline: 2px solid var(--rm-coral-ink); outline-offset: -4px; }

/* --------------------------------------------------------------------------
   3. A SPECIES PANEL
   One quiet plate on the ivory, a fine rule around it, and a coral edge on the
   header so the eye finds the top of each species while scrolling. Two columns
   split by a hairline: the fish and what it is on the left, the grades and
   what they are for on the right.
   -------------------------------------------------------------------------- */
.sp-list {
  background: var(--ivory);
  padding-bottom: clamp(56px, 8vh, 110px);
}

.sp {
  position: relative;
  /* clears the header AND the index, so a heading is never landed on */
  scroll-margin-top: calc(var(--header-h) + 68px);
  margin-top: clamp(28px, 4vh, 48px);
  background: var(--rm-panel);
  border: 1px solid var(--rm-rule);
  border-radius: 4px;
  overflow: hidden;
}

/* TWO LEAVES, NOT A CARD WITH A TITLE. The name and the fish are one page and
   the data is the facing one; the header sits inside the left leaf rather than
   spanning the pair. */
.sp__body {
  display: grid;
  grid-template-columns: minmax(0, 1.02fr) minmax(0, 1fr);
}
.sp__left {
  display: flex;
  flex-direction: column;
}
.sp__right {
  position: relative;
  padding: clamp(26px, 3.2vw, 44px);
  display: flex;
  flex-direction: column;
}
/* THE GUTTER RULE STOPS SHORT of the top and bottom edges, as a printed spread
   does — run edge to edge it cuts the plate in half instead of separating two
   leaves of it. Drawn on the right leaf rather than as a border on the left so
   it can be inset at all. */
.sp__right::before {
  content: "";
  position: absolute;
  left: -1px;
  top: clamp(18px, 2vw, 28px);
  bottom: clamp(18px, 2vw, 28px);
  width: 1px;
  background: var(--rm-rule);
}

/* --- the header ---------------------------------------------------------- */
.sp__head { padding: clamp(24px, 3vw, 40px) clamp(24px, 3vw, 40px) clamp(20px, 2.4vw, 30px); }

.sp__index {
  font-family: var(--font-body);
  font-size: var(--text-micro);
  font-weight: 600;
  letter-spacing: var(--track-micro);
  text-transform: uppercase;
  color: var(--ink);
}
.sp__index-n { color: var(--rm-coral-ink); }

/* The name and the two other names it goes by, sharing a baseline. The display
   size does the ranking, so neither of the smaller two needs a label. */
.sp__names {
  margin-top: clamp(12px, 1.6vw, 20px);
  display: flex;
  /* LAST baseline, not first. Plain `baseline` aligns a flex item by the first
     line it contains, which put the scientific name on the display name's line
     and hung the English name below it. The bottom line of that little stack is
     the English name, and that is the one that belongs on the same line as the
     Japanese. */
  align-items: last baseline;
  flex-wrap: wrap;
  gap: 4px clamp(16px, 2vw, 30px);
}
.sp__name {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(38px, 4.2vw, 60px);
  line-height: 0.98;
  letter-spacing: var(--track-display);
  color: var(--ink);
}
.sp__name:focus { outline: none; }
.sp__name:focus-visible { outline: 2px solid var(--rm-coral-ink); outline-offset: 4px; }

.sp__alt { padding-bottom: 2px; }
.sp__latin {
  font-size: var(--text-small);
  font-style: italic;
  color: var(--ink-meta);
}
.sp__common {
  margin-top: 2px;
  font-size: clamp(15px, 1.15vw, 18px);
  color: var(--ink-soft);
}

/* --- the left leaf -------------------------------------------------------- */
/* THE ONE THING THAT BLEEDS. Everything else on the sheet sits inside the
   margin; the fish runs the full width of its own leaf, which is what stops it
   reading as an illustration dropped into a document.

   HEIGHT, NOT WIDTH, IS WHAT IS FIXED. The four cut-outs are 2.76, 2.94, 3.00
   and 5.46 to one, so sized by width alone the same leaf gave Himeji a fish
   223px tall and Eso one of 113 — the stubby ones came out half as big again
   as they should be. A set height and contain puts every species at one scale;
   the long ones simply reach further across the leaf, which is the true thing
   about them. They are cut out on transparency, so the spare width beside a
   short fish is the sheet, not a box. */
.sp__photo {
  display: block;
  width: 100%;
  height: clamp(112px, 12.5vw, 168px);
  object-fit: contain;
  object-position: center;
}

.sp__leaf {
  display: flex;
  flex-direction: column;
  flex: 1;
  padding: clamp(24px, 3vw, 40px);
}

.sp__desc {
  font-size: clamp(15px, 1.2vw, 17px);
  line-height: 1.62;
  color: var(--ink);
  max-width: 46ch;
}

.sp__notes {
  margin-top: clamp(24px, 3vw, 38px);
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(20px, 2.4vw, 34px);
}

.sp__label,
.sp__sub {
  font-family: var(--font-body);
  font-size: var(--text-micro);
  font-weight: 600;
  letter-spacing: var(--track-micro);
  text-transform: uppercase;
  color: var(--ink);
}

.sp__marks { margin-top: var(--s-12); }
.sp__marks li {
  position: relative;
  padding-left: 22px;
  font-size: var(--text-small);
  line-height: 1.5;
  color: var(--ink-soft);
}
.sp__marks li + li { margin-top: 9px; }
/* An en-dash rather than a bullet: these are notes on a specification sheet,
   not a shopping list. */
.sp__marks li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.72em;
  width: 11px;
  height: 1px;
  background: var(--rm-coral);
}

/* --- the right leaf ------------------------------------------------------- */
.sp__grades-head { position: relative; }
.sp__h {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(24px, 2.2vw, 34px);
  line-height: 1.15;
  letter-spacing: var(--track-headline);
  color: var(--ink);
}
.sp__unit {
  margin-top: 6px;
  font-size: var(--text-small);
  color: var(--ink-meta);
}
.sp__unit abbr,
.grades abbr { text-decoration: none; border-bottom: 1px dotted var(--border-dark); cursor: help; }

/* --- the grades ----------------------------------------------------------- */
.grades {
  position: relative;
  width: 100%;
  margin-top: clamp(22px, 2.6vw, 32px);
  border-collapse: collapse;
  text-align: left;
}
.grades th,
.grades td { padding: clamp(13px, 1.4vw, 17px) var(--s-12) clamp(13px, 1.4vw, 17px) 0; }
.grades thead th {
  padding-top: 0;
  padding-bottom: 10px;
  font-family: var(--font-body);
  font-size: var(--text-micro);
  font-weight: 600;
  letter-spacing: var(--track-micro);
  text-transform: uppercase;
  color: var(--ink-meta);
  border-bottom: 1px solid var(--rm-rule);
  white-space: nowrap;
}
.grades tbody th,
.grades tbody td {
  font-size: clamp(15px, 1.2vw, 17px);
  color: var(--ink-soft);
  border-bottom: 1px solid var(--rm-rule);
}
/* The grade itself is the row's own heading — set to match, so a buyer reading
   down the first column reads names and not labels. */
.grades tbody th {
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
}
/* A range is one value. Left to wrap, 600-800 broke across two lines on a
   phone and read as two figures. */
.grades tbody td:first-of-type { white-space: nowrap; }
.grades tbody tr:last-child th,
.grades tbody tr:last-child td { border-bottom: 0; }

/* --- applications, supply, and the two links ------------------------------ */
.sp__uses { margin-top: clamp(24px, 3vw, 34px); }
.sp__uses p {
  margin-top: var(--s-12);
  font-size: var(--text-small);
  line-height: 1.55;
  color: var(--ink-soft);
}

.sp__supply {
  margin-top: clamp(22px, 2.6vw, 32px);
  padding-top: clamp(20px, 2.4vw, 28px);
  border-top: 1px solid var(--rm-rule);
}
.sp__spec { margin-top: var(--s-12); }
.sp__spec > div {
  display: grid;
  grid-template-columns: minmax(0, 15ch) minmax(0, 1fr);
  gap: var(--s-16);
  font-size: var(--text-small);
  line-height: 1.55;
}
.sp__spec > div + div { margin-top: 7px; }
.sp__spec dt { font-weight: 600; color: var(--ink); }
.sp__spec dd { color: var(--ink-soft); }
/* The browser default puts 40px of indent on a dd. Inside the two-column grid
   that showed as the value hanging off its own column. */
.sp__spec dd { margin-inline-start: 0; display: flex; align-items: baseline; }

/* Pushed to the foot of the leaf so the two sheets end level however many
   grades a species has — Himeji and Eso have one row where Itoyori has three. */
.sp__foot {
  margin-top: auto;
  padding-top: clamp(24px, 3vw, 38px);
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-16);
}

.sp__how,
.sp__view {
  display: inline-flex;
  align-items: center;
  gap: var(--s-8);
  padding-bottom: 5px;
  font-family: var(--font-body);
  font-size: var(--text-caption);
  font-weight: 600;
  letter-spacing: var(--track-micro);
  text-transform: uppercase;
  transition: opacity 200ms var(--ease-out), color 200ms var(--ease-out),
              border-color 200ms var(--ease-out);
}
.sp__how {
  color: var(--ink);
  border-bottom: 1px solid var(--border-dark);
}
.sp__how:hover { opacity: 0.65; }
.sp__view {
  color: var(--rm-coral-ink);
  border-bottom: 1px solid var(--rm-coral);
}
.sp__view:hover { opacity: 0.7; }
.sp__view:focus-visible { outline: 2px solid var(--rm-coral-ink); outline-offset: 3px; }
.sp__how .btn__arrow,
.sp__view .btn__arrow { transition: transform 260ms var(--ease-out); }
.sp__how:hover .btn__arrow,
.sp__view:hover .btn__arrow { transform: translateX(3px); }
.sp__how:focus-visible { outline: 2px solid var(--rm-coral-ink); outline-offset: 3px; }

/* THE ONE CALL ON THE SHEET, and the only place coral carries type. Underlined
   rather than boxed: four filled buttons down a specification sheet would read
   as the point of it. */
.sp__tds {
  display: inline-flex;
  align-items: center;
  gap: var(--s-8);
  padding-bottom: 5px;
  font-family: var(--font-body);
  font-size: var(--text-caption);
  font-weight: 600;
  letter-spacing: var(--track-micro);
  text-transform: uppercase;
  color: var(--rm-coral-ink);
  border-bottom: 1px solid var(--rm-coral);
  transition: opacity 200ms var(--ease-out);
}
.sp__tds:hover { opacity: 0.7; }
.sp__tds:focus-visible { outline: 2px solid var(--rm-coral-ink); outline-offset: 3px; }
.sp__tds .btn__arrow { transition: transform 260ms var(--ease-out); }
.sp__tds:hover .btn__arrow { transform: translateX(3px); }

@media (prefers-reduced-motion: reduce) {
  .sp__tds .btn__arrow,
  .sp__how .btn__arrow,
  .sp__view .btn__arrow { transition: none; }
  .sp__tds:hover .btn__arrow,
  .sp__how:hover .btn__arrow,
  .sp__view:hover .btn__arrow { transform: none; }
}

/* --------------------------------------------------------------------------
   TABLET
   The two columns hold until the grade figures stop having room to be figures.
   -------------------------------------------------------------------------- */
@media (max-width: 560px) {
  /* Label over value. Side by side at this width the value column was about
     14 characters wide, which broke VIEW DETAILS across two lines and left its
     arrow stranded on the second. */
  .sp__spec > div { grid-template-columns: minmax(0, 1fr); gap: 3px; }
  .sp__spec > div + div { margin-top: var(--s-12); }
}

@media (max-width: 1080px) {
  .sp__body { grid-template-columns: minmax(0, 1fr); }
  /* Stacked, the rule between the leaves lies down and insets from the sides
     instead of the ends. */
  .sp__right::before {
    left: clamp(24px, 3vw, 40px);
    right: clamp(24px, 3vw, 40px);
    top: 0;
    bottom: auto;
    width: auto;
    height: 1px;
  }
}


/* --------------------------------------------------------------------------
   NARROW
   Everything stacks. The index keeps its place under the header and starts
   scrolling sideways rather than squeezing four names into four columns.
   -------------------------------------------------------------------------- */
@media (max-width: 720px) {
  .rm-intro { padding-top: calc(var(--header-h) + var(--s-40)); }
  .sx__item { min-height: 52px; }
  .sp__head { flex-direction: column; gap: var(--s-16); }
  .sp__tds { align-self: flex-start; }
  .sp__notes { grid-template-columns: minmax(0, 1fr); gap: var(--s-24); }
}

@media (max-width: 480px) {
  .sp__photo { aspect-ratio: 20 / 10; }
  .grades td:first-child { width: 40%; }
}

@media (prefers-reduced-motion: reduce) {
  .sx__item, .sx__jp, .sp__tds, .sp__how { transition: none; }
  html { scroll-behavior: auto; }
}


/* Reads as an empty state, not as a value. Nothing on this page is invented,
   so a row with no figure says so plainly rather than showing a dash. */
.grades__pending,
.pending {
  color: var(--ink-meta);
  font-style: italic;
}
.grades__pending { padding-block: var(--s-32); text-align: center; }

/* --------------------------------------------------------------------------
   THE JS LINK
   Written out beside the column name rather than hidden behind an icon. A
   figure means little without the method it was taken by, and a mark you
   have to discover is no use to someone who did not know to look.

   Set in sentence case so it reads as a link rather than a second heading —
   the header around it is uppercase and letterspaced.
   -------------------------------------------------------------------------- */
.js-link {
  margin-left: var(--s-8);
  font-family: var(--font-body);
  font-size: var(--text-caption);
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  color: var(--seaglass);
  border-bottom: 1px solid rgba(220, 232, 230, 0.45);
  transition: color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out);
}
.js-link:hover { color: var(--cream); border-bottom-color: var(--cream); }
.js-link:focus-visible { outline: 2px solid var(--seaglass); outline-offset: 3px; }

/* The header wraps now: the name and the link together are longer than a
   narrow column, and nowrap would push the table past its own card. */
.grades th { white-space: normal; }

@media (prefers-reduced-motion: reduce) {
  .js-link { transition: none; }
}

/* --------------------------------------------------------------------------
   HOW WE MEASURE
   Cream, so it reads as its own chapter after the sea-glass species band.
   -------------------------------------------------------------------------- */
.js-method { background: var(--ivory); }

/* TOP HALF: the argument and the picture of it. Below 900 the picture goes
   under the copy rather than beside it — at half of 900 the frame is too small
   to be a photograph of anything. */
.jsm__top {
  display: grid;
  grid-template-columns: minmax(0, 0.86fr) minmax(0, 1.14fr);
  gap: clamp(28px, 4vw, 64px);
  /* The photograph runs the height of the copy beside it rather than sitting
     at a fixed 16:9 with a gap under it — the two columns are one block. */
  align-items: stretch;
}
/* Same register as "the method at a glance" further down, which is the pair
   the mockup sets these two labels in. */
.jsm__heading { margin-top: clamp(14px, 1.6vw, 20px); max-width: 14ch; }

.js-method__lede {
  margin-top: var(--s-20);
  font-size: clamp(15px, 1.2vw, 17px);
  line-height: 1.62;
  color: var(--ink-soft);
  max-width: 42ch;
}

/* --- the caution ----------------------------------------------------------
   The inverse of the blush callout further up the page: wine ground, pale
   mark. Two cautions on one sheet only work as a pair, so they are built as
   one — same drawn exclamation, same motions, opposite way round. */
.jsm__note {
  position: relative;
  overflow: hidden;
  margin-top: clamp(26px, 3vw, 40px);
  padding: clamp(20px, 2.2vw, 28px) clamp(22px, 2.4vw, 30px);
  border-radius: 6px;
  background: var(--jsm-wine, #7A293D);
  max-width: 46ch;
  transition: transform 320ms var(--ease-out);
}
/* Stops short of the mark, so the two never share a column of the card. */
.jsm__note-copy { position: relative; z-index: 1; max-width: 30ch; }
.jsm__note-title {
  font-size: var(--text-small);
  font-weight: 600;
  line-height: 1.4;
  color: var(--cream);
}
.jsm__note-body {
  margin-top: var(--s-8);
  font-size: var(--text-small);
  line-height: 1.55;
  color: rgba(245, 242, 236, 0.82);
}

/* Cropped by the card's own edge rather than drawn to fit inside it, which is
   what makes it read as a mark on the card and not a badge parked on it. */
.jsm__mark {
  position: absolute;
  /* Lifted six per cent. At top: 0 the dot fell half outside the card and read
     as a broken shape rather than a cropped one; from here the whole mark is
     in and only its foot touches the edge. */
  top: -6%;
  right: clamp(26px, 3.4vw, 54px);
  height: 118%;
  width: auto;
  opacity: 0.2;
  pointer-events: none;
}
.jsm__bang-stem {
  stroke: var(--cream);
  stroke-width: 26;
  stroke-linecap: round;
  fill: none;
}
.jsm__bang-dot { fill: var(--cream); }
.jsm__bang {
  transform-origin: 60px 126px;
  transition: transform 420ms var(--ease-out);
}
.jsm__bang-dot {
  transform-origin: 60px 126px;
  transition: transform 420ms var(--ease-out) 90ms;
}
.jsm__note:hover { transform: translateY(-2px); }
.jsm__note:hover .jsm__bang { transform: rotate(-7deg) translateY(-5px); }
.jsm__note:hover .jsm__bang-dot { transform: translateY(5px); }

/* --- the photograph -------------------------------------------------------- */
.jsm__shot { margin: 0; display: flex; }
.jsm__shot-img {
  display: block;
  width: 100%;
  height: 100%;
  /* A floor for the crop: stretched to a short copy column it would otherwise
     become a letterbox strip. */
  min-height: min(26vw, 380px);
  object-fit: cover;
  border-radius: 6px;
}

/* --- the three stages ------------------------------------------------------ */
.jsm__glance {
  margin-top: clamp(44px, 5.5vw, 78px);
  padding-top: clamp(22px, 2.6vw, 32px);
  border-top: 1px solid var(--rm-rule);
}

/* Both section labels in one register, which is the pair the mockup sets
   them in. */
.jsm__eyebrow,
.jsm__glance-label {
  font-family: var(--font-body);
  font-size: var(--text-micro);
  font-weight: 600;
  letter-spacing: var(--track-micro);
  text-transform: uppercase;
  color: var(--ink);
}

.js-steps {
  margin-top: clamp(24px, 3vw, 38px);
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(26px, 3.4vw, 54px);
}

/* THE RULE IS THE STEP. The numeral sits on a line that runs to the end of its
   own column, so three stages read as three measured lengths of one process
   rather than as three paragraphs that happen to be numbered. */
.js-step__n {
  display: flex;
  align-items: center;
  gap: var(--s-16);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(26px, 2.4vw, 34px);
  line-height: 1;
  letter-spacing: var(--track-display);
  color: var(--rm-coral-ink);
}
.js-step__n::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--rm-coral);
}

.js-step__title {
  margin-top: clamp(14px, 1.6vw, 20px);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(17px, 1.4vw, 20px);
  line-height: 1.25;
  letter-spacing: var(--track-headline);
  color: var(--ink);
}
.js-step__body {
  margin-top: var(--s-12);
  font-size: var(--text-small);
  line-height: 1.6;
  color: var(--ink-soft);
}
/* What decides the number, named but not yet answered — the values are behind
   the disclosure below. */
.js-step__vars {
  margin-top: clamp(18px, 2vw, 26px);
  font-size: var(--text-caption);
  line-height: 1.5;
  color: var(--ink-meta);
}
.js-step__vars span { color: var(--rm-coral); margin-inline: 3px; }

/* --- the disclosure -------------------------------------------------------- */
.jsm__more {
  margin-top: clamp(30px, 3.4vw, 46px);
  border-top: 1px solid var(--rm-rule);
  border-bottom: 1px solid var(--rm-rule);
}
.jsm__more-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-16);
  padding-block: clamp(16px, 1.8vw, 22px);
  cursor: pointer;
  list-style: none;
  font-family: var(--font-body);
  font-size: var(--text-caption);
  font-weight: 600;
  letter-spacing: var(--track-micro);
  text-transform: uppercase;
  color: var(--ink);
  transition: color 200ms var(--ease-out);
}
.jsm__more-summary::-webkit-details-marker { display: none; }
.jsm__more-summary:hover { color: var(--rm-coral-ink); }
.jsm__more-summary:focus-visible { outline: 2px solid var(--rm-coral-ink); outline-offset: 3px; }

/* A plus that becomes a minus. Drawn from two rules rather than set as a
   character so the two strokes are the same weight as everything else here. */
.jsm__plus {
  position: relative;
  flex: none;
  width: 14px;
  height: 14px;
}
.jsm__plus::before,
.jsm__plus::after {
  content: "";
  position: absolute;
  inset: 50% 0 auto 0;
  height: 1px;
  background: var(--rm-coral);
}
.jsm__plus::after {
  transform: rotate(90deg);
  transition: transform 300ms var(--ease-out);
}
.jsm__more[open] .jsm__plus::after { transform: rotate(0deg); }

.jsm__conditions { padding-bottom: clamp(20px, 2.4vw, 30px); }
.jsm__conditions > div {
  display: grid;
  grid-template-columns: minmax(0, 26ch) minmax(0, 1fr);
  gap: var(--s-20);
  padding-block: var(--s-12);
  border-top: 1px solid var(--rm-rule);
  font-size: var(--text-small);
  line-height: 1.55;
}
.jsm__conditions dt { font-weight: 600; color: var(--ink); }
.jsm__conditions dd { margin-inline-start: 0; color: var(--ink-soft); }

/* --- the closing line ------------------------------------------------------ */


@media (max-width: 900px) {
  .jsm__top { grid-template-columns: minmax(0, 1fr); }
  /* Stacked, there is no column to match, so it goes back to its own shape. */
  .jsm__shot-img { height: auto; min-height: 0; aspect-ratio: 16 / 9; }
  .jsm__heading { max-width: none; }
  .js-steps { grid-template-columns: minmax(0, 1fr); gap: var(--s-32); }
  .jsm__conditions > div { grid-template-columns: minmax(0, 1fr); gap: 3px; }
}

@media (prefers-reduced-motion: reduce) {
  .jsm__note, .jsm__bang, .jsm__bang-dot, .jsm__plus::after { transition: none; }
  .jsm__note:hover { transform: none; }
  .jsm__note:hover .jsm__bang,
  .jsm__note:hover .jsm__bang-dot { transform: none; }
}

/* Sea-glass, between two cream bands. */
.js-method { background: var(--seaglass); }

/* --------------------------------------------------------------------------
   PACKAGING
   -------------------------------------------------------------------------- */
.packaging { background: var(--ivory); }

/* Copy and carton side by side, then the specifications the full width below
   them — the same shape the method section above uses, so the two read as a
   pair rather than as two different ideas about a page. */
.packaging__top {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  gap: clamp(28px, 4vw, 64px);
  align-items: center;
}
.packaging__shot { margin: 0; }
.packaging__shot img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border-radius: 20px;
}

@media (max-width: 900px) {
  .packaging__top { grid-template-columns: minmax(0, 1fr); }
}

.pack-specs {
  margin-top: var(--s-40);
  border-top: 1px solid var(--border-dark);
}

/* A definition list read as rows, because that is what it is: a term and its
   figure, five times. */
.pack-spec {
  display: grid;
  grid-template-columns: minmax(0, 0.32fr) minmax(0, 0.68fr);
  gap: var(--s-24);
  padding: var(--s-20) 0;
  border-bottom: 1px solid var(--border);
}

.pack-spec dt {
  font-family: var(--font-body);
  font-size: var(--text-micro);
  font-weight: 600;
  letter-spacing: var(--track-micro);
  text-transform: uppercase;
  color: var(--ink);
}

.pack-spec dd {
  font-size: var(--text-small);
  line-height: 1.6;
  color: var(--ink-soft);
}

@media (max-width: 900px) {
  .pack-spec { grid-template-columns: 1fr; gap: var(--s-8); padding: var(--s-16) 0; }
}

/* --------------------------------------------------------------------------
   GEL STRENGTH, EXPLAINED
   The definition on the left, the scale on the right, and what the number does
   not cover underneath — given a band of its own, because a buyer who reads a
   JS figure as the whole specification is the one this page has failed.
   -------------------------------------------------------------------------- */
.jsx {
  background: var(--ivory);
  /* the drawings hang below the panel; the section has to hold them */
  padding-bottom: clamp(96px, 12vh, 168px);
}

.jsx__grid {
  display: grid;
  grid-template-columns: minmax(0, 27fr) minmax(0, 73fr);
  gap: clamp(32px, 5vw, 84px);
  align-items: start;
}

.jsx__eyebrow {
  font-family: var(--font-body);
  font-size: var(--text-micro);
  font-weight: 600;
  letter-spacing: var(--track-micro);
  text-transform: uppercase;
  color: var(--ink-meta);
}
.jsx__heading {
  margin-top: var(--s-12);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(28px, 2.6vw, 38px);
  line-height: 1.08;
  letter-spacing: var(--track-headline);
  color: var(--ink);
}
/* The one coral mark in the column, and it is a rule rather than a flourish:
   it separates the title from the definition under it. */
.jsx__heading::after {
  content: "";
  display: block;
  width: 44px;
  height: 2px;
  margin-top: var(--s-24);
  background: var(--rm-coral);
}
.jsx__lede {
  margin-top: var(--s-20);
  font-size: var(--text-body);
  line-height: var(--leading-body);
  color: var(--ink-soft);
}

/* --- the scale ----------------------------------------------------------- */
/* FULL WIDTH, and the drawings hang off it. The bottom padding is deep
   because the two illustrations overlap the panel's foot: they need a band of
   plain sea-glass to sit against rather than the "suited to" line. */
.jsx__scale {
  position: relative;
  margin-top: clamp(40px, 5vw, 72px);
  background: var(--seaglass);
  padding: clamp(22px, 2.6vw, 34px) clamp(28px, 4vw, 72px) clamp(56px, 7vw, 96px);
}

/* The page's only illustration, and mostly outside the panel rather than in
   it. Each sits under the part of the scale it belongs to: the tofu under the
   middle, the crab stick under the firm end. */
.jsx__art {
  position: absolute;
  z-index: 1;
  height: auto;
  pointer-events: none;
  user-select: none;
}
/* THE TWO ANSWER A HOVER ON THE SCALE, each in its own way and neither in
   time with the other — the same idea as the exclamation mark in the callout
   below. The tofu is a cube and tips; the crab stick is long and rolls. Both
   rest at an angle already, so the hover is a change of angle rather than a
   move from nothing, and neither leaves the ground it sits on. */
.jsx__art {
  transition: transform 460ms var(--ease-out);
}
.jsx__art--tofu {
  width: clamp(92px, 11vw, 158px);
  left: clamp(-6px, 1.6vw, 34px);
  bottom: clamp(-92px, -6vw, -52px);
  transform: rotate(-4deg);
  transform-origin: 50% 92%;
}
.jsx__scale:hover .jsx__art--tofu {
  transform: rotate(-9deg) translateY(-8px) scale(1.04);
}
.jsx__art--crab {
  width: clamp(106px, 12.5vw, 182px);
  right: clamp(-6px, 1.6vw, 34px);
  bottom: clamp(-88px, -5.6vw, -48px);
  transform: rotate(6deg);
  transform-origin: 30% 70%;
  /* a beat behind the tofu, so the pair does not move as one object */
  transition-delay: 110ms;
}
.jsx__scale:hover .jsx__art--crab {
  transform: rotate(1deg) translateY(-6px) scale(1.04);
}

.jsx__scale-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-16);
  font-family: var(--font-body);
  font-size: var(--text-caption);
  font-weight: 600;
  letter-spacing: var(--track-micro);
  text-transform: uppercase;
  color: var(--ink);
}
.jsx__scale-head abbr { text-decoration: none; }

.jsx__track {
  position: relative;
  margin-top: clamp(26px, 3vw, 40px);
}

/* Thickening left to right, because that is the axis the scale runs on. One
   polygon rather than a gradient: it stays crisp at any width, and the page
   has no gradients on it. */
.jsx__rule {
  position: absolute;
  left: 0;
  right: 0;
  top: 5px;
  width: 100%;
  height: 6px;
  fill: var(--ink);
}

.jsx__stops {
  position: relative;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s-16);
}
.jsx__stop {
  position: relative;
  padding-top: 44px;
  text-align: center;
}

.jsx__dot {
  position: absolute;
  top: 0;
  left: 50%;
  width: 16px;
  height: 16px;
  margin-left: -8px;
  border-radius: 9999px;
  background: var(--rm-coral);
  /* fill-box so the growth happens around the dot rather than the column */
  transform-box: fill-box;
  transition: transform 260ms var(--ease-out);
}
/* THE RING. Drawn at the dot's own size and taken outward once by the
   keyframes, so it starts exactly on the dot's edge. Declared on the hover
   state, which is what makes it play once per pointer entry rather than loop. */
.jsx__dot::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  border: 1.5px solid var(--rm-coral);
  opacity: 0;
}

.jsx__figure {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(24px, 2.2vw, 32px);
  letter-spacing: var(--track-headline);
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.jsx__what {
  margin-top: var(--s-8);
  font-size: var(--text-small);
  line-height: 1.4;
  color: var(--ink-soft);
}
.jsx__who {
  margin-top: var(--s-20);
  font-size: var(--text-small);
  color: var(--ink-meta);
}
/* What each grade is bought for. A step quieter than the grade names above
   it, because the grade is the fact and this is the consequence. */
.jsx__for {
  margin-top: 6px;
  font-family: var(--font-body);
  font-size: var(--text-caption);
  letter-spacing: var(--track-micro);
  text-transform: uppercase;
  color: var(--ink-meta);
}

/* HOVER MOVES THE WHOLE STOP, not the dot on its own: the figure, what it
   means and which grades sit there are one reading, so they lift together. */
.jsx__figure,
.jsx__what,
.jsx__who,
.jsx__for {
  transition: transform 260ms var(--ease-out), color 260ms var(--ease-out);
}
.jsx__stop:hover .jsx__dot { transform: scale(1.4); }
.jsx__stop:hover .jsx__dot::after { animation: jsx-ring 640ms var(--ease-out) 1; }
.jsx__stop:hover .jsx__figure,
.jsx__stop:hover .jsx__what,
.jsx__stop:hover .jsx__who,
.jsx__stop:hover .jsx__for { transform: translateY(-4px); }
.jsx__stop:hover .jsx__what,
.jsx__stop:hover .jsx__who,
.jsx__stop:hover .jsx__for { color: var(--ink); }

@keyframes jsx-ring {
  from { opacity: 0.7; transform: scale(1); }
  to   { opacity: 0;   transform: scale(2.6); }
}

.jsx__sub {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-subheading);
  letter-spacing: var(--track-headline);
  color: var(--ink);
}

/* --- the caveat ---------------------------------------------------------- */
/* --- the callout ---------------------------------------------------------
   Low, wide, warm and quietly distinctive. No border and no shadow: it is
   separated from the ground by tone, which is how everything else on this page
   is separated from it.

   THE TWO COLOURS. The brief's list and its own description of the graphic
   disagree; the description and the mockup both have a pale rose shape with a
   dark maroon mark in it, and a burgundy slab in the corner of a blush card is
   the alarming version the brief asks to avoid. So: rose shape, maroon mark.
   -------------------------------------------------------------------------- */
.jsc {
  --jsc-bg:    #EEE5E4;
  --jsc-rose:  #D9A9B1;
  --jsc-wine:  #7A293D;

  position: relative;
  overflow: hidden;
  border-radius: 22px;
  background: var(--jsc-bg);
  padding: clamp(28px, 3.2vw, 44px) clamp(26px, 3.4vw, 48px);
  transition: transform 320ms var(--ease-out), background-color 320ms var(--ease-out);
}
/* The copy stops well short of the graphic: the two never share a column of
   the card at any width, which is why the shape needs no text wrapping. */
.jsc__copy { position: relative; z-index: 1; max-width: min(100%, 46ch); }

.jsc__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(19px, 1.6vw, 23px);
  line-height: 1.2;
  letter-spacing: var(--track-headline);
  color: var(--ink);
}
.jsc__body {
  margin-top: var(--s-16);
  font-size: var(--text-small);
  line-height: 1.65;
  color: var(--ink);
}
/* A step heavier than the body: it is the answer the body sets up. */
.jsc__qualities {
  margin-top: var(--s-20);
  font-size: var(--text-small);
  font-weight: 600;
  line-height: 1.9;
  color: var(--ink);
}
.jsc__qualities span { color: var(--jsc-wine); margin-inline: 4px; }

.jsc__cta {
  display: inline-flex;
  align-items: center;
  gap: var(--s-8);
  margin-top: clamp(20px, 2.4vw, 32px);
  padding-bottom: 7px;
  font-family: var(--font-body);
  font-size: var(--text-caption);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--jsc-wine);
  border-bottom: 1px solid var(--jsc-wine);
  transition: opacity 220ms var(--ease-out);
}
.jsc__cta:hover { opacity: 0.72; }
.jsc__cta:focus-visible { outline: 2px solid var(--jsc-wine); outline-offset: 4px; }

/* --- the corner graphic --------------------------------------------------- */
.jsc__mark {
  position: absolute;
  top: 0;
  right: 0;
  width: clamp(96px, 20%, 172px);
  height: auto;
  pointer-events: none;
  overflow: visible;
}
.jsc__blob {
  fill: var(--jsc-rose);
  transform-origin: 88% 6%;
  transition: transform 460ms var(--ease-out);
}
.jsc__bang-stem {
  stroke: var(--jsc-wine);
  stroke-width: 15;
  stroke-linecap: round;
  fill: none;
}
.jsc__bang-dot { fill: var(--jsc-wine); }

/* THE MARK MOVES DIFFERENTLY FROM THE CARD, which is the point of it.
   The card lifts two pixels and warms very slightly — the whole plate
   acknowledging the pointer. The shape swells from the corner it hangs off.
   The mark itself tilts and rises, and its dot rises further and later, so it
   reads as a thing with a bit of character rather than as part of the plate.
   Nothing bounces and nothing loops. */
.jsc__bang {
  transform-origin: 170px 127px;
  transition: transform 420ms var(--ease-out);
}
.jsc__bang-dot {
  transform-origin: 170px 127px;
  transition: transform 420ms var(--ease-out) 90ms;
}

.jsc:hover { transform: translateY(-2px); background-color: #F2E9E8; }
.jsc:hover .jsc__blob { transform: scale(1.06); }
.jsc:hover .jsc__bang { transform: rotate(-7deg) translateY(-4px); }
.jsc:hover .jsc__bang-dot { transform: translateY(4px); }

@media (max-width: 720px) {
  /* Smaller, and the heading keeps its distance. At this width the copy runs
     the whole card, so the only line that can reach the graphic is the one
     level with it — and that is the heading. The rest sit below it. */
  .jsc { border-radius: 18px; padding: var(--s-32) var(--s-24); }
  .jsc__mark { width: clamp(62px, 22%, 88px); }
  /* Both of the lines that sit level with the graphic, not just the heading:
     at 600 the body's first line reaches it too. The qualities and the call to
     action are below it and keep the full measure. */
  .jsc__title,
  .jsc__body { padding-right: 100px; }
}

@media (prefers-reduced-motion: reduce) {
  .jsc, .jsc__blob, .jsc__bang, .jsc__bang-dot, .jsc__cta { transition: none; }
  .jsc:hover { transform: none; }
  .jsc:hover .jsc__blob,
  .jsc:hover .jsc__bang,
  .jsc:hover .jsc__bang-dot { transform: none; }
}

@media (max-width: 1080px) {
  .jsx__grid { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 720px) {
  /* Three stops in 335px is three one-word columns. Stacked, each stop keeps
     its figure, its meaning and its grades together, and the rule becomes a
     vertical one down the left. */
  .jsx__rule { display: none; }
  .jsx__stops { grid-template-columns: minmax(0, 1fr); gap: var(--s-24); }
  .jsx__stop {
    padding-top: 0;
    padding-left: var(--s-32);
    text-align: left;
    border-left: 2px solid var(--ink);
  }
  .jsx__dot { top: 6px; left: -9px; margin-left: 0; }
  .jsx__who { margin-top: var(--s-8); }
  /* Under a stacked scale the drawings have nowhere to go that is not on top
     of a figure, so they step out rather than shrink to nothing. */
  .jsx__art--tofu { width: 84px; left: -12px; bottom: -48px; }
  .jsx__art--crab { width: 96px; right: -10px; bottom: -44px; }
}

@media (prefers-reduced-motion: reduce) {
  .jsx__dot, .jsx__figure, .jsx__what, .jsx__who, .jsx__for, 
  .jsx__stop:hover .jsx__dot { transform: none; }
  .jsx__stop:hover .jsx__dot::after { animation: none; }
  .jsx__stop:hover .jsx__figure,
  .jsx__stop:hover .jsx__what,
  .jsx__stop:hover .jsx__who,
  .jsx__stop:hover .jsx__for { transform: none; }
}
