/** Shopify CDN: Minification failed

Line 728:2 Unexpected "}"

**/
/* Hallmark · redesign: polish · brand: ViprTech, kept (Press Start 2P wordmark, matcha + blush, Newsreader + Karla, glass panes, vines) · genre: editorial · nav: glass bar with the terminal caret · footer: wordmark beside shop, support and contact · hero: pane beside the build carousel · built: the project */
/* Hallmark · pre-emit critique: polish only, layout kept · weakest: the glass and drop shadows read as generated, but they are the brand's surface and stay; fixed type size, contrast, labels, states and tokens instead */

  :root {
    /* type */
    --font-body: 'Karla', system-ui, sans-serif;
    --font-display: 'Newsreader', Georgia, serif;
    --font-mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;   /* code only; the UI no longer uses it */
    --font-brand: 'Press Start 2P', ui-monospace, monospace;

    /* colour roles - components use these, not the raw values */
    --color-page: #FCFBF4;
    --color-text: #23211c;
    --color-text-secondary: rgba(35, 33, 28, .8);
    --color-text-muted: rgba(35, 33, 28, .68);   /* the floor for readable grey: 5:1 on every surface */
    --color-text-inverse: #FCFBF4;
    --color-fill-strong: #23211c;
    --color-band: #F9EEEC;
    /* Affirm's own blues, read from affirm.com's stylesheet (see
       .hallmark/brand-spec.md); only the Financing page uses them */
    --affirm-blue: #4A4AF4;          /* ivory text on it: 5.7:1 */
    --affirm-blue-dark: #2F2FC1;          /* the blush, washed into the ivory: the band behind How it's made */

    --matcha: #7C9A57;
    --matcha-deep: #597433;          /* darkened from #64803F so small green text clears 4.5:1 on the page and the pink band */
    /* Blush, used by the cart button so the one thing we want clicked reads
       apart from the matcha the rest of the site runs on. The deep tones are
       picked to clear 4.5:1 against both the ivory page and the pastel fills. */
    --blush: #E9A8C0;
    --blush-soft: #F4C9D8;
    --blush-deep: #8E3A57;
    --blush-deeper: #7E3049;
    /* One lane shared by the bar and the hero, so their edges
       stay flush. Change this number to widen or narrow the whole page. */
    --lane: min(1400px, calc(100% - 44px));
  }

  html, body {
    height: 100%;
    margin: 0;
  }
  body {
    background: var(--color-page);
    font-family: var(--font-body);
  }

  /* no double-tap zoom delay on anything tappable */
  a, button, label, input, select, textarea, summary { touch-action: manipulation; }

  /* Hidden until a keyboard user tabs to it, then it drops in above the
     ticker so it can't be covered by the fixed bar. */
  .skip-link {
    position: fixed;
    top: 8px;
    left: 8px;
    z-index: 100;
    padding: 10px 16px;
    border-radius: 999px;
    background: var(--color-fill-strong);
    color: var(--color-text-inverse);
    font-size: .95rem;
    text-decoration: none;
    transform: translateY(-160%);
    transition: transform .2s ease;
  }
  .skip-link:focus { transform: none; outline: 2px solid var(--matcha); outline-offset: 2px; }
  #main:focus { outline: none; }  /* the skip target, not a control */

  /* Desktop runs at 90%.
     zoom rather than transform: scale - a transform would make .bar and
     .ticker position against the scaled box instead of the window, and the
     fixed header would come off its perch. zoom scales the layout itself, so
     everything keeps its relationship to the viewport and the page reflows
     with more room rather than being shrunk in place.

     Held to wide screens on purpose. The breakpoints below still measure the
     real window, so applying this any lower would fire the tablet rules while
     the layout actually had a quarter more room than they assume - and phones
     are already sized for the hand they are held in. */
  @media (min-width: 1100px) {
    :root { zoom: .9; }
  }


  /* glass surface */
  .glass {
    --delay: 0s;
    background: rgba(255, 255, 255, .35);
    backdrop-filter: blur(16px) saturate(180%);
    -webkit-backdrop-filter: blur(16px) saturate(180%);

    border: 1px solid rgba(255, 255, 255, .60);
    border-radius: 16px;
    box-shadow:
      0 8px 32px rgba(60, 55, 40, .10),
      inset 0 1px 0 rgba(255, 255, 255, .70);

    position: relative;
    overflow: hidden;               /* keeps the sheen inside the pane */
    animation: unfold 1.15s cubic-bezier(.19, 1, .22, 1) var(--delay) both;
  }

  /* scrolling ticker */
  .ticker {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 20;                    /* rides above the nav bar */
    height: 38px;
    display: flex;
    align-items: center;
    overflow: hidden;

    background: rgba(255, 255, 255, .38);
    backdrop-filter: blur(14px) saturate(180%);
    -webkit-backdrop-filter: blur(14px) saturate(180%);
    border-bottom: 1px solid rgba(255, 255, 255, .60);
    box-shadow:
      0 4px 20px rgba(60, 55, 40, .07),
      inset 0 1px 0 rgba(255, 255, 255, .70);

    animation: drop .8s cubic-bezier(.19, 1, .22, 1) both;
  }

  @keyframes drop { from { transform: translateY(-100%); } }

  /* Two identical groups sliding exactly half the row width = seamless loop */
  .ticker__row {
    display: flex;
    flex: none;
    animation: marquee 34s linear infinite;
  }
  .ticker:hover .ticker__row { animation-play-state: paused; }

  .ticker__group {
    display: flex;
    flex: none;
    align-items: center;
  }

  .ticker__group span {
    padding: 0 26px;
    white-space: nowrap;
    /* sentence case at a readable size - wide-tracked tiny caps were hard
       to read while moving */
    font-size: 0.9rem;
    font-weight: 500;
    letter-spacing: .01em;
    color: rgba(35, 33, 28, .86);
  }
  /* separator dot */
  .ticker__group span::after {
    content: "";
    display: inline-block;
    vertical-align: middle;
    width: 4px;
    height: 4px;
    margin-left: 26px;
    border-radius: 50%;
    background: rgba(35, 33, 28, .28);
  }

  @keyframes marquee { to { transform: translateX(-50%); } }

  /* the ticker fades out at both ends instead of clipping mid-letter */
  .ticker::before,
  .ticker::after {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    width: 70px;
    z-index: 2;
    pointer-events: none;
  }
  .ticker::before { left: 0;  background: linear-gradient(90deg, var(--color-page), transparent); }
  .ticker::after  { right: 0; background: linear-gradient(270deg, var(--color-page), transparent); }

  /* the bar */
  .bar {
    position: fixed;
    top: 52px;                      /* sits below the ticker */
    left: 50%;
    transform: translateX(-50%);
    width: var(--lane);
    height: 68px;
    z-index: 10;

    /* 1fr | auto | 1fr keeps the nav centred on the bar itself,
       regardless of how wide the wordmark gets */
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    padding: 0 22px;
  }

  /* Sits in front of the bar and dangles over its lower-right corner.
     Its own layer, because .glass clips anything inside the bar. */
  .bar-layer {
    position: fixed;
    top: 52px;
    left: 50%;
    transform: translateX(-50%);
    width: var(--lane);             /* identical geometry to .bar */
    height: 68px;
    z-index: 11;
    pointer-events: none;
  }

  .flower {
    position: absolute;
    top: -11px;                     /* stem starts at the bar's top edge */
    right: 12px;
    width: 84px;                    /* the frames carry transparent padding,
                                       so the visible bloom is smaller than this */
    aspect-ratio: 230 / 304;        /* the frames' own ratio */
    transform-origin: 50% 0;        /* hangs from the stem */
    animation: unfurl 1.1s cubic-bezier(.19, 1, .22, 1) 1.15s both;

    /* The box is mostly transparent margin, and it hangs over the cart
       button beside it - so the box itself stays click-through and only the
       drawn flower takes clicks. See ::after. */
    pointer-events: none;
    cursor: default;
  }

  /* Hit target trimmed to the artwork. Measured on the 230x304 frames: the
     opaque pixels run x 22.6%-81.7%, y 8.6%-93.8%. Everything outside that
     was dead space that still swallowed clicks aimed at the cart. */
  .flower::after {
    content: "";
    position: absolute;
    left: 22.6%;
    right: 18.3%;
    top: 8.6%;
    bottom: 6.2%;
    pointer-events: auto;
    cursor: pointer;
  }

  /* One-shot sparkle burst, centred on the bloom.
     The fl frames are 194×500 but the sparkles only occupy x 53-142,
     y 210-287 - so the box is mostly empty and its width is a poor guide
     to how big the effect looks. At this width the sparkles render ~53px
     across, against a bloom of ~29px: a halo, still clearly attached.
     Offsets put the artwork's centre (50.3% / 49.7% of the canvas) on the
     bloom's centre - change the width and both must be recomputed. */
  .bloom-fx {
    position: absolute;
    top: -66px;
    right: -5px;
    width: 115px;
    aspect-ratio: 194 / 500;
    pointer-events: none;
  }
  /* no pointer cursor while the burst is mid-flight - it can't be retriggered */
  .flower:has(~ .bloom-fx.playing)::after { cursor: default; }
  @keyframes unfurl {
    from { opacity: 0; transform: scale(.8) rotate(-6deg); }
  }

  /* Every frame stacked; only one is visible at a time. No src swapping,
     so each frame is on screen for exactly the same duration. */
  .sprite .frame {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
  }
  .sprite .frame.on { opacity: 1; }

  @media (max-width: 860px) {
    .flower { width: 70px; right: 8px; top: -9px; }
    .bloom-fx { width: 96px; right: -7px; top: -57px; }
  }

  /* social icons, in the bar's empty third column */
  .social {
    justify-self: end;
    display: flex;
    align-items: center;
    gap: 4px;
    /* clears the flower hanging off the bar's right end */
    padding-right: 84px;
  }

  /* Scoped to the icon row, not every link in .social - the cart button is
     also an <a> in here, and `.social a` outranked `.cart-link`, forcing it
     back into a 30px icon box. */
  .social-icons a {
    display: grid;
    place-items: center;
    width: 30px;
    height: 30px;
    border-radius: 8px;
    color: var(--matcha);
    transition: color .22s ease, background .22s ease, transform .22s cubic-bezier(.19, 1, .22, 1);
  }
  .social-icons a:hover {
    color: var(--matcha-deep);
    background: rgba(124, 154, 87, .12);
    transform: translateY(-2px);
  }
  .social-icons a:focus-visible {
    outline: 2px solid rgba(35, 33, 28, .45);
    outline-offset: 2px;
  }
  .social-icons svg {
    width: 16px;
    height: 16px;
    display: block;
  }

  .social-icons { display: flex; align-items: center; gap: 4px; }

  /* The cart is the one thing in the bar we want people to reach for, so it
     reads as a real button rather than another quiet icon - and it stays
     reachable at every width; only the social row gives up room to the nav. */
  .cart-link {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    height: 38px;
    padding: 0 15px;
    margin-left: 12px;
    border-radius: 999px;
    background: rgba(233, 168, 192, .22);
    border: 1px solid rgba(233, 168, 192, .62);
    color: var(--blush-deep);
    text-decoration: none;
    font-family: var(--font-body);
    font-size: 0.84rem;
    letter-spacing: 0;
    white-space: nowrap;
    transition:
      background .22s ease,
      border-color .22s ease,
      color .22s ease,
      box-shadow .22s ease,
      transform .22s cubic-bezier(.19, 1, .22, 1), scale .12s ease-out;
  }
  .cart-link:hover {
    background: var(--blush-soft);
    border-color: var(--blush);
    color: var(--blush-deeper);
    transform: translateY(-2px);
    box-shadow: 0 6px 16px rgba(184, 106, 137, .28);
  }
  .cart-link:focus-visible {
    outline: 2px solid var(--blush-deep);
    outline-offset: 3px;
  }
  .cart-link svg { width: 19px; height: 19px; display: block; flex: none; }
  .cart-link__label { line-height: 1; }

  /* filled once there's something in it, so a loaded cart is obvious */
  .cart-link.has-items {
    background: var(--blush-soft);
    border-color: var(--blush);
    color: var(--blush-deeper);
  }
  .cart-link.has-items:hover {
    background: #EFB8CD;
    border-color: #DE93B0;
  }

  .cart-count {
    min-width: 21px;
    height: 21px;
    padding: 0 6px;
    border-radius: 999px;
    background: var(--color-page);
    color: var(--blush-deeper);
    font-size: .72rem;
    font-weight: 600;
    line-height: 21px;
    text-align: center;
  }

  @media (max-width: 1040px) {
    .social-icons { display: none; } /* the nav needs the room first */
  }

  /* the label is the first thing to go when the bar gets tight */
  @media (max-width: 1200px) {
    .cart-link__label { display: none; }
    .cart-link { padding: 0 11px; gap: 6px; }
  }

  /* cart preview
     Same glass panel as the nav dropdowns, positioned by JS against the cart
     button. Lives outside .bar because .glass clips its children. */
  .cart-peek {
    position: fixed;
    z-index: 31;
    width: 330px;
    padding: 16px;

    background: rgba(255, 255, 255, .62);
    backdrop-filter: blur(18px) saturate(180%);
    -webkit-backdrop-filter: blur(18px) saturate(180%);
    border: 1px solid rgba(255, 255, 255, .72);
    border-radius: 16px;
    box-shadow:
      0 14px 40px rgba(60, 55, 40, .18),
      inset 0 1px 0 rgba(255, 255, 255, .70);

    transform-origin: top right;
    opacity: 0;
    transform: translateY(-6px) scale(.97);
    pointer-events: none;
    transition: opacity .2s ease, transform .26s cubic-bezier(.19, 1, .22, 1);
  }
  .cart-peek.open {
    opacity: 1;
    transform: none;
    pointer-events: auto;
  }

  .cart-peek__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
    padding-bottom: 11px;
    margin-bottom: 4px;
    border-bottom: 1px solid rgba(35, 33, 28, .1);
  }
  .cart-peek__title {
    font-family: var(--font-display);
    font-size: 1.06rem;
    color: var(--color-text);
  }
  .cart-peek__count {
    font-family: var(--font-body);
    font-size: .9rem;
    letter-spacing: 0;
    color: var(--blush-deep);
  }

  .cart-peek__list {
    list-style: none;
    margin: 0;
    padding: 0;
    max-height: 292px;
    overflow-y: auto;
  }

  .peek-line {
    display: grid;
    grid-template-columns: 46px minmax(0, 1fr) auto;
    align-items: center;
    gap: 11px;
    padding: 10px 0;
    border-bottom: 1px solid rgba(35, 33, 28, .07);
  }
  .peek-line:last-child { border-bottom: 0; }

  .peek-line__media {
    width: 46px;
    height: 46px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 4px;
    box-sizing: border-box;
    border-radius: 8px;
    background: rgba(255, 255, 255, .6);
    border: 1px solid rgba(35, 33, 28, .08);
  }
  .peek-line__media img {
    max-width: 100%;
    max-height: 100%;
    width: auto;
    height: auto;
    object-fit: contain;
  }

  .peek-line__info { min-width: 0; }
  .peek-line__title {
    display: block;
    font-family: var(--font-display);
    font-size: 0.96rem;
    color: var(--color-text);
    text-decoration: none;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .peek-line__title:hover { color: var(--blush-deep); }
  .peek-line__variant,
  .peek-line__qty {
    margin: 2px 0 0;
    font-family: var(--font-body);
    font-size: 0.76rem;
    color: var(--color-text-muted);
  }
  .peek-line__price {
    margin: 0;
    font-family: var(--font-body);
    font-size: 0.86rem;
    color: var(--color-text);
    white-space: nowrap;
  }

  .cart-peek__more {
    margin: 8px 0 0;
    font-family: var(--font-body);
    font-size: 0.76rem;
    color: var(--color-text-muted);
    text-align: center;
  }

  .cart-peek__total {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px solid rgba(35, 33, 28, .12);
    font-size: 0.92rem;
    color: rgba(35, 33, 28, .7);
  }
  .cart-peek__total strong {
    font-family: var(--font-body);
    font-size: 1.06rem;
    color: var(--color-text);
  }

  .cart-peek__view {
    display: block;
    margin-top: 14px;
    padding: 11px 16px;
    border-radius: 999px;
    background: var(--blush-soft);
    border: 1px solid var(--blush);
    color: var(--blush-deeper);
    font-family: var(--font-body);
    font-size: 0.86rem;
    letter-spacing: 0;
    text-align: center;
    text-decoration: none;
    transition: background .2s ease, border-color .2s ease, scale .12s ease-out;
  }
  .cart-peek__view:hover { background: #EFB8CD; border-color: #DE93B0; }

  .cart-peek__empty {
    margin: 14px 0 0;
    text-align: center;
    font-size: 0.92rem;
    color: var(--color-text-muted);
  }

  @media (max-width: 420px) {
    .cart-peek { width: calc(100% - 24px); }
  }
  @media (prefers-reduced-motion: reduce) {
    .cart-peek { transition: opacity .15s ease; transform: none; }
  }

  /* Contents wait for the pane to finish unfolding */
  .brand, .nav, .social { animation: contentIn .5s ease .58s both; }
  @keyframes contentIn { from { opacity: 0; } }

  .brand {
    font-family: var(--font-brand);
    font-size: .78rem;              /* this face runs large for its size */
    letter-spacing: .01em;
    line-height: 1;
    color: var(--color-text);
    text-decoration: none;
    white-space: nowrap;
    justify-self: start;
    padding-top: 2px;               /* the face sits high in its box */
  }
  /* only one weight exists, so the split is carried by colour alone */
  .brand span { opacity: .42; }

  .nav {
    position: relative;             /* the caret is positioned against this */
    display: flex;
    align-items: center;
    gap: 2px;
    justify-self: center;
    min-width: 0;
    overflow-x: auto;               /* narrow screens scroll rather than wrap */
    scrollbar-width: none;

    /* the decode locks each label's width (viprtech.js), so the body face
       can carry it without the row reflowing */
    font-family: var(--font-body);
  }
  .nav::-webkit-scrollbar { display: none; }

  /* the travelling caret */
  .caret {
    position: absolute;
    left: 0;
    z-index: 1;
    background: var(--color-fill-strong);
    border-radius: 6px;
    pointer-events: none;
    transition:
      transform .34s cubic-bezier(.6, 0, .2, 1),
      width .34s cubic-bezier(.6, 0, .2, 1);
  }
  /* block cursor blinking on the trailing edge */
  .caret::after {
    content: "";
    position: absolute;
    right: 5px;
    top: 50%;
    width: 7px;
    height: 14px;
    margin-top: -7px;
    background: var(--color-page);
    animation: blink 1.05s steps(2, start) infinite;
  }
  /* Support already ends in a chevron - the cursor just collides with it */
  .caret.bare::after { display: none; }

  @keyframes blink { 50% { opacity: 0; } }

  .nav-item {
    position: relative;
    z-index: 2;                     /* text rides above the caret */
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 9px 13px;
    border: none;
    border-radius: 10px;
    background: transparent;
    font: inherit;
    /* Nudged rather than fully scaled with the rest of the type: the bar has
       no room to spare and already crowds the wordmark on phones. */
    font-size: 0.82rem;
    font-weight: 500;
    letter-spacing: .02em;
    color: #3b382f;
    white-space: nowrap;
    text-decoration: none;
    cursor: pointer;
    transition: color .28s ease;
  }
  /* the caret supplies the background, so the item only changes ink */
  .nav-item.lit { color: var(--color-text-inverse); }
  .nav-item:focus-visible {
    outline: 2px solid rgba(35, 33, 28, .45);
    outline-offset: 2px;
  }

  .nav-item .chev {
    width: 9px;
    height: 9px;
    border-right: 1.6px solid currentColor;
    border-bottom: 1.6px solid currentColor;
    transform: translateY(-2px) rotate(45deg);
    transition: transform .25s ease;
  }
  .nav-item[aria-expanded="true"] .chev {
    transform: translateY(1px) rotate(-135deg);
  }

  /* Support dropdown: its own layer, so the bar's overflow can't clip it */
  .menu {
    position: fixed;
    z-index: 30;
    width: 244px;
    padding: 7px;

    background: rgba(255, 255, 255, .55);
    backdrop-filter: blur(18px) saturate(180%);
    -webkit-backdrop-filter: blur(18px) saturate(180%);
    border: 1px solid rgba(255, 255, 255, .70);
    border-radius: 14px;
    box-shadow:
      0 14px 40px rgba(60, 55, 40, .16),
      inset 0 1px 0 rgba(255, 255, 255, .70);

    transform-origin: top right;
    opacity: 0;
    transform: translateY(-6px) scale(.97);
    pointer-events: none;
    transition: opacity .2s ease, transform .26s cubic-bezier(.19, 1, .22, 1);
  }
  .menu.open {
    opacity: 1;
    transform: none;
    pointer-events: auto;
  }

  .menu a {
    display: block;
    padding: 10px 12px;
    border-radius: 9px;
    font-size: 0.9rem;
    color: #3b382f;
    text-decoration: none;
    white-space: nowrap;
    transition: background .18s ease, color .18s ease;
  }
  .menu a:hover,
  .menu a:focus-visible {
    background: rgba(255, 255, 255, .85);
    color: var(--color-text);
    outline: none;
  }

  /* Opens outward from a single lozenge - no fade, no drift.
     Only a `from` block: the browser interpolates back to the rule above. */
  /* Opens outward from a single lozenge, as before - but revealed with a
     clip-path mask rather than by animating width and height, so the browser
     never re-lays-out the bar mid-animation. The mask ends 40px outside the
     bar so the shadow is never clipped, and the fill state keeps it there. */
  @keyframes unfold {
    from { clip-path: inset(0 calc(50% - 34px) round 34px); }
    to   { clip-path: inset(-40px round 16px); }
  }
  }

  /* A single pass of light across the glass once it's open */
  .glass::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: linear-gradient(
      100deg,
      transparent 38%,
      rgba(255, 255, 255, .55) 50%,
      transparent 62%
    );
    transform: translateX(-130%);
    animation: sheen 1.1s cubic-bezier(.4, 0, .2, 1) calc(var(--delay) + .72s) both;
  }

  @keyframes sheen {
    to { transform: translateX(130%); }
  }

  /* product carousel */

  /* Two columns in the same 1100px lane as the bar */
  .hero {
    width: var(--lane);
    margin: 0 auto;
    /* the 22px matches the bar's inner padding, so the panel's left edge
       lines up with the wordmark rather than with the bar's outer edge */
    padding: 152px 22px 46px;       /* top clears the ticker + the fixed bar */

    display: grid;
    grid-template-columns: minmax(0, 470px) minmax(0, 1fr);
    gap: 30px;
    align-items: stretch;
  }

  /* the panel to the left of the carousel */
  .panel-wrap {
    position: relative;             /* the vine hangs off this, not the panel */
    min-width: 0;
  }
  .panel {
    /* A fixed height of its own. Tying it to the carousel (height:100%) made
       it run as tall as the product shot; letting it shrink to the text made
       it stubby. This just sets the card's size. */
    min-height: 540px;
    display: flex;
    flex-direction: column;
    justify-content: flex-start;    /* content sits up top, not centred */
    /* the top padding still has to clear the vine on the left corner */
    padding: 58px 26px 30px;
    /* No entrance: this panel is the first thing read on the page, so it is
       simply there. The header bar keeps its unfold - .glass is shared, which
       is why these opt out here rather than the keyframes being removed. */
    animation: none;
  }
  .panel::after { content: none; }   /* and no sheen sweeping across it */

  /* The headline is the first thing read, so it leads the screen: display
     size, tight leading, and the supporting line sits right under it. */
  .panel h1 {
    margin: 0 0 22px;
    font-family: var(--font-display);
    font-optical-sizing: auto;
    font-size: clamp(2.3rem, 3.2vw, 3.2rem);
    font-weight: 400;               /* variable 300-600 - dial this to taste */
    line-height: 1.02;
    letter-spacing: -.025em;
    text-wrap: balance;
    color: var(--color-text);
  }
  .panel h1 em {                    /* the italic is the whole personality */
    font-style: normal;
    color: inherit;
  }

  .panel p {
    margin: 0 0 30px;
    max-width: 32ch;
    font-size: 1.12rem;
    line-height: 1.55;
    color: var(--color-text-secondary);
  }

  /* Bare text link. The hover decode swaps glyphs; viprtech.js holds the width
     steady while it does, so the body face is fine here. Was: monospace,
     and anything proportional would jitter as the widths changed. */
  .cta {
    align-self: flex-start;
    font-family: var(--font-body);
    font-size: 1rem;
    letter-spacing: .02em;
    color: var(--color-text);
    text-decoration: none;
    border-bottom: 1px solid rgba(35, 33, 28, .28);
    padding-bottom: 3px;
    transition: border-color .25s ease;
  }
  .cta:hover { border-bottom-color: rgba(35, 33, 28, .75); }
  .cta + .cta { margin-top: 13px; }

  /* trust row, pinned to the bottom of the panel */
  .facts {
    list-style: none;
    padding-left: 0;
    margin-bottom: 0;
    margin-top: auto;               /* sits on the floor of the panel */
    padding-top: 22px;
    border-top: 1px solid rgba(35, 33, 28, .1);
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 13px 14px;
  }

  .fact {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.94rem;
    letter-spacing: .01em;
    line-height: 1.25;
    color: var(--color-text-secondary);
  }
  .fact svg {
    width: 16px;
    height: 16px;
    flex: none;
    color: var(--matcha);
    stroke-width: 1.7;
  }

  /* The vine has to live outside .panel - .glass clips its children */
  .vine {
    position: absolute;
    top: -8px;                      /* tip pokes above the panel's top edge */
    left: -5px;
    width: 72px;
    height: auto;
    z-index: 3;
    pointer-events: none;

    transform-origin: 12% 88%;      /* unfurls from its root, bottom-left */
    animation: unfurl 1.1s cubic-bezier(.19, 1, .22, 1) 1.2s both;
  }
  @keyframes unfurl {
    from { opacity: 0; transform: scale(.82) rotate(-7deg); }
  }

  /* perched on the vine, near its lower bend */
  .butterfly {
    position: absolute;
    top: 32px;
    left: 18px;
    width: 27.5px;
    aspect-ratio: 320 / 260;
    z-index: 4;                     /* above the vine */
    pointer-events: none;
    transform: rotate(35deg);
    animation: alight .8s cubic-bezier(.19, 1, .22, 1) 2s both;
  }
  /* keeps the tilt through the reveal - a plain unfurl would unset it */
  @keyframes alight {
    from { opacity: 0; transform: rotate(35deg) scale(.75); }
  }

  @media (max-width: 860px) {
    .vine { width: 60px; top: -6px; left: -4px; }
    .butterfly { width: 23px; top: 25px; left: 15px; }
  }

  .showcase {
    position: relative;
    min-width: 0;                   /* lets the track shrink inside the grid */
  }

  @media (max-width: 860px) {
    .hero {
      grid-template-columns: minmax(0, 1fr);
      padding-top: 138px;
    }
    .panel { order: 2; }
  }

  /* The track is a genuine scroller - wheel, drag and swipe all work,
     and scroll-snap parks it on a whole build every time. */
  .track {
    display: flex;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    /* Scrolling via scrollLeft + this, rather than scrollTo({behavior:'smooth'}):
       mandatory snap can abort an in-flight programmatic smooth scroll and
       snap back to where it started. */
    scroll-behavior: smooth;
    scrollbar-width: none;          /* the dots are the affordance */
  }
  .track::-webkit-scrollbar { display: none; }

  .slide {
    flex: 0 0 100%;
    box-sizing: border-box;         /* keeps the padding inside the 100%, so
                                       clientWidth × index still lands true */
    scroll-snap-align: center;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 22px;
    /* The track scrolls horizontally, which forces it to clip vertically too.
       The shadow reaches ~62px below the case, so the bottom padding has to
       clear that as well as the name underneath it. */
    padding: 40px 24px 78px;
  }

  .slide img {
    /* A fixed stage: every build gets the same box and `contain` fits it
       inside, so nothing spills toward the panel or down over the name -
       whatever shape or size the photo is. */
    width: 100%;
    max-width: min(640px, 100%);
    /* the build is what's for sale, so it gets the most room on screen */
    height: min(54vh, 520px);
    object-fit: contain;
    /* Two stacked shadows ground the cut-out render on the flat ivory: a
       tight one for contact, a wide soft one for the ambient cast.
       Each offset is larger than its blur, so neither shadow reaches above
       the image - nothing up there for the scroll container to clip. */
    filter:
      drop-shadow(0 11px 9px rgba(60, 55, 40, .30))
      drop-shadow(0 34px 28px rgba(60, 55, 40, .36));

    transform: scale(.94);
    opacity: .55;
    transition: transform .7s cubic-bezier(.19, 1, .22, 1), opacity .5s ease;
  }
  .slide.is-active img {
    transform: scale(1);
    opacity: 1;
  }

  .slide h2 {
    margin: 0;
    font-size: clamp(1.5rem, 4vw, 2.3rem);
    font-weight: 600;
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--color-text);
    transition: opacity .5s ease .1s, transform .5s ease .1s;
  }
  /* the name waits for its slide only when the carousel script is running */
  .js .slide h2 { opacity: 0; transform: translateY(6px); }
  .slide.is-active h2 { opacity: 1; transform: none; }

  /* diamond over label: the active diamond floods over the 3s dwell */
  .dots {
    display: flex;
    justify-content: center;
    gap: 34px;
    margin-top: -34px;              /* the track's bottom padding sits above */
  }

  .dot {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 9px;
    padding: 0;
    border: none;
    background: none;
    cursor: pointer;

    font-family: inherit;
    font-size: 0.86rem;
    letter-spacing: 0;
    text-transform: none;
    /* the inactive names are still links, so they keep readable contrast */
    color: var(--color-text-muted);
    transition: color .45s ease;
  }
  .dot:hover,
  .dot[aria-current="true"] { color: var(--color-text); }
  .dot:focus-visible {
    outline: 2px solid rgba(35, 33, 28, .4);
    outline-offset: 4px;
    border-radius: 3px;
  }

  /* a diamond is just a square stood on its corner */
  .dot i {
    display: block;
    width: 10px;
    height: 10px;
    border-radius: 3px;             /* softens the four points */
    transform: rotate(45deg);
    background: linear-gradient(0deg, var(--color-fill-strong) 0 0) no-repeat,
                rgba(35, 33, 28, .16);
    background-size: 100% 0%;
    background-position: bottom;    /* so it fills upward */
  }
  .dot[aria-current="true"] i {
    animation: dwell 3s linear forwards;
  }
  .showcase.is-paused .dot i { animation-play-state: paused; }

  /* This animation is the carousel's clock - see the animationend handler. */
  @keyframes dwell { to { background-size: 100% 100%; } }

  /* arrows */
  .arrow {
    position: absolute;
    top: calc(50% + 20px);
    transform: translateY(-50%);
    width: 46px;
    height: 46px;
    display: grid;
    place-items: center;

    border: 1px solid rgba(255, 255, 255, .70);
    border-radius: 999px;
    background: rgba(255, 255, 255, .45);
    backdrop-filter: blur(10px) saturate(180%);
    -webkit-backdrop-filter: blur(10px) saturate(180%);
    box-shadow: 0 6px 20px rgba(60, 55, 40, .12);

    color: var(--color-text);
    font-size: 1.16rem;
    cursor: pointer;
    opacity: 0;
    transition: opacity .3s ease, background .2s ease, scale .12s ease-out;
  }
  .showcase:hover .arrow,
  .arrow:focus-visible { opacity: 1; }
  .arrow:hover { background: rgba(255, 255, 255, .75); }
  .arrow.prev { left: max(18px, 4vw); }
  .arrow.next { right: max(18px, 4vw); }

  @media (prefers-reduced-motion: reduce) {
    .glass, .glass::after, .dot i, .ticker, .ticker__row { animation: none; }
    .glass::after { opacity: 0; }
    .slide img, .slide h2 { transition: none; }
  }
