/* ALLIN MAKI · sections, in page order. Numbers are Apron's, measured 2026-09-03. */

/* ---- 0. Sticky header group (banner + masthead) -------------------------- */
.site-head { position: sticky; top: 0; z-index: 20; display: grid; }

.banner { background: var(--ink); color: var(--white); }
.banner__inner {
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr) max-content;
  align-items: center; min-height: var(--banner-h);
}
.banner__text {
  display: flex; align-items: center; justify-content: center; gap: var(--s-8);
  font-size: 16px; line-height: 24px; letter-spacing: 0.16px; text-align: center;
}
.banner__text svg { width: 20px; height: 20px; flex-shrink: 0; color: var(--accent); }
/* .link outdents itself by -0.375em, which pushed the tail of this line outside
   the flex column: 4 to 6px unreachable at 820 and 390. The outdent exists to
   optically align a link at the start of a paragraph and does nothing here. */
.banner__text { min-width: 0; }
.banner__text .link { margin-inline: 0; }
.banner[hidden] { display: none; }
/* On a phone the line wraps at the link rather than mid-phrase, and the bar is
   as tall as its text: it used to hold three lines of sentence in 48px and
   more, above a header that was already the first thing on the screen. */
@media (max-width: 767px) {
  .banner__inner { min-height: 0; padding-block: 6px; }
  /* 11px, not 11.5: at 11.5 the two numbers came to 250px on one line and a
     320px phone has 248 */
  .banner__text { justify-content: start; flex-wrap: wrap; row-gap: 2px; column-gap: var(--s-10); text-align: left; font-size: 11px; line-height: 14px; font-weight: 700; }
  .banner__text svg { display: none; }
  .banner__text span { white-space: nowrap; }
}

.masthead { background: var(--tint); color: var(--ink); }
.masthead__inner {
  display: grid; grid-auto-flow: column; align-items: center; gap: var(--s-48);
  min-height: var(--header-h); grid-auto-columns: 1fr auto;
}
.masthead__logo { display: grid; align-items: center; }
.masthead__logo svg { height: 32px; width: auto; }
.masthead__links { display: none; grid-auto-flow: column; grid-auto-columns: max-content; justify-content: start; gap: var(--s-28); align-items: center; }
.masthead__actions { display: none; grid-auto-flow: column; gap: var(--s-6); align-items: center; }
.masthead__trigger { display: grid; grid-auto-flow: column; align-items: center; gap: var(--s-8); }
.masthead__trigger button svg { width: 32px; height: 32px; }
/* The switch grew a flag on 16 September, 24 pixels, and gives some of it
   back in padding so the bar keeps fitting where it did. */
.masthead__actions .btn.lang { padding-inline: var(--s-12); }
/* 1340, and it was 1220 when the bar held five links. Private label made it
   six and the bar stopped fitting where it used to. Found the same way the old
   number was: force the desktop bar on at every width, step through it a few
   pixels at a time, and ask the browser whether any two items in the bar
   overlap, which is a question a page that does not scroll sideways still
   answers yes to. English clears at 1316, so 1340 keeps the same margin the
   old pair were chosen with. Below this the burger menu carries the same links
   and the same buttons, so nothing is lost. */
@media (min-width: 1340px) {
  .masthead__inner { grid-auto-columns: auto 1fr auto; }
  .masthead__links, .masthead__actions { display: grid; }
  .masthead__trigger { display: none; }
}
/* Spanish needs another hundred and forty pixels before it fits, because
   Colecciones, Conformidad and Nuestra historia are each longer than their
   English counterpart and so is Inicie su pedido. It clears at 1464, so it
   keeps the burger to 1480 rather than showing a broken bar. */
@media (min-width: 1340px) and (max-width: 1479px) {
  html[lang="es"] .masthead__links, html[lang="es"] .masthead__actions { display: none; }
  html[lang="es"] .masthead__trigger { display: grid; }
  /* and the bar goes back to the two column layout it has below the
     breakpoint, or the burger sits beside the logo instead of at the end. */
  html[lang="es"] .masthead__inner { grid-auto-columns: 1fr auto; }
}
/* With the flag in the switch the Spanish bar came out 27 pixels over the
   1360 the header is capped at, so it overlapped at every width. The links
   close up a little instead, which nobody notices. */
@media (min-width: 1480px) {
  html[lang="es"] .masthead__links { gap: var(--s-20); }
}
/* Just past the breakpoint the English bar is still tight, so the gaps close
   up first: nobody notices a narrower gap and everybody notices two buttons
   touching. Spanish does not appear until 1480, where there is room for the
   wide gaps already. */
@media (min-width: 1340px) and (max-width: 1439px) {
  .masthead__links { gap: var(--s-12); }
  .masthead__actions { gap: var(--s-4); }
}

/* Dropdown under a menu item */
.menu-wrap { position: relative; }
.dropdown {
  position: absolute; top: calc(100% + 22px); left: -24px; z-index: 30;
  min-width: 280px; padding: var(--s-16); border-radius: var(--r-16);
  background: var(--white); box-shadow: var(--shadow-card);
  display: grid; gap: var(--s-4);
  animation: fadeIn var(--t-menu) ease-out;
}
.dropdown[hidden] { display: none; }
.dropdown a { display: grid; gap: 2px; padding: var(--s-10) var(--s-12); border-radius: var(--r-8); transition: background-color var(--t-link); }
.dropdown a:hover { background: var(--ink-a05); }
.dropdown a strong { font-weight: 700; }
.dropdown a small { font-size: 14px; color: rgba(0,0,0,.6); }

