/* ALLIN MAKI · base: fonts, reset, type roles, layout primitives */

@font-face { font-family: "Champ"; src: url("../fonts/Champ-Medium.woff2") format("woff2"); font-weight: 400; font-display: swap; }
@font-face { font-family: "Champ"; src: url("../fonts/Champ-ExtraBold.woff2") format("woff2"); font-weight: 800; font-display: swap; }

/* THE STAND-IN FOR CHAMP WHILE CHAMP IS LOADING, CUT TO THE SAME MEASUREMENTS.
   font-display: swap means the heading is painted in a system font first and
   repainted in Champ a moment later. Champ ExtraBold is 5.6% wider than Arial
   Bold and Champ Medium is 11.6% wider than Arial, so on a hero heading of four
   lines that repaint moved everything under it: Lighthouse measured a layout
   shift of 0.29 on the home page, which is most of the way to failing, and it
   held the largest paint at 3.9 seconds because the biggest thing on the page
   was text waiting for a font.
   These three numbers make the stand-in occupy exactly the space Champ will:
   measured at 100px in a browser over a 116 character sample, webfont against
   fallback, rather than read off a table. Nothing swaps visibly any more,
   because nothing moves. */
@font-face {
  font-family: "Champ fallback";
  src: local("Arial Bold"), local("Helvetica Bold"), local("Arial");
  font-weight: 800;
  size-adjust: 105.6%;
  ascent-override: 95.7%;
  descent-override: 23.7%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Champ fallback";
  src: local("Arial"), local("Helvetica");
  font-weight: 400;
  size-adjust: 111.6%;
  ascent-override: 88.7%;
  descent-override: 23.3%;
  line-gap-override: 0%;
}

/* And the same for the body font, which is where the shift actually came from.
   DM Sans is within half a percent of Arial, so this looked like the harmless
   one, but the stack said "DM Sans", sans-serif and the generic is whatever
   the machine happens to have. On the banner, eleven pixels of bold text at
   the very top of the page, that difference was enough to fit on one line in
   the stand-in and wrap onto two in DM Sans. The banner grew sixteen pixels,
   the header and the whole hero went down with it, and that one wrap was the
   entire 0.29. Naming Arial and cutting it to size takes the guess out. */
@font-face {
  font-family: "DM Sans fallback";
  src: local("Arial"), local("Helvetica");
  font-weight: 400;
  size-adjust: 100.4%;
  ascent-override: 96.6%;
  descent-override: 25.9%;
  line-gap-override: 0%;
}
/* 102 and not the 100.0 the long sample gave. One number cannot make every
   string identical, and the string that decides this page is the banner: at
   eleven pixels Arial Bold renders it 315px wide and DM Sans 321px, and those
   six pixels are the difference between "Check collection" fitting on the line
   and dropping under it. Tuned against that line and then measured, because a
   fallback that is a shade too narrow wraps late and moves the page, while one
   that is a shade too wide wraps early and merely unwraps, which nothing
   notices. */
@font-face {
  font-family: "DM Sans fallback";
  src: local("Arial Bold"), local("Helvetica Bold"), local("Arial");
  font-weight: 700;
  size-adjust: 102.0%;
  ascent-override: 96.1%;
  descent-override: 26.5%;
  line-gap-override: 0%;
}
/* DM Sans and DM Mono without their TrueType hinting. With it, Windows snapped
   the u a pixel below the line at 13 and 15 pixels and text read as wavy
   (found on the CRM, 16 September; the shop had the same files). Same
   outlines, no instructions, made with fontTools. A new file name, because
   /fonts is served immutable for a year. */
@font-face { font-family: "DM Sans"; src: url("../fonts/DMSans-Regular-unhinted.woff2") format("woff2"); font-weight: 400; font-display: swap; }
@font-face { font-family: "DM Sans"; src: url("../fonts/DMSans-Medium-unhinted.woff2") format("woff2"); font-weight: 500; font-display: swap; }
@font-face { font-family: "DM Sans"; src: url("../fonts/DMSans-SemiBold-unhinted.woff2") format("woff2"); font-weight: 600; font-display: swap; }
@font-face { font-family: "DM Sans"; src: url("../fonts/DMSans-Bold-unhinted.woff2") format("woff2"); font-weight: 700; font-display: swap; }
@font-face { font-family: "DM Mono"; src: url("../fonts/DMMono-Regular-unhinted.woff2") format("woff2"); font-weight: 400; font-display: swap; }