/* Store pages (product, collection, cart, search...). These weren't
   in the original design - deliberately plain, in the same palette,
   so they read as the same site until you style them properly. */

.pad {
  width: var(--lane);
  margin: 0 auto;
  padding: 152px 22px 90px;        /* clears the ticker + fixed bar */
}
.pad--narrow { max-width: 760px; }

.page-title {
  margin: 0 0 34px;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.9rem, 3.4vw, 2.8rem);
  letter-spacing: -.01em;
  color: var(--color-text);
}

/* product */
.prod {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr);
  gap: 48px;
  /* stretch, not start: both columns then share the taller column's height,
     so the trailing block in each (case card / trust row) can be pinned to
     the shared bottom line below instead of trailing at its own height */
  align-items: stretch;
}
.prod img { width: 100%; height: auto; }
.prod__media { display: flex; flex-direction: column; }
.prod__info { display: flex; flex-direction: column; }
/* auto top-margin absorbs the leftover column height, flush-aligning the
   case card and the trust row to the same bottom line */
.prod__media .casecard { margin-top: auto; }

/* Breathing room under the thumbnails. It goes on the gallery rather than the
   card: the card's own margin-top is auto so it can bottom-align, and an
   explicit margin there would override that. Spacing the gallery pushes the
   card down when the columns are already the same height (the usual case)
   without disturbing the alignment when there is slack to absorb. */
.prod__media .gallery { margin-bottom: 20px; }
.prod__info .prod__facts { margin-top: auto; }
.prod__info h1 {
  margin: 0 0 10px;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.7rem, 3vw, 2.4rem);
  letter-spacing: -.01em;
}
.prod__price { margin: 0 0 26px; font-size: 1.11rem; color: rgba(35, 33, 28, .7); }
.prod__label {
  display: block;
  margin: 14px 0 6px;
  font-size: .9rem;
  letter-spacing: 0;
  text-transform: none;
  color: var(--color-text-muted);
}
.prod__select {
  width: 100%;
  padding: 10px 12px;
  font: inherit;
  font-size: 0.93rem;
  color: var(--color-text);
  background: rgba(255, 255, 255, .6);
  border: 1px solid rgba(35, 33, 28, .18);
  border-radius: 8px;
}
.prod__desc { margin-top: 30px; font-size: 1.06rem; }

/* the one solid button in the theme - carts need an obvious target */
.cta--solid {
  position: relative;
  display: inline-block;
  margin-top: 22px;
  padding: 12px 20px;
  border: none;
  border-radius: 8px;
  background: var(--color-fill-strong);
  color: var(--color-text-inverse);
  font-family: var(--font-body);
  font-size: 0.88rem;
  letter-spacing: .02em;
  cursor: pointer;
  transition: background .2s ease, scale .12s ease-out;
}
.cta--solid:hover { background: #35322a; }
.cta--solid[disabled] { opacity: .45; cursor: not-allowed; }
.cta--solid.is-loading { opacity: .7; cursor: progress; }

/* the label swaps for a confirmation via ::after, not textContent - the
   variant-select script owns the real label and keeps writing to it
   (e.g. flipping to "Sold out") even while this class is briefly on */
.cta--solid.is-added {
  background: var(--matcha-deep);
  color: transparent;
}
.cta--solid.is-added::after {
  content: "Added \2713";
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-text-inverse);
}

.cta--ghost {
  display: inline-block;
  margin-top: 22px;
  padding: 11px 20px;
  background: none;
  border: 1px solid rgba(35, 33, 28, .25);
  border-radius: 8px;
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: 0.88rem;
  letter-spacing: .02em;
  cursor: pointer;
  transition: border-color .2s ease, background .2s ease, scale .12s ease-out;
}
.cta--ghost:hover { background: rgba(35, 33, 28, .05); border-color: rgba(35, 33, 28, .4); }

/* "added to cart" toast
   Always in the DOM (never [hidden]) so the entrance can transition; a
   class toggles it instead. */
.toast {
  position: fixed;
  right: 24px;
  bottom: 24px;
  z-index: 60;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 16px 18px;
  max-width: 340px;
  border-radius: 14px;
  background: rgba(255, 255, 255, .88);
  backdrop-filter: blur(16px) saturate(180%);
  -webkit-backdrop-filter: blur(16px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, .7);
  box-shadow:
    0 12px 40px rgba(60, 55, 40, .18),
    inset 0 1px 0 rgba(255, 255, 255, .7);
  transform: translateY(18px) scale(.97);
  opacity: 0;
  pointer-events: none;
  transition: transform .4s cubic-bezier(.19, 1, .22, 1), opacity .3s ease;
}
.toast.is-visible {
  transform: translateY(0) scale(1);
  opacity: 1;
  pointer-events: auto;
}

.toast__icon {
  flex: none;
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: rgba(124, 154, 87, .16);
  color: var(--matcha-deep);
}
.toast__icon svg { width: 16px; height: 16px; }
.toast__alert { display: none; }

/* rejected add - usually "there are only N in stock" from Shopify */
.toast.is-error .toast__icon {
  background: rgba(179, 70, 44, .14);
  color: #b3462c;
}
.toast.is-error .toast__check { display: none; }
.toast.is-error .toast__alert { display: block; }
.toast.is-error .toast__item { white-space: normal; }
.toast.is-error .toast__link { display: none; }
/* only the checkmark draws itself in; the alert icon is just shown */
.toast__check path {
  stroke-dasharray: 26;
  stroke-dashoffset: 26;
}
.toast.is-visible .toast__check path { animation: toastCheck .5s ease .15s forwards; }
@keyframes toastCheck { to { stroke-dashoffset: 0; } }