/* Mobile menu: Apron opens it with a clip-path circle from the top right corner */
.mobile-menu {
  position: fixed; inset: 0; z-index: 40; background: var(--tint); color: var(--ink);
  padding: var(--s-24) var(--gutter) var(--s-48); overflow: auto;
  clip-path: circle(150% at 100% 0);
  animation: menuOpen 0.4s ease-out;
}
.mobile-menu[hidden] { display: none; }
.mobile-menu.closing { animation: menuClose 0.3s ease-in forwards; }
.mobile-menu__top { display: flex; justify-content: space-between; align-items: center; min-height: var(--header-h); }
.mobile-menu__top svg { height: 32px; width: auto; }
.mobile-menu__list { display: grid; gap: var(--s-4); margin-top: var(--s-24); }
.mobile-menu__list a, .mobile-menu__list button { display: block; width: 100%; padding: var(--s-16) 0; border-bottom: 2px dotted var(--ink-a20); font-family: var(--font-display); font-weight: 400; font-size: 28px; }
.mobile-menu__actions { display: grid; gap: var(--s-12); margin-top: var(--s-32); }
.mobile-menu__actions .btn { width: 100%; }

@keyframes fadeIn { from { opacity: 0 } to { opacity: 1 } }
@keyframes menuOpen { from { clip-path: circle(0 at 100% 0) } to { clip-path: circle(150% at 100% 0) } }
@keyframes menuClose { from { clip-path: circle(150% at 100% 0) } to { clip-path: circle(0 at 100% 0) } }

/* ---- 1. Hero -------------------------------------------------------------
   The hero was a full-bleed video with a scrim and a centred headline. It is
   a white studio with one photograph now, and it lives entirely in
   css/landing.css, because it is the only page that has one. Nothing here.
   --------------------------------------------------------------------------- */

/* ---- 2. Why buyers switch: two-part head, then four USP cards ----------- */
.switch { padding-block: var(--s-80) var(--s-48); }
@media (min-width: 768px) { .switch { padding-block: var(--s-120) var(--s-64); } }

/* One centre line: eyebrow, headline, then the lede underneath it. */
/* minmax(0, 1fr) and not the implicit auto. An auto track is never narrower
   than the min-content of its widest child, so one child that refuses to
   shrink takes the whole head off the side of the page. That is exactly what
   happened on /es/tiendas at 360: the eyebrow's own max-content track below
   was the child, and the cause is fixed there. This is the cap, so the next
   child to try it cannot do the same. Spanish found it; English never would
   have, and there are six more languages coming. */
.switch__head {
  display: grid; grid-template-columns: minmax(0, 1fr);
  gap: var(--s-20); justify-items: center; text-align: center;
  max-width: 900px; margin-inline: auto; margin-block-end: var(--s-48);
}
@media (min-width: 1024px) { .switch__head { margin-block-end: var(--s-64); } }
.switch__head .t-h2 { max-width: 19ch; }
.switch__lede { color: rgba(0, 0, 0, .70); max-width: 46ch; margin-block-start: var(--s-8); }

/* The other silhouette. The centred head is right for a page opening and for a
   single statement; four and five of them in a row on one page is a drumbeat,
   and every one of them leaves the width unused above a grid that does not.
   This one stands the eyebrow and the heading on the left edge of whatever
   they introduce and puts the lede beside them, so the head fills the same
   band as the object under it and the reader can tell one section from the
   next before reading a word. Below 1024 it is the same stacked block, left
   set instead of centred. */
.switch__head--rule,
.switch__head--split {
  justify-items: start; text-align: start;
  max-width: var(--stack-w); margin-inline: auto;
}
/* The quiet one: an eyebrow with the site's dotted rule running from it to the
   right edge of the column, and the heading under it. For a section that
   continues the thought before it and does not want a lede beside it. */
.switch__head--rule { width: 100%; }
/* Same fault one level down: a bare max-content track cannot shrink, so a
   long eyebrow in a long-worded language pushed the dotted rule and itself
   off the page. minmax(0, max-content) still takes the width it wants when
   there is room and gives it back when there is not. */
.switch__head--rule > .t-eyebrow {
  display: grid; grid-template-columns: minmax(0, max-content) minmax(24px, 1fr);
  align-items: center; gap: var(--s-16); width: 100%;
}
.switch__head--rule > .t-eyebrow::after {
  content: ""; height: 2px;
  background-image: radial-gradient(circle, var(--ink-a20) 1px, transparent 1.1px);
  background-size: 8px 2px; background-repeat: repeat-x;
}
@media (min-width: 1024px) { .switch__head--rule > .t-h2 { max-width: 24ch; } }
@media (min-width: 1024px) {
  .switch__head--split {
    grid-template-columns: minmax(0, 1fr) minmax(0, 42ch);
    grid-template-areas: "eyebrow lede" "title lede";
    column-gap: var(--s-64); row-gap: var(--s-16); align-items: end;
  }
  .switch__head--split > .t-eyebrow { grid-area: eyebrow; }
  .switch__head--split > .t-h1,
  .switch__head--split > .t-h2 { grid-area: title; max-width: 24ch; text-wrap: balance; }
  .switch__head--split > .switch__lede { grid-area: lede; align-self: end; margin-block-start: 0; }
}

