/* Homepage. Lifted verbatim from the scrollcraft build; asset paths are the
   only thing the template changes. */
  /* Gallery / catalog. Light ground, because every machine in the profile is
     photographed on light and a dark page would fight all 109 of them. */
  :root {
    --sc-canvas:     #F4F5F3;
    --sc-surface:    #FFFFFF;
    --sc-ink:        #0B1F17;
    --sc-ink-soft:   #6C7A72;
    --sc-accent:     #036C35;   /* logo flag green, two steps darker */
    --sc-accent-ink: #FFFFFF;
    --sc-font-display: "Archivo", system-ui, sans-serif;
    --sc-font-text:    "IBM Plex Sans", system-ui, sans-serif;
    --line: #DDE2DE;
    --mono: "IBM Plex Mono", ui-monospace, monospace;
  }

  body { background: var(--sc-canvas); color: var(--sc-ink); }
  /* Kills the rubber-band bounce at the top and bottom of the page. A fixed
     header is dragged along by that bounce on a phone, which is the one way
     this bar can appear to move despite never leaving its position. */
  html, body { overscroll-behavior-y: none; }
  img { display: block; max-width: 100%; }

  /* Every object in the collection carries the same label. The schema is what
     makes this a collection rather than a grid, so there are no exceptions. */
  .label { font-family: var(--mono); font-size: .68rem; letter-spacing: .1em;
           text-transform: uppercase; color: var(--sc-ink-soft); margin: 0; }
  .label b { color: var(--sc-ink); font-weight: 500; }
  .label--lead { color: var(--sc-ink); }
  .label--lead b { color: var(--sc-ink); }

  .display { font-family: var(--sc-font-display); font-variation-settings: "wdth" 108;
             font-weight: 600; line-height: 1.02; letter-spacing: -.02em; margin: 0;
             text-wrap: balance; }
  .d-xl { font-size: clamp(2.3rem, 5vw, 4rem); }
  .d-lg { font-size: clamp(1.7rem, 3.2vw, 2.6rem); }
  .prose { font-size: clamp(1rem, 1.3vw, 1.1rem); line-height: 1.6;
           color: var(--sc-ink-soft); max-width: 56ch; margin: 0; }
  .wrap { width: min(1240px, 100% - clamp(2rem, 8vw, 6rem)); margin-inline: auto; }

  /* Nav: transparent over the hero, as asked for. It becomes an index of the
     collection once the hero is behind you, which is what this grammar needs. */
  /* A floating bar rather than a full-width band: the page shows above it and
     down both sides, which is what gives the reference its layered look. */
  .bar { position: fixed; z-index: 40; display: flex; align-items: center; gap: 1.5rem;
         top: clamp(.6rem, 1.8vh, 1.2rem);
         left: clamp(.75rem, 3vw, 2.25rem); right: clamp(.75rem, 3vw, 2.25rem);
         padding: .8rem clamp(1rem, 2vw, 1.6rem);
         background: #3A3A3A; color: #fff; }
  .bar__mark { font-family: var(--sc-font-display); font-variation-settings: "wdth" 112;
               font-weight: 700; letter-spacing: -.01em; font-size: 1.05rem; }
  .bar__index { margin-left: auto; display: flex; gap: 1.3rem; font-family: var(--mono);
                font-size: .72rem; letter-spacing: .06em; text-transform: uppercase; }
  .bar__index a { color: inherit; text-decoration: none; opacity: .78; }
  .bar__index a:hover, .bar__index a:focus-visible { opacity: 1; }
  .bar__cta { font-family: var(--mono); font-size: .72rem; letter-spacing: .06em;
              text-transform: uppercase; border: 1px solid currentColor;
              padding: .5rem .9rem; text-decoration: none; color: inherit; }
  .bar__cta:hover { background: var(--sc-accent); border-color: var(--sc-accent); color: #fff; }
  /* A wrapper only so the phone breakpoint has one thing to drop down. On a wide
     screen it does nothing: its children stay flex items of the bar itself. */
  .bar__menu { display: contents; }
  .bar__burger { display: none; }

  /* 1 · Arrival. Object one, full bleed, a label rather than a claim. */
  .hero { position: relative; min-height: 100svh; overflow: hidden; }
  .hero img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
  /* Two scrims, both anchored where the copy is rather than across the frame:
     the plaza and sky are light enough that white type was dissolving into them. */
  /* No scrim. The photograph is the point, so legibility is solved by where the
     chrome sits and what colour it is, not by washing the image. */
  .hero__scrim { display: none; }
  /* The block sizes itself to the longest headline line, and the city bar then
     stretches to exactly that width. Both sit on solid green, so the photograph
     underneath stays completely untinted and the type still reads. */
  .hero__label { position: absolute; left: clamp(1.25rem, 5vw, 3.5rem);
                 bottom: clamp(2rem, 8vh, 4.5rem); right: auto;
                 width: max-content; max-width: calc(100% - clamp(2.5rem, 10vw, 7rem));
                 display: grid; gap: .42rem; }

  /* No block behind these, so they read as a caption under the statement rather
     than a second banner competing with it. Ink, because the plaza beneath is
     light: white would disappear into it. */
  /* Left-packed rather than stretched to the headline width. Spanning the full
     width pushed the last two cities onto the dark brushes, where ink stops
     reading; keeping them left holds them all on the pale plaza. */
  .hero__cities { display: flex; align-items: center; justify-content: flex-start;
                  flex-wrap: wrap; gap: .4rem .7rem; margin: .55rem 0 0; padding: 0 .12em;
                  color: #fff;
                  font-family: var(--mono); font-size: clamp(.86rem, 1.18vw, 1.12rem);
                  font-weight: 600; letter-spacing: .045em; text-transform: uppercase;
                  /* white sits on a pale plaza here, so the glyphs carry their own
                     contrast rather than putting a wash back over the photograph */
                  text-shadow: 0 1px 3px rgba(6,16,12,.55), 0 2px 14px rgba(6,16,12,.5); }
  .hero__cities i { font-style: normal; opacity: .6; }

  .hero__name { margin: 0; display: grid; justify-items: start; gap: 0;
                font-family: var(--sc-font-display); text-transform: uppercase;
                font-variation-settings: "wdth" 88, "wght" 900;
                font-size: clamp(2.6rem, 7.7vw, 6.6rem); line-height: .95;
                letter-spacing: -.01em; color: var(--sc-accent); }
  /* Tight to the letterforms: the block should read as a highlight on the type,
     not a panel the type sits inside. */
  .hero__name span { background: #fff; padding: .035em .11em .075em;
                     display: block; }
  /* First line flips: green ground, white type. The second keeps the inverse,
     so the two lines read as one lockup rather than two banners. */
  .hero__name span:first-child { background: var(--sc-accent); color: #fff; }

  @media (max-width: 560px) {
    /* The dock spans the full width down here and sat straight over the bottom
       corner. The statement moves to the top of the frame, and the cities line
       goes rather than sit behind three buttons that hide it completely. */
    .hero__label { top: clamp(6.5rem, 15vh, 9rem); bottom: auto; gap: .14rem; }
    /* Nothing covers it up here, so it comes back, centred under the block.
       Zero width contribution so the label is sized by the statement alone, then
       stretched back to that width: the line is exactly as wide as the block and
       centres inside it. Smaller type so it holds two rows rather than four. */
    .hero__cities { width: 0; min-width: 100%; justify-content: space-between;
                    text-align: center; font-size: min(3.05vw, .82rem);
                    gap: .25em .3em; margin-top: 0; padding: 0;
                    /* Brand green straight on the photograph, heavier weight so the
                       letterforms hold their own against it. */
                    color: var(--sc-accent); font-weight: 800; text-shadow: none; }
  }
  /* Below this width "At every scale." no longer fits on one line, and once it
     wraps the white block stretches to the full label width and leaves a slab of
     empty white after SCALE. The type scales with the viewport instead so the
     line always fits and the block keeps hugging the letters. 9.6vw meets the
     41.6px floor almost exactly at 430px, so nothing jumps at the breakpoint. */
  @media (max-width: 430px) {
    .hero__name { font-size: 9.6vw; }
  }

  /* 2 · Standing. Real figures only, straight off the profile. */
  .figures { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px;
             background: var(--line); border: 1px solid var(--line); margin-top: 2.5rem; }
  .figures div { background: var(--sc-surface); padding: 1.4rem 1.2rem; }
  .figures .n { font-family: var(--sc-font-display); font-variation-settings: "wdth" 110;
                font-weight: 600; font-size: clamp(1.8rem, 3.4vw, 2.6rem); line-height: 1; }

  /* 2 · The range. White ground, no frames, nothing but the machines: the
     products are cut out on white already, so any border or panel would fight
     them. Arrows sit flush to the viewport edge. */
  .range { background: #fff; padding-block: clamp(3.5rem, 7vw, 6rem); }
  .range__head { text-align: center; padding-inline: clamp(.75rem, 4vw, 1.5rem);
                 margin-bottom: clamp(2rem, 4vw, 3.25rem); }
  /* One line at every width. The size is driven off the viewport rather than
     clamped to a floor, because a floor is exactly what makes it wrap on a phone. */
  .range__title { margin: 0; font-family: var(--sc-font-display);
                  font-variation-settings: "wdth" 100, "wght" 400;
                  font-size: clamp(.95rem, 3.4vw, 2.9rem); line-height: 1.15;
                  white-space: nowrap; letter-spacing: -.005em; color: #333; }
  .range__title i { font-style: normal; color: #b9bfba; padding-inline: .28em; }
  .range__sub { margin: .7rem 0 0; font-size: clamp(.95rem, 1.15vw, 1.08rem);
                color: #8b918d; }

  .carousel { position: relative; }
  /* Transform-driven, not native scroll. Scroll-snap kept cancelling every
     programmatic move, which froze the carousel; a translated track gives exact
     control and a seamless wrap. */
  .carousel__view { overflow: hidden; padding: 0 clamp(3rem, 5vw, 5rem); }
  .carousel__track {
    --eq-gap: clamp(1rem, 2.6vw, 2.75rem);
    display: flex; align-items: flex-end; gap: var(--eq-gap);
    margin: 0; padding: 0; list-style: none;
    will-change: transform; touch-action: pan-y;
  }
  /* No CSS transition here on purpose: one got stuck permanently at
     currentTime 0 and pinned the computed transform, so every later move was
     ignored. The slide is driven frame by frame in script instead. */

  /* exactly three to a view, so a page is three machines */
  .eq { flex: 0 0 calc((100% - 2 * var(--eq-gap)) / 3); }
  @media (max-width: 900px) { .eq { flex-basis: calc((100% - var(--eq-gap)) / 2); } }
  @media (max-width: 600px) { .eq { flex-basis: 100%; } }
  .eq a { display: grid; gap: 0; text-decoration: none; color: inherit; text-align: center; }
  .eq__fig { display: grid; place-items: center; height: clamp(11rem, 17vw, 15.5rem); }
  .eq__fig img { max-width: 100%; max-height: 100%; width: auto; height: auto;
                 object-fit: contain; transition: transform .45s cubic-bezier(.16,.84,.34,1); }
  .eq a:hover .eq__fig img, .eq a:focus-visible .eq__fig img { transform: scale(1.03); }
  .eq__name { margin: 1.5rem 0 0; font-family: var(--sc-font-text); font-weight: 600;
              text-transform: uppercase; letter-spacing: .015em;
              font-size: clamp(.78rem, .92vw, .9rem); line-height: 1.35; color: #1b1b1b; }

  /* flush to the edge of the viewport, exactly as the reference has them */
  .carousel__nav {
    position: absolute; top: 50%; translate: 0 -50%; z-index: 2;
    width: clamp(1.9rem, 2.4vw, 2.4rem); height: clamp(5rem, 8vw, 7rem);
    display: grid; place-items: center; cursor: pointer; border: 0;
    background: #8d8d8d; color: #fff; font-size: 1.15rem; line-height: 1;
    font-family: var(--sc-font-text); transition: background .15s ease;
  }
  .carousel__nav:hover { background: var(--sc-accent); }
  .carousel__nav--prev { left: 0; }
  .carousel__nav--next { right: 0; }

  .carousel__dots { display: flex; justify-content: center; gap: .55rem; margin-top: 2.25rem; }
  .carousel__dots button { width: .62rem; height: .62rem; border-radius: 50%; border: 0;
                           background: #d2d5d3; cursor: pointer; padding: 0;
                           transition: background .2s ease; }
  .carousel__dots button[aria-selected="true"] { background: var(--sc-accent); }

  /* 5 · Service. The quietest act, and it follows the peak on purpose. */
  .steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px;
           background: var(--line); border: 1px solid var(--line); margin-top: 2.5rem; }
  .steps div { background: var(--sc-surface); padding: 1.6rem 1.3rem; display: grid;
               gap: .6rem; align-content: start; }

  /* 6 · The ask. An inquiry plate, typeset exactly like a label. */
  .plate { border: 1px solid var(--line); background: var(--sc-surface);
           padding: clamp(2rem, 6vw, 4rem); display: grid; gap: 1.5rem; }
  .plate__cta { justify-self: start; font-family: var(--mono); font-size: .78rem;
                letter-spacing: .08em; text-transform: uppercase; text-decoration: none;
                background: var(--sc-accent); color: #fff; padding: .95rem 1.6rem; }
  .plate__cta:hover { background: var(--sc-ink); }
  /* The shared footer in site.css owns .foot now; the homepage used to carry
     its own one-line version inside the closing plate. */

  @media (max-width: 900px) {
    .figures, .steps { grid-template-columns: repeat(2, 1fr); }
    /* Phone bar carries the mark and three dashes, nothing else. Everything it
       used to show sits in the panel the dashes open. */
    .bar__menu { display: none; position: absolute; top: 100%; left: 0; right: 0;
                 flex-direction: column; align-items: stretch; gap: 0;
                 background: #3A3A3A; padding: .25rem 0 .9rem; }
    .bar.is-open .bar__menu { display: flex; }
    .bar__index { display: flex; flex-direction: column; margin: 0; gap: 0;
                  font-size: .78rem; }
    .bar__index a { padding: .9rem clamp(1rem, 4vw, 1.6rem); opacity: 1; }
    .bar__cta { margin: .55rem clamp(1rem, 4vw, 1.6rem) 0; text-align: center;
                padding: .85rem; }
    .bar__burger { display: grid; gap: 5px; margin-left: auto; padding: .55rem .35rem;
                   background: none; border: 0; cursor: pointer; }
    .bar__burger span { display: block; width: 23px; height: 2px; background: #fff; }
  }
  @media (max-width: 560px) {
    .figures { grid-template-columns: 1fr 1fr; }
    .steps { grid-template-columns: 1fr; }
    .object { flex-basis: 14rem; }
  }

  /* --- real logo ------------------------------------------------------- */
  .bar__mark { display: block; line-height: 0; }
  .bar__mark img { height: 42px; width: auto;
                   /* the artwork is vector; keep the browser from resampling it */
                   image-rendering: auto; transform: translateZ(0); }
  /* The mark is the light cut now: it sits on the dark bar at every scroll
     position, so there is nothing to swap. */


  /* --- opening sequence ------------------------------------------------- */
  /* One orchestrated arrival rather than scattered effects: the frame lifts,
     then the four copy lines follow it in order. */
  @keyframes sc-rise { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
  @keyframes sc-frame { from { transform: scale(1.06); } to { transform: scale(1); } }
  .hero img { animation: sc-frame 1.6s cubic-bezier(.16,.84,.34,1) both; }
  [data-in] { opacity: 0; animation: sc-rise .8s cubic-bezier(.16,.84,.34,1) both; }
  [data-in="1"] { animation-delay: .18s; }
  [data-in="2"] { animation-delay: .30s; }
  [data-in="3"] { animation-delay: .46s; }
  [data-in="4"] { animation-delay: .62s; }
  .bar { animation: sc-rise .7s ease both; animation-delay: .05s; }
  .dock { animation: sc-rise .7s ease both; animation-delay: .9s; }
  @media (prefers-reduced-motion: reduce) {
    .hero img, [data-in], .bar, .dock { animation: none; opacity: 1; transform: none; }
  }

  /* --- corner dock ------------------------------------------------------ */
  /* The dock is styled in site.css, which every page loads. It used to be
     duplicated here, and the phone layout diverged as a result. */

  .object--all { background: var(--sc-accent); color: #fff; align-content: center;
                 grid-template-rows: auto; }
  .object--all .label { color: rgba(255,255,255,.8); }
  .object--all .object__label { border-top: 0; }

  @media (max-width: 560px) {
    /* WhatsApp full width on top, the two white ones side by side beneath it. */
    .bar__mark img { height: 30px; }
  }

  /* --- hero slider ------------------------------------------------------ */
  /* Slides cross-fade rather than translate, so slide one renders in exactly
     the position it always did and nothing about it shifts. */
  .hero__slide { position: absolute; inset: 0; opacity: 0; visibility: hidden;
                 transition: opacity .55s ease; }
  .hero__slide.is-on { opacity: 1; visibility: visible; }
  @media (prefers-reduced-motion: reduce) { .hero__slide { transition: none; } }

  /* Slide two: one flat green field, two columns. Copy left, machines right,
     nothing overlapping. The image is cropped to the machines, so its own ground
     is gone and the page colour carries straight through behind them. */
  /* The supplied render already sits on this exact green, so the slide is painted
     the same value and the picture's ground disappears into the field. Sampled
     from the file's own border rather than assumed. */
  .hero__slide--scrub { --field: #026E37; background: var(--field); }
  /* Each render sits on its own slightly different green, so every slide is
     painted its own file's border value. Otherwise the crop shows a seam. */
  .hero__slide--sweepers { --field: #026E3B; }
  .hero__slide--vacuums  { --field: #027039; }
  .scrub { position: absolute; inset: 0; display: grid; align-items: center;
           grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
           gap: 0; }
  .scrub__copy { padding: clamp(5rem, 12vh, 8rem) clamp(1.5rem, 4vw, 3.5rem)
                         clamp(5rem, 12vh, 7rem) clamp(1.25rem, 5vw, 3.5rem); }
  .scrub__copy { display: grid; gap: 1.15rem; justify-items: start; align-content: center; }
  .scrub__figure { display: grid; place-items: center; min-width: 0;
                   align-self: stretch; padding: clamp(.5rem, 2vw, 1.5rem); }
  /* .hero img is absolute + cover for slide one's full-bleed photograph; this
     image is a grid child, so that has to be undone rather than layered over. */
  .scrub__figure img { position: static; inset: auto;
                       max-width: 100%; max-height: 100%; width: auto; height: auto;
                       object-fit: contain; }

  /* Same device as slide one: the line sits in a block, so switching between the
     two reads as one page rather than two. Colours inverted for the green field. */
  .scrub__title { margin: 0; font-family: var(--sc-font-display);
                  font-variation-settings: "wdth" 88, "wght" 900;
                  text-transform: uppercase; line-height: 1.18; letter-spacing: -.01em;
                  font-size: clamp(1.9rem, 4.4vw, 3.9rem); }
  /* White behind the page's own green, so the letterforms read as the background
     showing through. Inline with box-decoration-break, so the white hugs each
     line exactly rather than stretching to the column, and it keeps hugging
     however the text rewraps. */
  .scrub__title span { display: inline; background: #fff; color: var(--field);
                       padding: .05em .14em; box-decoration-break: clone;
                       -webkit-box-decoration-break: clone; }

  .scrub__text { margin: .35rem 0 0; color: #fff; max-width: 34ch;
                 font-size: clamp(.92rem, 1.1vw, 1.06rem); line-height: 1.55; }
  .scrub__cta { margin-top: .4rem; background: #fff; color: var(--sc-ink);
                font-family: var(--mono); font-size: .74rem; letter-spacing: .09em;
                text-transform: uppercase; text-decoration: none;
                padding: .9rem 1.7rem; border-radius: 999px;
                transition: background .15s ease, color .15s ease; }
  .scrub__cta:hover { background: var(--sc-ink); color: #fff; }

  /* Same line, same corner as slide one, so the two read as one page. */
  .scrub__cities { position: absolute; z-index: 3;
                   left: clamp(1.25rem, 5vw, 3.5rem); bottom: clamp(1.5rem, 5vh, 2.75rem);
                   margin: 0; display: flex; flex-wrap: wrap; align-items: center;
                   gap: .4rem .7rem; color: #fff; font-family: var(--mono);
                   font-size: clamp(.86rem, 1.18vw, 1.12rem); font-weight: 600;
                   letter-spacing: .045em; text-transform: uppercase; }
  .scrub__cities i { font-style: normal; opacity: .6; }

  @media (max-width: 860px) {
    /* One column, stacked. The figure takes whatever height the copy leaves
       instead of running off the bottom of the screen, and the cities line drops
       into the flow because the dock owns the bottom corner on a phone. */
    /* Picture first and it takes the slack, so the copy sits low on the screen
       the way the cities line does on slide one. */
    .scrub { grid-template-columns: 1fr;
             grid-template-rows: minmax(0, 1fr) auto auto;
             align-content: stretch; gap: .9rem;
             padding: clamp(4.5rem, 11vh, 6.5rem) 0 10.5rem; }
    .scrub__copy { padding-top: 0; padding-bottom: 0; align-content: start; }
    .scrub__cities { position: static; padding: 0 clamp(1.25rem, 5vw, 3.5rem); }
    .scrub__figure { order: -1; min-height: 0; padding-bottom: 0; }
    /* A viewport cap, not max-height:100%: the percentage resolves against a
       stretched track and the tallest render was painting over the headline. */
    .scrub__figure img { max-height: 26vh; }
  }

  /* Centred on a phone only. Wider than this the line is left aligned under the
     Discover more button, the same corner slide one puts its cities in. */
  @media (max-width: 560px) {
    .scrub__cities { justify-content: center; text-align: center; }
  }

  .hero__nav { position: absolute; top: 50%; translate: 0 -50%; z-index: 3;
               width: clamp(1.9rem, 2.4vw, 2.4rem); height: clamp(5rem, 8vw, 7rem);
               display: grid; place-items: center; cursor: pointer; border: 0;
               background: rgba(11,31,23,.82); color: #fff; font-size: 1.15rem;
               font-family: var(--sc-font-text); transition: background .15s ease; }
  .hero__nav:hover { background: var(--sc-accent); }
  .hero__nav--prev { left: 0; }
  .hero__nav--next { right: 0; }