.toast__body { min-width: 0; display: flex; flex-direction: column; }
.toast__title {
  font-family: var(--font-display);
  font-size: 1rem;
  color: var(--color-text);
}
.toast__item {
  margin-top: 2px;
  font-family: var(--font-body);
  font-size: 0.8rem;
  color: var(--color-text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.toast__link {
  flex: none;
  margin-left: auto;
  font-family: var(--font-body);
  font-size: 0.82rem;
  color: var(--matcha-deep);
  text-decoration: none;
  border-bottom: 1px solid rgba(124, 154, 87, .4);
  padding-bottom: 2px;
}
.toast__link:hover { border-bottom-color: var(--matcha-deep); }

@media (prefers-reduced-motion: reduce) {
  .toast { transition: opacity .2s ease; transform: none; }
  .toast__check path { animation: none; stroke-dashoffset: 0; }
}

@media (max-width: 480px) {
  .toast { left: 16px; right: 16px; bottom: 16px; max-width: none; }
}

/* cart */
.cart-empty {
  max-width: 420px;
  margin: 0 auto;
  padding: 60px 0 40px;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.cart-empty__icon {
  width: 62px;
  height: 62px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: rgba(124, 154, 87, .12);
  color: var(--matcha-deep);
  margin-bottom: 20px;
}
.cart-empty__icon svg { width: 28px; height: 28px; }
.cart-empty .page-title { margin: 0 0 8px; }
.cart-empty p { margin: 0 0 24px; color: var(--color-text-muted); }
.cart-empty .cta--solid { margin-top: 0; }

.cart-count-label {
  font-family: var(--font-body);
  font-size: 1.06rem;
  font-weight: 400;
  color: var(--color-text-muted);
}

.cart-layout {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
  align-items: start;
  gap: 48px;
  margin-top: 34px;
}

.cart-lines { display: flex; flex-direction: column; gap: 20px; min-width: 0; }

.line {
  display: grid;
  grid-template-columns: 84px minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 20px;
  padding-bottom: 20px;
  border-bottom: 1px solid rgba(35, 33, 28, .1);
  min-width: 0;
}

.line__media {
  position: relative;
  width: 84px;
  height: 84px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 10px;
  background: rgba(255, 255, 255, .5);
  border: 1px solid rgba(35, 33, 28, .08);
  overflow: hidden;
}
/* The photo is wrapped in a link. Left inline, that anchor has no definite
   height, so max-height:100% on the image resolves against nothing, the image
   renders at its full attribute size and overflow:hidden crops it. Giving the
   anchor the box makes the percentages resolve. */
.line__media a {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  padding: 6px;
  box-sizing: border-box;
}
.line__media img { max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain; }

.line__info { min-width: 0; }
.line__title {
  display: block;
  font-family: var(--font-display);
  font-size: 1.11rem;
  color: var(--color-text);
  text-decoration: none;
}
.line__title:hover { color: var(--matcha-deep); }
.line__variant {
  margin: 4px 0 0;
  font-family: var(--font-body);
  font-size: .92rem;
  color: var(--color-text-muted);
}
.line__specs {
  margin: 6px 0 0;
  font-size: .96rem;
  color: var(--color-text-muted);
}
.line__remove {
  margin-top: 10px;
  padding: 0;
  border: none;
  background: none;
  font-family: var(--font-body);
  font-size: 0.8rem;
  letter-spacing: 0;
  color: var(--color-text-muted);
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}
.line__remove:hover { color: #b3462c; }

.line__qtywrap { display: flex; flex-direction: column; align-items: center; gap: 6px; }
.line__qty-label {
  font-size: .9rem;
  letter-spacing: 0;
  text-transform: none;
  color: var(--color-text-muted);
}
.line__qty {
  width: 58px;
  padding: 8px 6px;
  text-align: center;
  border: 1px solid rgba(35, 33, 28, .18);
  border-radius: 8px;
  background: rgba(255, 255, 255, .6);
  font-family: var(--font-body);
  font-size: 0.93rem;
  color: var(--color-text);
}
.line__update {
  padding: 5px 10px;
  border: 1px solid rgba(35, 33, 28, .2);
  border-radius: 6px;
  background: none;
  font-family: var(--font-body);
  font-size: 0.78rem;
  letter-spacing: 0;
  color: var(--color-text-muted);
  cursor: pointer;
  transition: border-color .2s ease, color .2s ease;
}
.line__update:hover { border-color: var(--matcha-deep); color: var(--matcha-deep); }
.line__cap {
  font-family: var(--font-body);
  font-size: .9rem;
  letter-spacing: 0;
  text-transform: none;
  color: #b3462c;
}

.line__prices { text-align: right; }
.line__unit {
  margin: 0 0 4px;
  font-family: var(--font-body);
  font-size: 0.8rem;
  color: var(--color-text-muted);
  white-space: nowrap;
}
.line__unit s { opacity: .6; margin-right: 4px; }
.line__price {
  margin: 0;
  min-width: 80px;
  font-family: var(--font-body);
  font-size: 1rem;
  color: var(--color-text);
}

/* order summary panel */
.cart-summary {
  width: 100%;
  padding: 26px;
  border-radius: 16px;
  background: rgba(255, 255, 255, .35);
  backdrop-filter: blur(16px) saturate(180%);
  -webkit-backdrop-filter: blur(16px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, .6);
  box-shadow:
    0 8px 32px rgba(60, 55, 40, .10),
    inset 0 1px 0 rgba(255, 255, 255, .70);
  position: sticky;
  top: 168px;
  min-width: 0;
  box-sizing: border-box;
}
.cart-summary h2 {
  margin: 0 0 18px;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.16rem;
}
.cart-summary__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  font-size: 1rem;
  color: rgba(35, 33, 28, .7);
}
.cart-summary__row strong { color: var(--color-text); font-size: 1.21rem; }
.cart-summary__note {
  margin: 8px 0 0;
  font-size: 0.82rem;
  color: var(--color-text-muted);
}

.cart-checkout { width: 100%; text-align: center; margin-top: 20px; }

/* fit-content, so the underline is only as wide as the words */
.cart-summary__continue {
  display: block;
  width: fit-content;
  margin: 14px auto 0;
  font-family: var(--font-body);
  font-size: 0.86rem;
  color: var(--matcha-deep);
  text-decoration: none;
  border-bottom: 1px solid transparent;
}
.cart-summary__continue:hover { border-bottom-color: var(--matcha-deep); }

.cart-summary__facts {
  list-style: none;
  margin: 24px 0 0;
  padding-top: 20px;
  border-top: 1px solid rgba(35, 33, 28, .1);
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px 14px;
}
.cart-summary__facts li {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 0.8rem;
  color: var(--color-text-muted);
}
/* When the cart mixes covered and salvage builds, this line turns into a
   disclosure naming both, so the claim can't overstate what's covered. It
   sits in a column like the other facts, and only takes the full width once
   the list is open and needs the room. */
.cart-summary__warranty:has(details[open]) {
  grid-column: 1 / -1;
  align-items: flex-start;
}
/* A salvage-only cart states the absence plainly, in the same red the rest
   of the site uses for a restriction. */
.cart-summary__nowarranty { color: #b3462c; }
.cart-summary__nowarranty svg { color: #b3462c; }

.warranty-note { min-width: 0; }
.warranty-note summary {
  cursor: pointer;
  list-style: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.warranty-note summary::-webkit-details-marker { display: none; }

/* a small chevron, turning when the list opens */
.warranty-note summary::after {
  content: "";
  width: 5px;
  height: 5px;
  border-right: 1px solid currentColor;
  border-bottom: 1px solid currentColor;
  transform: rotate(45deg) translate(-1px, -1px);
  transition: transform .2s ease;
}
.warranty-note[open] summary::after {
  transform: rotate(-135deg) translate(-2px, -2px);
}

.warranty-note__body { margin-top: 10px; }
.warranty-note__head {
  margin: 0 0 4px;
  font-family: var(--font-body);
  font-size: .9rem;
  letter-spacing: 0;
  text-transform: none;
  color: var(--color-text-muted);
}
.warranty-note__body ul {
  list-style: none;
  margin: 0 0 12px;
  padding: 0;
  display: grid;
  gap: 3px;
}
.warranty-note__body li {
  display: block;
  font-size: .8rem;
  color: rgba(35, 33, 28, .72);
}
.warranty-note__why {
  margin: 0;
  font-size: .78rem;
  line-height: 1.5;
  color: #b3462c;
}

.cart-summary__facts svg {
  width: 14px;
  height: 14px;
  flex: none;
  color: var(--matcha);
  stroke-width: 1.8;
}

@media (max-width: 860px) {
  .cart-layout { grid-template-columns: minmax(0, 1fr); }
  .cart-summary { position: static; }
}

@media (max-width: 560px) {
  .line {
    grid-template-columns: 64px minmax(0, 1fr);
    grid-template-areas: "media info" "media qty" "media price";
    row-gap: 10px;
  }
  .line__media { width: 64px; height: 64px; grid-area: media; }
  .line__info { grid-area: info; min-width: 0; }
  .line__qtywrap { grid-area: qty; align-items: flex-start; }
  .line__prices { grid-area: price; text-align: left; }
  .line__unit { white-space: normal; }
}

/* you might also like (product pages)
   A real scroller, like the home page carousel: wheel, drag and swipe all
   work and the arrows only nudge it along. */
.also {
  width: var(--lane);
  margin: 0 auto;
  padding: 0 22px 90px;
  box-sizing: border-box;
}

.also__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 22px;
}

.also__title {
  margin: 0;
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-weight: 400;
  font-size: clamp(1.4rem, 2.2vw, 1.75rem);
  line-height: 1.1;
  letter-spacing: -.01em;
  color: var(--color-text);
}

.also__nav { display: flex; gap: 8px; flex: none; }

.also__arrow {
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  border: 1px solid rgba(35, 33, 28, .18);
  border-radius: 50%;
  background: rgba(255, 255, 255, .5);
  font-size: .8rem;
  color: var(--color-text);
  cursor: pointer;
  transition: border-color .2s ease, background .2s ease, opacity .2s ease, scale .12s ease-out;
}
.also__arrow:hover { border-color: var(--color-fill-strong); background: rgba(255, 255, 255, .8); }
.also__arrow:focus-visible { outline: 2px solid var(--matcha); outline-offset: 3px; }
.also__arrow[disabled] { opacity: .35; cursor: not-allowed; background: transparent; color: var(--color-text-muted); }
.also__arrow[disabled]:hover { border-color: rgba(35, 33, 28, .18); background: rgba(255, 255, 255, .5); }

/* the arrows are a mouse affordance - a touch screen just swipes */
@media (hover: none) {
  .also__nav { display: none; }
}

.also__track {
  display: flex;
  /* Wider than the card shadow's 32px blur. At 20px the neighbouring
     shadows overlapped and, since the card fill is semi-transparent glass,
     showed through as a hard seam down the side of the card. */
  gap: 34px;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  scroll-behavior: smooth;
  scrollbar-width: none;
  /* A scroller crops at its own edges, and these cards lift on hover and
     carry a soft shadow well outside their box. The padding gives that room
     on all four sides; the matching negative margin puts the first card back
     on the same line as the heading. */
  padding: 12px 22px 30px;
}

/* The ends dissolve into the page rather than being sliced off, the same idea
   the ticker uses at its own edges. These live on the frame, not the track:
   the track is the scroller, so anything painted on it would slide away with
   the cards. Each side only appears when there is something past it to scroll
   to - a fade over the first card while the row is parked at the start reads
   as a bug, not a hint. */
.also__frame {
  position: relative;
  margin: 0 -22px;
}

.also__frame::before,
.also__frame::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  width: 96px;
  z-index: 2;
  pointer-events: none;
  opacity: 0;
  transition: opacity .25s ease;
}
.also__frame::before {
  left: 0;
  background: linear-gradient(90deg, var(--color-page) 14%, rgba(252, 251, 244, 0));
}
.also__frame::after {
  right: 0;
  background: linear-gradient(270deg, var(--color-page) 14%, rgba(252, 251, 244, 0));
}
.also__frame.can-prev::before { opacity: 1; }
.also__frame.can-next::after  { opacity: 1; }

/* Top and bottom, the same idea running the other way. These are always on:
   the row only scrolls sideways, so there is never anything above or below to
   scroll to. Both are set just deep enough to cover the track's own padding
   and take the hard edge off the cards and their shadows - any deeper and it
   starts eating the product photos. */
.also__veil {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background: linear-gradient(
    180deg,
    var(--color-page) 0,
    rgba(252, 251, 244, 0) 26px,
    rgba(252, 251, 244, 0) calc(100% - 38px),
    #FCFBF4 100%);
}
.also__track::-webkit-scrollbar { display: none; }

.also__track > .build {
  flex: 0 0 clamp(232px, 25vw, 290px);
  scroll-snap-align: start;
}

/* collection + search grid */
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 34px 26px;
}
.card { text-decoration: none; color: inherit; display: block; }
.card img {
  width: 100%;
  height: auto;
  filter: drop-shadow(0 11px 9px rgba(60, 55, 40, .18));
  transition: transform .5s cubic-bezier(.19, 1, .22, 1);
}
.card:hover img { transform: translateY(-5px); }
.card h2 {
  margin: 16px 0 4px;
  font-size: 0.9rem;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
}
.card__price { margin: 0; font-size: 0.9rem; color: var(--color-text-muted); }

/* blog */
.post { padding: 22px 0; border-bottom: 1px solid rgba(35, 33, 28, .1); }
.post a { color: inherit; text-decoration: none; }
.post h2 { margin: 0 0 6px; font-family: var(--font-display); font-weight: 400; }
.post__date { margin: 0 0 10px; font-size: 0.88rem; color: var(--color-text-muted); }

.rte { line-height: 1.7; color: rgba(35, 33, 28, .74); }
.rte a { color: var(--matcha-deep); }

/* footer */
.vt-footer {
  margin-top: 90px;
  background: #F4F1E6;           /* a step deeper than the page: the edge without a line */
}
.vt-footer__inner {
  width: var(--lane);
  margin: 0 auto;
  padding: 54px 22px 26px;
}

.vt-footer__top {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) repeat(3, minmax(0, 1fr));
  gap: 40px;
  padding-bottom: 40px;
}

.vt-footer__mark {
  margin: 0 0 14px;
  font-family: var(--font-brand);
  font-size: .82rem;
  line-height: 1;
  color: var(--color-text);
}
.vt-footer__mark span { opacity: .42; }

.vt-footer__blurb {
  margin: 0 0 20px;
  max-width: 34ch;
  font-size: .98rem;
  line-height: 1.6;
  color: var(--color-text-secondary);
}

.vt-footer__social { display: flex; align-items: center; gap: 6px; }
.vt-footer__social a {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: 8px;
  color: var(--matcha);
  transition: color .22s ease, background .22s ease, transform .22s cubic-bezier(.19, 1, .22, 1);
}
.vt-footer__social a:hover {
  color: var(--matcha-deep);
  background: rgba(124, 154, 87, .12);
  transform: translateY(-2px);
}
.vt-footer__social svg { width: 17px; height: 17px; display: block; }

.vt-footer__col h2 {
  /* a column title, read like one - not a tiny tracked label */
  margin: 0 0 14px;
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: 400;
  color: var(--color-text);
}
.vt-footer__col ul { margin: 0; padding: 0; list-style: none; }
.vt-footer__col li { margin-bottom: 9px; }
.vt-footer__col a {
  position: relative;
  font-size: .98rem;
  color: var(--color-text-secondary);
  text-decoration: none;
  transition: color .18s ease;
}
.vt-footer__col a:hover { color: var(--color-text); }

.vt-footer__hours {
  margin: 14px 0 0;
  font-size: .9rem;
  line-height: 1.55;
  color: rgba(35, 33, 28, .7);
}
.vt-footer__hours span { display: block; }

/* legal bar */
.vt-footer__bar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px 26px;
  padding-top: 34px;             /* set apart by space, not a rule */
}
.vt-footer__fine {
  margin: 0;
  font-size: .86rem;
  color: var(--color-text-muted);
}
.vt-footer__legal { display: flex; flex-wrap: wrap; gap: 18px; }
.vt-footer__legal a {
  position: relative;
  font-size: .86rem;
  color: rgba(35, 33, 28, .7);
  text-decoration: none;
  transition: color .18s ease;
}
.vt-footer__legal a:hover { color: var(--color-text); }

/* Hovering a footer link draws a line under it, left to right. A scaleX on a
   pseudo-element rather than an animated width, so it stays on the compositor
   and the text never reflows. */
.vt-footer__col a::after,
.vt-footer__legal a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -3px;
  height: 1px;
  background: var(--color-fill-strong);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform .3s cubic-bezier(.19, 1, .22, 1);
}
.vt-footer__col a:hover::after,
.vt-footer__col a:focus-visible::after,
.vt-footer__legal a:hover::after,
.vt-footer__legal a:focus-visible::after {
  transform: scaleX(1);
}

@media (prefers-reduced-motion: reduce) {
  .vt-footer__col a::after,
  .vt-footer__legal a::after { transition: none; }
}

.vt-footer__pay {
  display: flex;
  align-items: center;
  gap: 7px;
  margin: 0 0 0 auto;
  padding: 0;
  list-style: none;
}
.vt-footer__pay li { display: flex; }
.vt-footer__pay-icon { width: 34px; height: 22px; display: block; }

@media (max-width: 860px) {
  .vt-footer__top { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 32px; }
}
@media (max-width: 520px) {
  .vt-footer__top { grid-template-columns: minmax(0, 1fr); }
  .vt-footer__pay { margin-left: 0; }
}

@media (max-width: 860px) {
  .prod { grid-template-columns: minmax(0, 1fr); gap: 30px; }
  .pad { padding-top: 138px; }
}

/* The slide is a link in the theme (it wasn't in the static mockup). Without
   this the anchor is inline, so the title aligns to the link box rather than
   the image, and picks up the default underline. */
.slide a {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 22px;
  text-decoration: none;
  color: inherit;
}

/* The dropdown item for the page you're already on */
.menu a[aria-current="page"] {
  background: rgba(255, 255, 255, .85);
  color: var(--color-text);
  font-weight: 600;
}

/* Price under each build in the carousel. Pulled from the product, so it
   always matches what's listed in Shopify. */
.slide-price {
  margin: -8px 0 0;
  font-family: var(--font-body);
  font-size: 1.03rem;
  letter-spacing: .04em;
  color: var(--color-text-muted);
}
/* struck original, same red as the product cards' was-price */
.slide-was {
  margin-left: 10px;
  color: #b3462c;
  text-decoration-color: #b3462c;
  font-size: .86em;
}
.slide-price .sold {
  margin-left: 8px;
  font-size: 0.9rem;
  letter-spacing: 0;
  text-transform: none;
  color: var(--color-text-muted);
}

/* variant picker: swatches, not a dropdown */
.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* colour picker on the left, quantity + add-to-cart on the right of it -
   keeps the right column compact so the spec sheet and the case card don't
   trail behind a tall gap under the photo */
.prod__row {
  display: flex;
  align-items: flex-start;
  flex-wrap: wrap;
  gap: 20px 56px;
}
.prod__row-left { flex: none; min-width: 0; }
.prod__row-right { flex: none; }

.opt { margin: 24px 0; }

.opt__head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin: 0 0 11px;
}
.opt__name {
  font-size: .9rem;
  letter-spacing: 0;
  text-transform: none;
  color: var(--color-text-muted);
}
.opt__value {
  font-family: var(--font-body);
  font-size: 0.92rem;
  color: var(--color-text);
}

.swatches { display: flex; flex-wrap: wrap; gap: 10px; }

.swatch { cursor: pointer; }
.swatch input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

/* colour circles */
.swatch__dot {
  display: block;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--dot);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .5),
    inset 0 0 0 1px rgba(35, 33, 28, .18);
  transition: transform .25s cubic-bezier(.19, 1, .22, 1),
              box-shadow .25s ease;
}
.swatch--dot:hover .swatch__dot { transform: scale(1.08); }

/* the ring sits outside the circle, so it reads on dark and light alike */
.swatch input:checked + .swatch__dot {
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .5),
    inset 0 0 0 1px rgba(35, 33, 28, .18),
    0 0 0 2px #FCFBF4,
    0 0 0 4px #23211c;
}
.swatch input:focus-visible + .swatch__dot {
  box-shadow:
    inset 0 0 0 1px rgba(35, 33, 28, .18),
    0 0 0 2px #FCFBF4,
    0 0 0 4px var(--matcha);
}

/* anything that isn't a colour gets a pill instead */
.swatch__label {
  display: block;
  padding: 9px 15px;
  border-radius: 8px;
  border: 1px solid rgba(35, 33, 28, .18);
  font-family: var(--font-body);
  font-size: 0.9rem;
  color: rgba(35, 33, 28, .7);
  transition: border-color .2s ease, color .2s ease, background .2s ease;
}
.swatch--pill:hover .swatch__label { border-color: rgba(35, 33, 28, .4); }
.swatch input:checked + .swatch__label {
  background: var(--color-fill-strong);
  border-color: var(--color-fill-strong);
  color: var(--color-text-inverse);
}

/* product gallery */
.gallery__main {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
  border-radius: 14px;
}
.gallery__main::-webkit-scrollbar { display: none; }

.shot {
  flex: 0 0 100%;
  scroll-snap-align: center;
  margin: 0;
  padding: 0 0 14px;
}
.shot[hidden] { display: none; }
.shot img {
  /* Every frame is the same box, whatever the photo's shape. Some of your
     shots are landscape and some portrait - `contain` fits them inside
     without cropping or stretching, so the page never jumps between slides. */
  width: 100%;
  height: min(58vh, 560px);
  object-fit: contain;
  display: block;
  /* offset larger than the blur, so nothing reaches above to be clipped */
  filter: drop-shadow(0 14px 12px rgba(60, 55, 40, .18));
}

.gallery__thumbs {
  display: flex;
  gap: 10px;
  margin-top: 6px;
  flex-wrap: wrap;
}
.thumb {
  width: 62px;
  height: 62px;
  padding: 4px;
  /* Same fix as .build__media: without border-box, the 4px padding is added
     on top of the fixed size instead of being carved out of it, so the
     image inside never actually gets less room to fill. */
  box-sizing: border-box;
  border: 1px solid rgba(35, 33, 28, .14);
  border-radius: 10px;
  background: rgba(255, 255, 255, .5);
  cursor: pointer;
  transition: border-color .2s ease, transform .25s cubic-bezier(.19, 1, .22, 1);
}
.thumb[hidden] { display: none; }
.thumb img { width: 100%; height: 100%; object-fit: contain; display: block; }
.thumb:hover { transform: translateY(-2px); border-color: rgba(35, 33, 28, .32); }
.thumb[aria-current="true"] { border-color: var(--color-fill-strong); }