.switch__grid {
  display: grid; gap: var(--s-16); grid-template-columns: minmax(0, 1fr);
  max-width: var(--stack-w); margin-inline: auto;
}
@media (min-width: 620px) { .switch__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1024px) { .switch__grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

/* The counter is a foot, not a head: the four cards stretch to the tallest and
   pack their content to the top, so the free space all fell under the copy and
   the accent chips sat at four different heights. auto auto 1fr puts the slack
   in the middle and the chips on one line across the row, with the DOM order
   unchanged. */
.usp { grid-template-rows: auto auto 1fr; }
.usp__n { order: 3; align-self: end; margin-block: var(--s-8) 0; }
.usp {
  position: relative; isolation: isolate; overflow: hidden;
  display: grid; gap: var(--s-12); align-content: start;
  padding: var(--s-28) var(--s-20) var(--s-32);
  border-radius: var(--r-20); background: var(--tint-card);
  transition: transform var(--t-hover) cubic-bezier(.2, .8, .2, 1),
              box-shadow var(--t-hover) ease,
              background-color var(--t-hover) ease;
}
.usp__n {
  display: grid; place-items: center; width: 40px; height: 40px;
  border-radius: var(--r-pill); background: var(--accent); color: var(--ink);
  font-family: var(--font-mono); font-size: 13px; letter-spacing: .06em;
  font-variant-numeric: tabular-nums; margin-block-end: var(--s-4);
  transition: background-color var(--t-hover), color var(--t-hover);
}
/* Under the cursor the whole card lifts a little and casts the page's one card
   shadow, while the numeral inks over. Same 0.3s the buttons use, so everything
   reacts at one speed. Gated on a real pointer, or the state sticks after a tap. */
/* The lift used to come with a transform and the card shadow. Thirteen of
   these on services, ten on compliance, two on ordering and four on the
   homepage, and not one of them is a link or contains a button: on the
   ordering page the .pair slabs span the whole column, so the lift fired
   almost anywhere the pointer moved. It also spent the card shadow on
   paragraphs, which the components file says is budgeted for the collage
   frames, the stamps and the story card and nowhere else. The wash stays,
   because acknowledging the pointer is not the same as promising a click, and
   the two .route__card doors on services keep the movement, which makes them
   the site's one card affordance. */
@media (hover: hover) and (pointer: fine) {
  .usp:hover {
    transform: translateY(-6px);
    box-shadow: 0 14px 30px rgba(70, 58, 0, .14);
    background-color: var(--tint);
  }
  .usp:hover .usp__n { background: var(--ink); color: var(--paper); }
}

@media (prefers-reduced-motion: reduce) {
  .usp { transition: none; }
  .usp:hover { transform: none; box-shadow: none; }
}
/* the .t-h6 card-title role, see base.css */
.usp__t {
  font-family: var(--font-display); font-weight: 800; font-size: 21px;
  line-height: 1.16; letter-spacing: 0.01em; max-width: 18ch;
}
.usp__b { font-family: var(--font-body); font-size: 16px; line-height: 1.5; letter-spacing: 0.16px; color: rgba(0, 0, 0, .70); }
@media (min-width: 1024px) { .usp__t { font-size: 21px; } }

.switch__ctas { display: grid; gap: var(--s-16); place-content: center; margin-block-start: var(--s-48); }
@media (min-width: 768px) {
  .switch__ctas { grid-auto-flow: column; grid-auto-columns: minmax(min-content, max-content); }
}

/* ---- 3. "Make time": copy left, photo collage right, marquee below ------- */
.time { max-width: 100%; overflow: hidden; }
/* minmax(0, 1fr), not 1fr: the marquee in the footer cell declares
   grid-auto-columns: max-content, so its min-content is the full cloned
   track. A bare 1fr adopts that as the column's minimum, grows to 10,487px
   and centres every row of this section a viewport and a half off screen,
   where overflow: hidden hides the evidence. Only the base template needs
   it; the >=1024 rule below replaces this one outright. */
.time__grid {
  display: grid; padding-block: var(--s-48) var(--s-80); gap: var(--s-24); justify-items: center;
  grid-template: "title" "description" "frames" "footer" / minmax(0, 1fr);
}
@media (min-width: 1024px) {
  .time__grid { justify-items: normal; grid-template: "title frames" "description frames" "footer footer" / 1fr 1fr; }
}
.time__title { grid-area: title; align-self: end; text-align: center; }
.time__desc { grid-area: description; align-self: start; max-width: 405px; text-align: center; }
@media (min-width: 1024px) { .time__title, .time__desc { text-align: start; } }
.time__frames { grid-area: frames; display: grid; align-items: center; }

/* The photo fan is out of the homepage for now, and everything that built it is
   still here, unchanged, above and below this rule. Putting it back is two
   moves: paste the .time__frames block from REMOVED-BLOCKS.md into index.html
   and take .time--plain off the section.

   Without that cell the two-column template at 1024 leaves the copy stranded in
   the left half of the page, so this collapses the section to the one centred
   column it already uses on a phone. */
.time--plain .time__grid { grid-template: "title" "description" "footer" / minmax(0, 1fr); justify-items: center; }
.time--plain .time__title, .time--plain .time__desc { text-align: center; }
/* A centred display line across the whole container reads as a banner and
   leaves one word alone on the second row. Held to a measure and balanced,
   it reads as a statement. */
.time--plain .time__title { max-width: 900px; text-wrap: balance; }
/* Four portrait plates in one fan: same width, same 3:4 crop, even overlap, so
   the group reads as a set rather than four loose photographs. The workshop clip
   sits second and on top, because it is the only one that moves. */
.collage {
  display: grid; width: 1040px; place-self: center; justify-content: center;
  grid-auto-flow: column; grid-auto-columns: auto; align-items: center;
  padding-block-start: var(--s-24);
}
.collage > * { position: relative; width: var(--plate, 196px); margin: 0; }
.collage .frame__inner { display: block; width: 100%; }
.collage img, .collage video {
  display: block; width: 100%; height: auto;
  aspect-ratio: 3 / 4; object-fit: cover; background: var(--white);
}
.collage > :nth-child(1) { transform: rotate(-7.5deg) translateY(20px); z-index: 1; }
.collage > :nth-child(2) { transform: rotate(2.5deg) translateY(-24px); margin-left: calc(var(--plate, 196px) * -.194); z-index: 4; }
.collage > :nth-child(3) { transform: rotate(-2.5deg) translateY(26px); margin-left: calc(var(--plate, 196px) * -.194); z-index: 3; }
.collage > :nth-child(4) { transform: rotate(7.5deg) translateY(-12px); margin-left: calc(var(--plate, 196px) * -.194); z-index: 2; }
/* Below 1024 the clip is the one that goes, not the two photographs after it.
   It is muted, it loops, and at this size it reads as a duller still among
   three stills rather than as something moving. Three photographs instead,
   and the first of the three carries no negative margin, so the overlap is
   still even.

   The plates are rotated and lifted out of the line, and a transform does not
   move the box they came from, so the group needs padding under it or the
   marquee runs through the bottom corner of the low plate. */
@media (max-width: 1023px) {
  .collage { --plate: 168px; padding-block: var(--s-24) var(--s-48); }
  .collage > :nth-child(2) { display: none; }
}
@media (max-width: 619px) { .collage { --plate: 146px; } }
@media (min-width: 1024px) {
  .collage { min-height: 440px; place-content: center start; justify-self: start; }
  .collage > * { width: 244px; }
  .collage > :nth-child(1) { transform: rotate(-7.5deg) translateY(30px); }
  .collage > :nth-child(2) { transform: rotate(2.5deg) translateY(-34px); margin-left: -48px; }
  .collage > :nth-child(3) { transform: rotate(-2.5deg) translateY(36px); margin-left: -48px; }
  .collage > :nth-child(4) { transform: rotate(7.5deg) translateY(-16px); margin-left: -48px; }
  .collage > :nth-child(n+3) { display: block; }
}
/* The strip needs the same air above it as it has below it, or it reads
   as a caption hanging off the photographs rather than a band of its own.
   The grid's own 24px row gap is part of the measurement. */
/* One column the width of the container, not max-content: the marquee's own
   max-content is the whole cloned track, thousands of pixels wide, and the
   line above it would be centred in that column and land off screen. The
   marquee pulls itself out to the window from here, the way it always did. */
.time__footer {
  grid-area: footer; display: grid; grid-template-columns: minmax(0, 1fr);
  gap: var(--s-16); justify-items: center; margin-block-start: var(--s-64);
}
/* The strip is a row of place names in the display face, so it needs a word
   saying what they are. Quiet and small, the same mono label the spec lists
   use, and deliberately not a section eyebrow: the section already has one. */
.time__cap {
  font-family: var(--font-mono); font-size: 12px; letter-spacing: .12em;
  text-transform: uppercase; color: rgba(0, 0, 0, .60);
}
/* 64, not 120. The photo fan that used to fill the right half of this band was
   taken out on purpose, so the 120 was holding a gap open under four short
   centred lines: 168px of paper between the lede and the client row. */
@media (min-width: 1024px) { .time__footer { margin-block-start: var(--s-64); } }

/* Marquee: track is cloned N times by JS (--marquee-mirrors), then slides one copy's width */
.marquee { margin-inline: calc(50% - 50vw); overflow: hidden; --marquee-gap: 48px; --marquee-mirrors: 5; }
.marquee__track {
  display: grid; grid-auto-flow: column; grid-auto-columns: max-content; align-items: center;
  margin-inline: auto; opacity: 0.5; width: max-content; height: 38px; gap: var(--marquee-gap);
  animation: marquee var(--marquee-duration) linear infinite;
}
.marquee:hover .marquee__track { animation-play-state: paused; }
.marquee__item {
  font-family: var(--font-mono); font-size: 18px; letter-spacing: .12em; text-transform: uppercase;
  white-space: nowrap; display: flex; align-items: center; gap: 12px;
}
.marquee__item b { font-family: var(--font-display); font-weight: 800; font-size: 26px; letter-spacing: 0; text-transform: none; }
@keyframes marquee {
  from { transform: translateX(0); }
  to { transform: translateX(calc((-100% - var(--marquee-gap)) / (var(--marquee-mirrors) + 1))); }
}

/* ---- 4. Feature section with folding cards ------------------------------- */
.feature { padding-block: var(--s-80); }
.feature__head { display: grid; gap: var(--s-32); margin-inline: auto; margin-block-end: var(--s-48); max-width: 843px; }
@media (min-width: 1024px) { .feature__head { margin-block-end: var(--s-80); } }
/* Every stack deals itself sideways and steps its pinned cards, so you see a
   strip of every fawn card in the pile rather than three of them at exactly
   the same height hiding each other. --fold-step is the height between pinned
   cards, --fold-slide is how far right a card starts. js/main.js reads both.

   overflow-x: clip with overflow-y: visible is the one pair that clips a card
   mid-entrance without turning the stack into a scroll container, which would
   break the sticky pinning the whole thing depends on. */
.fold-stack { --fold-step: 15; --fold-slide: 60; overflow-x: clip; overflow-y: visible; }
@media (max-width: 899px) { .fold-stack { --fold-step: 11; --fold-slide: 32; } }
/* seven cards, so a smaller step keeps the pile inside the screen */
.fold-stack--steps { --fold-step: 10; }

.fold-stack {
  --fold-top: 100px;
  display: grid; gap: var(--s-32); max-width: var(--stack-w); margin-inline: auto; margin-bottom: var(--s-80);
}
@media (min-width: 768px) { .fold-stack { --fold-top: 140px; } }
.fold {
  position: sticky; overflow: hidden; border-radius: var(--r-16);
  background-color: var(--tint-card); color: var(--ink);
  --fold-media-opacity: 1; --fold-text-opacity: 1; --fold-mb: 60px;
  margin-bottom: var(--fold-mb);
  will-change: transform, background-color;
}
.fold:last-child { --fold-mb: 0px; }
@media (min-width: 1024px) { .fold { border-radius: var(--r-20); } }
.fold__grid {
  /* A floor, never a ceiling. max-height here does not shrink the rows, it
     just stops the grid growing, so a card whose copy needs more than 500px
     ran its last line into the media row and the media painted over it. Found
     on the ordering steps at 390 and on four more cards besides. */
  display: grid; gap: var(--s-8); min-height: 500px;
  grid-template: ". . ." 26px ". title ." auto ". content ." auto ". . ." 14px "media media media" 1fr / 22px 1fr 22px;
}
.fold__title { grid-area: title; margin-top: var(--s-4); opacity: var(--fold-text-opacity); }
/* A range card is the whole link to its collection, so it has to look like
   one: the heading takes an underline under the cursor and the photograph
   lifts a little, which is the only thing on the card that can move without
   disturbing the stack it is pinned in. The modifier is on the grid rather
   than on .fold, because the why-cards and the ordering steps are built from
   the same box and go nowhere. */
.fold__grid--link { color: inherit; cursor: pointer; }
.fold__grid--link .fold__title {
  text-decoration: underline; text-decoration-color: transparent; text-underline-offset: 5px;
  text-decoration-thickness: 2px; transition: text-decoration-color var(--t-hover);
}
.fold__grid--link:is(:hover, :focus-visible) .fold__title { text-decoration-color: currentColor; }
.fold__grid--link .fold__media > img { transition: transform var(--t-hover); }
.fold__grid--link:hover .fold__media > img { transform: scale(1.015); }
.fold__grid--link:focus-visible { outline: 2px solid var(--ink); outline-offset: -6px; border-radius: var(--r-16); }
@media (prefers-reduced-motion: reduce) {
  .fold__grid--link .fold__media > img { transition: none; }
  .fold__grid--link:hover .fold__media > img { transform: none; }
}
/* The copy keeps its measure while the card grows with --stack-w: the box is
   allowed to widen, a line of text is not. */
.fold__text { grid-area: content; align-content: end; margin-bottom: var(--s-4); opacity: var(--fold-text-opacity); display: grid; gap: var(--s-24); max-width: 46ch; }
.fold__media { grid-area: media; display: grid; place-content: center; opacity: var(--fold-media-opacity); max-width: 512px; position: relative; }
/* Apron's media are 513x440 PNGs on the card tint. Our photos and clips are opaque,
   so they sit inset with the card's own radius, the way Apron's card graphic does. */
.fold__media > img, .fold__media > video { width: 100%; height: auto; border-radius: var(--r-16); object-fit: cover; }
.fold__media video { clip-path: inset(2px round var(--r-16)); isolation: isolate; }
.fold__media { padding-inline: 22px; }
/* Stacked, the photograph would run the full width of the card, and on a
   tablet that is a 526px image under four lines of text. Capped, every card
   in the stack lands on the same 500px floor. */
@media (max-width: 899px) { .fold__media { max-width: 400px; margin-inline: auto; } }
/* 900, not 768: at 768 the media column takes 400 of the card and leaves the
   copy 250, which needs a card half as tall again and made the stack ragged.
   The ordering steps already switch at 900 for the same reason. */
/* The bottom spacer takes the free space, so a card's heading and the
   sentence under it stay together and the heading stays at the top of the
   card, which is the only part of it a reader sees while the next card slides
   over. Sending the slack to both ends brought the pair together and then put
   the pair in the middle: the exposed band of every pinned card went blank and
   the incoming edge began cutting each heading through its x-height at full
   ink. They were fixed at 38px and the two auto
   rows were not, and align-content defaults to stretch, so the surplus a 380px
   media column creates was split evenly between the title row and the content
   row: the heading pinned to the top of the card, its own paragraph pinned to
   the bottom, and 125 to 180px of nothing between them, on ten cards on the
   homepage and five on the private label page. An fr track resolves during
   track sizing, before align-content ever sees any free space, so the two auto
   rows collapse back to their content and the media column still spans all
   four rows against the 440px floor. */
@media (min-width: 900px) {
  .fold__grid {
    gap: var(--s-24); min-height: 440px;
    grid-template: ". . media" 38px ". title media" auto ". content media" auto ". . media" minmax(38px, 1fr) / 30px 1fr auto;
  }
  .fold__title { margin-top: var(--s-8); }
  .fold__text { margin-bottom: var(--s-8); }
  .fold__media { place-content: center; max-width: 400px; margin: auto; padding-inline: 0 30px; }
  .fold__media > img, .fold__media > video { width: 370px; height: 380px; }
}
@media (min-width: 1024px) {
  .fold__media { max-width: 512px; width: 512px; }
  .fold__media > img, .fold__media > video { width: 452px; height: 380px; }
}
/* place-content: center sizes this grid column to whatever is in it, so a
   child with a fixed width never sees the card at all and its max-width:
   100% has nothing to bite on: the 404px pill stayed 404 inside a 257px
   card and the card clipped it. This variant hands the column the space
   instead, and the pill takes the width it is actually given. */
.fold__media--fit { grid-template-columns: minmax(0, 1fr); justify-items: center; }
.fold__media--pad { padding: 0 var(--s-30) 0 0; }
.feature > .container > .btn { margin-inline: auto; }
/* Two ways out of one section. The buttons drop out of the rule above, so
   .btn's own margin-inline: auto is all that is left to beat, and without
   beating it a flex row pushes the pair to opposite ends. */
.feature__actions { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s-12); }
.feature__actions .btn { margin-inline: 0; }

