/** Shopify CDN: Minification failed

Line 1477:16 Expected identifier but found whitespace
Line 1477:18 Unexpected "{"
Line 1477:28 Expected ":"
Line 1502:16 Expected identifier but found whitespace
Line 1502:17 Unexpected "'Roboto Mono'"
Line 1502:33 Unexpected "{"
Line 1502:43 Expected ":"
Line 1502:91 Expected identifier but found ","

**/
/* SHOPIFY_STYLESHEETS_VERSION: 1.0 */


/* CSS from section stylesheet tags */
/* START_SECTION:cozy-club (INDEX:13) */
/* ==========================================================
     Cozy Club
     ========================================================== */

  .cc,
  .cc * {
    letter-spacing: 0;
  }

  .cc {
    background: var(--cc-bg, #0d5b8b);
    color: var(--cc-fg, #fff);
  }

  /* Mobile is the base. 120px top and bottom is a desktop
     value; on a phone it turns the section into a screen and a
     half of empty ground. */
  .cc__panel {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--cc-pad-m, 64px) clamp(2rem, 5vw, 8rem);
  }

  @media screen and (min-width: 750px) {
    .cc__panel {
      padding: var(--cc-pad, 120px) clamp(2rem, 5vw, 8rem);
    }
  }

  .cc__inner {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: clamp(1.2rem, 2vw, 1.8rem);
    width: 100%;
  }

  .cc__eyebrow {
    margin: 0;
    font-size: var(--cc-meta, 11px);
    text-transform: uppercase;
    opacity: 0.65;
  }

  .cc__title {
    margin: 0;
    font-family: var(--cc-family, inherit);
    font-variation-settings: var(--cc-variation, normal);
    font-size: var(--cc-title-m, 28px);
    line-height: 0.98;
    text-transform: var(--cc-case, none);
    font-weight: 400;
    max-width: var(--cc-measure, 16ch);
    text-wrap: balance;
  }

  @media screen and (min-width: 750px) {
    .cc__title {
      font-size: var(--cc-title, 46px);
    }
  }

  .cc__body {
    margin: 0;
    font-size: var(--cc-body, 15px);
    line-height: 1.55;
    opacity: 0.85;
    max-width: 42ch;
  }

  /* ── form ───────────────────────────────────────────────── */

  .cc__form {
    margin: 0.4rem 0 0;
    width: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.9rem;
  }

  .cc__field {
    display: flex;
    max-width: 100%;
    box-sizing: border-box;
    width: min(100%, var(--cc-field-w, 440px));
    border: 1px solid var(--cc-field, #fff);
    /* Its own value: an input matching a pill button reads as a
       search box rather than a signup field. */
    border-radius: var(--cc-field-radius, 2px);
    overflow: hidden;
  }

  .cc__field input {
    flex: 1;
    min-width: 0;
    background: none;
    border: none;
    padding: 1.5rem 1.6rem;
    color: inherit;
    font-family: inherit;
    font-size: var(--cc-body, 15px);
    letter-spacing: 0;
  }

  .cc__field input::placeholder {
    color: currentColor;
    opacity: 0.5;
  }

  .cc__field input:focus {
    outline: none;
  }

  /* The ring goes on the wrapper, since the input has no border
     of its own to highlight. */
  .cc__field:focus-within {
    outline: 2px solid var(--cc-field, #fff);
    outline-offset: 2px;
  }

  /* Shape from the theme's button tokens; colour stays local. */
  .cc__btn {
    flex: 0 0 auto;
    border: none;
    padding: 0 2.2rem;
    background: var(--cc-btn-bg, #fff);
    color: var(--cc-btn-fg, #0d5b8b);
    font-family: inherit;
    font-size: var(--cc-meta, 11px);
    text-transform: var(--button-text-transform, none);
    cursor: pointer;
    transition: opacity 0.2s ease;
  }

  .cc__btn:hover {
    opacity: 0.86;
  }

  .cc__btn:focus-visible {
    outline: 2px solid var(--cc-btn-bg, #fff);
    outline-offset: 3px;
  }

  .cc__note {
    margin: 0;
    font-size: var(--cc-body, 15px);
    line-height: 1.5;
  }

  .cc__note--ok {
    padding: 1.4rem 1.8rem;
    border: 1px solid var(--cc-field, #fff);
    border-radius: 2px;
  }

  .cc__note--error {
    opacity: 0.9;
    text-decoration: underline;
    text-underline-offset: 0.3em;
  }

  /* ── sms and fine print ─────────────────────────────────── */

  /* When SMS leads, the email field is quieter: smaller, and
     introduced rather than presented as the ask. */
  .cc__aside {
    margin: 0.6rem 0 0;
    font-size: calc(var(--cc-meta, 11px) * 1.05);
    opacity: 0.7;
  }

  [data-primary='sms'] .cc__field {
    width: min(100%, calc(var(--cc-field-w, 440px) * 0.82));
  }

  [data-primary='sms'] .cc__field input {
    padding: 1.1rem 1.3rem;
    font-size: calc(var(--cc-body, 15px) * 0.94);
  }

  /* Zero vertical padding is right only while the button is
     joined to the input. Scoped to that layout, because two
     selectors here outrank the single class in the mobile rule
     no matter which comes later, and the stacked button
     collapsed to line height. */
  @media screen and (min-width: 481px) {
    [data-primary='sms'] .cc__btn {
      padding: 0 1.7rem;
    }
  }

  [data-primary='sms'] .cc__form {
    opacity: 0.9;
  }

  /* An underlined link rather than a filled button. A solid pill
     the width of a phone number dominates the section, and the
     email field below it then reads as the more considered of
     the two, which is the opposite of the intent. */
  .cc__sms-btn {
    display: inline-block;
    font-size: var(--cc-sms-size, 22px);
    line-height: 1.3;
    color: inherit;
    text-decoration: none;
    border-bottom: 1px solid currentColor;
    padding-bottom: 0.5rem;
    transition: opacity 0.2s ease;
  }

  .cc__sms-btn:hover {
    opacity: 0.7;
  }

  .cc__sms-btn:focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 4px;
  }

  @media screen and (max-width: 749px) {
    .cc__sms-btn {
      font-size: var(--cc-sms-size-m, 18px);
    }
  }

  .cc__sms {
    margin: 0;
    font-size: var(--cc-meta, 11px);
    text-transform: uppercase;
    opacity: 0.75;
  }

  .cc__sms a {
    color: inherit;
    text-decoration: none;
    border-bottom: 1px solid currentColor;
    padding-bottom: 0.2rem;
  }

  .cc__sms a:hover {
    opacity: 0.7;
  }

  .cc__fine {
    margin: 0.4rem 0 0;
    font-size: calc(var(--cc-meta, 11px) * 0.95);
    opacity: 0.5;
    max-width: 46ch;
  }

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

  /* ── split ──────────────────────────────────────────────── */

  .cc__media {
    background: rgba(0, 0, 0, 0.12);
    overflow: hidden;
  }

  .cc__img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
  }

  @media screen and (min-width: 900px) {
    [data-layout='split'] {
      display: grid;
      grid-template-columns: 1fr var(--cc-split, 45%);
    }

    [data-layout='split'] .cc__panel { grid-column: 1; grid-row: 1; }
    [data-layout='split'] .cc__media { grid-column: 2; grid-row: 1; }

    [data-layout='split'][data-media-side='left'] {
      grid-template-columns: var(--cc-split, 45%) 1fr;
    }

    [data-layout='split'][data-media-side='left'] .cc__panel { grid-column: 2; }
    [data-layout='split'][data-media-side='left'] .cc__media { grid-column: 1; }

    [data-layout='split'] .cc__inner {
      align-items: flex-start;
      text-align: left;
    }
  }

  @media screen and (max-width: 899px) {
    [data-layout='split'] .cc__media {
      min-height: 40svh;
    }
  }

  /* On a phone the button sits under the field rather than
     squeezing it to nothing. */
  @media screen and (max-width: 480px) {
    /* Stacked, so the field is no longer a joined control. The
       radius and overflow exist to clip the input and button
       into one pill on desktop; left in place here they clip
       the children instead, cutting the input's top edge and
       corners. */
    .cc__field {
      flex-direction: column;
      border: none;
      border-radius: 0;
      overflow: visible;
      gap: 0.7rem;
    }

    .cc__field input {
      border: 1px solid var(--cc-field, #fff);
      border-radius: var(--cc-field-radius, 2px);
    }

    .cc__btn,
    [data-primary='sms'] .cc__btn {
      padding: 1.4rem 2.2rem;
      border-radius: var(--button-border-radius, 2px);
    }

    .cc__field:focus-within {
      outline: none;
    }

    .cc__field input:focus-visible {
      outline: 2px solid var(--cc-field, #fff);
      outline-offset: 2px;
    }
  }
/* END_SECTION:cozy-club */

/* START_SECTION:feature (INDEX:20) */
/* ==========================================================
     Feature
     ========================================================== */

  /* Nothing in this section inherits tracking from the theme.
     Elements that set their own via a variable still win, since
     they come later in the sheet. */
  .ft,
  .ft * {
    letter-spacing: 0;
  }

  .ft {
    position: relative;
    background: var(--ft-bg, #f4efe5);
    color: var(--ft-fg, #1a1815);
    transition: background-color var(--ft-hover-speed, 500ms) ease,
      color var(--ft-hover-speed, 500ms) ease;
  }

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

  /* ── media ──────────────────────────────────────────────── */

  .ft__media {
    position: relative;
    background: var(--ft-media-bg, #eae4d8);
    overflow: hidden;
  }

  .ft__still,
  .ft__video {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
  }

  .ft__video {
    position: absolute;
    inset: 0;
  }

  .ft__still--empty {
    min-height: 100%;
    background: linear-gradient(160deg, #eae4d8, #d8d0c0);
  }

  @media (prefers-reduced-motion: reduce) {
    .ft__video { display: none; }
  }

  .ft__scrim {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, var(--ft-scrim, 0.3));
    pointer-events: none;
  }

  /* ── panel ──────────────────────────────────────────────── */

  .ft__panel {
    display: flex;
    align-items: center;
    padding: var(--ft-pad, 110px) clamp(2rem, 5vw, 8rem);
  }

  .ft__inner {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: clamp(1.4rem, 2.2vw, 2.2rem);
    width: 100%;
  }

  [data-align='center'] .ft__inner {
    align-items: center;
    text-align: center;
  }

  .ft__eyebrow {
    margin: 0;
    font-size: var(--ft-meta, 11px);
    letter-spacing: 0;
    text-transform: uppercase;
    opacity: 0.6;
  }

  .ft__title {
    margin: 0;
    font-family: var(--ft-family, inherit);
    font-variation-settings: var(--ft-variation, normal);
    font-size: calc(var(--ft-title-m, 30px) * var(--ft-scale, 1));
    line-height: 0.98;
    letter-spacing: 0;
    text-transform: var(--ft-case, none);
    font-weight: 400;
    max-width: var(--ft-measure, 18ch);
    text-wrap: balance;
  }

  @media screen and (min-width: 750px) {
    .ft__title {
      font-size: calc(var(--ft-title, 54px) * var(--ft-scale, 1));
    }
  }

  .ft__body {
    margin: 0;
    font-size: var(--ft-body, 16px);
    line-height: 1.6;
    letter-spacing: 0;
    max-width: 50ch;
  }

  .ft__body--muted {
    opacity: 0.68;
  }

  .ft__body p {
    margin: 0 0 0.9em;
  }

  .ft__body p:last-child {
    margin-bottom: 0;
  }


  .ft__actions {
    display: flex;
    align-items: center;
    gap: clamp(1rem, 2vw, 1.8rem);
    flex-wrap: wrap;
    margin-top: 0.4rem;
  }

  /* Carries the theme's own .theme-button class, so it matches
     every other button on the site. Colour comes from the
     theme's button variables, set above from the section's
     settings, so the hover swap can still recolour it. */
  .ft__btn {
    text-decoration: none;
  }

  /* Follows the theme's button case. */
  .ft__link {
    font-size: var(--ft-meta, 11px);
    letter-spacing: 0;
    text-transform: var(--button-text-transform, none);
    color: var(--ft-fg, #1a1815);
    text-decoration: none;
    border-bottom: 1px solid currentColor;
    padding-bottom: 0.4rem;
    transition: opacity 0.2s ease;
  }

  .ft__link:hover { opacity: 0.65; }

  .ft__btn:focus-visible,
  .ft__link:focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 3px;
  }

  /* A band across the foot of the section: this row is what is
     actually in the box, so it gets its own space rather than
     sitting inside the copy column. */
  .ft__strip {
    grid-column: 1 / -1;
    padding: 0 clamp(2rem, 5vw, 8rem) var(--ft-pad, 110px);
    background: var(--ft-bg, #f4efe5);
  }

  /* Set like the side of the box: small, factual, hairline
     separated. Answers what a sampler buyer actually asks. */
  .ft__spec {
    margin: 0;
    padding: 0;
    border-top: 1px solid currentColor;
    width: 100%;
    max-width: var(--ft-spec-max, 540px);
  }

  .ft__strip .ft__spec {
    max-width: none;
    display: grid;
    grid-template-columns: repeat(var(--ft-spec-cols, 3), minmax(0, 1fr));
    column-gap: clamp(2rem, 4vw, 5rem);
    border-top: 1px solid currentColor;
  }

  .ft__spec-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    flex-wrap: nowrap;
    gap: 1.6rem;
    padding: 0.95rem 0;
    border-bottom: 1px solid currentColor;
  }

  .ft__spec dt a {
    color: inherit;
    text-decoration: none;
    border-bottom: 1px solid transparent;
    transition: border-color 0.2s ease;
  }

  .ft__spec dt a:hover {
    border-bottom-color: currentColor;
  }

  .ft__strip .ft__spec-row {
    flex-direction: column;
    justify-content: flex-start;
    gap: 0.5rem;
    padding: 1.4rem 1.6rem 1.6rem 0;
    border-bottom: none;
  }

  /* Sized on its own rather than inheriting the body size: the
     row is a list, not prose, and it reads better tighter. */
  .ft__spec dt {
    margin: 0;
    flex: 0 1 auto;
    min-width: 0;
    font-size: var(--ft-name-m, 13px);
    line-height: 1.4;
    letter-spacing: 0;
    white-space: nowrap;
  }

  @media screen and (min-width: 750px) {
    .ft__spec dt {
      font-size: var(--ft-name, 15px);
    }
  }

  /* One row, one line. The 26ch cap that used to sit here forced
     a wrap even with several hundred pixels free in the row. */
  .ft__spec dd {
    margin: 0;
    font-size: calc(var(--ft-name-m, 13px) * var(--ft-notes-scale, 0.85));
    line-height: 1.45;
    letter-spacing: 0;
    text-align: right;
    max-width: none;
    min-width: 0;
  }

  @media screen and (min-width: 750px) {
    .ft__spec dd {
      font-size: calc(var(--ft-name, 15px) * var(--ft-notes-scale, 0.85));
    }
  }

  @media screen and (min-width: 900px) {
    .ft__spec dd {
      white-space: nowrap;
    }
  }

  .ft__strip .ft__spec dd {
    text-align: left;
    max-width: none;
  }

  @media screen and (max-width: 749px) {
    .ft__strip .ft__spec {
      grid-template-columns: 1fr;
    }

    .ft__strip .ft__spec-row {
      padding: 1.1rem 0;
      border-bottom: 1px solid currentColor;
    }
  }

  @media screen and (max-width: 899px) {
    .ft__strip {
      padding-top: clamp(2rem, 6vw, 3.4rem);
    }
  }

  /* ── split ──────────────────────────────────────────────── */

  @media screen and (min-width: 900px) {
    [data-layout='split'] {
      display: grid;
      grid-template-columns: var(--ft-split, 50%) 1fr;
      min-height: calc(var(--ft-min-h, 76) * 1svh);
    }

    [data-layout='split'] .ft__media { grid-column: 1; grid-row: 1; }
    [data-layout='split'] .ft__panel { grid-column: 2; grid-row: 1; }
    [data-layout='split'] .ft__strip { grid-column: 1 / -1; grid-row: 2; }

    [data-layout='split'][data-media-side='right'] {
      grid-template-columns: 1fr var(--ft-split, 50%);
    }

    [data-layout='split'][data-media-side='right'] .ft__media { grid-column: 2; }
    [data-layout='split'][data-media-side='right'] .ft__panel { grid-column: 1; }
  }

  /* Below 900 a split stacks: media on top, copy under it.

     min-height is not a definite height, so height: 100% on the
     image resolved to auto and left the image sitting at its
     natural size inside a taller box. Letting the container wrap
     the image removes the gap and avoids cropping.

     A video cannot size a container that way, so a slide using
     one keeps a fixed height and fills it. */
  @media screen and (max-width: 899px) {
    [data-layout='split'] .ft__media,
    [data-layout='stack'] .ft__media {
      min-height: 0;
    }

    [data-layout='split'] .ft__still,
    [data-layout='stack'] .ft__still {
      height: auto;
    }

    [data-layout='split'] .ft__media:has(.ft__video),
    [data-layout='stack'] .ft__media:has(.ft__video) {
      min-height: 52svh;
    }

    [data-layout='split'] .ft__media:has(.ft__video) .ft__still,
    [data-layout='stack'] .ft__media:has(.ft__video) .ft__still {
      height: 100%;
    }

    /* The empty placeholder has no intrinsic size at all. */
    [data-layout='split'] .ft__still--empty,
    [data-layout='stack'] .ft__still--empty {
      min-height: 52svh;
    }
  }

  /* ── statement ──────────────────────────────────────────── */

  [data-layout='statement'] {
    display: grid;
    min-height: calc(var(--ft-min-h, 76) * 1svh);
  }

  [data-layout='statement'] .ft__media,
  [data-layout='statement'] .ft__panel {
    grid-column: 1;
    grid-row: 1;
  }

  [data-layout='statement'] .ft__panel {
    justify-content: center;
    color: #fff;
    z-index: 2;
  }

  [data-layout='statement'] .ft__inner {
    align-items: center;
    text-align: center;
  }

  [data-layout='statement'] .ft__title {
    color: #fff;
  }

  /* ── stack ──────────────────────────────────────────────── */

  @media screen and (min-width: 900px) {
    [data-layout='stack'] .ft__media {
      min-height: 54svh;
    }
  }

  [data-layout='stack'] .ft__inner {
    align-items: center;
    text-align: center;
    margin: 0 auto;
    max-width: 62ch;
  }

  /* ── text only ──────────────────────────────────────────── */

  [data-layout='text'] .ft__panel {
    min-height: auto;
  }
/* END_SECTION:feature */

/* START_SECTION:hero (INDEX:33) */
/* ==========================================================
     Hero
     Two layouts per slide, driven by data-layout. Overlay is
     full-bleed media with the panel on top; split is a two
     column grid where the panel is a colour block.
     ========================================================== */

  /* Nothing in this section inherits tracking from the theme.
     Elements that set their own via a variable still win, since
     they come later in the sheet. */
  .hero,
  .hero * {
    letter-spacing: 0;
  }

  .hero {
    position: relative;
    min-height: calc(var(--hero-h, 90) * 1svh);
    overflow: hidden;
    background: #1a1815;
    isolation: isolate;
  }

  /* Grid stacking rather than absolute positioning. Absolutely
     positioned slides contribute no height, so only the first
     one sized the section and anything taller on another slide
     was clipped. Overlapping in one grid cell keeps the
     crossfade and lets the container size to the tallest. */
  .hero__slides {
    position: relative;
    display: grid;
    grid-template-columns: 1fr;
    min-height: inherit;
  }

  /* Slides stack; only the active one is visible. The first sits
     in normal flow so the section has height before JS runs. */
  .hero__slide {
    grid-area: 1 / 1;
    position: relative;
    min-height: calc(var(--hero-h, 90) * 1svh);
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--hero-fade, 700ms) ease,
      visibility 0s linear var(--hero-fade, 700ms);
    color: var(--slide-fg, #f4efe5);
  }

  .hero__slide.is-active {
    opacity: 1;
    visibility: visible;
    transition: opacity var(--hero-fade, 700ms) ease, visibility 0s;
    z-index: 1;
  }

  /* ── media ──────────────────────────────────────────────── */

  .hero__media {
    position: absolute;
    inset: 0;
    z-index: 0;
    overflow: hidden;
  }

  .hero__still,
  .hero__video {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
  }

  .hero__still {
    z-index: 0;
  }

  /* Above the still, so a blocked or failed video falls back to
     the image already painted underneath. */
  .hero__video {
    z-index: 1;
  }

  .hero__still--empty {
    background: linear-gradient(160deg, #2b381c, #1a1815);
  }

  @media (prefers-reduced-motion: reduce) {
    .hero__video {
      display: none;
    }
  }

  .hero__scrim {
    position: absolute;
    inset: 0;
    z-index: 2;
    background: linear-gradient(
      180deg,
      rgba(0, 0, 0, var(--slide-scrim-top, 0.35)) 0%,
      transparent 30%,
      transparent 46%,
      rgba(0, 0, 0, var(--slide-scrim-bottom, 0.65)) 100%
    );
    pointer-events: none;
  }

  /* ── panel ──────────────────────────────────────────────── */

  .hero__panel {
    position: relative;
    z-index: 3;
    height: 100%;
    min-height: inherit;
    display: flex;
    flex-direction: column;
  }

  .hero__content {
    flex: 1;
    display: flex;
    padding: clamp(2rem, 5vw, 8rem);
  }

  .hero__text {
    max-width: 100%;
  }

  /* nine-point placement */
  [data-pos^='top'] .hero__content { align-items: flex-start; }
  [data-pos^='center'] .hero__content { align-items: center; }
  [data-pos^='bottom'] .hero__content { align-items: flex-end; }
  [data-pos$='left'] .hero__content { justify-content: flex-start; text-align: left; }
  [data-pos$='center'] .hero__content { justify-content: center; text-align: center; }
  [data-pos='center'] .hero__content { justify-content: center; text-align: center; }
  [data-pos$='right'] .hero__content { justify-content: flex-end; text-align: right; }

  [data-pos$='center'] .hero__title,
  [data-pos='center'] .hero__title {
    margin-left: auto;
    margin-right: auto;
  }

  /* ── split layout ───────────────────────────────────────── */

  @media screen and (min-width: 900px) {
    [data-layout='split'] {
      display: grid;
      grid-template-columns: var(--slide-split, 50%) 1fr;
    }

    [data-layout='split'] .hero__media {
      position: relative;
      inset: auto;
      grid-column: 2;
      grid-row: 1;
    }

    [data-layout='split'] .hero__panel {
      grid-column: 1;
      grid-row: 1;
      background: var(--slide-panel, #2b381c);
    }

    [data-layout='split'][data-media-side='left'] {
      grid-template-columns: 1fr var(--slide-split, 50%);
    }

    [data-layout='split'][data-media-side='left'] .hero__media { grid-column: 1; }
    [data-layout='split'][data-media-side='left'] .hero__panel { grid-column: 2; }
  }

  /* Below 900 a split slide stacks: media on top, colour block
     under it. A half-width column of type is unreadable on a
     phone. */
  @media screen and (max-width: 899px) {
    /* A stacked split is media plus copy, so a viewport minimum
       just adds dead space under the button. Overlay slides keep
       theirs, since they have nothing else to give them height.
       The grid sizes to the tallest slide either way. */
    .hero {
      min-height: 0;
    }

    /* Mobile gets its own height. A viewport share that reads
       well on a wide screen is proportionally taller on a phone,
       where the screen is already long. */
    .hero__slide {
      min-height: calc(var(--hero-h-m, 80) * 1svh);
    }

    [data-layout='overlay'] {
      min-height: calc(var(--hero-h-m, 80) * 1svh);
    }

    /* Targets the mobile height rather than being purely content
       sized. The copy takes what it needs and the image absorbs
       whatever is left, down to its minimum, so the slide only
       grows past the target when the copy genuinely requires it.

       Without this the split slide was always the tallest, and
       since the grid sizes to the tallest slide, the mobile
       height setting appeared to do nothing. */
    [data-layout='split'] {
      min-height: calc(var(--hero-h-m, 80) * 1svh);
      display: flex;
      flex-direction: column;
    }

    /* The image is the flexible part: it crops to whatever is
       left after the copy, never below its minimum. The copy is
       never compressed. */
    [data-layout='split'] .hero__media {
      position: relative;
      inset: auto;
      flex: 1 1 auto;
      height: auto;
      min-height: var(--slide-media-h, 30svh);
    }

    [data-layout='split'] .hero__panel {
      flex: 0 0 auto;
      background: var(--slide-panel, #2b381c);
    }

    [data-layout='split'] .hero__content {
      padding: clamp(2rem, 6vw, 3.4rem);
    }
  }


  /* ── type ───────────────────────────────────────────────── */

  .hero__title {
    margin: 0;
    font-family: var(--hero-family, inherit);
    font-variation-settings: var(--hero-variation, normal);
    font-size: calc(var(--hero-title-m, 48px) * var(--slide-scale, 1));
    line-height: 0.9;
    letter-spacing: var(--hero-tracking, 0);
    text-transform: var(--hero-case, none);
    font-weight: 400;
    max-width: var(--slide-measure, 14ch);
    text-wrap: balance;
  }

  @media screen and (min-width: 750px) {
    .hero__title {
      font-size: calc(var(--hero-title, 120px) * var(--slide-scale, 1));
    }
  }

  /* Supporting line, then the buttons under it. Side by side,
     the sub and the button competed for the same eyeline and the
     button lost. */
  .hero__foot {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: clamp(1.4rem, 2.4vw, 2.2rem);
    margin-top: clamp(1rem, 1.6vw, 1.8rem);
  }

  [data-pos$='center'] .hero__foot,
  [data-pos='center'] .hero__foot { align-items: center; }
  [data-pos$='right'] .hero__foot { align-items: flex-end; }

  .hero__sub {
    margin: 0;
    font-size: calc(var(--hero-meta, 11px) * 1.05);
    letter-spacing: 0;
    line-height: 1.5;
    opacity: 0.9;
    max-width: var(--slide-sub-measure, 52ch);
  }

  .hero__actions {
    display: flex;
    align-items: center;
    gap: clamp(1rem, 2vw, 1.8rem);
    flex-wrap: wrap;
  }

  /* Carries the theme's own .theme-button class, so shape, size,
     padding and case all come from the theme and stay in step
     with it. Only the colour is overridden, per slide, because
     the theme's palette cannot know what is behind a button
     sitting on a photograph. That override is done by setting
     the theme's own button colour variables on the slide, so no
     colour is declared here at all. */
  .hero__btn {
    text-decoration: none;
  }

  /* Follows the theme's button case, so the pair never end up
     one uppercase and one not. */
  .hero__link {
    font-size: var(--hero-meta, 11px);
    letter-spacing: 0;
    text-transform: var(--button-text-transform, none);
    color: var(--slide-link, inherit);
    text-decoration: none;
    border-bottom: 1px solid currentColor;
    padding-bottom: 0.4rem;
    transition: opacity 0.2s ease;
  }

  .hero__link:hover { opacity: 0.7; }

  .hero__btn:focus-visible {
    outline: 2px solid var(--slide-btn-bg, #f4efe5);
    outline-offset: 3px;
  }

  .hero__link:focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 3px;
  }

  /* ── controls ───────────────────────────────────────────── */

  /* A dashed rule: one dash per slide, no container, no frost.
     The controls should read as a caption, not a widget. */
  /* Offset and side are settings, because where the controls can
     sit depends on whether the slide carries a card and where the
     copy is anchored. */
  .hero__controls {
    position: absolute;
    z-index: 6;
    bottom: var(--hero-controls-offset, 20px);
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    align-items: center;
    gap: 14px;
    color: var(--hero-controls, #fff);
  }

  [data-controls-align='left'] .hero__controls {
    left: clamp(2rem, 5vw, 8rem);
    right: auto;
    transform: none;
  }

  [data-controls-align='right'] .hero__controls {
    left: auto;
    right: clamp(2rem, 5vw, 8rem);
    transform: none;
  }

  /* The controls, the card and the copy are all anchored to the
     bottom independently, so moving one does not make room in
     the others. This reserves a band along the foot that the
     content sits above, and the controls sit inside. Applied
     only when there is a slideshow, since that is the only time
     controls exist. */
  .hero.is-slideshow .hero__content {
    padding-bottom: calc(clamp(2rem, 5vw, 8rem) + var(--hero-controls-band, 56px));
  }

  .hero.is-slideshow [data-card-pos='bottom-right'],
  .hero.is-slideshow [data-card-pos='bottom-left'] {
    bottom: calc(var(--card-offset, 28px) + var(--hero-controls-band, 56px));
  }

  @media screen and (max-width: 749px) {
    .hero__controls {
      bottom: var(--hero-controls-offset-m, 20px);
    }

    .hero.is-slideshow .hero__content {
      padding-bottom: calc(clamp(2rem, 5vw, 8rem) + var(--hero-controls-band-m, 48px));
    }

    .hero.is-slideshow .hero__card {
      bottom: calc(var(--card-offset-m, 16px) + var(--hero-controls-band-m, 48px));
    }

    /* On a phone the card spans the width along the bottom, so
       edge alignment would put the controls on top of it. */
    [data-controls-align='left'] .hero__controls,
    [data-controls-align='right'] .hero__controls {
      left: 50%;
      right: auto;
      transform: translateX(-50%);
    }
  }

  .hero__dots {
    display: flex;
    align-items: center;
    gap: 7px;
  }

  /* Two styles. Numbers is the default because a button with text
     content always renders: it cannot collapse to nothing the way
     an empty element can when a size declaration fails. */
  .hero__dot {
    position: relative;
    padding: 0;
    border: none;
    background: none;
    -webkit-appearance: none;
    appearance: none;
    color: var(--hero-controls, #fff);
    opacity: 0.45;
    cursor: pointer;
    transition: opacity 0.3s ease;
    font-family: inherit;
    line-height: 1;
  }

  [data-style='numbers'] .hero__dot {
    font-size: calc(var(--hero-meta, 11px) * 0.95);
    letter-spacing: 0;
    padding: 6px 7px;
    font-variant-numeric: tabular-nums;
  }

  [data-style='dashes'] .hero__dot {
    display: block;
    width: 28px;
    height: 2px;
    min-width: 16px;
    min-height: 2px;
    flex: 0 0 auto;
    background: var(--hero-controls, #fff);
  }

  .hero__dot.is-active {
    opacity: 1;
  }

  /* The dash carries no text, so it needs a padded hit area. */
  [data-style='dashes'] .hero__dot::before {
    content: '';
    position: absolute;
    inset: -12px -3px;
  }

  .hero__dot:focus-visible {
    opacity: 1;
    outline: 1px solid var(--hero-controls, #fff);
    outline-offset: 4px;
  }

  .hero__arrow {
    position: relative;
    width: 14px;
    height: 14px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: none;
    border-radius: 0;
    background: none;
    color: var(--hero-controls, #fff);
    opacity: 0.5;
    cursor: pointer;
    transition: opacity 0.25s ease;
  }

  .hero__arrow::before {
    content: '';
    position: absolute;
    inset: -12px;
  }

  .hero__arrow:hover {
    opacity: 1;
  }

  .hero__arrow:focus-visible {
    opacity: 1;
    outline: 1px solid var(--hero-controls, #fff);
    outline-offset: 6px;
  }

  @media screen and (max-width: 749px) {
    /* Mobile placement overrides desktop when a slide sets one. */
    [data-pos-m^='top'] .hero__content { align-items: flex-start; }
    [data-pos-m^='center'] .hero__content { align-items: center; }
    [data-pos-m^='bottom'] .hero__content { align-items: flex-end; }
    [data-pos-m$='left'] .hero__content { justify-content: flex-start; text-align: left; }
    [data-pos-m$='center'] .hero__content,
    [data-pos-m='center'] .hero__content { justify-content: center; text-align: center; }

    [data-pos-m$='left'] .hero__foot { align-items: flex-start; }
    [data-pos-m$='center'] .hero__foot,
    [data-pos-m='center'] .hero__foot { align-items: center; }

    [data-pos-m$='center'] .hero__title,
    [data-pos-m='center'] .hero__title { margin-left: auto; margin-right: auto; }

    /* The card spans the width along the bottom on mobile, so
       bottom-anchored text has to clear it. */
    .hero__slide.has-card[data-pos^='bottom'] .hero__content,
    .hero__slide.has-card[data-pos-m^='bottom'] .hero__content {
      padding-bottom: calc(var(--hero-card-clear, 150px) + 1rem);
    }

    .hero__foot { gap: 1.3rem; }

    .hero__btn { padding: 1.4rem 2.2rem; }
  }

  /* ── frosted product card ───────────────────────────────── */

  .hero__card {
    position: absolute;
    z-index: 5;
    width: min(var(--card-w, 320px), calc(100% - 3rem));
    display: flex;
    flex-direction: column;
    gap: 0.9rem;
    padding: 1.4rem;
    /* Its own value: a pill button radius would turn the card
       into a lozenge. */
    border-radius: var(--card-radius, 4px);
    border: none;
    background: var(--card-tint, rgba(255, 255, 255, 0.18));
    color: var(--card-fg, #fff);
    text-decoration: none;
    overflow: hidden;
    transition: transform 0.4s cubic-bezier(0.2, 0, 0.2, 1);
  }

  /* The frost itself. Where backdrop-filter is unsupported the
     tint alone still gives a readable panel, so this is layered
     rather than depended on. */
  @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
    .hero__card {
      -webkit-backdrop-filter: blur(var(--card-blur, 18px)) saturate(1.3);
      backdrop-filter: blur(var(--card-blur, 18px)) saturate(1.3);
    }
  }

  .hero__card:hover {
    transform: translateY(-3px);
  }

  .hero__card:focus-visible {
    outline: 2px solid var(--card-fg, #fff);
    outline-offset: 4px;
  }

  [data-card-pos='bottom-right'] { right: var(--card-inset, 26px); bottom: var(--card-offset, 28px); }
  [data-card-pos='bottom-left']  { left:  var(--card-inset, 26px); bottom: var(--card-offset, 28px); }
  [data-card-pos='top-right']    { right: var(--card-inset, 26px); top:    var(--card-offset, 28px); }
  [data-card-pos='top-left']     { left:  var(--card-inset, 26px); top:    var(--card-offset, 28px); }

  .hero__card-hint {
    position: absolute;
    z-index: 5;
    width: min(var(--card-w, 320px), calc(100% - 3rem));
    margin: 0;
    padding: 1.1rem 1.3rem;
    border: 1px dashed rgba(255, 255, 255, 0.5);
    border-radius: 4px;
    background: rgba(0, 0, 0, 0.45);
    color: #fff;
    font-size: 1.2rem;
    line-height: 1.5;
  }

  .hero__card-label {
    font-size: calc(var(--hero-meta, 11px) * 0.9);
    letter-spacing: 0;
    text-transform: uppercase;
    opacity: 0.75;
  }

  .hero__card-media {
    display: block;
    width: 100%;
    aspect-ratio: 1 / 1;
    overflow: hidden;
    border-radius: 2px;
  }

  .hero__card-img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
  }

  .hero__card-body {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
  }

  /* Always caps, regardless of the heading case setting: the
     card is a label, not a headline. */
  .hero__card-name {
    font-family: var(--hero-family, inherit);
    font-variation-settings: var(--hero-variation, normal);
    font-size: var(--card-name-m, 30px);
    line-height: 0.98;
    text-transform: uppercase;
  }

  @media screen and (min-width: 750px) {
    .hero__card-name {
      font-size: var(--card-name, 42px);
    }
  }

  /* Notes run longer than a fixed descriptor, so this wraps
     rather than sitting on one forced line. */
  .hero__card-desc {
    font-size: calc(var(--hero-meta, 11px) * 0.9);
    letter-spacing: 0;
    line-height: 1.5;
    opacity: 0.75;
  }

  .hero__card-foot {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    padding-top: 0.9rem;
    border-top: 1px solid rgba(255, 255, 255, 0.22);
    font-size: calc(var(--hero-meta, 11px) * 0.95);
    letter-spacing: 0;
  }

  .hero__card-cta {
    text-transform: uppercase;
    opacity: 0.8;
  }

  .hero__card-price {
    font-variant-numeric: tabular-nums;
  }

  /* On a phone the card spans the width at the bottom rather
     than floating in a corner, where it would cover the frame. */
  @media screen and (max-width: 749px) {
    .hero__card {
      left: 1rem;
      right: 1rem;
      bottom: var(--card-offset-m, 16px);
      top: auto;
      width: auto;
      flex-direction: row;
      align-items: center;
      gap: 1rem;
      padding: 1rem;
      flex-wrap: wrap;
    }

    .hero__card-media {
      width: 68px;
      flex: 0 0 auto;
    }

    .hero__card-body { flex: 1; min-width: 0; }
    .hero__card-hint {
    position: absolute;
    z-index: 5;
    width: min(var(--card-w, 320px), calc(100% - 3rem));
    margin: 0;
    padding: 1.1rem 1.3rem;
    border: 1px dashed rgba(255, 255, 255, 0.5);
    border-radius: 4px;
    background: rgba(0, 0, 0, 0.45);
    color: #fff;
    font-size: 1.2rem;
    line-height: 1.5;
  }

  .hero__card-label { width: 100%; }

    .hero__card-name { font-size: var(--card-name-m, 30px); }

    .hero__card-foot {
      width: 100%;
      padding-top: 0.7rem;
    }
  }

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

  .hero__empty {
    padding: 6rem 2rem;
    text-align: center;
    opacity: 0.6;
  }
/* END_SECTION:hero */

/* START_SECTION:journal (INDEX:37) */
/* ==========================================================
     Journal
     ========================================================== */

  .jr {
    background: var(--jr-bg, #f4efe5);
    color: var(--jr-fg, #1a1815);
    padding: var(--jr-pad, 100px) 0;
    font-family: {{ settings.type_body_font.family | default: 'Roboto, sans-serif' }};
  }

  .jr__inner {
    padding: 0 clamp(2rem, 5vw, 8rem);
  }

  .jr__head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 2rem;
    flex-wrap: wrap;
    padding-bottom: clamp(1.4rem, 2.4vw, 2rem);
    border-bottom: 1px solid var(--jr-rule, #000);
  }

  /* Section label and meta always sit in the supporting mono
     face, tracked out like a caption — never the display font
     used for post titles, and never whatever serif the theme
     assigns h2 elements by default. */
  .jr__heading,
  .jr__more,
  .jr__meta,
  .jr__readmore {
    font-family: 'Roboto Mono', {{ settings.type_body_font.family | default: 'monospace' }}, monospace;
    letter-spacing: 0.06em;
  }

  .jr__heading {
    margin: 0;
    font-size: var(--jr-heading, 12px);
    font-weight: 400;
    text-transform: uppercase;
    opacity: 0.55;
  }

  .jr__more {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    font-size: var(--jr-meta, 11px);
    text-transform: uppercase;
    color: inherit;
    text-decoration: none;
  }

  .jr__more-label {
    border-bottom: 1px solid currentColor;
    padding-bottom: 0.3rem;
  }

  .jr__more-arrow {
    display: inline-flex;
    transition: transform 0.25s cubic-bezier(0.2, 0, 0.2, 1);
  }

  .jr__more:hover .jr__more-arrow {
    transform: translateX(4px);
  }

  /* ── list ───────────────────────────────────────────────── */

  .jr__list {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--jr-gap, 48px);
    list-style: none;
    margin: 0;
    padding: clamp(2rem, 3.4vw, 3rem) 0 0;
  }

  @media screen and (min-width: 750px) {
    .jr__list {
      grid-template-columns: repeat(var(--jr-cols, 3), minmax(0, 1fr));
    }

    [data-show-divider='true'] .jr__item {
      position: relative;
    }

    [data-show-divider='true'] .jr__item::before {
      content: '';
      position: absolute;
      left: calc(var(--jr-gap, 48px) / -2);
      top: 0.2em;
      bottom: 0.2em;
      width: 1px;
      background: var(--jr-rule, #000);
      opacity: 0.15;
    }

    /* Custom properties can't drive nth-child formulas, so the
       first column in each row is set explicitly per column
       count and its divider suppressed. */
    [data-show-divider='true'][data-cols='1'] .jr__item::before { content: none; }
    [data-show-divider='true'][data-cols='2'] .jr__item:nth-child(2n+1)::before { content: none; }
    [data-show-divider='true'][data-cols='3'] .jr__item:nth-child(3n+1)::before { content: none; }
    [data-show-divider='true'][data-cols='4'] .jr__item:nth-child(4n+1)::before { content: none; }
  }

  .jr__link {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    color: inherit;
    text-decoration: none;
  }

  .jr__media {
    display: block;
    margin-bottom: 0.6rem;
    overflow: hidden;
    border-radius: 2px;
    background: rgba(0, 0, 0, 0.06);
  }

  .jr__img {
    width: 100%;
    height: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    display: block;
    transition: transform 0.7s cubic-bezier(0.2, 0, 0.2, 1);
  }

  @media (hover: hover) {
    .jr__link:hover .jr__img {
      transform: scale(1.03);
    }
  }

  .jr__meta {
    display: flex;
    align-items: baseline;
    gap: 0.9rem;
    font-size: var(--jr-meta, 11px);
    text-transform: uppercase;
    opacity: 0.5;
  }

  .jr__title {
    display: block;
    font-family: var(--jr-family, inherit);
    font-variation-settings: var(--jr-variation, normal);
    letter-spacing: 0;
    font-size: var(--jr-title-m, 16px);
    line-height: 1.32;
    font-weight: 400;
  }

  @media screen and (min-width: 750px) {
    .jr__title {
      font-size: var(--jr-title, 17px);
    }
  }

  .jr__link:hover .jr__title {
    text-decoration: underline;
    text-underline-offset: 0.22em;
  }

  .jr__excerpt {
    display: block;
    font-size: var(--jr-excerpt, 14px);
    line-height: 1.55;
    opacity: 0.62;
    letter-spacing: 0;
  }

  .jr__readmore {
    display: block;
    margin-top: 0.2rem;
    font-size: var(--jr-meta, 11px);
    text-transform: uppercase;
    opacity: 0;
    transform: translateY(-2px);
    transition: opacity 0.2s ease, transform 0.2s ease;
  }

  .jr__link:hover .jr__readmore {
    opacity: 0.55;
    transform: translateY(0);
  }

  .jr__link:focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 6px;
  }

  .jr__empty {
    padding: 3rem 0;
    opacity: 0.6;
    letter-spacing: 0;
  }
/* END_SECTION:journal */

/* START_SECTION:note-wall (INDEX:60) */
/* ==========================================================
     Note Wall
     Tiles rest muted and resolve to true tone on hover.
     ========================================================== */

  /* Nothing in this section inherits tracking from the theme.
     Elements that set their own via a variable still win, since
     they come later in the sheet. */
  .nw,
  .nw * {
    letter-spacing: 0;
  }

  .nw {
    background: var(--nw-bg, #1a1815);
    color: var(--nw-fg, #f4efe5);
    padding: var(--nw-pad-top, 120px) 0 var(--nw-pad-bottom, 120px);
  }

  .nw__head {
    display: flex;
    justify-content: space-between;
    align-items: flex-end;
    gap: 2rem;
    flex-wrap: wrap;
    padding: 0 clamp(2rem, 5vw, 8rem) clamp(1.6rem, 2.2vw, 2.8rem);
  }

  .nw__eyebrow {
    margin: 0 0 1.1rem;
    font-size: 1.05rem;
    letter-spacing: var(--nw-track, 0);
    text-transform: var(--nw-case, none);
    opacity: 0.6;
  }

  .nw__heading {
    margin: 0;
    font-family: var(--nw-heading-family, inherit);
    font-variation-settings: var(--nw-heading-variation, normal);
    font-size: var(--nw-heading-size-m, 44px);
    line-height: 0.94;
    text-transform: var(--nw-case, none);
    letter-spacing: 0;
    font-weight: 400;
  }

  @media screen and (min-width: 750px) {
    .nw__heading {
      font-size: var(--nw-heading-size, 88px);
    }
  }

  .nw__sub {
    margin: 0;
    font-size: 1.05rem;
    letter-spacing: 0;
    opacity: 0.6;
    max-width: none;
  }

  /* Held to one line beside the heading. The flex row would
     otherwise squeeze it into a narrow column and wrap it. */
  @media screen and (min-width: 990px) {
    .nw__sub {
      white-space: nowrap;
      flex: 0 0 auto;
    }
  }

  /* ── grid ───────────────────────────────────────────────── */

  .nw__grid {
    display: grid;
    grid-template-columns: repeat(var(--nw-cols-m, 3), minmax(0, 1fr));
    gap: var(--nw-gap, 2px);
    list-style: none;
    margin: 0;
    padding: 0 clamp(2rem, 5vw, 8rem);
  }

  /* Forty tiles three across is fourteen rows of scrolling on a
     phone. Two rows swiped sideways keeps the wall a wall, and
     matches the gesture the press rail already uses.

     Runs edge to edge by cancelling the wrapper padding and
     restoring it as scroll padding, so the first tile still
     lines up with the heading above. */
  @media screen and (max-width: 749px) {
    [data-mobile='scroll'] .nw__grid {
      grid-template-columns: none;
      grid-auto-flow: column;
      grid-auto-columns: var(--nw-tile-w, 42vw);
      grid-template-rows: repeat(var(--nw-rows-m, 2), auto);
      overflow-x: auto;
      -webkit-overflow-scrolling: touch;
      scroll-snap-type: x proximity;
      scrollbar-width: none;
      margin-left: calc(clamp(2rem, 5vw, 8rem) * -1);
      margin-right: calc(clamp(2rem, 5vw, 8rem) * -1);
      padding-left: clamp(2rem, 5vw, 8rem);
      padding-right: clamp(2rem, 5vw, 8rem);
    }

    [data-mobile='scroll'] .nw__grid::-webkit-scrollbar {
      display: none;
    }

    [data-mobile='scroll'] .nw__item {
      scroll-snap-align: center;
    }
  }

  @media screen and (min-width: 750px) {
    .nw__grid {
      grid-template-columns: repeat(var(--nw-cols, 8), minmax(0, 1fr));
    }
  }

  /* ── filter ─────────────────────────────────────────────── */

  .nw__filters {
    display: block;
    padding: 0 clamp(2rem, 5vw, 8rem) clamp(2rem, 3vw, 3.2rem);
    line-height: 2.2;
  }

  .nw__filters[hidden] {
    display: none;
  }

  .nw__filter {
    display: inline;
    font-family: inherit;
    font-size: 1.05rem;
    letter-spacing: var(--nw-track, 0);
    text-transform: var(--nw-case, none);
    padding: 0;
    border: none;
    background: none;
    color: inherit;
    opacity: 0.45;
    cursor: pointer;
    transition: opacity 0.25s ease;
  }

  .nw__filter:hover {
    opacity: 0.8;
  }

  .nw__filter[aria-pressed='true'] {
    opacity: 1;
  }

  /* Separator sits on the button but ignores the pointer, so the
     slash is never part of the click target. */
  .nw__filter:not(:last-child)::after {
    content: '/';
    margin: 0 var(--nw-filter-gap, 0.75em);
    opacity: 0.3;
    pointer-events: none;
  }

  .nw__filter:focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 3px;
  }

  /* Dimming rather than hiding keeps the grid from reflowing, so
     the wall stays one composition while it answers the query.
     Opacity only: a grayscale filter on the tile fights the
     saturation filter already on the image inside it. */
  .nw__item {
    min-width: 0;
    transition: opacity 0.45s ease;
  }

  /* Must out-specify the reveal rule further down, which sets
     opacity 1 on .is-in from four selectors deep. Without the
     second selector the class applies but nothing changes. */
  .nw .nw__item.is-muted,
  .nw[data-reveal='true'] .nw__item.is-in.is-muted {
    opacity: var(--nw-dim, 0.16);
    pointer-events: none;
  }

  .nw__item[hidden] {
    display: none;
  }

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

  .nw__tile {
    position: relative;
    display: block;
    aspect-ratio: var(--nw-ratio, 4 / 5);
    overflow: hidden;
    border-radius: var(--nw-radius, 0);
    background: rgba(255, 255, 255, 0.05);
  }

  .nw__img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    filter: saturate(var(--nw-sat, 0.55)) brightness(var(--nw-bright, 0.72));
    transition: transform 0.85s cubic-bezier(0.2, 0, 0.2, 1), filter 0.5s ease;
  }


  .nw__label {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    padding: 0.9rem;
    display: block;
    font-size: 0.95rem;
    letter-spacing: var(--nw-track, 0);
    text-transform: var(--nw-case, none);
    color: #fff;
    background: linear-gradient(transparent, rgba(0, 0, 0, 0.78));
    opacity: 0;
    transform: translateY(8px);
    transition: opacity 0.4s ease, transform 0.4s ease;
    pointer-events: none;
  }



  @media (hover: hover) {
    .nw__tile:hover .nw__img {
      transform: scale(1.06);
      filter: saturate(1) brightness(1);
    }

    .nw__tile:hover .nw__label {
      opacity: 1;
      transform: none;
    }
  }

  /* Keyboard users get the same reveal as hover. */
  .nw__tile:focus-visible {
    outline: 2px solid var(--nw-fg, #f4efe5);
    outline-offset: -3px;
  }

  .nw__tile:focus-visible .nw__img {
    filter: saturate(1) brightness(1);
  }

  .nw__tile:focus-visible .nw__label {
    opacity: 1;
    transform: none;
  }

  /* No pointer, so nothing is discoverable by hovering. */
  @media (hover: none) {
    .nw__img {
      filter: saturate(0.8) brightness(0.85);
    }

    .nw__label {
      opacity: 1;
      transform: none;
      font-size: 0.8rem;
      padding: 0.6rem;
    }

  }

  /* ── reveal ─────────────────────────────────────────────── */

  .nw[data-reveal='true'] .nw__item {
    opacity: 0;
    transform: translateY(14px);
    transition: opacity 0.7s ease, transform 0.7s cubic-bezier(0.2, 0, 0.2, 1);
  }

  .nw[data-reveal='true'] .nw__item.is-in {
    opacity: 1;
    transform: none;
  }

  /* ── foot ───────────────────────────────────────────────── */

  .nw__foot {
    padding: clamp(2.6rem, 4vw, 4.4rem) clamp(2rem, 5vw, 8rem) 0;
  }

  .nw__link {
    font-size: 1.1rem;
    letter-spacing: var(--nw-track, 0);
    text-transform: var(--nw-case, none);
    text-decoration: none;
    color: inherit;
    border-bottom: 1px solid currentColor;
    padding-bottom: 0.4rem;
    display: inline-block;
    transition: opacity 0.2s ease;
  }

  .nw__link:hover {
    opacity: 0.6;
  }

  .nw__empty {
    padding: 4rem clamp(2rem, 5vw, 8rem);
    text-align: center;
    opacity: 0.6;
  }


  @media (prefers-reduced-motion: reduce) {
    .nw__img,
    .nw__label,
    .nw[data-reveal='true'] .nw__item {
      transition: none;
      transform: none;
      opacity: 1;
    }

    .nw__label {
      opacity: 0;
    }

    .nw__tile:hover .nw__label,
    .nw__tile:focus-visible .nw__label {
      opacity: 1;
    }
  }
/* END_SECTION:note-wall */

/* START_SECTION:press-section (INDEX:63) */
/* ==========================================================
     Press
     ========================================================== */

  /* Nothing here inherits tracking from the theme. */
  .pr,
  .pr * {
    letter-spacing: 0;
  }

  .pr {
    background: var(--pr-bg, #f4efe5);
    color: var(--pr-fg, #1a1815);
    padding: var(--pr-pad, 110px) 0;
  }

  .pr__inner {
    padding: 0 clamp(2rem, 5vw, 8rem);
  }

  .pr__label {
    margin: 0 0 clamp(1.4rem, 2.4vw, 2.2rem);
    font-size: var(--pr-meta, 11px);
    text-transform: uppercase;
    opacity: 0.55;
  }

  /* ── logos ──────────────────────────────────────────────── */

  .pr__logos {
    display: grid;
    grid-template-columns: repeat(var(--pr-cols-m, 3), minmax(0, 1fr));
    gap: var(--pr-gap, 40px);
    align-items: center;
    list-style: none;
    margin: 0;
    padding: clamp(1.8rem, 3vw, 2.8rem) 0;
    border-top: 1px solid var(--pr-rule, #000);
    border-bottom: 1px solid var(--pr-rule, #000);
  }

  @media screen and (min-width: 750px) {
    .pr__logos {
      grid-template-columns: repeat(var(--pr-cols, 9), minmax(0, 1fr));
    }
  }

  /* On a phone nine logos in a grid becomes three stacked rows.
     A single scrolling line keeps the rail a rail. It runs edge
     to edge by cancelling the wrapper padding, then restoring it
     as scroll padding so the first and last logos still align
     with the copy above. */
  @media screen and (max-width: 749px) {
    [data-mobile='scroll'] .pr__logos {
      display: flex;
      grid-template-columns: none;
      overflow-x: auto;
      -webkit-overflow-scrolling: touch;
      scroll-snap-type: x proximity;
      scrollbar-width: none;
      margin-left: calc(clamp(2rem, 5vw, 8rem) * -1);
      margin-right: calc(clamp(2rem, 5vw, 8rem) * -1);
      padding-left: clamp(2rem, 5vw, 8rem);
      padding-right: clamp(2rem, 5vw, 8rem);
      gap: var(--pr-gap-m, 32px);
    }

    [data-mobile='scroll'] .pr__logos::-webkit-scrollbar {
      display: none;
    }

    [data-mobile='scroll'] .pr__logo {
      flex: 0 0 auto;
      min-width: var(--pr-logo-min, 88px);
      scroll-snap-align: center;
    }

    [data-mobile='scroll'] .pr__logo-text {
      white-space: nowrap;
    }
  }

  .pr__logo {
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: 0;
  }

  .pr__logo-link {
    display: flex;
    align-items: center;
    justify-content: center;
    color: inherit;
    text-decoration: none;
  }

  .pr__logo-img {
    display: block;
    width: auto;
    max-width: 100%;
    height: var(--pr-logo-h-m, 20px);
    object-fit: contain;
    opacity: var(--pr-logo-op, 0.55);
    transition: opacity 0.25s ease;
  }

  @media screen and (min-width: 750px) {
    .pr__logo-img {
      height: var(--pr-logo-h, 26px);
    }
  }

  /* The typographic fallback sits at the same weight as a logo
     would, so a mixed rail does not look half-finished. */
  .pr__logo-text {
    display: block;
    font-size: calc(var(--pr-meta, 11px) * 0.95);
    line-height: 1.3;
    text-align: center;
    text-transform: uppercase;
    opacity: var(--pr-logo-op, 0.55);
    transition: opacity 0.25s ease;
  }

  .pr__logo-link:hover .pr__logo-img,
  .pr__logo-link:hover .pr__logo-text {
    opacity: 1;
  }

  .pr__logo-link:focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 6px;
  }

  /* ── quote ──────────────────────────────────────────────── */

  .pr__quote {
    margin: clamp(3rem, 6vw, 6rem) auto 0;
    max-width: var(--pr-quote-measure, 40ch);
    text-align: center;
  }

  .pr__quote blockquote,
  .pr__source {
    transition: opacity 0.22s ease;
  }

  .pr__quote.is-swapping blockquote,
  .pr__quote.is-swapping .pr__source {
    opacity: 0;
  }

  @media (prefers-reduced-motion: reduce) {
    .pr__quote blockquote,
    .pr__source {
      transition: none;
    }
  }

  /* Held at the tallest quote's height so swapping does not
     jump the page. */
  .pr__quote {
    min-height: var(--pr-quote-min, 0);
  }

  .pr__quote blockquote {
    margin: 0;
    font-family: var(--pr-quote-family, inherit);
    font-variation-settings: var(--pr-quote-variation, normal);
    font-size: var(--pr-quote-m, 21px);
    line-height: 1.22;
    font-weight: 400;
    text-wrap: balance;
  }

  @media screen and (min-width: 750px) {
    .pr__quote blockquote {
      font-size: var(--pr-quote, 30px);
    }
  }

  .pr__quote figcaption {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: clamp(1.2rem, 2.4vw, 2.4rem);
    flex-wrap: wrap;
    margin-top: clamp(1.4rem, 2.4vw, 2.2rem);
    font-size: var(--pr-meta, 11px);
    text-transform: uppercase;
  }

  .pr__source {
    opacity: 0.55;
  }

  .pr__link {
    color: inherit;
    text-decoration: none;
    border-bottom: 1px solid currentColor;
    padding-bottom: 0.3rem;
    transition: opacity 0.2s ease;
  }

  .pr__link:hover {
    opacity: 0.6;
  }

  .pr__link:focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 3px;
  }
/* END_SECTION:press-section */

/* START_SECTION:scent-color-grid (INDEX:71) */
/* ==========================================================
     Horizontal Scent Spectrum

     Panels receive --ground, --type and --shadow as inline
     custom properties from Liquid.

     Layout is mobile-first: a native scroll-snap carousel.
     The pinned scroll-driven behaviour is layered on at 990px
     by the JS adding .is-pinned, and removed again under
     prefers-reduced-motion.
     ========================================================== */

  /* Every piece of supporting text scales off one variable, so
     the mobile step is a single switch rather than a dozen
     overrides. Mobile is the base; desktop opts up. */
  /* Nothing in this section inherits tracking from the theme.
     Elements that set their own via a variable still win, since
     they come later in the sheet. */
  .hsp,
  .hsp * {
    letter-spacing: 0;
  }

  .hsp {
    position: relative;
    background: var(--hsp-bg, #2b381c);
    color: var(--hsp-fg, #f4efe5);
    --hsp-meta: var(--hsp-meta-size-m, 10px);
  }

  @media screen and (min-width: 750px) {
    .hsp {
      --hsp-meta: var(--hsp-meta-size, 12px);
    }
  }

  .hsp__viewport {
    position: relative;
    padding: clamp(2.8rem, 5vw, 5.2rem) 0;
  }

  /* ── header ─────────────────────────────────────────────── */

  .hsp__head {
    display: flex;
    justify-content: space-between;
    align-items: flex-end;
    gap: 2rem;
    flex-wrap: wrap;
    padding: 0 clamp(2rem, 5vw, 8rem);
    margin-bottom: clamp(2rem, 3vw, 3.4rem);
  }

  .hsp__head > div {
    min-width: 0;
  }

  .hsp__eyebrow {
    margin: 0 0 1.1rem;
    font-size: 1.1rem;
    letter-spacing: 0;
    text-transform: uppercase;
    opacity: 0.62;
  }

  /* Mobile is the base and desktop opts up, the same way the
     scent names and supporting text work in this section. */
  .hsp__heading {
    margin: 0;
    max-width: none;
    font-family: var(--hsp-title-family, inherit);
    font-variation-settings: var(--hsp-title-variation, normal);
    font-size: var(--hsp-heading-size-m, 28px);
    line-height: 0.98;
    letter-spacing: 0;
    text-transform: var(--hsp-heading-case, none);
    font-weight: 400;
  }

  /* The measure only exists to hold the intro inside its narrow
     column on desktop. On mobile the intro sits above the
     carousel with the full width free, so capping it there just
     wraps a short heading for no reason. */
  @media screen and (min-width: 750px) {
    .hsp__heading {
      font-size: var(--hsp-heading-size, 44px);
      max-width: var(--hsp-heading-measure, 14ch);
    }
  }

  .hsp__headlink {
    font-size: 1.1rem;
    letter-spacing: 0;
    text-transform: uppercase;
    text-decoration: none;
    color: inherit;
    opacity: 0.72;
    border-bottom: 1px solid currentColor;
    padding-bottom: 0.4rem;
    white-space: nowrap;
    transition: opacity 0.2s ease;
  }

  .hsp__headlink:hover {
    opacity: 1;
  }

  /* ── track: mobile carousel by default ──────────────────── */

  .hsp__track {
    display: flex;
    gap: var(--hsp-gap, 3px);
    list-style: none;
    margin: 0;
    padding: 0 clamp(2rem, 5vw, 8rem);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }

  .hsp__track::-webkit-scrollbar {
    display: none;
  }

  .hsp__panel {
    flex: 0 0 auto;
    width: min(86vw, 430px);
    aspect-ratio: 3 / 4.4;
    scroll-snap-align: center;
    min-width: 0;
  }

  /* ── card ───────────────────────────────────────────────── */

  /* Idle: neutral ground, muted type. Active: the scent takes
     over. Revealing one colour at a time is what keeps a ten
     panel sweep editorial instead of loud. */
  .hsp__card {
    position: relative;
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    background: var(--hsp-idle-ground, #EFEBE3);
    color: var(--hsp-idle-type, #1A1815);
    padding: clamp(1.8rem, 2vw, 2.8rem);
    border-radius: var(--hsp-radius, 3px);
    overflow: hidden;
    transition: background-color 0.75s cubic-bezier(0.4, 0, 0.2, 1),
      color 0.55s ease;
  }

  /* Gradient and grain ride on a pseudo element so they can fade
     in independently of the base colour transition. */
  .hsp__card::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 0;
    opacity: 0;
    background-image: linear-gradient(
      180deg,
      var(--ground-top, transparent) 0%,
      var(--ground, transparent) 46%,
      var(--ground-bottom, transparent) 100%
    );
    transition: opacity 0.75s cubic-bezier(0.4, 0, 0.2, 1);
    pointer-events: none;
  }

  .hsp__card::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 0;
    opacity: 0;
    mix-blend-mode: overlay;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.42'/%3E%3C/svg%3E");
    transition: opacity 0.75s ease;
    pointer-events: none;
  }

  .hsp__panel.is-active .hsp__card {
    color: var(--type);
  }

  .hsp__panel.is-active .hsp__card::before {
    opacity: 1;
  }

  .hsp__panel.is-active .hsp__card::after {
    opacity: var(--hsp-grain, 0.5);
  }

  /* Every panel colours at once when focus mode is off, and on
     mobile where only one panel is visible anyway. */
  [data-focus='off'] .hsp__card,
  [data-focus='off'] .hsp__panel .hsp__card {
    color: var(--type);
  }

  [data-focus='off'] .hsp__card::before {
    opacity: 1;
  }

  [data-focus='off'] .hsp__card::after {
    opacity: var(--hsp-grain, 0.5);
  }

  /* Must sit BELOW the header and caption. Those are transparent
     to clicks via pointer-events, so the card stays fully
     clickable, but the buy column inside the caption can still
     receive its own clicks. At a higher z-index than the caption
     this anchor swallows the add to bag button, because the
     caption's own z-index creates a stacking context that traps
     the button's z-index inside it. */
  .hsp__link {
    position: absolute;
    inset: 0;
    z-index: 2;
    text-indent: -9999px;
    overflow: hidden;
  }

  .hsp__link:focus-visible {
    outline: 2px solid var(--type);
    outline-offset: -5px;
  }

  .hsp__top {
    position: relative;
    z-index: 3;
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 1rem;
    pointer-events: none;
  }

  .hsp__fam {
    font-size: calc(var(--hsp-meta, 12px) * 0.85);
    letter-spacing: 0;
    text-transform: uppercase;
    padding: 0.4rem 0.8rem;
    border: 1px solid currentColor;
    border-radius: var(--hsp-radius, 3px);
    color: inherit;
    white-space: nowrap;
  }

  /* Photography needs light type regardless of the scent's own
     type colour, which was chosen against a flat ground. */
  .hsp__panel.is-active .hsp__card.has-art,
  [data-focus='off'] .hsp__card.has-art {
    color: var(--hsp-art-type, #FFFFFF);
  }

  /* ── note imagery ───────────────────────────────────────── */

  /* Four photographs per scent, crossfading behind the product.
     They already carry the scent colour and real film grain, so
     where they exist the CSS gradient stands down. */
  .hsp__ground {
    position: absolute;
    inset: 0;
    z-index: 0;
    overflow: hidden;
    opacity: 0;
    transition: opacity 0.75s cubic-bezier(0.4, 0, 0.2, 1);
    pointer-events: none;
  }

  .hsp__panel.is-active .hsp__ground,
  [data-focus='off'] .hsp__ground {
    opacity: 1;
  }

  .hsp__layer {
    position: absolute;
    inset: 0;
    opacity: 0;
    transition: opacity var(--hsp-fade, 600ms) ease;
  }

  .hsp__layer.is-showing {
    opacity: 1;
  }

  .hsp__layer-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
  }

  /* Darkens top and bottom so the name above and the meta row
     below both stay legible over photography. */
  .hsp__scrim {
    position: absolute;
    inset: 0;
    background: linear-gradient(
      180deg,
      rgba(0, 0, 0, var(--hsp-scrim, 0.3)) 0%,
      transparent 26%,
      transparent 60%,
      rgba(0, 0, 0, var(--hsp-scrim, 0.3)) 100%
    );
  }

  /* Synthetic gradient and grain stand down for the real thing. */
  .hsp__card.has-art::before,
  .hsp__card.has-art::after {
    display: none;
  }

  /* ── the floating print ─────────────────────────────────── */

  /* Takes whatever height is left after the meta row and the
     caption, so a wrapping title can never overlap the print. */
  .hsp__stage {
    position: relative;
    flex: 1;
    min-height: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1.2rem 0;
    z-index: 1;
    will-change: transform;
    pointer-events: none;
  }

  .hsp__print {
    position: relative;
    width: min(var(--hsp-print, 78%), var(--hsp-print-max, 560px));
    min-width: 0;
    max-height: 100%;
    aspect-ratio: var(--hsp-print-ratio, 1 / 1);
    border-radius: 2px;
    overflow: hidden;
    box-shadow: 0 var(--hsp-shadow-y, 48px) var(--hsp-shadow-blur, 115px) var(--shadow, rgba(0, 0, 0, 0.38));
    transition: transform 0.5s cubic-bezier(0.2, 0, 0.2, 1);
  }

  /* A transparent cutout needs no frame, just a contact shadow
     that follows the object's own edges rather than a box. */
  .hsp__print.is-cutout {
    background: none;
    border-radius: 0;
    box-shadow: none;
    overflow: visible;
    aspect-ratio: auto;
    filter: drop-shadow(
      0 calc(var(--hsp-shadow-y, 48px) * 0.5) calc(var(--hsp-shadow-blur, 115px) * 0.4)
        var(--shadow, rgba(0, 0, 0, 0.38))
    );
  }

  .hsp__print.is-cutout .hsp__img {
    object-fit: contain;
    max-height: 100%;
    width: auto;
    margin: 0 auto;
  }

  .hsp__img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
  }

  .hsp__img--placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.08);
  }

  .hsp__placeholder-svg {
    width: 100%;
    height: 100%;
    opacity: 0.28;
    fill: currentColor;
  }

  /* ── caption ────────────────────────────────────────────── */

  /* Text left, buy column right. nowrap keeps the buy column
     on the same row rather than dropping beneath the notes. */
  /* Name at the top, everything else split across the bottom. */
  .hsp__head-block {
    position: relative;
    z-index: 3;
    flex: 0 0 auto;
    pointer-events: none;
  }

  [data-title-align='center'] .hsp__head-block {
    text-align: center;
  }

  .hsp__caption {
    position: relative;
    z-index: 3;
    flex: 0 0 auto;
    display: flex;
    justify-content: space-between;
    align-items: flex-end;
    gap: 1.8rem;
    pointer-events: none;
  }

  .hsp__left {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    text-align: left;
    gap: 0.7rem;
    min-width: 0;
  }

  .hsp__right {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 0.7rem;
    text-align: right;
    flex: 0 0 auto;
    white-space: nowrap;
  }

  .hsp__spec {
    display: flex;
    align-items: baseline;
    gap: 0.8rem;
  }

  .hsp__title {
    margin: 0;
    font-family: var(--hsp-title-family, inherit);
    font-variation-settings: var(--hsp-title-variation, normal);
    font-size: var(--hsp-title-size-m, 40px);
    line-height: 0.94;
    letter-spacing: var(--hsp-title-tracking, 0);
    text-transform: var(--hsp-title-case, uppercase);
    font-style: var(--hsp-title-style, normal);
    font-weight: 400;
    color: inherit;
    text-wrap: balance;
  }

  @media screen and (min-width: 750px) {
    .hsp__title {
      font-size: var(--hsp-title-size, 76px);
    }
  }

  /* On a phone the two caption columns fight over 320px, so they
     stack: labels above, then a full width row for the spec and
     the button. */
  @media screen and (max-width: 749px) {
    .hsp__card {
      padding: 1.5rem 1.4rem;
    }

    .hsp__caption {
      flex-direction: column;
      align-items: stretch;
      gap: 1.1rem;
    }

    .hsp__right {
      flex-direction: row;
      align-items: center;
      justify-content: space-between;
      width: 100%;
      text-align: left;
    }

    .hsp__notes {
      max-width: none;
    }
  }

  .hsp__descriptor,
  .hsp__size {
    margin: 0;
    font-size: calc(var(--hsp-meta, 12px) * 0.82);
    letter-spacing: 0;
    text-transform: uppercase;
    line-height: 1.4;
    color: inherit;
  }

  /* Both live in the left column and must stay left aligned even
     when they wrap, which align-items alone does not control. */
  .hsp__descriptor,
  .hsp__fam {
    text-align: left;
    align-self: flex-start;
  }

  /* Each note is its own nowrap span, so a line break can only
     fall between notes and never strands a separator. */
  /* A flex row rather than inline text. Liquid strips the
     whitespace between the spans, and each span is nowrap, so
     as inline content there is no break opportunity anywhere in
     the line and it simply overflows. Flex gives every note its
     own wrap point. */
  .hsp__notes {
    margin: 0.9rem 0 0;
    display: flex;
    flex-wrap: wrap;
    column-gap: 0.5rem;
    row-gap: 0.15rem;
    font-size: calc(var(--hsp-meta, 12px) * 0.95);
    letter-spacing: 0;
    line-height: 1.5;
    color: inherit;
    max-width: 46ch;
  }

  [data-title-align='center'] .hsp__notes {
    justify-content: center;
    margin-left: auto;
    margin-right: auto;
  }

  .hsp__note {
    white-space: nowrap;
  }

  .hsp__note + .hsp__note::before {
    content: '·';
    margin-right: 0.5rem;
  }

  /* Held back until the panel is the one being looked at, so the
     row of neighbours stays quiet. */
  .hsp__buy {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 0.7rem;
    pointer-events: auto;
    position: relative;
    z-index: 5;
    opacity: 0;
    transform: translateY(6px);
    transition: opacity 0.45s ease 0.1s, transform 0.45s ease 0.1s;
  }

  .hsp__panel.is-active .hsp__buy,
  [data-focus='off'] .hsp__buy {
    opacity: 1;
    transform: none;
  }

  .hsp__panel:not(.is-active) .hsp__buy {
    pointer-events: none;
  }

  [data-focus='off'] .hsp__panel:not(.is-active) .hsp__buy {
    pointer-events: auto;
  }

  .hsp__price {
    font-size: calc(var(--hsp-meta, 12px) * 0.95);
    letter-spacing: 0;
    color: inherit;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
  }

  .hsp__price s {
    opacity: 0.55;
    margin-right: 0.6rem;
  }

  .hsp__form {
    margin: 0;
  }

  .hsp__add {
    display: inline-block;
    font-size: calc(var(--hsp-meta, 12px) * 0.85);
    letter-spacing: 0;
    text-transform: var(--button-text-transform, none);
    padding: 0.95rem 1.7rem;
    border: 1px solid var(--hsp-btn-bg, #FFFFFF);
    border-radius: var(--button-border-radius, 999px);
    background: var(--hsp-btn-bg, #FFFFFF);
    color: var(--hsp-btn-text, #1A1815);
    cursor: pointer;
    white-space: nowrap;
    font-family: inherit;
    line-height: 1;
    transition: opacity 0.2s ease;
  }

  .hsp__add span {
    color: var(--hsp-btn-text, #1A1815);
  }

  /* Separator lives on the price so it disappears with it. */
  .hsp__add-price::before {
    content: ' · ';
    white-space: pre;
  }

  .hsp__add:hover {
    opacity: 0.85;
  }

  .hsp__add:focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 3px;
  }

  /* Two treatments for sold out. Outlined keeps unavailable
     visually distinct from a live button, which is the safer
     pattern. Solid matches the live button and leans on the
     label alone to say it is unavailable. */
  [data-soldout='outline'] .hsp__add--disabled {
    background: transparent;
    border-color: currentColor;
    color: inherit;
    opacity: 0.5;
    cursor: not-allowed;
    pointer-events: none;
  }

  /* When it links to the product page it has to stay clickable,
     and it is an action rather than a disabled control. */
  .hsp__add--link {
    pointer-events: auto;
    cursor: pointer;
    text-decoration: none;
    opacity: 0.85;
  }

  .hsp__add--link:hover {
    opacity: 1;
  }

  [data-soldout='outline'] .hsp__add--disabled span {
    color: inherit;
  }

  [data-soldout='solid'] .hsp__add--disabled {
    opacity: 0.55;
    cursor: not-allowed;
    pointer-events: none;
  }

  [data-soldout='solid'] .hsp__add--link,
  [data-soldout='outline'] .hsp__add--link {
    pointer-events: auto;
    cursor: pointer;
    opacity: 0.85;
  }

  .hsp__add[aria-busy='true'] {
    opacity: 0.6;
    pointer-events: none;
  }

  /* ── rail ───────────────────────────────────────────────── */

  .hsp__rail {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    gap: 3px;
    margin: 2.4rem clamp(2rem, 5vw, 8rem) 0;
  }

  .hsp__rail-btn {
    height: 5px;
    padding: 0;
    border: none;
    border-radius: 2px;
    background: var(--rail);
    opacity: 0.32;
    cursor: pointer;
    transition: opacity 0.3s ease, height 0.3s ease;
  }

  .hsp__rail-btn.is-active {
    opacity: 1;
    height: 11px;
  }

  .hsp__rail-btn:focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 3px;
  }

  /* Self-contained rather than relying on a theme utility class
     that may not exist, which would leak this text on screen. */
  .hsp__sr {
    position: absolute !important;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }

  .hsp__empty {
    padding: 4rem 0;
    text-align: center;
    opacity: 0.6;
  }

  /* ══════════════════════════════════════════════════════════
     DESKTOP — pinned, scroll-driven
     ══════════════════════════════════════════════════════════ */

  @media screen and (min-width: 990px) {
    .hsp.is-pinned {
      height: var(--hsp-scroll-height, 500vh);
    }

    .hsp.is-pinned .hsp__viewport {
      position: sticky;
      top: 0;
      height: 100svh;
      display: flex;
      flex-direction: column;
      justify-content: center;
      overflow: hidden;
      padding: 0;
    }

    /* The intro sits in the leading space, aligned to the panel
       height, and stays put while the track translates. Panels
       carry their own backgrounds and sit above it, so the first
       one slides over the text as you scroll. */
    /* Top edge matched to the panels. The viewport centres them,
       so the panel top is half the leftover height. */
    .hsp.is-pinned .hsp__head {
      position: absolute;
      top: calc((100svh - (var(--hsp-panel-h, 66) * 1svh)) / 2);
      left: clamp(2rem, 5vw, 8rem);
      right: auto;
      width: var(--hsp-intro-w, 340px);
      max-height: calc(var(--hsp-panel-h, 66) * 1svh);
      z-index: 1;
      margin: 0;
      padding: 0;
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      justify-content: flex-start;
      gap: 1.6rem;
    }

    .hsp.is-pinned .hsp__track {
      overflow: visible;
      scroll-snap-type: none;
      will-change: transform;
      position: relative;
      z-index: 2;
    }

    /* Leading space has to clear the intro, not just centre the
       first panel. Trailing space still lets the last panel reach
       the middle. */
    .hsp.is-pinned .hsp__track {
      padding-left: calc(var(--hsp-intro-w, 340px) + clamp(2rem, 5vw, 8rem) * 2);
    }

    .hsp.is-pinned[data-edge-centre='true'] .hsp__track {
      padding-right: max(
        clamp(2rem, 5vw, 8rem),
        calc(50vw - min(var(--hsp-panel-w, 46vw), var(--hsp-panel-max, 660px)) / 2)
      );
    }

    .hsp.is-pinned .hsp__panel {
      width: min(var(--hsp-panel-w, 46vw), var(--hsp-panel-max, 660px));
      height: calc(var(--hsp-panel-h, 66) * 1svh);
      aspect-ratio: auto;
    }

    .hsp.is-pinned .hsp__rail {
      position: absolute;
      left: 0;
      right: 0;
      bottom: clamp(2.4rem, 4vw, 4.4rem);
      z-index: 6;
      margin: 0 clamp(2rem, 5vw, 8rem);
    }
  }

  /* ══════════════════════════════════════════════════════════
     REDUCED MOTION — never pin, never parallax
     ══════════════════════════════════════════════════════════ */

  @media (prefers-reduced-motion: reduce) {
    .hsp,
    .hsp.is-pinned {
      height: auto;
    }

    .hsp .hsp__viewport {
      position: static;
      height: auto;
      overflow: visible;
      padding: clamp(2.8rem, 5vw, 5.2rem) 0;
    }

    .hsp .hsp__head,
    .hsp .hsp__rail {
      position: static;
      margin-left: clamp(2rem, 5vw, 8rem);
      margin-right: clamp(2rem, 5vw, 8rem);
    }

    .hsp .hsp__track {
      overflow-x: auto;
      scroll-snap-type: x mandatory;
      transform: none !important;
    }

    .hsp .hsp__panel {
      width: min(84vw, 420px);
      aspect-ratio: 4 / 5;
      height: auto;
    }

    .hsp .hsp__stage {
      transform: none !important;
    }

    .hsp .hsp__print {
      transform: none !important;
      transition: none;
    }
  }
/* END_SECTION:scent-color-grid */

/* START_SECTION:ticker (INDEX:82) */
/* ==========================================================
     Colophon ticker
     ========================================================== */

  /* Nothing in this section inherits tracking from the theme.
     Elements that set their own via a variable still win, since
     they come later in the sheet. */
  .tick,
  .tick * {
    letter-spacing: 0;
  }

  .tick {
    position: relative;
    background: var(--tick-bg, #eae4d8);
    color: var(--tick-fg, #7a7468);
    border-top: var(--tick-rule, 0 none);
    border-bottom: var(--tick-rule, 0 none);
    padding: var(--tick-pad, 22px) 0;
    overflow: hidden;
    font-family: var(--tick-family, inherit);
    font-variation-settings: var(--tick-variation, normal);
    font-size: var(--tick-size-m, 11px);
    letter-spacing: var(--tick-tracking, 0);
    text-transform: var(--tick-case, none);
    line-height: 1.4;
  }

  @media screen and (min-width: 750px) {
    .tick {
      font-size: var(--tick-size, 12px);
    }
  }

  .tick a {
    color: inherit;
    text-decoration: none;
    border-bottom: 1px solid transparent;
    transition: border-color 0.25s ease;
  }

  .tick a:hover {
    border-bottom-color: currentColor;
  }

  /* ── scroll ─────────────────────────────────────────────── */

  .tick__viewport {
    overflow: hidden;
  }

  .tick__track {
    display: flex;
    width: max-content;
    will-change: transform;
    animation: tick-scroll var(--tick-duration, 30s) linear infinite;
  }

  .tick--scroll[data-direction='right'] .tick__track {
    animation-direction: reverse;
  }

  @keyframes tick-scroll {
    from { transform: translate3d(0, 0, 0); }
    to { transform: translate3d(-50%, 0, 0); }
  }

  .tick[data-pause='true']:hover .tick__track,
  .tick__track:focus-within {
    animation-play-state: paused;
  }

  .tick__group {
    display: flex;
    align-items: center;
    list-style: none;
    margin: 0;
    padding: 0;
    flex: 0 0 auto;
  }

  .tick__item {
    display: flex;
    align-items: center;
    white-space: nowrap;
    padding-left: calc(var(--tick-gap, 32px) / 2);
    padding-right: calc(var(--tick-gap, 32px) / 2);
  }

  .tick__sep {
    margin-left: calc(var(--tick-gap, 32px) / 2);
    opacity: 0.5;
  }

  /* ── rotate ─────────────────────────────────────────────── */

  .tick__rotator {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 1.4em;
    text-align: center;
    padding: 0 clamp(1.6rem, 5vw, 8rem);
  }

  .tick__phrase {
    position: absolute;
    opacity: 0;
    visibility: hidden;
    white-space: nowrap;
    transition: opacity var(--tick-fade, 500ms) ease,
      visibility 0s linear var(--tick-fade, 500ms);
  }

  .tick__phrase.is-active {
    position: relative;
    opacity: 1;
    visibility: visible;
    transition: opacity var(--tick-fade, 500ms) ease, visibility 0s;
  }

  /* ── motion ─────────────────────────────────────────────── */

  /* Movement is the whole point of a marquee, so under reduced
     motion it becomes a static, wrapping row instead. */
  @media (prefers-reduced-motion: reduce) {
    .tick__track {
      animation: none;
      width: auto;
      flex-wrap: wrap;
      justify-content: center;
    }

    .tick__group:nth-child(2) {
      display: none;
    }

    .tick__group {
      flex-wrap: wrap;
      justify-content: center;
    }

    .tick__phrase {
      position: relative;
      opacity: 1;
      visibility: visible;
      transition: none;
    }

    .tick__rotator {
      flex-wrap: wrap;
      gap: 0 var(--tick-gap, 32px);
    }
  }

  .tick__empty {
    padding: 2rem;
    text-align: center;
    opacity: 0.6;
  }
/* END_SECTION:ticker */