/* the finishes each build comes in, under its name in the carousel */
.slide-colors {
  display: flex;
  justify-content: center;
  gap: 7px;
  margin: -10px 0 0;
  padding: 0;
  list-style: none;
}
.slide-colors li { display: block; line-height: 0; }
.slide-colors i {
  display: block;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: var(--dot);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .45),
    inset 0 0 0 1px rgba(35, 33, 28, .2);
}

/* collection: glass build cards */
.coll__head { margin-bottom: 40px; }
.coll__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}
.coll__tools {
  display: flex;
  align-items: center;
  gap: 10px;
}

/* sort */
.sort { position: relative; }
/* it sits on the left of the pair, so its panel opens from that edge */
.sort__panel { left: 0; right: auto; }

.sort__options {
  display: grid;
  gap: 2px;
}
.sort__opt {
  padding: 8px 10px;
  border: none;
  border-radius: 8px;
  background: none;
  text-align: left;
  font-family: var(--font-body);
  font-size: .82rem;
  color: rgba(35, 33, 28, .72);
  cursor: pointer;
  transition: background .18s ease, color .18s ease;
}
.sort__opt:hover { background: rgba(35, 33, 28, .05); }
.sort__opt:focus-visible { outline: 2px solid var(--matcha); outline-offset: 2px; }
.sort__opt[aria-checked="true"] {
  background: var(--color-fill-strong);
  color: var(--color-text-inverse);
}
.coll__desc { max-width: 62ch; margin-bottom: 10px; }
.coll__count {
  margin: 0;
  font-family: var(--font-body);
  font-size: .9rem;
  letter-spacing: 0;
  text-transform: none;
  color: var(--color-text-muted);
}

.builds {
  display: grid;
  /* min(300px, 100%) rather than a bare 300px: on a phone the container is
     narrower than that, and a bare minimum forces a 300px track that pushes
     the whole page sideways. */
  grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr));
  gap: 26px;
}

/* the site's glass surface, as a card */
.build {
  display: block;
  padding: 20px;
  border-radius: 16px;
  text-decoration: none;
  color: inherit;

  background: rgba(255, 255, 255, .35);
  backdrop-filter: blur(16px) saturate(180%);
  -webkit-backdrop-filter: blur(16px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, .60);
  box-shadow:
    0 8px 32px rgba(60, 55, 40, .10),
    inset 0 1px 0 rgba(255, 255, 255, .70);

  transition: transform .35s cubic-bezier(.19, 1, .22, 1), box-shadow .35s ease;
}
.build:hover {
  transform: translateY(-4px);
  box-shadow:
    0 16px 40px rgba(60, 55, 40, .16),
    inset 0 1px 0 rgba(255, 255, 255, .70);
}

/* Fixed media box, so every card lines up whatever shape the photo is.
   overflow:hidden is load-bearing: Shopify's image_tag sets width/height
   HTML attributes from the source file's own size, and while the image is
   still loading (or if those attributes win a sizing tug-of-war) it can
   render larger than this box and bleed into the row below - which is
   exactly what was happening. Locking width/height to 100% + object-fit
   makes the box authoritative no matter what the tag's attributes say. */
.build__link {
  display: block;
  text-decoration: none;
  color: inherit;
}

.build__media {
  position: relative;               /* holds the sold out stamp */
  height: 250px;
  box-sizing: border-box;
  padding: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Deliberately NO overflow:hidden. Combined with the max-width/max-height
     on the image below, nothing can ever exceed this box - so there is
     nothing to clip. Clipping was the only mechanism that could crop a
     product photo here; removing it makes cropping structurally impossible
     rather than merely unlikely. */
}

.build__media img {
  /* max-* + auto (rather than width/height:100% + object-fit) means the image
     shrinks to fit and keeps its aspect ratio by itself. Even if a rule here
     ever fails to apply, the worst case is a slightly larger image - never a
     cropped one. Holds for any crop or orientation, including future builds. */
  display: block;
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  filter: drop-shadow(0 8px 7px rgba(60, 55, 40, .18));
}

.build__name {
  margin: 14px 0 2px;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.55rem;
  letter-spacing: -.01em;
}
.build__price {
  margin: 0 0 14px;
  font-family: var(--font-body);
  font-size: 0.98rem;
  color: var(--color-text-muted);
}
.build__price .sold {
  margin-left: 8px;
  font-size: .9rem;
  letter-spacing: 0;
  text-transform: none;
  color: var(--color-text-muted);
}

.build__specs {
  margin: 0 0 16px;
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 5px 12px;
  font-size: .92rem;
}
.build__specs dt {
  font-family: var(--font-body);
  font-size: .9rem;
  letter-spacing: 0;
  color: var(--color-text-muted);
}
.build__specs dd { margin: 0; text-align: right; }

.build__colors {
  display: flex;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Reset the button chrome - the coloured dot inside is the whole control. */
.build__swatch {
  display: block;
  padding: 4px;          /* invisible hit area, so the 13px dot is tappable */
  margin: -4px;
  border: 0;
  background: none;
  cursor: pointer;
  line-height: 0;
}
.build__swatch i {
  display: block;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: var(--dot);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .45),
    inset 0 0 0 1px rgba(35, 33, 28, .2);
  transition: transform .22s cubic-bezier(.19, 1, .22, 1), box-shadow .22s ease;
}
.build__swatch:hover i,
.build__swatch:focus-visible i {
  transform: scale(1.55);
}
/* the ring sits outside the dot, so it reads on a white swatch and a black one */
.build__swatch[aria-pressed=true] i {
  transform: scale(1.35);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .45),
    inset 0 0 0 1px rgba(35, 33, 28, .2),
    0 0 0 2px #FCFBF4,
    0 0 0 3.5px #23211c;
}
.build__swatch:focus-visible { outline: none; }

.pager {
  margin-top: 44px;
  font-family: var(--font-body);
  font-size: 0.9rem;
}
.pager a { color: var(--color-text-muted); }

/* Rule between product series on a collection page. grid-column: 1 / -1 makes
   it span every column, so it takes its own row no matter how many columns
   the grid resolves to at the current width. */
.series-rule {
  grid-column: 1 / -1;
  margin: 24px 0 18px;          /* the gap between series is space alone - no rule */
  border: 0;
  height: 0;
  background: none;
}

/* product page */
.crumbs {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 16px;
  font-family: var(--font-body);
  font-size: .9rem;
  letter-spacing: 0;
  color: var(--color-text-muted);
}
.crumbs a { color: inherit; text-decoration: none; }
.crumbs a:hover { color: var(--color-text); }
.crumbs [aria-current] { color: rgba(35, 33, 28, .7); }

.prod__meta {
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 28px;
}
.prod__meta .prod__price { margin: 0; font-size: 1.4rem; color: var(--color-text); }
.prod__was {
  font-size: 1.03rem;
  color: #b3462c;
  text-decoration-color: #b3462c;
}

/* Availability reads as a state, not a button - a filled pill would compete
   with the actual add-to-cart control right below it. */
.prod__stock {
  font-family: var(--font-body);
  font-size: .9rem;
  font-weight: 500;
  letter-spacing: 0;
  padding: 4px 9px;
  border-radius: 999px;
  color: var(--matcha-deep);
  background: rgba(124, 154, 87, .14);
}
.prod__stock.is-out {
  color: var(--color-text-muted);
  background: rgba(35, 33, 28, .07);
}

/* spec sheet */
.prod__specs {
  margin-top: 38px;
  padding-top: 26px;
  border-top: 1px solid rgba(35, 33, 28, .12);
}
.prod__specs h2 {
  margin: 0 0 16px;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.3rem;
  letter-spacing: -.01em;
}
.prod__specs dl { margin: 0; }

/* Each row is its own grid so the label column can't be dragged wide by one
   long value - the rule between rows is what makes it read as a spec sheet. */
.prod__specs .spec {
  display: grid;
  grid-template-columns: 126px 1fr;
  gap: 14px;
  padding: 11px 0;
  border-bottom: 1px solid rgba(35, 33, 28, .07);
  font-size: 1rem;
}
.prod__specs .spec:last-child { border-bottom: 0; }
.prod__specs dt {
  font-family: var(--font-body);
  font-size: .9rem;
  letter-spacing: 0;
  color: var(--color-text-muted);
  padding-top: 3px;
}
.prod__specs dd { margin: 0; color: var(--color-text); }

/* trust row */
.prod__facts {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 13px 16px;
  margin: 32px 0 0;
  padding: 24px 0 0;
  border-top: 1px solid rgba(35, 33, 28, .12);
  list-style: none;
}
.prod__facts li {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: .98rem;
  color: var(--color-text-muted);
}
.prod__facts svg {
  width: 15px;
  height: 15px;
  flex: none;
  color: var(--matcha);
  stroke-width: 1.7;
}

@media (max-width: 560px) {
  .prod__facts { grid-template-columns: 1fr; }
  .prod__specs .spec { grid-template-columns: 106px 1fr; }
}

/* quantity stepper */
.qty { margin: 26px 0 0; }
.qty__row { display: flex; align-items: center; gap: 14px; }
.qty__row .cta--solid { margin-top: 0; }
.qty__note {
  margin: 10px 0 0;
  font-family: var(--font-body);
  font-size: .9rem;
  letter-spacing: 0;
  color: #b3462c;
}
.qty__note[hidden] { display: none; }
.qty__label {
  display: block;
  margin-bottom: 8px;
  font-size: .9rem;
  letter-spacing: 0;
  text-transform: none;
  color: var(--color-text-muted);
}
.qty__box {
  display: inline-flex;
  align-items: stretch;
  border: 1px solid rgba(35, 33, 28, .18);
  border-radius: 8px;
  overflow: hidden;
  background: rgba(255, 255, 255, .6);
}
.qty__step {
  width: 38px;
  border: 0;
  background: none;
  cursor: pointer;
  font-size: 1.06rem;
  color: var(--color-text-muted);
  transition: background .18s ease, color .18s ease, scale .12s ease-out;
}
.qty__step:hover { background: rgba(35, 33, 28, .06); color: var(--color-text); }
.qty__input {
  width: 54px;
  padding: 10px 0;
  border: 0;
  border-left: 1px solid rgba(35, 33, 28, .12);
  border-right: 1px solid rgba(35, 33, 28, .12);
  background: none;
  text-align: center;
  font-family: var(--font-body);
  font-size: 0.98rem;
  color: var(--color-text);
  -moz-appearance: textfield;
}
/* the native spinners duplicate the - / + buttons */
.qty__input::-webkit-outer-spin-button,
.qty__input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* image viewer */
.gallery__main .shot img { cursor: zoom-in; }

/* the dimmed area behind the panel */
.viewer {
  position: fixed;
  inset: 0;
  z-index: 200;                     /* over the fixed bar and its flower layer */
  display: grid;
  place-items: center;
  padding: 4vh 4vw;
  background: rgba(35, 33, 28, .42);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  animation: viewerIn .22s ease both;
}
.viewer[hidden] { display: none; }
@keyframes viewerIn { from { opacity: 0; } }

/* the window itself - most of the screen, deliberately not all of it */
.viewer__panel {
  position: relative;
  /* A window, not a takeover. Capped well under the viewport so the page
     is clearly visible around it - at 1180/92vw it filled almost the whole
     screen on a laptop, which is what we were trying to avoid. */
  width: min(880px, 76vw);
  height: min(620px, 72vh);
  display: flex;
  flex-direction: column;
  padding: 26px;
  border-radius: 20px;
  background: var(--color-page);
  box-shadow: 0 30px 80px rgba(35, 33, 28, .35);
  animation: panelIn .34s cubic-bezier(.19, 1, .22, 1) both;
}
@keyframes panelIn { from { transform: scale(.965); opacity: 0; } }

/* The image area fills the panel. overflow:hidden is what crops the magnified
   image to the window rather than letting it spill over the chrome. */
.viewer__stage {
  flex: 1;
  min-height: 0;
  /* position:relative gives the image below a definite box to resolve
     against. Without it, height:100% on the image had nothing to measure
     (this stage is sized by flex, not by an explicit height), so the image
     fell back to its natural proportions, overflowed, and overflow:hidden
     cropped it. That was the actual bug. */
  position: relative;
  overflow: hidden;
  border-radius: 12px;
  cursor: zoom-in;
}
.viewer__stage img {
  /* Absolutely positioned against the stage: inset gives it a definite box on
     both axes, which is what object-fit:contain needs to letterbox properly.
     The 18px inset is the breathing room around the photo. */
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* padding + border-box shrinks the content area, and object-fit works on
     the content box - so this is the breathing room around the photo */
  padding: 18px;
  box-sizing: border-box;
  object-fit: contain;
  transition: transform .3s cubic-bezier(.19, 1, .22, 1);
  will-change: transform;
}
.viewer__stage.is-zoomed { cursor: zoom-out; }
.viewer__stage.is-zoomed img { transform: scale(2.2); }
.viewer__stage.is-zoomed.is-panning img { transition: none; }

.viewer__close,
.viewer__nav {
  position: absolute;
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border: 1px solid rgba(35, 33, 28, .14);
  border-radius: 999px;
  background: rgba(255, 255, 255, .92);
  color: var(--color-text);
  font-size: 1.11rem;
  cursor: pointer;
  transition: background .2s ease, transform .2s cubic-bezier(.19, 1, .22, 1);
}
.viewer__close:hover,
.viewer__nav:hover { background: #FFFEF8; transform: scale(1.07); }

.viewer__close { top: -14px; right: -14px; font-size: 1.35rem; line-height: 1; }
.viewer__nav { top: 50%; margin-top: -21px; }
.viewer__nav.prev { left: -14px; }
.viewer__nav.next { right: -14px; }
.viewer__nav[hidden] { display: none; }

.viewer__count {
  margin: 14px 0 0;
  text-align: center;
  font-family: var(--font-body);
  font-size: .86rem;
  letter-spacing: 0;
  font-variant-numeric: tabular-nums;
  color: var(--color-text-muted);
}

@media (max-width: 640px) {
  .viewer { padding: 3vh 3vw; }
  .viewer__panel { width: 94vw; height: 86vh; padding: 18px; border-radius: 16px; }
  .viewer__close { top: -12px; right: -6px; }
  .viewer__nav.prev { left: -6px; }
  .viewer__nav.next { right: -6px; }
}

@media (prefers-reduced-motion: reduce) {
  .viewer, .viewer__panel { animation: none; }
  .viewer__stage img { transition: none; }
}

/* case card */
.casecard {
  margin-top: 30px;
  padding: 22px;
  border-radius: 16px;
  background: rgba(255, 255, 255, .35);
  backdrop-filter: blur(16px) saturate(180%);
  -webkit-backdrop-filter: blur(16px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, .6);
  box-shadow:
    0 8px 32px rgba(60, 55, 40, .10),
    inset 0 1px 0 rgba(255, 255, 255, .70);
}

.casecard__head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}
.casecard__head h2 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.21rem;
  letter-spacing: -.01em;
}
.casecard__name {
  margin: 0;
  font-family: var(--font-body);
  font-size: .94rem;
  letter-spacing: 0;
  color: var(--matcha-deep);
}

.casecard__body {
  display: grid;
  grid-template-columns: 250px 1fr;
  gap: 26px;
  /* stretch, not start: the photo box then matches the height of the spec
     list beside it, so the card ends just under the content instead of
     trailing a block of empty space below it */
  align-items: stretch;
}

/* Fixed box + contain, so any chassis photo sits the same way regardless of
   its shape - same reasoning as the collection cards. */
.casecard__media {
  position: relative;
  min-height: 240px;
}
.casecard__media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  /* Each PNG frames its chassis differently - the H60 fills its canvas, the
     UO1 only 75% of it - so object-fit alone renders them at different
     visible sizes. This per-case scale (set inline by the snippet) cancels
     that out so every case reads the same size. The overflow is transparent
     padding, never the chassis itself. */
  /* translate runs after the scale here, so the nudge is a plain offset and
     is not multiplied again - it re-centres a chassis that sits off-centre
     inside its own canvas, which scaling would otherwise exaggerate */
  transform: translateY(var(--case-shift, 0)) scale(var(--case-scale, 1));
  /* Two layers, same as the builds: a tight contact shadow and a wider
     ambient one. drop-shadow follows the PNG cut-out rather than the box. */
  filter:
    drop-shadow(0 8px 7px rgba(60, 55, 40, .20))
    drop-shadow(0 22px 20px rgba(60, 55, 40, .22));
}

.casecard__specs { margin: 0; }
.casecard__specs > div {
  display: grid;
  grid-template-columns: 112px 1fr;
  gap: 10px;
  padding: 7px 0;
  border-bottom: 1px solid rgba(35, 33, 28, .07);
  font-size: .96rem;
}
.casecard__specs > div:last-child { border-bottom: 0; }
.casecard__specs dt {
  font-family: var(--font-body);
  font-size: .9rem;
  letter-spacing: 0;
  text-transform: none;
  color: var(--color-text-muted);
  padding-top: 2px;
}
.casecard__specs dd { margin: 0; color: var(--color-text-secondary); }

@media (max-width: 720px) {
  .casecard__body { grid-template-columns: 1fr; }
  .casecard__media { height: 300px; }
  .casecard__specs > div { grid-template-columns: 102px 1fr; }
}

/* the case photo opens the same viewer as the product gallery */
.casecard__media {
  cursor: zoom-in;
  border-radius: 10px;
  transition: background .2s ease;
}
.casecard__media:hover { background: rgba(35, 33, 28, .03); }
.casecard__media:focus-visible {
  outline: 2px solid var(--matcha);
  outline-offset: 3px;
}

/* keyboard + mouse card (Overlord only) */
.kbcard {
  margin-top: 40px;
  padding: 26px;
  border-radius: 16px;
  background: rgba(255, 255, 255, .35);
  backdrop-filter: blur(16px) saturate(180%);
  -webkit-backdrop-filter: blur(16px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, .6);
  box-shadow:
    0 8px 32px rgba(60, 55, 40, .10),
    inset 0 1px 0 rgba(255, 255, 255, .70);
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr);
  gap: 40px;
  align-items: center;
}

.kbcard__media {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 220px;
}
.kbcard__media img {
  width: 100%;
  height: auto;
  max-height: 320px;
  object-fit: contain;
  filter:
    drop-shadow(0 8px 7px rgba(60, 55, 40, .18))
    drop-shadow(0 22px 20px rgba(60, 55, 40, .20));
}

.kbcard__head { margin-bottom: 16px; }
.kbcard__head h2 {
  margin: 0 0 6px;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.21rem;
  letter-spacing: -.01em;
}
.kbcard__name {
  margin: 0;
  font-size: 0.9rem;
  color: var(--color-text-muted);
}

.kbcard__specs { margin: 0; }
.kbcard__specs > div {
  display: grid;
  grid-template-columns: 126px 1fr;
  gap: 10px;
  padding: 9px 0;
  border-bottom: 1px solid rgba(35, 33, 28, .07);
  font-size: .98rem;
}
.kbcard__specs > div:last-child { border-bottom: 0; }
.kbcard__specs dt {
  font-family: var(--font-body);
  font-size: .9rem;
  letter-spacing: 0;
  text-transform: none;
  color: var(--color-text-muted);
  padding-top: 2px;
}
.kbcard__specs dd { margin: 0; color: var(--color-text-secondary); }

@media (max-width: 720px) {
  .kbcard { grid-template-columns: 1fr; }
  .kbcard__media { min-height: 180px; }
}

/* what's-in-the-box card (every build) */
.kitcard {
  margin-top: 40px;
  padding: 26px;
  border-radius: 16px;
  background: rgba(255, 255, 255, .35);
  backdrop-filter: blur(16px) saturate(180%);
  -webkit-backdrop-filter: blur(16px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, .6);
  box-shadow:
    0 8px 32px rgba(60, 55, 40, .10),
    inset 0 1px 0 rgba(255, 255, 255, .70);
  display: grid;
  grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr);
  gap: 40px;
  align-items: center;
}

.kitcard__head { margin-bottom: 16px; }
.kitcard__head h2 {
  margin: 0 0 6px;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.21rem;
  letter-spacing: -.01em;
}
.kitcard__name {
  margin: 0;
  font-size: .98rem;
  color: var(--color-text-muted);
}