/* ---- 5. Stories carousel ------------------------------------------------- */
.stories { width: 100%; margin: 0 auto; padding-block-end: var(--s-64); }
@media (min-width: 768px) { .stories { padding-block-end: var(--s-120); } }
.stories__inner { display: grid; gap: var(--s-32); }
.carousel {
  display: flex; overflow: auto; scroll-snap-type: x mandatory; scrollbar-width: none;
  padding-block-end: var(--s-16);
}
.carousel::-webkit-scrollbar { display: none; }
@media (min-width: 1024px) { .carousel { padding-block-end: 0; } }
.slide {
  width: max(246px, 70%); flex-shrink: 0; scroll-snap-align: start; padding-inline-start: var(--s-8);
  display: grid; grid-template: "z" 1fr / 1fr; overflow: hidden;
}
.slide > * { grid-area: z; }
.slide:first-child { padding-inline-start: var(--gutter); }
.slide:last-child { padding-inline-end: var(--gutter); }
.slide__media { height: 1px; }
.slide__media picture, .slide__media img { display: block; width: 100%; height: auto; opacity: 0; transition: opacity var(--t-media); }
.slide__body { margin-inline: auto; place-self: end center; padding-block-start: 148px; }
.card-story {
  display: grid; grid-auto-rows: auto 1fr; min-height: 400px; position: relative;
  background: var(--white); margin-block-start: -1px;
  padding: var(--s-32) var(--s-20);
  box-shadow: var(--shadow-card);
  /* the perforated top edge: a row of 16px holes, 31px apart, showing the photo behind */
  -webkit-mask: radial-gradient(circle 8px at 15.5px 21px, transparent 98%, #000 100%) 0 0 / 31px 100% repeat-x;
  mask: radial-gradient(circle 8px at 15.5px 21px, transparent 98%, #000 100%) 0 0 / 31px 100% repeat-x;
}
.card-story__grid { display: grid; gap: var(--s-16); grid-template: "label" "title" "separator" "description" "." 1fr "action" / 1fr; padding-top: var(--s-24); }
.card-story__label { grid-area: label; }
.card-story__title { grid-area: title; }
.card-story__sep { grid-area: separator; }
.card-story__desc { grid-area: description; }
.card-story__action { grid-area: action; display: inline-flex; width: fit-content; margin-block-start: auto; }
@media (min-width: 768px) {
  .slide { padding: 0; width: 100%; max-height: 600px; }
  .slide:first-child, .slide:last-child { padding: 0; }
  .slide__media { height: auto; }
  .slide__media picture, .slide__media img { opacity: 1; width: 100%; height: 600px; object-fit: cover; }
  /* On the page's spine. It was a fixed container-width box with auto side
     margins inside a full-bleed slide plus a 120px inner pad, so the card's
     left edge landed at 120 at 1440 and 360 at 1920, while the stack and the
     obsidian panel directly above it start at 195 and 435. */
  /* The box takes the page's own column and the card sits at the start of it,
     so the receipt lands on the same left edge as the folding stack and the
     obsidian panel above it. The card keeps the width it was drawn at: giving
     it the column turned a 510px receipt into a 1160px slab with a 1100px rule
     running under four short lines. */
  .slide__body {
    display: grid; justify-items: start;
    justify-self: center; padding-block-start: 120px; padding-inline: 0;
    width: min(var(--stack-w), calc(100% - var(--gutter) * 2));
  }
  .card-story { width: 100%; max-width: 508px; min-height: 456px; padding: var(--s-32); }
  .card-story__grid { gap: 34px; }
  .card-story__action { margin-block-start: 0; }
}
@media (min-width: 1024px) {
  .slide { position: relative; }
  .slide::before {
    content: ""; position: absolute; bottom: 0; left: 0; right: 0; height: var(--s-32); z-index: 1;
    background-image: linear-gradient(rgba(217,217,217,.06) 16%, rgba(0,0,0,.06) 83.5%); mix-blend-mode: multiply;
  }
}
/* the 80px inset the card used to need is what the column gives it now */
.carousel__nav { display: grid; gap: var(--s-24); grid-auto-flow: column; grid-auto-columns: 40px; justify-content: center; }

/* ---- 6. FAQ ----------------------------------------------------------------- */
.faq { padding-block: var(--s-64); }
@media (min-width: 768px) { .faq { padding-block: var(--s-120); } }
/* It was the one block on the page narrower than everything else, and the
   heading sat 80px above three closed rows in the top half of a large empty
   rectangle, with the stipple behind all three. The heading stands beside the
   list instead, and the list occupies the band the watermark had to itself. */
.faq .container { max-width: var(--stack-w); }
.faq__grid { display: grid; gap: var(--s-48); }
@media (min-width: 768px) { .faq__grid { gap: var(--s-80); } }
@media (min-width: 1024px) {
  .faq__grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.7fr);
    column-gap: var(--s-64); row-gap: 0; align-items: start;
  }
}
.faq__title { text-align: center; }
@media (min-width: 768px) { .faq__title { text-align: start; } }
.faq__list { display: grid; gap: var(--s-24); }
.faq__item + .rule-dotted:last-child { display: none; }
.faq__btn { width: 100%; text-align: start; display: grid; grid-template-columns: auto max-content; align-items: center; gap: var(--s-24); }
@media (min-width: 768px) { .faq__btn { gap: var(--s-32); } }
.faq__q { display: flex; min-height: 28px; align-items: center; }
.faq__icon { display: flex; align-items: center; }
.faq__icon::before { content: "A"; visibility: hidden; width: 0; font-weight: 700; font-size: 16px; line-height: 140%; }
@media (min-width: 768px) { .faq__icon::before { font-size: 20px; } }
.faq__icon svg { width: 24px; height: 24px; }
.faq__icon .minus { display: none; }
.faq__btn[aria-expanded="true"] .plus { display: none; }
.faq__btn[aria-expanded="true"] .minus { display: block; }
.faq__panel { overflow: hidden; }
.faq__panel[hidden] { display: none; }
.faq__panel.opening { animation: growOpen var(--t-fast) var(--ease-io); }
.faq__panel.closing { animation: growClose var(--t-fast) var(--ease-io) forwards; }
.faq__answer { padding-block: var(--s-16) var(--s-8); max-width: 760px; color: rgba(0,0,0, .80); }
@keyframes growOpen { from { height: 0 } to { height: var(--panel-h) } }
@keyframes growClose { from { height: var(--panel-h) } to { height: 0 } }