*, *::before, *::after { box-sizing: border-box; }
html {
  color: var(--ink);
  background-color: var(--paper);
  transition: background-color var(--t-bg);
  scrollbar-gutter: stable;
  scroll-behavior: smooth;
  /* Scroll anchoring off, on purpose. The sticky header collapses into a pill
     as soon as the page moves, which takes about 90px of banner and padding
     out of the flow above the viewport. With anchoring on, the browser answers
     that by pulling the scroll position down by the same amount to keep the
     view still, which drops the page back under the 12px that triggered the
     pill, so the header opens again, which pushes the scroll position back up,
     and the two states flip at every frame for as long as you sit in the first
     90px of the page. The trigger was being measured against a number the
     trigger itself moves.

     With anchoring off the collapse does what the .35s animation was written
     for: the content below glides up as the banner closes and the scroll
     position stays where the reader put it. Nothing else here was leaning on
     anchoring, because every image on the shipping pages carries a width and a
     height. See the header driver in js/landing.js section 1. */
  overflow-anchor: none;
  -webkit-text-size-adjust: 100%;
}
body {
  margin: 0;
  /* No background-colour here on purpose. html carries the paper and paints
     the canvas with it, so the page looks identical either way; but an opaque
     background on body paints over body's own negative z-index children, and
     the chakana behind every page is one of those. See the bottom of this
     file. */
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.5;
  letter-spacing: 0.16px;
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3, h4, h5, h6, p { margin: 0; }
a { color: inherit; text-decoration: none; }
button {
  appearance: none; font: inherit; color: inherit; border: none; background: none;
  padding: 0; margin: 0; text-align: unset; cursor: pointer;
}
img, video, svg { display: block; max-width: 100%; height: auto; }
ul { margin: 0; padding: 0; list-style: none; }
:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }

/* ---- Type roles (Apron "website-*" variants) ------------------------------ */
/* text-wrap: balance on both, which the hero, the compliance headings and the
   value cards have had all along and the two shared display sizes never got.
   A heading is short enough for the browser to balance and long enough to
   strand a word: "Rainbow alpacas in naturally dyed alpaca fur" put "fur" on a
   line of its own at 1512. It changes where a line breaks and never how wide
   the box is, so nothing measured moves. */
.t-h1 {
  font-family: var(--font-display); font-weight: 800;
  font-size: 40px; line-height: 42px; letter-spacing: 0.4px;
  text-wrap: balance;
}
.t-h2 {
  font-family: var(--font-display); font-weight: 800;
  font-size: 28px; line-height: 120%; letter-spacing: 0.28px;
  text-wrap: balance;
}
.t-h3 {                                     /* folding card title */
  font-family: var(--font-display); font-weight: 400;
  font-size: 20px; line-height: 120%; letter-spacing: normal;
}
.t-h4 {                                     /* carousel card title */
  font-family: var(--font-display); font-weight: 400;
  font-size: 20px; line-height: 120%;
}
.t-h6 {                                     /* card title, narrow columns */
  font-family: var(--font-display); font-weight: 800;
  font-size: 21px; line-height: 1.16; letter-spacing: 0.01em;
}
.t-h5 {                                     /* FAQ question */
  font-family: var(--font-body); font-weight: 700;
  font-size: 16px; line-height: 140%; letter-spacing: 0.16px;
}
.t-p {
  font-family: var(--font-body); font-weight: 400;
  font-size: 16px; line-height: 150%; letter-spacing: 0.16px;
}
.t-small {
  font-family: var(--font-body); font-weight: 400;
  font-size: 14px; line-height: 150%; letter-spacing: 0.14px;
}
.t-eyebrow {
  font-family: var(--font-mono); font-weight: 400;
  font-size: 16px; line-height: normal; letter-spacing: 0.16px; text-transform: uppercase;
}
.t-button {
  font-family: var(--font-body); font-weight: 500;
  font-size: 16px; line-height: 100%; letter-spacing: 0.16px;
}
@media (min-width: 768px) {
  .t-h1 { font-size: 72px; line-height: 73px; letter-spacing: normal; }
  .t-h2 { font-size: 54px; line-height: 116%; letter-spacing: 0.54px; }
  .t-h3 { font-size: 38px; }
  .t-h4 { font-size: 26px; line-height: 140%; }
  .t-h5 { font-size: 20px; letter-spacing: -0.4px; }
  .t-p { font-size: 20px; letter-spacing: 0.2px; }
  .t-small { font-size: 16px; letter-spacing: 0.16px; }
  .t-eyebrow { font-size: 18px; letter-spacing: 0.18px; }
}
.t-center { text-align: center; }
.t-bold { font-weight: 700; }
.t-underline { text-decoration: underline 1px; text-underline-offset: 2px; }
.sup-new {                                  /* "NEW" superscript in nav and footer */
  display: inline-block; font-size: 0.645em; transform: translateY(-0.5em);
}