.kitcard__list { margin: 0; padding: 0; list-style: none; }
.kitcard__list li {
  padding: 9px 0;
  border-bottom: 1px solid rgba(35, 33, 28, .07);
  font-size: 1.02rem;
  line-height: 1.45;
  color: var(--color-text);
}
.kitcard__list li:last-child { border-bottom: 0; }
.kitcard__note {
  display: block;
  margin-top: 2px;
  font-size: .92rem;
  color: var(--color-text-muted);
}

.kitcard__media {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 220px;
}
.kitcard__media img {
  width: 100%;
  height: auto;
  max-height: 320px;
  object-fit: contain;
  filter:
    drop-shadow(0 8px 7px rgba(60, 55, 40, .18))
    drop-shadow(0 22px 20px rgba(60, 55, 40, .20));
}

@media (max-width: 720px) {
  .kitcard { grid-template-columns: 1fr; }
  .kitcard__media { min-height: 180px; }
}

/* FAQ */
.faq__head { margin-bottom: 8px; }
.faq__intro {
  margin-bottom: 6px;
  font-size: 1rem;
  color: var(--color-text-muted);
}

.faq { margin-top: 26px; }

.faq__group {
  margin: 34px 0 4px;
  font-family: var(--font-body);
  font-size: .9rem;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  color: var(--matcha-deep);
}
.faq__group:first-child { margin-top: 0; }

.faq__item { border-bottom: 1px solid rgba(35, 33, 28, .12); }

/* generous target, so it's easy to hit without aiming */
.faq__q {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 18px;
  padding: 20px 2px;
  cursor: pointer;
  list-style: none;
  transition: color .18s ease;
}
.faq__q::-webkit-details-marker { display: none; }  /* default triangle */
.faq__q:hover { color: var(--matcha-deep); }
.faq__q:focus-visible {
  outline: 2px solid var(--matcha-deep);
  outline-offset: 3px;
  border-radius: 6px;
}

.faq__q-text {
  font-family: var(--font-display);
  font-size: 1.12rem;
  line-height: 1.4;
  color: inherit;
}

/* a plus that becomes a minus, drawn in CSS so there's no icon to load */
.faq__icon {
  position: relative;
  flex: none;
  width: 17px;
  height: 17px;
  margin-top: 4px;
}
.faq__icon::before,
.faq__icon::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 0;
  width: 100%;
  height: 1.5px;
  background: currentColor;
  border-radius: 2px;
  transform: translateY(-50%);
  transition: transform .24s cubic-bezier(.19, 1, .22, 1), opacity .2s ease;
}
.faq__icon::after { transform: translateY(-50%) rotate(90deg); }
.faq__item[open] .faq__icon::after { transform: translateY(-50%) rotate(0deg); opacity: 0; }

.faq__a {
  padding: 0 46px 22px 2px;
  font-size: 1rem;
  line-height: 1.65;
  color: var(--color-text-secondary);
}
.faq__a p { margin: 0 0 12px; }
.faq__a p:last-child { margin-bottom: 0; }
.faq__a a { color: var(--matcha-deep); }

.faq__help {
  margin-top: 44px;
  padding: 24px 26px;
  border-radius: 16px;
  background: rgba(255, 255, 255, .35);
  backdrop-filter: blur(16px) saturate(180%);
  -webkit-backdrop-filter: blur(16px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, .6);
  box-shadow:
    0 8px 32px rgba(60, 55, 40, .10),
    inset 0 1px 0 rgba(255, 255, 255, .70);
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 14px 20px;
}
.faq__help-text { margin: 0; font-size: 1rem; color: rgba(35, 33, 28, .72); }
.faq__help-link {
  flex: none;
  padding: 11px 20px;
  border-radius: 999px;
  background: var(--blush-soft);
  border: 1px solid var(--blush);
  color: var(--blush-deeper);
  font-family: var(--font-body);
  font-size: .82rem;
  letter-spacing: 0;
  text-decoration: none;
  transition: background .2s ease, border-color .2s ease;
}
.faq__help-link:hover { background: #EFB8CD; border-color: #DE93B0; }

@media (max-width: 560px) {
  .faq__q-text { font-size: 1.04rem; }
  .faq__a { padding-right: 8px; }
  .faq__help { flex-direction: column; align-items: stretch; text-align: center; }
}
@media (prefers-reduced-motion: reduce) {
  .faq__icon::before, .faq__icon::after { transition: none; }
}

/* support ticket */
.support__head { margin-bottom: 30px; }
.support__intro {
  max-width: 62ch;
  font-size: 1rem;
  line-height: 1.6;
  color: rgba(35, 33, 28, .68);
}

.support__layout {
  display: grid;
  grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr);
  align-items: start;
  gap: 44px;
}

/* The widget renders Freshdesk's own iframe in here. It brings its own
   styling, so the card is what ties it back to the rest of the site. */
.support__form {
  padding: 12px 14px;
  border-radius: 16px;
  background: rgba(255, 255, 255, .42);
  backdrop-filter: blur(16px) saturate(180%);
  -webkit-backdrop-filter: blur(16px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, .6);
  box-shadow:
    0 8px 32px rgba(60, 55, 40, .10),
    inset 0 1px 0 rgba(255, 255, 255, .70);
  min-width: 0;
}
.support__iframe {
  width: 100%;
  border: 0;
  border-radius: 10px;
  background: #FFFEF8;
  display: block;
}

.support__fallback,
.support__noscript {
  margin: 12px 4px 6px;
  font-size: .84rem;
  color: var(--color-text-muted);
}
.support__fallback a,
.support__noscript a { color: var(--matcha-deep); }

.support__aside {
  padding: 26px;
  border-radius: 16px;
  background: rgba(255, 255, 255, .35);
  backdrop-filter: blur(16px) saturate(180%);
  -webkit-backdrop-filter: blur(16px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, .6);
  box-shadow:
    0 8px 32px rgba(60, 55, 40, .10),
    inset 0 1px 0 rgba(255, 255, 255, .70);
  position: sticky;
  top: 168px;
  min-width: 0;
  box-sizing: border-box;
}
.support__aside h2 {
  margin: 0 0 14px;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.1rem;
}
.support__tips { font-size: .94rem; line-height: 1.6; color: rgba(35, 33, 28, .72); }
.support__tips p { margin: 0 0 12px; }
.support__tips p:last-child { margin-bottom: 0; }
.support__tips strong { color: var(--color-text); font-weight: 600; }

.support__hours {
  margin: 18px 0 0;
  padding-top: 16px;
  border-top: 1px solid rgba(35, 33, 28, .1);
  font-size: .86rem;
  color: var(--color-text-muted);
}

.support__faq-link {
  display: inline-block;
  margin-top: 16px;
  padding: 10px 18px;
  border-radius: 999px;
  background: var(--blush-soft);
  border: 1px solid var(--blush);
  color: var(--blush-deeper);
  font-family: var(--font-body);
  font-size: .8rem;
  letter-spacing: 0;
  text-decoration: none;
  transition: background .2s ease, border-color .2s ease;
}
.support__faq-link:hover { background: #EFB8CD; border-color: #DE93B0; }

@media (max-width: 860px) {
  .support__layout { grid-template-columns: minmax(0, 1fr); }
  .support__aside { position: static; order: -1; }
}

/* warranty */
.warranty__head { margin-bottom: 26px; }
.warranty__intro { font-size: 1rem; line-height: 1.6; color: rgba(35, 33, 28, .68); }

/* the handful of numbers people actually came for */
/* An explicit 4-up row rather than auto-fit: auto-fit dropped the fourth
   fact onto a second row on its own, which read as a mistake. */
.warranty__facts {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 10px;
  margin: 0 0 26px;
  padding: 0;
}
.warranty__facts > div {
  padding: 13px 14px;
  background: rgba(255, 255, 255, .55);
  border: 1px solid rgba(35, 33, 28, .1);
  border-radius: 12px;
}
.warranty__facts dt {
  font-family: var(--font-body);
  font-size: .9rem;
  letter-spacing: 0;
  text-transform: none;
  line-height: 1.3;
  color: var(--color-text-muted);
}
.warranty__facts dd {
  margin: 5px 0 0;
  font-family: var(--font-display);
  font-size: .96rem;
  line-height: 1.3;
  color: var(--color-text);
}
@media (max-width: 720px) {
  .warranty__facts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* one quiet line of shortcuts, separated by dots - no card, so it doesn't
   compete with the document underneath it */
.warranty__toc {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px 0;
  margin: 0 0 38px;
  padding-bottom: 18px;
  border-bottom: 1px solid rgba(35, 33, 28, .12);
}
.warranty__toc-title {
  margin-right: 12px;
  font-family: var(--font-body);
  font-size: .9rem;
  letter-spacing: 0;
  text-transform: none;
  color: var(--color-text-muted);
}
.warranty__toc a {
  font-size: .9rem;
  color: var(--matcha-deep);
  text-decoration: none;
  border-bottom: 1px solid transparent;
}
.warranty__toc a:hover { border-bottom-color: var(--matcha-deep); }
/* dot separator between links, but not before the first or after the last */
.warranty__toc a + a::before {
  content: "·";
  margin: 0 9px;
  color: var(--color-text-muted);
}

.clause {
  padding-top: 34px;
  margin-top: 34px;
  border-top: 1px solid rgba(35, 33, 28, .12);
  scroll-margin-top: 150px;          /* clears the fixed bar on jump links */
}
.clause:first-child { padding-top: 0; margin-top: 0; border-top: 0; }
.clause__title {
  margin: 0 0 16px;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.32rem;
  letter-spacing: -.01em;
  color: var(--color-text);
}

/* legal copy: a comfortable measure and real spacing between paragraphs */
.clause__text, .clause__note {
  font-size: 1rem;
  line-height: 1.72;
  color: var(--color-text-secondary);
}
.clause__text p { margin: 0 0 16px; }
.clause__text p:last-child { margin-bottom: 0; }
.clause__text a, .clause__note a { color: var(--matcha-deep); }

.clause__list {
  margin: 16px 0 0;
  padding-left: 22px;
  font-size: 1rem;
  line-height: 1.65;
  color: var(--color-text-secondary);
}
.clause__list li { margin-bottom: 9px; }
.clause__list li::marker { color: var(--matcha); }

/* the all-caps disclaimer and the "Note:" asides read as set apart */
.clause__note {
  margin-top: 18px;
  padding: 16px 18px;
  border-left: 2px solid rgba(124, 154, 87, .5);
  border-radius: 0 10px 10px 0;
  background: rgba(255, 255, 255, .4);
  font-size: .94rem;
  line-height: 1.65;
  color: rgba(35, 33, 28, .72);
}
.clause__note p { margin: 0; }

.warranty__help {
  margin-top: 46px;
  padding: 24px 26px;
  border-radius: 16px;
  background: rgba(255, 255, 255, .35);
  backdrop-filter: blur(16px) saturate(180%);
  -webkit-backdrop-filter: blur(16px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, .6);
  box-shadow:
    0 8px 32px rgba(60, 55, 40, .10),
    inset 0 1px 0 rgba(255, 255, 255, .70);
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 14px 20px;
}
.warranty__help-text { margin: 0; font-size: 1rem; color: rgba(35, 33, 28, .72); }
.warranty__help-link {
  flex: none;
  padding: 11px 20px;
  border-radius: 999px;
  background: var(--blush-soft);
  border: 1px solid var(--blush);
  color: var(--blush-deeper);
  font-family: var(--font-body);
  font-size: .82rem;
  letter-spacing: 0;
  text-decoration: none;
  transition: background .2s ease, border-color .2s ease;
}
.warranty__help-link:hover { background: #EFB8CD; border-color: #DE93B0; }

.warranty__updated {
  margin: 22px 0 0;
  font-size: .82rem;
  color: var(--color-text-muted);
}

@media (max-width: 560px) {
  .warranty__help { flex-direction: column; align-items: stretch; text-align: center; }
  .clause__title { font-size: 1.2rem; }
}

/* Shopify policy pages
   Policies (/policies/*) are rendered by Shopify itself - a templates/policy.liquid
   in this theme is ignored - so they arrive with no measure and no clearance for the
   fixed bar, which left the title tucked underneath it. These rules give them the
   same reading width and spacing as the warranty page. */
.shopify-policy__container {
  width: 100%;
  max-width: 760px;
  margin: 0 auto;
  padding: 152px 22px 90px;
  box-sizing: border-box;
}

/* Shopify centres this, and its stylesheet loads after the theme's - so this
   needs the extra specificity to win. Every other page title is left-aligned. */
.shopify-policy__container .shopify-policy__title {
  margin-bottom: 30px;
  text-align: left;
}
.shopify-policy__title h1 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.9rem, 3.4vw, 2.8rem);
  letter-spacing: -.01em;
  color: var(--color-text);
}

.shopify-policy__body {
  font-size: 1rem;
  line-height: 1.72;
  color: var(--color-text-secondary);
}
.shopify-policy__body p { margin: 0 0 16px; }
.shopify-policy__body h2 {
  margin: 34px 0 14px;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.32rem;
  letter-spacing: -.01em;
  color: var(--color-text);
}
.shopify-policy__body h3 {
  margin: 26px 0 10px;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.1rem;
  color: var(--color-text);
}
.shopify-policy__body ul,
.shopify-policy__body ol { margin: 0 0 16px; padding-left: 22px; }
.shopify-policy__body li { margin-bottom: 9px; }
.shopify-policy__body li::marker { color: var(--matcha); }
.shopify-policy__body a { color: var(--matcha-deep); }
.shopify-policy__body strong { color: var(--color-text); }
.shopify-policy__body table { width: 100%; border-collapse: collapse; margin: 0 0 18px; display: block; overflow-x: auto; }
.shopify-policy__body td,
.shopify-policy__body th { padding: 9px 12px; border: 1px solid rgba(35, 33, 28, .12); text-align: left; font-size: .92rem; }

@media (max-width: 860px) {
  .shopify-policy__container { padding-top: 138px; }
}

/* search */
.search__head { margin-bottom: 34px; }

.searchbar {
  display: flex;
  align-items: center;
  gap: 10px;
  max-width: 560px;
  padding: 6px 6px 6px 16px;
  border-radius: 999px;
  background: rgba(255, 255, 255, .55);
  border: 1px solid rgba(35, 33, 28, .16);
  transition: border-color .2s ease, box-shadow .2s ease;
}
.searchbar:focus-within {
  border-color: var(--matcha);
  box-shadow: 0 0 0 3px rgba(124, 154, 87, .16);
}
.searchbar__icon {
  width: 18px;
  height: 18px;
  flex: none;
  color: var(--color-text-muted);
}
.searchbar__input {
  flex: 1;
  min-width: 0;
  padding: 10px 0;
  border: 0;
  background: none;
  font-family: inherit;
  font-size: .96rem;
  color: var(--color-text);
}
.searchbar__input::placeholder { color: rgba(35, 33, 28, .38); }
.searchbar__input:focus { outline: none; }
/* the browser's own clear button doesn't match anything else here */
.searchbar__input::-webkit-search-cancel-button { -webkit-appearance: none; }

.searchbar__go {
  flex: none;
  padding: 10px 20px;
  border: 0;
  border-radius: 999px;
  background: var(--color-fill-strong);
  color: var(--color-text-inverse);
  font-family: var(--font-body);
  font-size: .78rem;
  letter-spacing: .02em;
  cursor: pointer;
  transition: background .2s ease, scale .12s ease-out;
}
.searchbar__go:hover { background: #35322a; }

.search__count {
  margin: 16px 0 0;
  font-family: var(--font-body);
  font-size: .9rem;
  letter-spacing: 0;
  color: var(--color-text-muted);
}

.search__subhead {
  margin: 46px 0 16px;
  font-family: var(--font-body);
  font-size: .9rem;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  color: var(--color-text-muted);
}

.search__pages ul { margin: 0; padding: 0; list-style: none; }
.search__pages li {
  padding: 16px 0;
  border-top: 1px solid rgba(35, 33, 28, .1);
}
.search__pages li:last-child { border-bottom: 1px solid rgba(35, 33, 28, .1); }
.search__pages a {
  font-family: var(--font-display);
  font-size: 1.1rem;
  color: var(--color-text);
  text-decoration: none;
}
.search__pages a:hover { color: var(--matcha-deep); }
.search__pages p {
  margin: 6px 0 0;
  max-width: 70ch;
  font-size: .9rem;
  line-height: 1.6;
  color: var(--color-text-muted);
}

.search__empty {
  padding: 26px 0 10px;
  font-size: 1rem;
  color: var(--color-text-muted);
}
.search__empty-title {
  margin: 0 0 6px;
  font-family: var(--font-display);
  font-size: 1.3rem;
  color: var(--color-text);
}
.search__empty p { margin: 0 0 8px; }

.search__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin: 22px 0 0;
  padding: 0;
  list-style: none;
}
.search__chips a {
  display: inline-block;
  padding: 9px 18px;
  border-radius: 999px;
  background: rgba(255, 255, 255, .55);
  border: 1px solid rgba(35, 33, 28, .14);
  font-size: .86rem;
  color: rgba(35, 33, 28, .72);
  text-decoration: none;
  transition: border-color .2s ease, color .2s ease, background .2s ease, scale .12s ease-out;
}
.search__chips a:hover {
  background: rgba(124, 154, 87, .1);
  border-color: var(--matcha);
  color: var(--matcha-deep);
}

@media (max-width: 520px) {
  .searchbar { flex-wrap: wrap; border-radius: 18px; padding: 10px 14px; }
  .searchbar__go { width: 100%; }
}

/* sale pricing
   A struck original and the saving next to it. The card only shows these when
   a compare-at price is actually set in Shopify, so nothing appears on a
   product that isn't discounted. */
.prod__price { position: relative; }
.prod__was[hidden],
.prod__save[hidden] { display: none; }

.prod__save {
  padding: 4px 10px;
  border-radius: 999px;
  background: rgba(179, 70, 44, .1);
  color: #b3462c;
  font-family: var(--font-body);
  font-size: .7rem;
  letter-spacing: .04em;
  white-space: nowrap;
}

/* card price: struck original sits after the current one */
.build__was {
  margin-left: 8px;
  color: #b3462c;
  text-decoration-color: #b3462c;
  font-size: .86em;
}

.build { position: relative; }

/* The discount sits with the price it discounts, rather than as a sticker
   over the photo - the struck original is right beside it, so the two read
   as one thought. */
.build__off {
  margin-left: 8px;
  color: #b3462c;
  font-size: .86em;
}

/* Tags sit above the name as small labels, each led by the same matcha
   diamond the carousels use for their dots - enough of a mark to catch the
   eye without putting a badge back on top of the photo. */
/* Tags print whatever case they were typed in the admin, so capitals keep
   them consistent - kept readable: body face, light tracking. */
.build__tags {
  margin: 12px 0 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px;
  font-family: var(--font-body);
  font-size: .8rem;
  font-weight: 600;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--matcha-deep);
}
.build__tags + .build__name { margin-top: 4px; }

.build__tag {
  display: inline-flex;
  align-items: center;
  gap: 7px;
}
/* same weight and colour as the hero's fact icons */
.build__tag-icon {
  width: 15px;
  height: 15px;
  flex: none;
  color: var(--matcha);
  stroke-width: 1.7;
  transform-origin: center;
  /* Slow enough to read as a heartbeat rather than a blink, and it deepens
     instead of fading, so the icon never gets *less* visible mid-cycle. */
  animation: tagPulse 2.6s ease-in-out infinite;
}

@keyframes tagPulse {
  0%, 100% { transform: scale(1);    color: var(--matcha); }
  50%      { transform: scale(1.22); color: var(--matcha-deep); }
}

/* The label beats with its icon: same clock, same easing. It deepens and
   grows a little rather than fading, and it grows from its left edge so a
   neighbouring tag never gets shoved as it breathes. */
.build__tag {
  transform-origin: left center;
  animation: tagLabelPulse 2.6s ease-in-out infinite;
}