/* ---- 7. CTA band ------------------------------------------------------------ */
.cta {
  display: flex; min-height: 380px; flex-direction: column; align-items: center;
  background-color: var(--tint); padding: var(--s-64) var(--s-24);
  background-repeat: no-repeat; background-size: cover; background-position: 5% bottom;
  background-image: url("../media/cta-background.svg");
}
/* min-height, not a viewport: an eyebrow, a heading and a button do not need
   a whole screen, and on a laptop the section under it never showed. */
@media (min-width: 768px) { .cta { min-height: 460px; padding-block: var(--s-80); justify-content: center; background-position: 45% bottom; } }
.cta__inner { display: flex; flex-direction: column; align-items: center; gap: var(--s-24); max-width: 940px; text-align: center; }
@media (min-width: 768px) { .cta__inner { gap: var(--s-32); } }
.cta__actions { display: flex; flex-direction: column; gap: var(--s-16); }
@media (min-width: 768px) { .cta__actions { flex-direction: row; } }

/* ---- 8. Footer -------------------------------------------------------------- */
.footer { background: var(--ink); color: var(--white); font-size: 14px; line-height: 150%; letter-spacing: 0.14px; }
@media (min-width: 768px) { .footer { font-size: 16px; letter-spacing: 0.16px; } }
.footer .container { padding-block: var(--s-64); }
@media (min-width: 1024px) { .footer .container { padding-block: var(--s-80); } }
.footer__grid {
  display: grid; gap: var(--s-32);
  grid-template: "top-divider" "primary-links" "secondary-links" "bottom-divider" "terms" "tertiary-links" "copyright" / 1fr;
}
/* One sitemap across the width, not two blocks with a hole between them.
   The right column was capped at 405 with space-between holding the two halves
   apart, which at 1360 left 443px of black in the middle of the footer. It
   takes the rest of the row now, and display: contents on the two wrappers
   promotes the four link groups to columns of their own, so they read across
   the band instead of stacking two deep inside half of it. */