/* ---- Layout primitives ------------------------------------------------- */
.section { display: grid; padding-left: var(--gutter); padding-right: var(--gutter); }
/* min-width: 0 because .section is a grid and a grid item's automatic minimum
   is its min-content width, so one long word or one wide table drags the
   column past the viewport and the whole page scrolls sideways. Three page
   stylesheets had each patched this for themselves; it belongs here, next to
   the rule that creates the problem. */
.container { max-width: var(--container); width: 100%; min-width: 0; margin: 0 auto; }
.stack { display: grid; width: 100%; min-width: 0; grid-auto-flow: row; grid-auto-columns: minmax(0, 1fr); }
.row { display: grid; width: 100%; min-width: 0; grid-auto-flow: column; grid-auto-columns: minmax(min-content, max-content); }
.gap-8 { gap: var(--s-8); } .gap-16 { gap: var(--s-16); } .gap-24 { gap: var(--s-24); }
.gap-32 { gap: var(--s-32); } .gap-48 { gap: var(--s-48); }
.py-80 { padding-block: var(--s-80); }
.py-120 { padding-block: var(--s-120); }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* Dotted rule: Apron draws an SVG line, stroke 2, dasharray "0.1 8", round caps.
   Same geometry as a background: 2px dots every 8px. */
.rule-dotted {
  height: 2px; width: 100%;
  background-image: radial-gradient(circle, currentColor 1px, transparent 1.1px);
  background-size: 8px 2px; background-repeat: repeat-x; background-position: 1px 0;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: 0.001s !important; transition-duration: 0.001s !important; }
}

/* ---- The chakana behind the page ----------------------------------------
   An Andean cross, stippled, fixed off the right edge. It is not there at the
   top of the page, fades in as you read past the hero, and turns about a
   quarter of the way round over the length of the scroll.

   A watermark, not an ornament: it sits at z-index -1, so every card, panel
   and photograph paints over it and it shows only in the paper between them.
   That is also why it never lands on a dark panel and never has to fight text
   for contrast.

   Two things hold it up, and both look like tidying:
     - body must carry no background-colour. html has one; an opaque background
       on body paints over a negative z-index child of body. That is the rule
       at the top of this file, and this is why it is written the way it is.
     - it must stay a direct child of body. position: fixed is measured against
       the nearest ancestor with a transform or a filter, and these pages have
       plenty of those.

   From WEB ARTIFACTS/Peruvian alpaca artisan chakana website design.zip. The
   handoff drew it in a neutral grey chosen against a #f4efe6 ground; ours is
   #FDFBF6 and the whole palette is warm, so the asset is re-tinted to
   --fleece-walnut. Grey on this paper reads as smoke rather than fleece.

   It is here rather than in css/landing.css, where it was built, because it is
   on every page now. The driver is js/main.js section 7, which is loaded
   everywhere; css/landing.css and js/landing.js are not.

   How strong it goes is --chak-max, and it is set in CSS rather than in the
   script because it is a judgement about ink on paper. Peak opacity is a
   misleading number for a stipple: the dots cover about 30% of the square, so
   the tone you actually see is roughly a third of what the figure suggests.
   At .10, the hand-off's value, the shape averages nine levels off the paper
   and is invisible on a real monitor. At .22 it averages twenty and reads as
   a cross without competing with anything. A phone gets less: the same image
   covers far more of a 390px screen than of a 1440px one.

   A design pass on 2026-09-08 came back with five separate proposals to change
   this rule and no two of them agreed: --chak-max to .15, .13 or .10; right to
   -14vw, -16vw or a calculation; the width up to 900px or down to 420px. Three
   of the five would have made 1440 worse than it is now. The answer is that the
   mark is not the fault. It behaves exactly as it was meant to wherever content
   reaches it: over the catalogue grids, behind the folding cards, behind the
   standards cards, and across most of 1920. It only reads as noise on a screen
   where a section declined to occupy its own width, which is what --stack-w and
   the section-head variants are for. So this rule is not edited. If one screen
   still bites after those, scope it to that screen, through js/main.js section
   7, and never on the element.
   --------------------------------------------------------------------------- */
.chakana {
  --chak-max: .22;
  position: fixed;
  top: 50%;
  right: -6vw;
  z-index: -1;
  width: min(58vw, 680px);
  height: auto;
  opacity: 0;                 /* the script raises it; nothing at the top */
  pointer-events: none;
  transform: translateY(-50%) rotate(30deg);
  will-change: transform, opacity;
}
/* On a phone it bleeds further off the edge, so what is on screen is one
   half of the cross rather than a small whole one. */
@media (max-width: 719px) {
  .chakana { --chak-max: .17; width: min(76vw, 440px); right: -20vw; }
}
/* Standing still it still belongs on the page, so it takes its end state
   rather than vanishing. */
@media (prefers-reduced-motion: reduce) {
  .chakana { opacity: var(--chak-max); transform: translateY(-50%) rotate(7deg); }
}