@keyframes tagLabelPulse {
  0%, 100% { transform: scale(1);    color: var(--matcha-deep); }
  50%      { transform: scale(1.05); color: #3f5528; }
}

/* A second tag on the same card beats slightly behind the first, so a pair
   reads as two marks rather than one flashing block. */
.build__tag:nth-child(2),
.build__tag:nth-child(2) .build__tag-icon { animation-delay: .5s; }
.build__tag:nth-child(3),
.build__tag:nth-child(3) .build__tag-icon { animation-delay: 1s; }

/* "Recently viewed" is a note about the shopper, not a claim about the
   product, so it holds still and stays neutral while the selling-point tags
   beat in matcha. Written in by viprtech.js from this browser's own list and
   never rendered on the server, so nobody is shown anyone else's history. */
.build__tag--seen,
.build__tag--seen .build__tag-icon {
  animation: none;
  transform: none;
}
.build__tag--seen { color: var(--color-text-muted); }
.build__tag--seen .build__tag-icon {
  color: var(--color-text-muted);
  stroke-width: 1.6;
}

/* final sale notice (product page) */
/* A rule and a serif line, the same way .facts sets itself off - no tinted
   box. The italic in the site's warning red carries the weight, so it still
   stops the eye under the buy button without a card pasted on the page. */
.finalsale {
  margin: 26px 0 0;
  padding-top: 18px;
  border-top: 1px solid rgba(179, 70, 44, .28);
}
.finalsale__title {
  margin: 0 0 8px;
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-size: 1.2rem;
  font-weight: 400;
  line-height: 1.25;
  letter-spacing: -.005em;
  color: var(--color-text);
}
.finalsale__title em {
  font-style: italic;
  color: #b3462c;
}
.finalsale__text {
  margin: 0;
  max-width: 62ch;
  font-size: .92rem;
  line-height: 1.6;
  color: var(--color-text-muted);
}
.finalsale__text a {
  color: #b3462c;
  text-decoration: none;
  border-bottom: 1px solid rgba(179, 70, 44, .35);
  transition: border-color .25s ease;
}
.finalsale__text a:hover { border-bottom-color: #b3462c; }

/* A sale restriction is information, not promotion: it takes the same red as
   the struck was-price and holds still, so it reads as a condition of the
   sale instead of another perk competing for a click. */
.build__tag--caution,
.build__tag--caution .build__tag-icon {
  color: #b3462c;
  animation: none;
}

@media (prefers-reduced-motion: reduce) {
  .build__tag,
  .build__tag-icon { animation: none; }
}

.peek-line__qty s { opacity: .55; margin: 0 4px 0 2px; }

/* announcement panel */
.intro {
  width: var(--lane);
  margin: 0 auto;
  padding: 0 22px 90px;
  box-sizing: border-box;
}
.intro__inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: center;
  gap: 48px;
  padding: 26px;
  border-radius: 20px;
  background: rgba(255, 255, 255, .35);
  backdrop-filter: blur(16px) saturate(180%);
  -webkit-backdrop-filter: blur(16px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, .6);
  box-shadow:
    0 8px 32px rgba(60, 55, 40, .10),
    inset 0 1px 0 rgba(255, 255, 255, .70);
}
/* the image can sit on either side without reordering the markup, so the
   heading still comes first for anyone reading the page as text */
.intro--flip .intro__media { order: 2; }

.intro__media { min-width: 0; border-radius: 14px; overflow: hidden; }   /* frames the photo's slow zoom */
.intro__img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 14px;
}

.intro__body { min-width: 0; padding: 8px 10px; }

.intro__eyebrow {
  margin: 0 0 12px;
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-body);
  font-size: .9rem;
  letter-spacing: 0;
  text-transform: none;
  color: var(--matcha-deep);
}
/* the same separator dot the ticker uses between its messages */
.intro__badge::after {
  content: "";
  display: inline-block;
  vertical-align: middle;
  width: 3px;
  height: 3px;
  margin-left: 10px;
  border-radius: 50%;
  background: currentColor;
  opacity: .5;
}
.intro__heading {
  margin: 0 0 18px;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.9rem, 3.2vw, 2.8rem);
  line-height: 1.05;
  letter-spacing: -.02em;
  text-wrap: balance;
  color: var(--color-text);
}
.intro__text {
  max-width: 46ch;
  font-size: 1.1rem;
  line-height: 1.6;
  color: var(--color-text-secondary);
}
.intro__text p { margin: 0 0 14px; }
.intro__text p:last-child { margin-bottom: 0; }

.intro__links { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 26px; }
.intro__link {
  display: inline-block;
  padding: 12px 22px;
  border-radius: 999px;
  border: 1px solid rgba(35, 33, 28, .2);
  background: rgba(255, 255, 255, .5);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: .92rem;
  letter-spacing: .02em;
  text-decoration: none;
  transition: background .2s ease, border-color .2s ease, transform .2s cubic-bezier(.19, 1, .22, 1), scale .12s ease-out;
}
.intro__link:hover { border-color: rgba(35, 33, 28, .45); transform: translateY(-2px); }
.intro__link--solid {
  background: var(--color-fill-strong);
  border-color: var(--color-fill-strong);
  color: var(--color-text-inverse);
}
.intro__link--solid:hover { background: #35322a; border-color: #35322a; }

@media (max-width: 860px) {
  .intro__inner { grid-template-columns: minmax(0, 1fr); gap: 26px; }
  .intro--flip .intro__media { order: 0; }
  .intro__body { padding: 0 4px 6px; }
}

/* salvage highlight + review carousel */
/* process band
   How it's made, as one more card in the homepage's run: the same lane,
   glass recipe, corner and type sizes as the Home & Office card above it.
   Heading left, its sentence on the right; the four stages across
   underneath, each led by a line icon like the hero's trust row. */
/* The band runs the full width in the site's blush, so the page has a change
   of ground partway down instead of one long ivory canvas. The card sits in
   it at exactly the width of the Home & Office card above. */
.process {
  margin: 0 0 90px;
  padding: 80px 0;
  background: var(--color-band);
}

.process__inner {
  width: calc(var(--lane) - 44px);
  margin: 0 auto;
  box-sizing: border-box;
  padding: 40px 44px 44px;
  border-radius: 20px;
  background: rgba(255, 255, 255, .35);
  backdrop-filter: blur(16px) saturate(180%);
  -webkit-backdrop-filter: blur(16px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, .6);
  box-shadow:
    0 8px 32px rgba(60, 55, 40, .10),
    inset 0 1px 0 rgba(255, 255, 255, .70);
}

.process__head {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  gap: 18px 48px;
  align-items: end;
}

.process__eyebrow {                  /* only shown if the setting is filled */
  grid-column: 1 / -1;
  margin: 0;
  font-size: 1rem;
  color: var(--color-text-muted);
}

/* same size and setting as .intro__heading */
.process__heading {
  margin: 0;
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-weight: 400;
  font-size: clamp(1.55rem, 3.2vw, 2.8rem);
  line-height: 1.05;
  letter-spacing: -.02em;
  text-wrap: balance;
  color: var(--color-text);
}
.process__heading em { font-style: italic; color: var(--matcha); }   /* as in the hero */

/* the sentence sits in its own pane, a step deeper than the card in the
   band's own blush, so it reads as the card's note rather than loose text */
.process__lede {
  margin: 0;
  padding: 18px 22px;
  border-radius: 14px;
  background: #EED8D7;
  font-size: 1.1rem;
  line-height: 1.6;
  color: var(--color-text);
  text-wrap: pretty;
}

/* the four stages */
.process__rail {
  list-style: none;
  margin: 44px 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 32px;
}

.process__node { min-width: 0; }

.process__title {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0 0 12px;
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-weight: 400;
  font-size: 1.5rem;
  line-height: 1.15;
  letter-spacing: -.01em;
  color: var(--color-text);
}

/* Each stage's mark: a ring holding the line icon. Its finished state -
   filled matcha, white icon, "signed off" - is the default; the homepage
   motion block below starts it empty and ticks it on in turn. */
.process__mark {
  position: relative;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  flex: none;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1.5px rgba(124, 154, 87, .45);
}
.process__mark::before {           /* the fill */
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: var(--matcha-deep);
}
.process__icon {
  position: relative;              /* above the fill */
  width: 20px;
  height: 20px;
  color: var(--color-text-inverse);
  stroke-width: 1.8;
}

.process__body {
  margin: 0;
  font-size: 1.02rem;
  line-height: 1.55;
  color: var(--color-text-secondary);
  text-wrap: pretty;
}

@media (max-width: 980px) {
  .process__rail { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: 32px; }
}
@media (max-width: 860px) {
  .process__head { grid-template-columns: minmax(0, 1fr); }
  .process__inner { padding: 28px 24px 30px; }
}
@media (max-width: 560px) {
  .process__rail { grid-template-columns: minmax(0, 1fr); gap: 24px; margin-top: 32px; }
}

/* Two equal columns filling the lane, same pattern as .intro__inner above it,
   so the pair reads as one full-width row rather than two loose cards. */
.reviews {
  width: var(--lane);
  margin: 0 auto 90px;
  padding: 0 22px;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 90px;                       /* the same gap as between the other cards */
}

/* salvage highlight */
/* Centered rather than left-aligned: the photo is a fixed, modest size (a
   tall product cutout, not something that should stretch edge to edge), so
   centering keeps the extra column width from reading as a stray gap. */
.salvage__card {
  padding: 26px;
  border-radius: 20px;
  background: rgba(255, 255, 255, .35);
  backdrop-filter: blur(16px) saturate(180%);
  -webkit-backdrop-filter: blur(16px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, .6);
  box-shadow:
    0 8px 32px rgba(60, 55, 40, .10),
    inset 0 1px 0 rgba(255, 255, 255, .70);
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  grid-template-areas: "body media";
  align-items: center;
  gap: 48px;
}

.salvage__media {
  grid-area: media;
  display: flex;
  justify-content: center;
  padding: 24px 0;
}
.salvage__body { grid-area: body; min-width: 0; padding: 8px 10px 8px 18px; }
.salvage__img {
  width: 100%;
  max-width: 300px;
  height: auto;
  filter:
    drop-shadow(0 8px 7px rgba(60, 55, 40, .20))
    drop-shadow(0 22px 20px rgba(60, 55, 40, .22));
}

/* Same plain-text treatment as .intro__eyebrow, so the Home & Office card and
   this one label themselves identically. */
.salvage__eyebrow {
  margin: 0 0 12px;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 10px;
  font-family: var(--font-body);
  font-size: .9rem;
  letter-spacing: 0;
  color: var(--matcha-deep);
}
/* the same separator dot the ticker uses between its messages */
.salvage__badge::after {
  content: "";
  display: inline-block;
  vertical-align: middle;
  width: 3px;
  height: 3px;
  margin-left: 10px;
  border-radius: 50%;
  background: currentColor;
  opacity: .5;
}
.salvage__heading {
  margin: 0 0 14px;
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-size: clamp(1.8rem, 2.8vw, 2.4rem);
  font-weight: 400;
  line-height: 1.05;
  letter-spacing: -.02em;
  color: var(--color-text);
}
.salvage__heading em {
  font-style: italic;
  color: var(--matcha);
}
.salvage__text {
  margin: 0;
  max-width: 46ch;
  font-size: 1.06rem;
  line-height: 1.55;
  color: var(--color-text-secondary);
}
.salvage__text p { margin: 0 0 12px; }
.salvage__text p:last-child { margin-bottom: 0; }
.salvage__link {
  margin-top: 22px;
  display: inline-block;
  padding: 12px 22px;
  border-radius: 999px;
  border: 1px solid var(--color-fill-strong);
  background: var(--color-fill-strong);
  color: var(--color-text-inverse);
  font-family: var(--font-body);
  font-size: .92rem;
  letter-spacing: .02em;
  text-decoration: none;
  transition: background .2s ease, border-color .2s ease, transform .2s cubic-bezier(.19, 1, .22, 1), scale .12s ease-out;
}
.salvage__link:hover { background: #35322a; border-color: #35322a; transform: translateY(-2px); }

/* review carousel */
/* The two cards stretch to a shared height, so whichever is shorter centres
   its contents rather than leaving all the slack pooled at the bottom. */
.reviews__card {
  padding: 26px;
  border-radius: 20px;
  background: rgba(255, 255, 255, .35);
  backdrop-filter: blur(16px) saturate(180%);
  -webkit-backdrop-filter: blur(16px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, .6);
  box-shadow:
    0 8px 32px rgba(60, 55, 40, .10),
    inset 0 1px 0 rgba(255, 255, 255, .70);
}

.reviews__inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);   /* halves, like the Home & Office card */
  grid-template-areas: "media body";
  align-items: center;
  gap: 48px;
}

/* Text centered and the carousel capped + centered below it, the same
   composition as the salvage card, so a wider column doesn't inflate the
   carousel into an oversized image with a much taller card as a result. */
.reviews__body { grid-area: body; min-width: 0; padding: 8px 10px; }
.reviews__eyebrow {
  margin: 0 0 14px;
  font-family: var(--font-body);
  font-size: .9rem;
  letter-spacing: 0;
  text-transform: none;
  color: var(--matcha-deep);
}
.reviews__heading {
  margin: 0 0 22px;
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-size: clamp(1.8rem, 2.8vw, 2.4rem);
  font-weight: 400;
  line-height: 1.05;
  letter-spacing: -.02em;
  color: var(--color-text);
}
.reviews__heading em {
  font-style: italic;
  color: var(--matcha);
}
.reviews__text {
  margin: 0;
  max-width: 46ch;
  font-size: 1.06rem;
  line-height: 1.55;
  color: var(--color-text-secondary);
}
.reviews__text p { margin: 0 0 14px; }
.reviews__text p:last-child { margin-bottom: 0; }

.reviews__media {
  grid-area: media;
  position: relative;
  width: 100%;
  max-width: 520px;                /* the same weight as the other cards' pictures */
  justify-self: start;
}

/* the reviews band: full width in the site's ink, the dark counterpart of the
   blush band around How it's made. The review content sits straight on it -
   no glass card - at the width of the cards above, in the page ivory. */
.reviews-band {
  margin: 0;
  padding: 96px 0;
  background: var(--color-fill-strong);
  color: var(--color-text-inverse);
}
.reviews-band .reviews__card {
  width: calc(var(--lane) - 44px);
  margin: 0 auto;
  box-sizing: border-box;
  padding: 0;
  background: none;
  border: 0;
  box-shadow: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border-radius: 0;
}
.reviews-band .reviews__heading { color: var(--color-text-inverse); font-size: clamp(2rem, 3.6vw, 3.2rem); }
.reviews-band .reviews__text { color: rgba(252, 251, 244, .78); }   /* 10:1 on the ink */
.reviews-band .reviews__eyebrow { color: rgba(252, 251, 244, .7); }
.reviews-band .reviews__body { padding: 8px 0 8px 24px; }
.reviews-band .reviews__media { max-width: 560px; }
.reviews-band .reviews__track { outline-color: rgba(252, 251, 244, .14); }
.reviews-band .reviews__dot i {
  background: linear-gradient(0deg, var(--color-text-inverse) 0 0) no-repeat, rgba(252, 251, 244, .25);
  background-size: 100% 0%;
  background-position: bottom;
}
.reviews-band .reviews__dot:focus-visible { outline-color: rgba(252, 251, 244, .6); }

/* the store's social links, moved here from the header bar: named pills in
   the band's ivory, so each says where it goes rather than being a bare mark */