@media (min-width: 1024px) {
  .footer__grid {
    row-gap: var(--s-48); column-gap: var(--s-32);
    /* The legal text sits under the rule rather than beside the links. It used
       to share a row with them, so the link band spanned two rows, and with
       each column packed to the top that left a slab of dead black under the
       links as tall as the terms beside it. */
    grid-template: "top-divider top-divider" "primary-links secondary-links" "bottom-divider bottom-divider" "terms terms" "tertiary-links copyright" / minmax(auto, 420px) minmax(0, 1fr);
  }
}
.footer__top { grid-area: top-divider; }
.footer__bottom { grid-area: bottom-divider; }
.footer__primary { grid-area: primary-links; display: grid; gap: var(--s-32); }
.footer__primary > div { display: grid; gap: var(--s-16); }
.footer__secondary { grid-area: secondary-links; display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: var(--s-32); align-items: start; }
.footer__secondary > div { display: grid; gap: var(--s-32); }
/* After the rule above, on purpose: it has the same specificity, so the order
   is what decides. display: contents promotes the four link groups out of
   their two wrappers and into the grid, which is what turns the right half of
   the footer from two stacks into four columns. */
@media (min-width: 1024px) {
  .footer__secondary { grid-auto-flow: row; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s-24); }
  .footer__secondary > div { display: contents; }
  .footer__group { align-content: start; }
}
.footer__group { display: grid; gap: var(--s-8); }
/* A 21px line of text is a link a thumb misses. The padding goes on and the
   gap comes off, so the list is a few pixels taller and every row is 33. */