.reviews__social { margin-top: 30px; }
.reviews__social-label {
  margin: 0 0 12px;
  font-size: .95rem;
  color: rgba(252, 251, 244, .7);
}
.reviews__social-list {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.reviews__social-list a {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 40px;
  padding: 0 16px 0 12px;
  border-radius: 999px;
  border: 1px solid rgba(252, 251, 244, .22);
  color: var(--color-text-inverse);
  font-size: .95rem;
  text-decoration: none;
  transition: background-color 180ms ease, border-color 180ms ease, scale .12s ease-out;
}
.reviews__social-list a:hover { background-color: rgba(252, 251, 244, .08); border-color: rgba(252, 251, 244, .45); }
.reviews__social-list a:active { scale: .96; }
.reviews__social-list a:focus-visible { outline: 2px solid var(--color-text-inverse); outline-offset: 3px; }
.reviews__social-list svg { width: 18px; height: 18px; flex: none; }
@media (pointer: coarse) { .reviews__social-list a { min-height: 44px; } }

/* phones: one column each - the PC above its words, the reviews' words
   above the carousel */
@media (max-width: 860px) {
  .salvage__card { grid-template-columns: minmax(0, 1fr); grid-template-areas: "media" "body"; gap: 8px; }
  .salvage__media { padding: 8px 0 0; }
  .salvage__body { padding: 0 4px 6px; }
  .reviews__inner { grid-template-columns: minmax(0, 1fr); grid-template-areas: "body" "media"; gap: 24px; }
  .reviews__body { padding: 4px 4px 0; }
}

.reviews__track {
  position: relative;
  width: 100%;
  aspect-ratio: 1448 / 1086;
  border-radius: 14px;
  overflow: hidden;
  cursor: zoom-in;
}
.reviews__track:focus-visible {
  outline: 2px solid var(--matcha);
  outline-offset: 3px;
}

.reviews__slide {
  position: absolute;
  inset: 0;
  transition: opacity .6s ease;
}
/* hidden only once viprtech.js is running to rotate them */
.js .reviews__slide { opacity: 0; }
.reviews__slide.is-active { opacity: 1; }
.reviews__slide img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.reviews__arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 32px;
  height: 32px;
  border-radius: 999px;
  border: none;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, .75);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  color: var(--color-text);
  font-size: .75rem;
  cursor: pointer;
  opacity: 0;
  transition: opacity .25s ease, background .2s ease, scale .12s ease-out;
}
.reviews__media:hover .reviews__arrow,
.reviews__arrow:focus-visible { opacity: 1; }
.reviews__arrow:hover { background: #FFFEF8; }
.reviews__arrow.prev { left: 12px; }
.reviews__arrow.next { right: 12px; }

/* Same diamond-that-floods indicator the build carousel uses, so the two
   carousels read as the same control. The fill is also the clock here -
   see the animationend handler in the section. */
.reviews__dots {
  display: flex;
  justify-content: center;
  gap: 20px;
  margin-top: 18px;
}
.reviews__dot {
  padding: 0;
  border: none;
  background: none;
  line-height: 0;
  cursor: pointer;
}
.reviews__dot:focus-visible {
  outline: 2px solid rgba(35, 33, 28, .4);
  outline-offset: 4px;
  border-radius: 3px;
}

/* a diamond is just a square stood on its corner */
.reviews__dot i {
  display: block;
  width: 10px;
  height: 10px;
  border-radius: 3px;             /* softens the four points */
  transform: rotate(45deg);
  background: linear-gradient(0deg, var(--color-fill-strong) 0 0) no-repeat,
              rgba(35, 33, 28, .16);
  background-size: 100% 0%;
  background-position: bottom;    /* so it fills upward */
}
.reviews__dot[aria-current="true"] i {
  animation: dwell 5s linear forwards;
}
.reviews__card.is-paused .reviews__dot i { animation-play-state: paused; }

@media (max-width: 860px) {
  .reviews { grid-template-columns: minmax(0, 1fr); }
  .salvage__card,
  .reviews__card { padding: 22px; }
}

@media (prefers-reduced-motion: reduce) {
  .reviews__slide { transition: none; }
  /* Same trade as the build carousel: no fill animation means no clock, so
     it holds on one review and waits to be advanced by hand. */
  .reviews__dot i { animation: none; }
}

/* review zoom overlay */
.reviews__lightbox {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  place-items: center;
  padding: 4vh 4vw;
  background: rgba(35, 33, 28, .42);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.reviews__lightbox[hidden] { display: none; }

.reviews__lightbox-panel {
  position: relative;
  width: min(640px, 88vw);
}
.reviews__lightbox-img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 16px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, .35);
}
.reviews__lightbox-close {
  position: absolute;
  top: -14px;
  right: -14px;
  width: 42px;
  height: 42px;
  display: grid;
  place-items: center;
  border: 1px solid rgba(35, 33, 28, .14);
  border-radius: 999px;
  background: rgba(255, 255, 255, .92);
  color: var(--color-text);
  font-size: 1.35rem;
  line-height: 1;
  cursor: pointer;
  transition: transform .2s ease, background .2s ease;
}
.reviews__lightbox-close:hover { background: #FFFEF8; transform: scale(1.07); }

@media (max-width: 600px) {
  .reviews__lightbox-close { top: -12px; right: -6px; }
}

/* sold out
   The photo carries the state: drained of colour and faded, so a sold build
   reads as unavailable at a glance down a grid. Type stays legible rather
   than being faded with it, since the name and the price are still the
   things a customer is scanning for, and the Sold out label itself keeps
   full contrast. */
.build--sold .build__media img,
.slide--sold img {
  filter: grayscale(1);
  opacity: .45;
}

.build--sold .build__name,
.build--sold .build__price,
.slide--sold h2,
.slide--sold .slide-price { color: var(--color-text-muted); }

/* nothing left to choose between */
.build--sold .build__colors,
.slide--sold .slide-colors { opacity: .4; }

/* The stamp is the signal. Laid across the middle of the photo so it is read
   before the name or the price, and left level rather than tilted, which
   would fight the type everywhere else on the site. Ink rather than the
   warning red: being sold out is a state, not something gone wrong. The
   matcha edge ties it to the rest of the site. */
.build__soldout {
  position: absolute;
  left: 16px;
  right: 16px;
  top: 50%;
  transform: translateY(-50%);
  z-index: 3;
  padding: 9px 0;
  border-radius: 999px;
  background: rgba(35, 33, 28, .84);
  border: 2px solid var(--matcha);
  color: var(--color-text-inverse);
  font-family: var(--font-body);
  font-size: .92rem;
  font-weight: 600;
  letter-spacing: .3em;
  text-indent: .3em;                /* the tracking pads the right edge only */
  text-transform: uppercase;
  text-align: center;
}

/* the inline label repeats it next to the price, for the same reason */
.build--sold .sold,
.slide--sold .sold {
  margin-left: 10px;
  padding: 3px 9px;
  border-radius: 999px;
  background: rgba(35, 33, 28, .84);
  border: 1px solid var(--matcha);            /* the same green edge */
  color: var(--color-text-inverse);
  font-weight: 600;
  letter-spacing: .12em;
}

/* On a slide there is no stamp: the photo is a cut-out with no box to lay
   one across, so the label beside the price does the work and is sized to
   match that line. */
.slide--sold .sold { font-size: .8rem; }

/* the struck price is noise once it can't be bought */
.build--sold .build__was,
.build--sold .build__off,
.slide--sold .slide-was { display: none; }

/* the card no longer invites a click */
.build--sold:hover { transform: none; }

@media (prefers-reduced-motion: no-preference) {
  .build--sold .build__media img,
  .slide--sold img { transition: filter .3s ease, opacity .3s ease; }
}

/* collection filter */
/* The panel hangs off the button rather than sitting in the flow, so opening
   it doesn't shove the grid down the page. */
.filter { position: relative; }

.filter__toggle {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 10px 18px;
  border: 1px solid rgba(35, 33, 28, .2);
  border-radius: 999px;
  background: rgba(255, 255, 255, .5);
  font-family: var(--font-body);
  font-size: .86rem;
  letter-spacing: .02em;
  color: var(--color-text);
  cursor: pointer;
  transition: border-color .2s ease, background .2s ease, scale .12s ease-out;
}
.filter__toggle:hover { border-color: rgba(35, 33, 28, .45); }
.filter__toggle:focus-visible { outline: 2px solid var(--matcha); outline-offset: 3px; }
.filter__toggle svg { width: 15px; height: 15px; flex: none; }

/* how many facets are on, so the state reads while the panel is shut */
.filter__count {
  min-width: 19px;
  height: 19px;
  padding: 0 6px;
  border-radius: 999px;
  background: var(--matcha-deep);   /* 5:1 under the white count; --matcha was 3:1 */
  color: var(--color-text-inverse);
  font-size: .7rem;
  line-height: 19px;
  text-align: center;
}
.filter__count[hidden] { display: none; }

.filter__panel {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 25;
  width: max-content;
  max-width: min(380px, calc(100vw - 44px));
  max-height: min(60vh, 420px);
  overflow-y: auto;

  padding: 14px 16px;
  border: 1px solid rgba(255, 255, 255, .7);
  border-radius: 14px;
  /* opaque enough to read against whatever card it lands on */
  background: rgba(252, 251, 244, .97);
  backdrop-filter: blur(14px) saturate(180%);
  -webkit-backdrop-filter: blur(14px) saturate(180%);
  box-shadow: 0 14px 40px rgba(60, 55, 40, .18);

  display: grid;
  gap: 12px;
  text-align: left;
}
.filter__panel[hidden] { display: none; }

.filter__label {
  margin: 0 0 8px;
  font-family: var(--font-body);
  font-size: .9rem;
  letter-spacing: 0;
  text-transform: none;
  color: var(--color-text-muted);
}
.filter__chips { display: flex; flex-wrap: wrap; gap: 6px; }

.chip {
  padding: 7px 13px;
  border: 1px solid rgba(35, 33, 28, .18);
  border-radius: 999px;
  background: rgba(255, 255, 255, .6);
  font-family: var(--font-body);
  font-size: .9rem;
  color: rgba(35, 33, 28, .72);
  cursor: pointer;
  transition: border-color .2s ease, background .2s ease, color .2s ease;
}
.chip:hover { border-color: rgba(35, 33, 28, .4); }
.chip:focus-visible { outline: 2px solid var(--matcha); outline-offset: 2px; }
.chip[aria-pressed="true"] {
  background: var(--color-fill-strong);
  border-color: var(--color-fill-strong);
  color: var(--color-text-inverse);
}

/* an option no product can currently satisfy, left visible so the range of
   the catalogue still reads, but plainly not selectable */
.chip[disabled] {
  opacity: .35;
  cursor: not-allowed;
}

.filter__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding-top: 2px;
  border-top: 1px solid rgba(35, 33, 28, .08);
  margin-top: 2px;
}
.filter__result {
  margin: 8px 0 0;
  font-size: .86rem;
  color: var(--color-text-muted);
}
.filter__clear {
  margin-top: 8px;
  padding: 0;
  border: none;
  background: none;
  font-family: var(--font-body);
  font-size: .84rem;
  color: var(--matcha-deep);
  text-decoration: none;
  border-bottom: 1px solid rgba(100, 128, 63, .4);
  cursor: pointer;
}
.filter__clear[hidden] { display: none; }

/* The cards set their own display, which outranks the browser's built-in
   [hidden] rule, so filtered-out cards need saying explicitly. */
.build[hidden],
.series-rule[hidden] { display: none; }

/* nothing matched */
.builds__empty {
  grid-column: 1 / -1;
  margin: 0;
  padding: 30px 0;
  font-size: 1rem;
  color: var(--color-text-muted);
}

@media (max-width: 560px) {
  /* not enough width to hang off the button, so it spans the lane instead */
  .filter__panel {
    left: 0;
    right: 0;
    width: auto;
    max-width: none;
  }
  .coll__tools { width: 100%; }
  .coll__tools .filter__toggle { flex: 1; justify-content: center; }
}

/* setup guide */
.setup {
  width: var(--lane);
  max-width: 780px;
  margin: 0 auto;
  padding: 152px 22px 90px;         /* clears the ticker + fixed bar */
}

.setup__head { margin-bottom: 46px; }
.setup__eyebrow {
  margin: 0 0 12px;
  font-family: var(--font-body);
  font-size: .9rem;
  letter-spacing: 0;
  text-transform: none;
  color: var(--matcha-deep);
}
.setup__heading {
  margin: 0 0 16px;
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-weight: 400;
  font-size: clamp(2rem, 4vw, 2.8rem);
  line-height: 1.08;
  letter-spacing: -.01em;
  color: var(--color-text);
}
.setup__intro {
  margin: 0;
  max-width: 58ch;
  font-size: 1.06rem;
  line-height: 1.6;
  color: var(--color-text-muted);
}
.setup__intro p { margin: 0; }

/* The rule down the left ties the steps into one run, with each number
   sitting on it. The numbering is content here, not decoration: it is an
   order the reader has to follow. */
.setup__steps {
  list-style: none;
  margin: 0;
  padding: 0 0 0 30px;
  border-left: 1px solid rgba(35, 33, 28, .12);
  display: grid;
  gap: 42px;
}

/* Layout. One photo sits in a column beside the points it illustrates; a
   pair is a comparison and runs full width underneath, as do the points on
   a step with no photo at all. */
.step {
  position: relative;               /* the number's marker hangs off this */
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  column-gap: 30px;
  align-items: start;
}
.step__no,
.step__title,
.step__list,
.step__media { grid-column: 1 / -1; }

.step--aside .step__list  { grid-column: 1; }
.step--aside .step__media { grid-column: 2; margin-top: 4px; }

/* Parts */
.step__no {
  margin: 0 0 8px;
  font-family: var(--font-body);
  font-size: .9rem;
  letter-spacing: 0;
  text-transform: none;
  color: var(--matcha-deep);
}
.step__no::before {                 /* the marker sits on the rule itself */
  content: "";
  position: absolute;
  left: -34px;
  top: 3px;
  width: 8px;
  height: 8px;
  border-radius: 2px;
  transform: rotate(45deg);
  background: var(--matcha);
}

.step__title {
  margin: 0 0 14px;
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-weight: 400;
  font-size: 1.5rem;
  line-height: 1.2;
  letter-spacing: -.005em;
  color: var(--color-text);
}

.step__list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 10px;
}
.step__list li {
  position: relative;
  padding-left: 18px;
  font-size: 1rem;
  line-height: 1.6;
  color: rgba(35, 33, 28, .72);
}
.step__list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: .62em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: rgba(35, 33, 28, .28);
}

.step__media {
  margin-top: 18px;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 18px 22px;
}
.step__figure {
  margin: 0;
  padding: 0;
  min-width: 0;
}

/* Height, not width. Filling the column made every photo the same size
   whatever its shape; capping the height keeps each one's proportions and
   still gives them a common weight. No frame either: several are cut out on
   transparency, where a border would outline empty space, so the shadow
   grounds them the way the build photos are grounded. */
.step__figure img {
  display: block;
  width: auto;
  max-width: 100%;
  height: auto;
  border-radius: 10px;
  filter: drop-shadow(0 6px 10px rgba(60, 55, 40, .13));
}
.step--aside .step__figure img { max-height: 150px; }
.step--pair .step__figure img { max-height: 280px; }   /* these carry detail */

.step__figure figcaption {
  margin-top: 8px;
  font-family: var(--font-body);
  font-size: .76rem;
  color: var(--color-text-muted);
}

.setup__done {
  margin-top: 52px;
  padding: 22px 24px;
  border-radius: 16px;
  background: rgba(124, 154, 87, .09);
  border: 1px solid rgba(124, 154, 87, .28);
  font-size: 1rem;
  line-height: 1.6;
  color: var(--color-text-secondary);
}
.setup__done p { margin: 0; }

@media (max-width: 860px) {
  .setup { padding: 128px 14px 60px; }
  .setup__head { margin-bottom: 34px; }
  .setup__steps { padding-left: 22px; gap: 34px; }
  .step__no::before { left: -26px; }
  .step__title { font-size: 1.3rem; }

  /* one column: nothing has the room to sit beside the text */
  .step { grid-template-columns: minmax(0, 1fr); }
  .step--aside .step__list { grid-column: 1; }
  .step--aside .step__media { grid-column: 1; margin-top: 18px; }
  .step--pair .step__figure img { max-height: 200px; }
}

/* load screen */
/* Clears itself on a timer as well as on window.load, so a blocked script
   can never leave a visitor on a blank panel. */
.pageload {
  position: fixed;
  inset: 0;
  z-index: 999;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 22px;
  background: var(--color-page);
  animation: pageloadOut .45s ease 2s both;
}
.pageload.is-done { animation: pageloadOut .4s ease 0s both; }
@keyframes pageloadOut {
  to { opacity: 0; visibility: hidden; pointer-events: none; }
}

.pageload__mark {
  font-family: var(--font-brand);
  font-size: 1rem;
  letter-spacing: .01em;
  line-height: 1;
  color: var(--color-text);
}
.pageload__mark span { opacity: .42; }

/* eleven discrete steps, to sit with the wordmark above it */
.pageload__bar {
  width: 132px;
  height: 8px;
  border-radius: 1px;
  background: rgba(35, 33, 28, .12);
  overflow: hidden;
}
.pageload__bar i {
  display: block;
  width: 100%;
  height: 100%;
  background: var(--color-fill-strong);
  transform-origin: left;
  animation: pageloadFill 1.6s steps(11, end) both;
}
@keyframes pageloadFill {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

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

/* menu button + phone menu
   The panel sits outside .bar in the markup. .bar is transformed, which makes
   it the containing block for any fixed child, and .glass then crops it. */
.nav-toggle {
  display: none;                    /* only exists below the breakpoint */
  width: 40px;
  height: 40px;
  padding: 0;
  border: none;
  border-radius: 10px;
  background: transparent;
  cursor: pointer;
  place-items: center;
  transition: scale .12s ease-out;
}
.nav-toggle__bars,
.nav-toggle__bars::before,
.nav-toggle__bars::after {
  display: block;
  width: 19px;
  height: 1.8px;
  border-radius: 2px;
  background: var(--color-fill-strong);
  transition: transform .3s cubic-bezier(.19, 1, .22, 1), opacity .2s ease;
}
.nav-toggle__bars { position: relative; }
.nav-toggle__bars::before,
.nav-toggle__bars::after { content: ""; position: absolute; left: 0; }
.nav-toggle__bars::before { top: -6px; }
.nav-toggle__bars::after  { top: 6px; }

/* the three bars fold into a cross while the panel is open */
.nav-toggle[aria-expanded="true"] .nav-toggle__bars { background: transparent; }
.nav-toggle[aria-expanded="true"] .nav-toggle__bars::before { transform: translateY(6px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bars::after  { transform: translateY(-6px) rotate(-45deg); }

.mnav { display: none; }

/* small screens
   Kept last. The base .nav and .brand rules sit further down the sheet than
   the rest of the bar, so a block placed earlier would lose to them. */

/* One too-wide child anywhere makes the whole page scroll sideways.
   clip instead of hidden, so body doesn't become a scroll container and
   break position: sticky. */
html,
body {
  overflow-x: hidden;               /* for browsers without clip */
  overflow-x: clip;
}

@media (max-width: 860px) {
  /* bar */
  .bar {
    grid-template-columns: auto 1fr auto;
    padding: 0 10px;
  }
  .nav-toggle { display: grid; order: 1; }
  .social     { order: 3; padding-right: 0; }   /* the 84px is flower clearance */
  .nav        { display: none; }                /* the caret needs a row */

  /* Centred on the bar, not on the column between the button and the cart.
     Those two differ in width, and the cart's grows with the item badge. */
  .brand {
    order: 2;
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
  }

  /* The script measures the wordmark and sets the exact position; this
     percentage is only the fallback. */
  .flower {
    width: 62px;
    right: 64%;
    top: -9px;
  }
  /* no bloom on touch: its hit area would land mid-swipe */
  .flower::after { pointer-events: none; }
  .bloom-fx { display: none; }

  /* phone menu */
  .mnav {
    display: block;
    position: fixed;
    top: 126px;                     /* clears the ticker (52) + the bar (68) */
    left: 50%;
    width: var(--lane);
    box-sizing: border-box;
    z-index: 30;

    padding: 8px;
    max-height: calc(100vh - 146px);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;

    background: rgba(255, 255, 255, .78);
    backdrop-filter: blur(18px) saturate(180%);
    -webkit-backdrop-filter: blur(18px) saturate(180%);
    border: 1px solid rgba(255, 255, 255, .70);
    border-radius: 14px;
    box-shadow:
      0 14px 40px rgba(60, 55, 40, .16),
      inset 0 1px 0 rgba(255, 255, 255, .70);

    opacity: 0;
    transform: translateX(-50%) translateY(-8px);
    pointer-events: none;
    transition: opacity .2s ease, transform .26s cubic-bezier(.19, 1, .22, 1);
  }
  .mnav.is-open {
    opacity: 1;
    transform: translateX(-50%);
    pointer-events: auto;
  }

  .mnav__item,
  .mnav__child {
    display: block;
    padding: 13px 14px;
    border-radius: 10px;
    font-family: var(--font-body);
    font-size: .92rem;
    letter-spacing: .02em;
    color: #3b382f;
    text-decoration: none;
  }
  .mnav__item.is-current,
  .mnav__child.is-current { color: var(--color-text); background: rgba(35, 33, 28, .06); }
  .mnav__item:active,
  .mnav__child:active { background: rgba(35, 33, 28, .09); }

  /* children indented under their parent, one quiet step down in size */
  .mnav__sub {
    margin: 2px 0 6px;
    padding-left: 12px;
    border-left: 1px solid rgba(35, 33, 28, .12);
  }
  .mnav__child {
    padding: 10px 12px;
    font-size: .86rem;
    color: var(--color-text-muted);
  }

  /* home */
  .hero {
    padding: 134px 10px 30px;       /* ticker (52) + bar (68) + clearance */
    gap: 22px;
  }
  .panel-wrap { order: 2; }         /* builds first, pitch under them */

  .panel {
    min-height: 0;                  /* the 540px floor is for the wide row */
    padding: 50px 20px 24px;        /* top still clears the vine */
  }
  .panel h1 { margin-bottom: 22px; }
  .panel p {
    margin-bottom: 20px;
    max-width: none;
    font-size: 1rem;
  }
  .facts {                          /* margin-top:auto had the floor to push on */
    margin-top: 26px;
    padding-top: 18px;
    gap: 11px 12px;
  }

  .slide { padding: 24px 12px 20px; }
  /* A portrait case fills its box exactly, so its shadow falls outside the
     element and iOS crops it inside .track. The padding gives the shadow
     room inside the box; content-box keeps height sizing the photo. */
  .slide img {
    box-sizing: content-box;
    height: min(38vh, 320px);
    padding-bottom: 58px;
  }

  .dots {
    gap: 16px;
    margin-top: 10px;               /* the -34px tuck needs the taller padding */
  }
  .dot {
    font-size: .76rem;
    letter-spacing: 0;
  }

  /* hover-only, so on touch these are invisible but still tappable */
  .arrow,
  .reviews__arrow { display: none; }

  .intro   { padding: 0 10px 56px; }
  .reviews { padding: 0 10px; margin-bottom: 56px; gap: 56px; }
  .reviews-band { padding: 56px 0; }
  .reviews-band + .reviews { margin-top: 56px; }
  .reviews-band .reviews__card { width: calc(var(--lane) - 20px); }
  .reviews-band .reviews__body { padding: 0; }

  .process { margin-bottom: 56px; padding: 48px 0; }
  .process__inner { width: calc(var(--lane) - 20px); }   /* lines up with .intro's 10px gutters */

  /* product */
  /* display: contents drops the .prod__media wrapper so the gallery, the buy
     block and the case card can be ordered separately. Without it the case
     card sits between the photos and Add to cart. */
  .prod {
    display: flex;
    flex-direction: column;
    gap: 26px;
  }
  .prod__media { display: contents; }
  .prod__media .gallery  { order: 1; margin-bottom: 0; }
  .prod__info            { order: 2; }
  .prod__media .casecard { order: 3; }

  .pad { padding: 128px 12px 56px; }

  /* both pin to a shared bottom line that the stacked layout hasn't got */
  .prod__media .casecard,
  .prod__info .prod__facts { margin-top: 24px; }

  /* same shadow clipping as the build carousel */
  .gallery__main { border-radius: 0; }
  .shot { padding-bottom: 0; }
  .shot img {
    box-sizing: content-box;
    height: min(44vh, 360px);
    padding-bottom: 30px;
  }
  .thumb { width: 54px; height: 54px; }

  .qty__row { flex-wrap: wrap; }
  .qty__row .cta--solid {           /* its own row rather than a cramped target */
    flex: 1 1 100%;
    text-align: center;
  }
  .prod__row { gap: 18px 24px; }

  .kitcard {
    grid-template-columns: minmax(0, 1fr);
    gap: 20px;
    padding: 20px;
  }
  .kbcard   { padding: 20px; }
  .casecard { padding: 18px; }
}

@media (max-width: 560px) {
  .cart-layout  { gap: 24px; margin-top: 22px; }
  .cart-summary { padding: 20px; }

  /* photo and details on top, then the controls and the money a row each */
  .line {
    grid-template-columns: 64px minmax(0, 1fr);
    grid-template-areas:
      "media info"
      "qty   qty"
      "price price";
    gap: 14px;
    row-gap: 12px;
    padding-bottom: 16px;
  }
  .line__title { font-size: 1.04rem; }

  .line__qtywrap {                  /* was a column: label over input over button */
    flex-direction: row;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
  }
  .line__qty    { padding: 10px 6px; }
  .line__update { padding: 9px 14px; }
  .line__remove { padding: 6px 0; }
  .qty__step    { width: 42px; height: 40px; }

  .line__prices {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    padding-top: 2px;
    border-top: 1px solid rgba(35, 33, 28, .07);
  }
  .line__unit  { margin: 0; }
  .line__price { min-width: 0; font-size: 1.06rem; }

  /* Full lane, scrolling as one panel, instead of a 330px card with its own
     292px scroller inside it. */
  .cart-peek {
    width: var(--lane);
    max-height: calc(100vh - 150px);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }
  .cart-peek__list {
    max-height: none;
    overflow-y: visible;
  }
}

/* ─────────────────────────────────────────────────────────────────────────
   Interface polish
   Small details that apply everywhere. Kept together so they are easy to
   find and to undo.
   ───────────────────────────────────────────────────────────────────────── */

:root {
  --image-edge: rgba(0, 0, 0, .1);   /* pure black at low alpha, never a tinted grey */
}

/* the browser's own surfaces take the palette too */
::selection { background: var(--blush-soft); color: var(--color-text); }
html { caret-color: var(--matcha-deep); scrollbar-color: rgba(35, 33, 28, .3) transparent; }

/* crisper text on macOS, set once at the root */
html {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* nothing can push the page sideways; clip (not hidden) keeps sticky working */
html, body { overflow-x: clip; }

/* headings wrap evenly, paragraphs never end on a lone word */
h1, h2, h3 { text-wrap: balance; }
p, li, dd { text-wrap: pretty; }

/* prices and counts keep one digit width, so nothing shifts as they change */
.slide-price, .build__price, .prod__price, .prod__was, .prod__save,
.line__price, .line__unit, .line__qty, .qty__input,
.cart-summary__row, .cart-peek__total, .peek-line__price, .cart-peek__count,
.cart-count, .card__price, .filter__count, .coll__count, .search__count {
  font-variant-numeric: tabular-nums;
}

/* press feedback: a small, quick squeeze on every button */
.cta--solid:active, .cta--ghost:active, .intro__link:active, .salvage__link:active,
.cart-link:active, .cart-peek__view:active, .filter__toggle:active, .searchbar__go:active,
.qty__step:active, .also__arrow:not([disabled]):active, .reviews__arrow:active,
.arrow:active, .nav-toggle:active, .search__chips a:active {
  scale: .96;
}

/* photographs get a faint edge so light images don't bleed into the page;
   the cut-out PC renders are left alone - an edge would box them in */
.intro__media, .reviews__track, .setup img {
  outline: 1px solid var(--image-edge);
  outline-offset: -1px;
}

/* touch targets: at least 40px on desktop, 44px where fingers are used */
.also__arrow, .reviews__arrow { width: 40px; height: 40px; }
.vt-footer__social a { width: 40px; height: 40px; }
.vt-footer__social { gap: 0; }
.reviews__dot { position: relative; }
.reviews__dot::before {           /* the diamond is 10px; the hit area is not */
  content: "";
  position: absolute;
  inset: -10px;                   /* dots sit 20px apart, so areas meet but never overlap */
}
.qty__step { min-height: 40px; }
@media (pointer: coarse) {
  .vt-footer__social a, .qty__step { min-width: 44px; min-height: 44px; }
}

/* iOS zooms the page when a field's text is under 16px */
@media (max-width: 1099px) {
  input:not([type="checkbox"]):not([type="radio"]), select, textarea { font-size: max(16px, 1em); }
}

@media (prefers-reduced-motion: reduce) {
  .js .slide h2 { opacity: 1; transform: none; }
}

/* ─────────────────────────────────────────────────────────────────────────
   Homepage motion
   1. How it's made: its four stages tick off one after another as the card
      reaches the middle of the screen.
   2. The cards land: each glass card that starts below the screen settles
      up into place, and each brings its
      own inner move - the photo opens like a shutter, the PC settles from a
      slight scale.
   Cards on screen at load never animate, nothing is ever faded out, and
   with reduced motion or no script everything simply sits in place.
   ───────────────────────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: no-preference) {

  /* 1 · the reveal, once. The four stages sign off one after another,
     260ms apart: the icon draws itself in green inside an empty ring, then
     the ring fills and the icon turns white - ticked. The stage name steps
     from muted grey up to full ink as its tick lands. About 1.6s in all. */
  .js [data-reveal] .process__mark::before {
    transform: scale(0);
    transition: transform 380ms cubic-bezier(.2, 0, 0, 1) calc(var(--i, 0) * 260ms + 420ms);
  }
  .js [data-reveal] .process__icon {
    color: var(--matcha-deep);
    transition: color 200ms cubic-bezier(.2, 0, 0, 1) calc(var(--i, 0) * 260ms + 480ms);
  }
  .js [data-reveal] .process__icon :is(path, circle, rect) {
    stroke-dasharray: 1;
    stroke-dashoffset: 1;
    transition: stroke-dashoffset 500ms cubic-bezier(.65, 0, .35, 1) calc(var(--i, 0) * 260ms);
  }
  .js [data-reveal] .process__title {
    color: var(--color-text-muted);
    transition: color 300ms cubic-bezier(.2, 0, 0, 1) calc(var(--i, 0) * 260ms + 520ms);
  }
  .js [data-reveal].is-in .process__mark::before { transform: none; }
  .js [data-reveal].is-in .process__icon { color: var(--color-text-inverse); }
  .js [data-reveal].is-in .process__icon :is(path, circle, rect) { stroke-dashoffset: 0; }
  .js [data-reveal].is-in .process__title { color: var(--color-text); }
  .process__node:nth-child(2) { --i: 1; }
  .process__node:nth-child(3) { --i: 2; }
  .process__node:nth-child(4) { --i: 3; }

  /* 2 · the cards land. A card that starts below the screen waits 32px low
     (.is-pending, set by viprtech.js) and settles as it comes up, on the same
     expo curve the header unfolds on. Never faded: the glass stays solid. */
  [data-settle] {
    transition: translate 900ms cubic-bezier(.19, 1, .22, 1) var(--land-delay, 0ms);
  }
  [data-settle].is-pending { translate: 0 32px; transition: none; }

  /* each card's own move, so no two arrive the same way */
  /* Home & Office: the photo opens upward like a shutter, settling from a slight zoom */
  [data-settle] .intro__media {
    clip-path: inset(0 0 0 0 round 14px);
    transition: clip-path 1200ms cubic-bezier(.19, 1, .22, 1) 120ms;
  }
  [data-settle] .intro__img { transition: scale 1400ms cubic-bezier(.19, 1, .22, 1) 120ms; }
  [data-settle].is-pending .intro__media { clip-path: inset(100% 0 0 0 round 14px); transition: none; }
  [data-settle].is-pending .intro__img { scale: 1.12; transition: none; }

  /* Salvage: the PC settles from a slight scale */
  [data-settle] .salvage__img {
    transition: scale 1100ms cubic-bezier(.19, 1, .22, 1) 120ms, opacity 600ms cubic-bezier(.22, 1, .36, 1) 120ms;
  }
  [data-settle].is-pending .salvage__img { scale: .94; opacity: 0; transition: none; }

  /* How it's made: its stages tick off row by row (part 1 above) */
}

/* hovering a stage: one signal, its ring darkens */
.process__mark::before { transition: background-color 220ms cubic-bezier(.2, 0, 0, 1); }
.process__node:hover .process__mark::before { background-color: #4A622A; }

/* The header glass, a little more solid than the shared .glass recipe: at
   .35 white it went grey over the ink reviews band and the nav links all but
   disappeared. Still frosted, now readable over any ground. */
.bar.glass { background: rgba(252, 251, 244, .78); }

/* the Salvage card follows the reviews band with the usual gap between cards */
.reviews-band + .reviews { margin-top: 90px; }

/* whichever band closes the page runs straight into the footer */
body:has(#main > :last-child > :is(.reviews-band, .process, .fin-close):last-child) .vt-footer { margin-top: 0; }
#main > :last-child > .process:last-child { margin-bottom: 0; }

/* ─────────────────────────────────────────────────────────────────────────
   Financing page (sections/vt-financing.liquid)
   The offer up front in a glass banner, the steps in the homepage's blush
   band, then the details in the Warranty page's reading layout.
   ───────────────────────────────────────────────────────────────────────── */

.fin {
  width: var(--lane);
  margin: 0 auto;
  padding: 152px 22px 90px;          /* clears the ticker + fixed bar, like .pad */
  box-sizing: border-box;
}

/* the banner: the same glass card as the homepage's Home & Office card */
.fin-hero {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  align-items: stretch;
  gap: 48px;
  padding: 26px;
  border-radius: 20px;
  background: rgba(255, 255, 255, .35);
  backdrop-filter: blur(16px) saturate(180%);
  -webkit-backdrop-filter: blur(16px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, .6);
  box-shadow:
    0 8px 32px rgba(60, 55, 40, .10),
    inset 0 1px 0 rgba(255, 255, 255, .70);
}
.fin-hero__body {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-width: 0;
  padding: 32px 10px 32px 22px;
}
.fin-hero__title {
  margin: 0 0 18px;
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-weight: 400;
  font-size: clamp(2.3rem, 4.4vw, 4rem);
  line-height: 1.02;
  letter-spacing: -.025em;
  text-wrap: balance;
  color: var(--color-text);
}
.fin-hero__lede {
  margin: 0;
  max-width: 44ch;
  font-size: 1.15rem;
  line-height: 1.55;
  color: var(--color-text-secondary);
  text-wrap: pretty;
}
.fin-hero__actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 30px; }

/* the offer, set large in Affirm's blue, with one of the store's own builds
   standing on it - the page shows what is being paid for, not just terms */
.fin-offer {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 24px;
  min-width: 0;
  padding: 40px 28px 0 36px;
  border-radius: 14px;               /* the same corners as the Home & Office photo */
  background: var(--affirm-blue);
  color: var(--color-text-inverse);
}
.fin-offer__words { padding-bottom: 40px; min-width: 0; }
.fin-offer__kicker { margin: 0 0 10px; font-size: 1rem; }
.fin-offer__big {
  margin: 0;
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-weight: 400;
  font-size: clamp(2.8rem, 5.6vw, 5rem);
  line-height: .95;
  letter-spacing: -.03em;
}
.fin-offer__text { margin: 12px 0 0; max-width: 28ch; font-size: 1.15rem; line-height: 1.4; }
.fin-offer__img {
  align-self: end;
  margin-bottom: 28px;             /* stands a little up from the panel's edge */
  width: auto;
  height: clamp(220px, 26vw, 340px);
  filter: drop-shadow(0 18px 22px rgba(20, 20, 70, .35));
}
.fin-offer__note {
  margin: 24px 0 0;
  font-size: .95rem;
  line-height: 1.5;
}

/* the steps band sits straight under the banner; three across, not four */
.fin-steps__rail { grid-template-columns: repeat(3, minmax(0, 1fr)); }

/* its rings tick on in Affirm's blue instead of the site's green */
.fin-steps .process__mark { box-shadow: inset 0 0 0 1.5px color-mix(in oklab, var(--affirm-blue) 40%, transparent); }
.fin-steps .process__mark::before { background: var(--affirm-blue); }
.fin-steps .process__node:hover .process__mark::before { background-color: var(--affirm-blue-dark); }
@media (prefers-reduced-motion: no-preference) {
  .js .fin-steps [data-reveal] .process__icon { color: var(--affirm-blue); }
  .js .fin-steps [data-reveal].is-in .process__icon { color: var(--color-text-inverse); }
}

/* the terms sheet: a glass card like every other container on the site, the
   heading on the left and the terms on the right. Rows are told apart by a
   step in tone on every other row, so each name sits with its answer. */
.fin-terms {
  display: grid;
  grid-template-columns: minmax(0, 4fr) minmax(0, 8fr);
  gap: 24px 56px;
  width: calc(var(--lane) - 44px);    /* the width of the banner card above */
  margin: 0 auto;
  padding: 40px 44px;
  box-sizing: border-box;
  border-radius: 20px;
  background: rgba(255, 255, 255, .35);
  backdrop-filter: blur(16px) saturate(180%);
  -webkit-backdrop-filter: blur(16px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, .6);
  box-shadow:
    0 8px 32px rgba(60, 55, 40, .10),
    inset 0 1px 0 rgba(255, 255, 255, .70);
}
.fin-terms__title {
  margin: 0 0 14px;
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-weight: 400;
  font-size: clamp(2rem, 3.6vw, 3.2rem);
  line-height: 1.02;
  letter-spacing: -.022em;
  color: var(--color-text);
}
.fin-terms__more {
  font-size: 1.02rem;
  color: var(--matcha-deep);
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}
.fin-terms__more:hover { color: var(--color-text); }
.fin-terms__list { margin: 0; display: grid; gap: 4px; }
.fin-terms__row {
  display: grid;
  grid-template-columns: minmax(10rem, 2fr) minmax(0, 5fr);
  gap: 6px 28px;
  align-items: baseline;
  padding: 16px 20px;
  border-radius: 12px;
}
.fin-terms__row:nth-child(odd) { background: rgba(35, 33, 28, .045); }
.fin-terms__row dt {
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-size: 1.3rem;
  line-height: 1.2;
  letter-spacing: -.01em;
  color: var(--color-text);
}
.fin-terms__row dd {
  margin: 0;
  font-size: 1.06rem;
  line-height: 1.55;
  color: var(--color-text);
  text-wrap: pretty;
}
.fin-terms__row dd p { margin: 0; }
.fin-terms__row dd a { color: var(--matcha-deep); }

/* the close: its own ink band, like the homepage's reviews band, running
   into the footer - the question in ivory, its two answers beside it */
.fin-close {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px 48px;
  margin-top: 120px;
  padding: 96px calc((100% - var(--lane)) / 2 + 22px);
  background: var(--color-fill-strong);
  color: var(--color-text-inverse);
}
.fin-close__title {
  margin: 0;
  max-width: 16ch;
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-weight: 400;
  font-size: clamp(2rem, 4vw, 3.6rem);
  line-height: 1.02;
  letter-spacing: -.025em;
  text-wrap: balance;
  color: var(--color-text-inverse);
}
.fin-close__actions { display: flex; flex-wrap: wrap; gap: 12px; }
.fin-close .intro__link {
  color: var(--color-text-inverse);
  background: transparent;
  border-color: rgba(252, 251, 244, .35);
}
.fin-close .intro__link:hover { border-color: rgba(252, 251, 244, .75); }
.fin-close .intro__link--solid {
  background: var(--color-text-inverse);
  border-color: var(--color-text-inverse);
  color: var(--color-text);
}
.fin-close .intro__link--solid:hover { background: #FFFEF8; border-color: #FFFEF8; }
.fin-close .intro__link:focus-visible { outline: 2px solid var(--color-text-inverse); outline-offset: 3px; }

@media (max-width: 860px) {
  .fin { padding: 138px 10px 56px; }
  .fin-terms { grid-template-columns: minmax(0, 1fr); width: calc(var(--lane) - 20px); padding: 26px 16px; gap: 16px; }
  .fin-terms__row { grid-template-columns: minmax(0, 1fr); padding: 14px 14px; }
  .fin-close { margin-top: 72px; padding: 56px 20px; align-items: flex-start; flex-direction: column; }
  .fin-hero { grid-template-columns: minmax(0, 1fr); gap: 16px; padding: 12px; }
  .fin-hero__body { padding: 20px 14px 10px; }
  .fin-offer { grid-template-columns: minmax(0, 1fr); padding: 28px 24px 0; gap: 4px; }
  .fin-offer__words { padding-bottom: 8px; }
  .fin-offer__text { max-width: none; }
  .fin-offer__img { justify-self: center; height: 230px; margin-bottom: 20px; }
  .fin-steps__rail { grid-template-columns: minmax(0, 1fr); }
}

/* "0% APR option with Affirm" under prices (snippets/affirm-badge.liquid):
   Affirm's pale indigo pill with its blue, the rest in the page's ink */
.affirm-badge {
  display: inline-flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 10px;
  font-size: .95rem;
  color: var(--color-text-secondary);
  text-decoration: none;
}
.affirm-badge__pill {
  padding: 3px 10px;
  border-radius: 999px;
  background: #E6E6FC;                 /* Affirm's --color-primary-lightest */
  color: var(--affirm-blue-dark);      /* 7.4:1 on the pill */
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
a.affirm-badge { transition: color 180ms ease; }
a.affirm-badge:hover { color: var(--color-text); }
a.affirm-badge:focus-visible { outline: 2px solid var(--affirm-blue); outline-offset: 3px; border-radius: 6px; }
.prod__meta + .affirm-badge { margin: 4px 0 18px; }
.build__price + .affirm-badge { margin: 6px 0 12px; font-size: .88rem; }   /* sits with the price, clear of the swatches */

/* Financing questions: the terms card again, its rows opening in place */
.fin-faq { margin-top: 32px; }
.fin-faq__help { margin-top: 4px; font-size: 1.02rem; color: var(--color-text-secondary); }
.fin-faq__help p { margin: 0; }
.fin-faq__help a, .fin-faq__answer a { color: var(--matcha-deep); }
.fin-faq__list { display: grid; gap: 4px; }
.fin-faq__item { border-radius: 12px; }
.fin-faq__item:nth-child(odd) { background: rgba(35, 33, 28, .045); }
.fin-faq__item summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: 44px;
  padding: 14px 20px;
  font-family: var(--font-display);
  font-size: 1.25rem;
  line-height: 1.25;
  color: var(--color-text);
  cursor: pointer;
  list-style: none;
}
.fin-faq__item summary::-webkit-details-marker { display: none; }
.fin-faq__item summary::after {            /* a plus that turns into a minus */
  content: "+";
  flex: none;
  font-family: var(--font-body);
  font-size: 1.4rem;
  line-height: 1;
  color: var(--affirm-blue-dark);
  transition: rotate 200ms ease-out;
}
.fin-faq__item[open] summary::after { content: "\2212"; }
.fin-faq__item summary:hover { color: var(--affirm-blue-dark); }
.fin-faq__item summary:focus-visible { outline: 2px solid var(--affirm-blue); outline-offset: 2px; border-radius: 12px; }
.fin-faq__answer { padding: 0 20px 18px; font-size: 1.04rem; line-height: 1.6; color: var(--color-text-secondary); max-width: 62ch; }
.fin-faq__answer p { margin: 0; }

/* Affirm's official logo files (assets/affirm-logo*.png), used as supplied */
/* scoped tighter than the product page's ".prod img { width: 100% }" so the logo stays text-sized */
.affirm-badge img.affirm-badge__logo { height: 1.35em; width: auto; max-width: none; vertical-align: middle; margin-top: -.2em; }
.fin-offer__logo { display: block; height: 34px; width: auto; margin: 0 0 18px; }
.fin-faq__logo { display: block; height: 40px; width: auto; margin: 0 0 28px; }

/* ─────────────────────────────────────────────────────────────────────────
   Phone text floor. Desktop runs at 90% zoom, so these small sizes were
   tuned there; on a phone 1rem is a true 16px and they fell under 13px.
   Lifted to ~13.5px. Icon arrows and the pixel wordmark are left as they are.
   ───────────────────────────────────────────────────────────────────────── */
@media (max-width: 1099px) {
  .peek-line__qty, .cart-peek__more, .toast__item, .line__remove, .line__update,
  .line__unit, .cart-summary__facts li, .warranty-note__body li, .warranty-note__why,
  .support__faq-link, .searchbar__go, .prod__save, .build__tags, .slide--sold .sold,
  .step__figure figcaption, .dot { font-size: .85rem; }
  .cart-count, .filter__count { font-size: .78rem; }
}

/* Accent words in headings are set like the rest of the heading - the skills
   read one italic coloured word as a generated-page tell. The accent settings
   still work; they just no longer change the face or colour. */
:is(.panel h1, .finalsale__title, .salvage__heading, .reviews__heading, .process__heading) em {
  font-style: normal;
  color: inherit;
}