@media (max-width: 767px) {
  .footer__group, .footer__terms { gap: 0; }
  .footer a { padding-block: 6px; }
}
.footer__terms { grid-area: terms; display: grid; gap: var(--s-8); opacity: .7; }
@media (min-width: 1024px) { .footer__terms p { max-width: 78ch; } }
.footer__tertiary { grid-area: tertiary-links; display: grid; grid-auto-flow: column; grid-auto-columns: max-content; gap: var(--s-32); }
.footer__copy { grid-area: copyright; }
@media (min-width: 1024px) { .footer__copy { text-align: end; } }
.footer a:hover { text-decoration: underline 1px; text-underline-offset: 3px; }

/* ---- 4e. The one dark panel on the page ----------------------------------
   Chocolate is a real fleece shade, so the only inverted surface on the site is
   still a product colour. Sits between the workshop and the stories, where the
   page has finished explaining itself and asks for the order. */
/* Even air above and below. It used to sit tight under the full-bleed
   workshop film, 24 above against 120 below, which read as the panel hanging
   off the clip rather than standing on its own. */
.panel-wrap { padding-block: var(--s-80); }
@media (min-width: 768px) { .panel-wrap { padding-block: var(--s-120); } }

.panel {
  /* The darkest shade on the fleece scale rather than chocolate: this is the
     one panel that has to read as the wordmark does. Not pure black, because
     the footer already owns that and two blacks in a row flatten the page. */
  background: var(--fleece-obsidian); color: var(--paper);
  border-radius: var(--r-32); overflow: hidden;
  display: grid; gap: var(--s-40);
  padding: var(--s-48) var(--s-32);
  max-width: var(--stack-w); margin-inline: auto;
}
@media (min-width: 900px) {
  .panel {
    grid-template-columns: minmax(0, 1fr) max-content;
    gap: var(--s-64); align-items: center;
    padding: var(--s-64);
  }
}
.panel__copy { display: grid; gap: var(--s-20); align-content: center; max-width: 46ch; }
/* a panel heading, one step under a section heading, so it does not shout over
   the workshop head just above it */
.panel__copy .t-h2 { font-size: clamp(30px, 3.6vw, 46px); max-width: 15ch; }
.panel__copy .t-p { color: rgba(253, 251, 246, .82); }
.panel__copy .btn { margin-inline: 0; justify-self: start; margin-block-start: var(--s-12); }

.panel__shots { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-20); }
@media (min-width: 900px) { .panel__shots { grid-template-columns: repeat(2, 200px); } }
.panel__shot { display: block; border-radius: var(--r-20); overflow: hidden; background: var(--white); }
.panel__shot img { display: block; width: 100%; height: auto; aspect-ratio: 1; object-fit: cover; }

/* A media slot with no photograph yet. The colour is the fleece, so the card
   still reads as that colourway, and the label says what is missing rather
   than pretending. Used where the only photography available carries someone
   else's watermark. */
.fold__ph {
  display: grid; place-items: center; width: 100%; height: 100%;
  min-height: 240px; border-radius: var(--r-16);
  background: linear-gradient(150deg, var(--a, #C9B192), color-mix(in srgb, var(--a, #C9B192) 72%, #241E1A));
}
.fold__ph b {
  font-family: var(--font-mono); font-size: 11px; letter-spacing: .12em;
  text-transform: uppercase; text-align: center; line-height: 1.7;
  color: rgba(255, 255, 255, .82); text-shadow: 0 1px 2px rgba(36, 30, 26, .3);
}
