/* ============================================================
   branding.css — Yes Ma’ams front-page sheet
   Palette sampled directly from docs/assets/flyer.png
       paper #F1D8BA   ink #000000   red #B00201
   Paper: paper/paper-grain.webp (multiplied over white, see --sheet)

   STATUS: WORKING / DRY RUN — not linked from any live page.
   Paths are relative to branding/proof/
   Desktop (>=1000px) is the poster. Below that the page reflows;
   see RESPONSIVE at the foot of this file.
   ============================================================ */

/* ---------- TYPEFACES ----------
   Both cut-outs of the flyer's own hand-set lettering are now taken straight
   from the poster rather than imitated:
       the headline  ("Yes Ma’ams" / "CLEANING")  -> headline-*.webp
       the script    ("We're about the details.") -> script-flyer.webp
   So there is exactly ONE webfont left, and it is a FREE LOOKALIKE, not the
   flyer's actual (unidentified, likely licensed) face:
     Oswald  -> the bold condensed sans on every shouty caps line
                ("TWO LOCAL WOMEN", the five chips, "NO THIRD PARTY",
                 "LOCALLY OWNED")
   Everything else stays Georgia: the flyer's phone numbers, "SERVING ST PAUL",
   "YESMAAMSCLEANING.COM" and the body copy are all serif, and Georgia is
   genuinely close to that schoolbook serif. */
@font-face {
  font-family: "Oswald";
  font-style: normal;
  font-weight: 500 600;
  font-display: swap;
  src: url("../fonts/oswald-latin.woff2") format("woff2");
}

:root {
  --paper:  #f1d8ba;  /* the flyer's ink-on-paper cream - used for text on black */
  --sheet:  #ffffff;  /* the grain now carries the colour, so the sheet stays white */
  --ink:    #000000;
  --red:    #b00201;
  --hero-top: 64px;   /* the mug's top edge; the steam is pinned 2px above it */
}

* { box-sizing: border-box; }

body {
  margin: 0;
  color: var(--ink);
  font-family: Georgia, "Times New Roman", serif;
}
/* the two numbers in the banner are tel: links so a phone can dial them; they
   must look exactly like the text they replace */
a { color: inherit; text-decoration: none; }

.defs { position: absolute; width: 0; height: 0; overflow: hidden; }

/* ---------- ICON SYSTEM -------------------------------------
   The SVG is used as a MASK, so the colour is set in CSS and
   nothing about the artwork has to change. One rule recolours
   every icon.
   ----------------------------------------------------------- */
.ic {
  display: inline-block;
  width: 46px;
  height: 46px;
  background-color: var(--ink);
  -webkit-mask-repeat: no-repeat;  mask-repeat: no-repeat;
  -webkit-mask-position: center;   mask-position: center;
  -webkit-mask-size: contain;      mask-size: contain;
}
.ic-house     { -webkit-mask-image: url("../icons/house.svg");        mask-image: url("../icons/house.svg"); }
.ic-bucket    { -webkit-mask-image: url("../icons/bucket.svg");       mask-image: url("../icons/bucket.svg"); }
.ic-key-black { -webkit-mask-image: url("../icons/black-key.svg");    mask-image: url("../icons/black-key.svg"); }
.ic-key-red   { -webkit-mask-image: url("../icons/red-key.svg");      mask-image: url("../icons/red-key.svg"); }
.ic-checklist { -webkit-mask-image: url("../icons/checklist.svg");    mask-image: url("../icons/checklist.svg"); }
.ic-broom     { -webkit-mask-image: url("../icons/broom.svg");        mask-image: url("../icons/broom.svg"); }
.ic-spray     { -webkit-mask-image: url("../icons/spray-bottle.svg"); mask-image: url("../icons/spray-bottle.svg"); }
.ic-star      { -webkit-mask-image: url("../icons/star.svg");         mask-image: url("../icons/star.svg"); }
.ic-star5     { -webkit-mask-image: url("../icons/star5.svg");        mask-image: url("../icons/star5.svg"); }
.ic-paw       { -webkit-mask-image: url("../icons/paw.webp");          mask-image: url("../icons/paw.webp"); }
.ic-cat-mug   { -webkit-mask-image: url("../icons/cat-and-mug.svg");  mask-image: url("../icons/cat-and-mug.svg"); }
/* the mug's shadow is inked into the art already; on the flyer the printed wash
   spreads to the LEFT and under it, so the soft layer goes that way too. Scoped
   to .ic-cat-mug so the red rag layer, which also carries .hero-illustration,
   does not cast a second one. */
.ic-cat-mug { filter: drop-shadow(-9px 11px 12px rgba(0, 0, 0, .45)); }
.ic-heat-large      { -webkit-mask-image: url("../icons/heat-large.svg");      mask-image: url("../icons/heat-large.svg"); }
.ic-heat-medium     { -webkit-mask-image: url("../icons/heat-medium.svg");     mask-image: url("../icons/heat-medium.svg"); }
.ic-heat-small      { -webkit-mask-image: url("../icons/heat-small.svg");      mask-image: url("../icons/heat-small.svg"); }
.ic-heat-small-bend { -webkit-mask-image: url("../icons/heat-small-bend.svg"); mask-image: url("../icons/heat-small-bend.svg"); }
.ic-script-w        { -webkit-mask-image: url("../icons/script-w.svg");        mask-image: url("../icons/script-w.svg"); }

.ic-red { background-color: var(--red); }
.ic-leaf { -webkit-mask-image: url("../icons/leaf.webp"); mask-image: url("../icons/leaf.webp"); }
.ic-flip { transform: scaleX(-1); }

/* ---------- THE RED LAYERS ----------
   house.svg, checklist.svg and cat-and-mug.svg are each a single
   `fill: currentColor` path, so the flyer's red is not in them at all - the roof
   edge, door and chimney, the clipboard's three ticks, and the mug's rag are
   punched out or traced as ink and read as black. These PNG alpha masks, keyed
   out of the original cut-out PNGs by redness with a soft ramp so the
   anti-aliased edges do not fizz, sit on top in red and put the colour back.
   mask-size and mask-position deliberately mirror .ic so the two line up pixel
   for pixel. */
.icon-red {
  position: absolute;
  background-color: var(--red);
  -webkit-mask-repeat: no-repeat;  mask-repeat: no-repeat;
  -webkit-mask-position: center;   mask-position: center;
  -webkit-mask-size: contain;      mask-size: contain;
  pointer-events: none;
}
.card-icon .icon-red { inset: 0; }
.icon-red-house   { -webkit-mask-image: url("../icons/house-red.webp");   mask-image: url("../icons/house-red.webp"); }
.icon-red-cat-mug { -webkit-mask-image: url("../icons/cat-mug-red.webp"); mask-image: url("../icons/cat-mug-red.webp"); }
.icon-red-checklist { -webkit-mask-image: url("../icons/checklist-red.webp"); mask-image: url("../icons/checklist-red.webp"); }

/* ---------- MODE A — PAPER ---------- */
.mode-paper .stage {
  position: relative;
  max-width: 1000px;
  margin: 0 auto;
}

/* soft shadow BEHIND the frame — this is the "lighting" that makes it lift */
.mode-paper .edge-shadow {
  position: absolute;
  inset: -16px;
  background: #000;
  filter: blur(28px);
  opacity: .5;
  z-index: 0;
}

/* the worn black border: a thin band printed on the paper's edge, etched
   until the cream scratches back through it */
.mode-paper .edge {
  position: absolute;
  inset: -6px;
  border: 16px solid #000;
  background: transparent;
  filter: url(#rough-edge);
  z-index: 4;
}

/* the cream sheet. Base colour stays as light as the flyer; the grain
   rides on its own layer so it can't darken the paper. */
/* the paper is the outermost layer - the border is printed ON it, so
   erosion reveals cream rather than the page behind */
.mode-paper .paper-bg {
  position: absolute;
  inset: 0;
  background-color: var(--sheet);
  filter: url(#rough-paper);
  z-index: 1;
}
.mode-paper .paper-bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: url("../paper/paper-grain.webp");
  background-size: cover;
  background-position: center;
  opacity: 1;
  mix-blend-mode: multiply;
}

/* fine ink flecks drifting inward from the paper's edge - this is the
   speckle that reads as wear, and it doubles as the edge vignette.
   The tile is 240 units of dots; at 300px they printed as 3-6px blobs that
   read as dirt specks in the corners. At 150px they are half the size and
   four times as many - the flyer's fine dust - with coverage unchanged, so
   the vignette holds. */
.mode-paper .edge-speckle {
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  background-image: url("../paper/ink-speckle.svg");
  background-size: 150px 150px;
  background-repeat: repeat;
  opacity: .8;
  -webkit-mask-image: url("../paper/edge-mask.svg");
          mask-image: url("../paper/edge-mask.svg");
  -webkit-mask-size: 100% 100%;
          mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
}

.mode-paper .poster {
  position: relative;
  z-index: 5;   /* above the band, so the mug can overlap it */
  overflow: hidden;   /* the hero illustration bleeds to the paper's edge and stops there */
  background: transparent;
  padding: 54px 112px 44px;   /* flyer: content 774px of 1000, margins 118/109 */
}

/* ============================================================
   MODE B — FLAT: no paper, no frame, edge to edge
   ============================================================ */
body.mode-flat {
  background: var(--paper);
  padding: 0;
}
.mode-flat .poster {
  max-width: 1080px;
  margin: 0 auto;
  padding: 68px 70px 58px;
  background: transparent;
}

/* ---------- MASTHEAD ---------- */
.masthead {
  position: relative;
  display: grid;
  /* the flyer's text column is .738 of the content width - wider than our old
     1.3fr/.9fr, which was squeezing the headline 30px short of its true size.
     Retuned when the content narrowed to the flyer's 774px: 3.25fr/1fr gives
     a 570px text column and a 175px art column. */
  grid-template-columns: 3.25fr 1fr;
  gap: 28px;
  align-items: start;
}

/* Brandon's call: the headline is the FLYER'S OWN LETTERING, cut out and keyed
   to transparent, exactly like the script line. That settles the weight, the
   tracking, the letterforms and the missing apostrophe all at once - it simply
   IS the flyer. Each cut-out is tight to its ink, so the box IS the ink box and
   the placement numbers below are straight off the poster at 1700 -> 1000.
   The real text stays in the DOM (pushed out of view) so the h1 is still text. */
.brand { margin: 0; }
.brand-line1,
.brand-line2 {
  display: block;
  background-repeat: no-repeat;
  background-position: left top;
  background-size: 100% 100%;
  text-indent: -9999px;
  overflow: hidden;
  white-space: nowrap;
}
.brand-line1 {
  width: 527.6px;   /* flyer ink 897px of 1700 */
  height: 72.9px;
  margin: 15.4px 0 0 16.8px;   /* ink at x128.8 / y69.4 of the paper */
  background-image: url("../icons/headline-yesmaams.webp");
}
.brand-line2 {
  width: 517.6px;   /* flyer ink 880px of 1700 */
  height: 78.2px;
  margin: 18.2px 0 0 23.9px;   /* ink at x135.9, 18.2px under line 1 */
  background-image: url("../icons/headline-cleaning.webp");
}

.promise {
  font-family: "Oswald", Georgia, serif;
  font-size: 40px;   /* flyer "TWO LOCAL WOMEN." = 326px wide, 31px cap */
  font-weight: 600;
  text-transform: uppercase;
  line-height: 1.14;
  letter-spacing: .005em;
  /* the flyer indents its masthead copy to x228 of 1700 (134.1 CSS) while the
     headline art sits at 219 and the script at 235. Ours were flush at the 112
     content edge, which only showed once the script grew. */
  margin: 22px 0 0 22.1px;
}

/* The flyer's own lettering, keyed to transparent - the same treatment as the
   headline and the script line. The flyer sets this line in a typewriter slab
   that Georgia only approximates, so it is cut out rather than set.
   The cut-out is 585x83 of 1700 = 344.1 x 48.8 at our scale, but it is kept at
   the 387.7px Brandon approved for body copy. The source is 585px wide, so that
   is still a downscale and costs no sharpness. The box IS the ink box and sits
   on the left edge of the text column. Real text stays in the DOM. */
.lede {
  width: 387.7px;
  height: 55px;      /* 83 flyer px x 387.7/344.1 */
  margin: 18px 0 0 22.1px;   /* the flyer's masthead indent, x228 of 1700 */
  background-image: url("../icons/lede-flyer.webp");
  background-repeat: no-repeat;
  background-size: 100% 100%;
  text-indent: -9999px;
  white-space: nowrap;
  overflow: hidden;
}

/* Brandon's call: use the flyer's own lettering rather than a lookalike font.
   The line AND its hand-drawn rule are one cut-out (714x114 of 1700), keyed to
   transparent so the paper grain shows through. The real text stays in the DOM
   and is only pushed out of view, so it is still selected and read aloud. */
.script {
  display: block;
  /* Brandon: "make 'Were about the details.' bigger to match the poster more
     closely", then again "make it a little bit bigger". The flyer sets it at
     418px of its 1320 content, but the lede beside it runs at 387.7 against the
     flyer's 344.1, so the script rides on the same enlargement: 473.3 restored
     the flyer's 1.22 script/lede ratio, and 500.0 is a further 5.6% on top. */
  width: 500.0px;    /* flyer 714px of 1700, x1.127 then x1.056 */
  height: 79.8px;    /* flyer 114px of 1700, same two steps */
  /* Brandon: "center vertically the 'Were about the details.' between 'You know
     who's coming into your home every visit, every time.' and 'We know pet hair.'"
     The cut carries its own rule, and the ink starts 1.4px inside the box at this
     scale, so 56.6 of margin puts the ink 58px below the lede's ink - the same 58
     the pet already sits at above the category chips. Both gaps are 58, so the
     script is centred between them.
     The flyer indents this lettering to x235 of 1700; the cut's own 3px of left
     margin becomes 2.1px here, so the box sits at 136.1 - a 24.1 indent. */
  margin: 56.6px 0 8px 24.1px;
  background-image: url("../icons/script-flyer.webp");
  background-repeat: no-repeat;
  background-position: left center;
  background-size: contain;
  text-indent: -9999px;
  white-space: nowrap;
  overflow: hidden;
}

/* The flyer's own lettering, and this time the paw comes with it: "We know pet
   hair." and the paw print are one cut (412x57 of 1700 -> 242.4 x 33.5), so the
   paw keeps the flyer's shape instead of being a separate traced mask. Real text
   stays in the DOM, pushed out of view. */
.pet {
  /* Brandon: make it match the size of "NO THIRD PARTY..." and sit centred in the
     gap between the script and the category chips. The flyer's pet cap is 28px of
     1700 against the shout's 29px, so at the shout's 1.5x the pet needs 1.554x:
     242.4 x 33.5 -> 376.5 x 52.1. Still a downscale of the 412x57 cut. */
  width: 376.5px;
  height: 52.1px;
  /* Rhythm pass: the flyer sets this line 6px under the script's rule, not 58.
     With the script's own 3.5px of tail that is a 2.5px margin. */
  margin: 2.5px 0 0 22.1px;
  background-image: url("../icons/pet-flyer.webp");
  background-repeat: no-repeat;
  background-size: 100% 100%;
  text-indent: -9999px;
  white-space: nowrap;
  overflow: hidden;
}

/* sized to the artwork's own ratio (728x856) so `contain` fills the box
   exactly and the edge lands where we put it. Dropped to clear headroom
   for the steam, pushed right until it sits on top of the band. */
.hero-illustration {
  position: absolute;
  top: var(--hero-top);
  right: -112px;   /* bleeds to the paper's own edge */
  width: 323px;
  height: 380px;
}

/* The flyer's steam: four squiggles standing on the mug's rim, over the mug's
   right half. Anchored to the same masthead box as the illustration so they
   move together. */
.steam {
  position: absolute;
  top: calc(var(--hero-top) - 2px);   /* rides with the mug */
  right: -36px;              /* pinned to the paper, not the column: it used to
                                be 18px inside a 58px margin, and the margin is
                                now 112px, so it hangs outside the grid box */
  transform: translateY(-100%);
  display: flex;
  align-items: flex-end;
  gap: 9px;
  height: 68px;
  pointer-events: none;
}
.steam .ic { align-self: flex-end; }
.hs1 { width: 32px; height: 44px; }
.hs2 { width: 30px; height: 66px; }
.hs3 { width: 20px; height: 68px; }
.hs4 { width: 14px; height: 48px; }

/* ---------- THE FIVE CARDS ---------- */
.cards {
  display: grid;
  /* minmax(0,1fr), not 1fr: the chips' natural width was pushing the tracks
     past their share (5x162 instead of 5x155, overflowing the content box) */
  grid-template-columns: repeat(5, minmax(0, 1fr));
  /* Rhythm pass: on the flyer the chips sit 16px under the pet line, and the
     card's own 18px top padding already supplies that. */
  margin-top: 0;
}
.card {
  position: relative;
  padding: 18px 13px 0;
  text-align: center;
}
/* The dividers run from the top of the cards down to the bottom of the LAST
   BLURB LINE - not to the bottom of the card. Brandon: "make the red divides
   shorter to where they line up on the bottom with the last sentence for the
   'We can start there.'" So this is a pseudo-element as tall as the card's
   content: the bottom padding is gone, the fifth blurb is the tallest, and the
   grid row's bottom is therefore its last line. */
.card::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  width: 1.5px;
  background: var(--red);
}
.card:last-child::after { display: none; }

.card-title {
  /* h2 now, for the document outline; the span it replaced had no margin, so
     zero it to keep the poster's spacing pixel-identical */
  margin: 0;
  position: relative;
  z-index: 0;
  display: inline-block;
  background: transparent;
  color: var(--paper);
  font-family: "Oswald", Georgia, serif;
  font-size: 18px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .03em;
  line-height: 1.2;
  padding: 6px 12px;
}
/* the poster's titles sit on a ragged paint smear, not a clean box */
.card-title::before {
  content: "";
  position: absolute;
  inset: -3px -7px;
  background: var(--ink);
  filter: url(#rough-chip);
  z-index: -1;
}

/* The flyer stands the five icons on one baseline, which is why its tall
   broom reaches up into the chip while the wide house sits lower. Centre
   alignment flattened that out. */
.card-icon {
  position: relative;
  height: 134px;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  margin: 16px 0 16px;
}
.card-icon .ic { width: 134px; height: 134px; }
/* The flyer prints a ground shadow under each card icon and the trace kept only
   the ink, so the shadow goes back on as a drop-shadow. Every one falls down and
   right on the flyer; the strength is read off the flyer - the house is the
   lightest, the bucket and the broom carry the heaviest hatched shadow, and the
   clipboard sits between. Offset downward so it reads as a ground shadow rather
   than a halo. */
.card-icon .ic { filter: drop-shadow(3px 5px 4px rgba(0, 0, 0, .45)); }         /* house: light */
.card-icon .ic-key-black { filter: drop-shadow(4px 6px 5px rgba(0, 0, 0, .5)); }
.card-icon .ic-checklist { filter: drop-shadow(5px 8px 6px rgba(0, 0, 0, .55)); }
.card-icon .ic-broom { filter: drop-shadow(4px 8px 7px rgba(0, 0, 0, .6)); }
.card-icon .ic-bucket { filter: drop-shadow(5px 9px 7px rgba(0, 0, 0, .6)); }   /* heaviest */
/* the Deep Cleans bucket is deliberately smaller - see THE ARCH below */
.card-icon .ic-bucket { width: 107px; height: 107px; }

/* ---------- THE ARCH (Deep Cleans) ----------
   The flyer rings its bucket with 14 four-point sparks, each one a thin black
   star with a small red diamond at its centre. Everything below is measured off
   docs/assets/flyer.png - the sparks were picked out as their own ink blobs and
   measured one by one - and then placed with the flyer's own offsets from the
   centre of its bucket, because our card columns and the flyer's are the same
   width (155px), so no scaling is needed. They are quoted against .card-icon
   itself ("50% +/- n px" across, "100% - n px" down) so the arch cannot drift.
   Be aware: the flyer's sparks sit just clear of the bucket's BODY, so if the
   bucket grows the arch will start to disappear behind it. mask-size 100% 100%
   (rather than contain) is deliberate - it reproduces the flyer's own variation
   in how long each spark's points are. */
.spark {
  position: absolute;
  background-color: var(--ink);
  -webkit-mask-image: url("../icons/star.svg");  mask-image: url("../icons/star.svg");
  -webkit-mask-repeat: no-repeat;                mask-repeat: no-repeat;
  -webkit-mask-size: 100% 100%;                  mask-size: 100% 100%;
}
/* the core is a diamond, not a smaller spark - the flyer's is ~33% of the width */
.spark::after {
  content: "";
  position: absolute;
  left: 33.5%;
  top: 50%;
  width: 33%;
  aspect-ratio: 1 / 1;
  transform: translateY(-50%);
  background-color: var(--red);
  clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
}
/*                                     from .card-icon's centre   up from its bottom */
.sp1  { left: calc(50% - 14.4px); top: calc(100% - 131.4px); width: 14.7px; height: 18.2px; }
.sp2  { left: calc(50% + 22.1px); top: calc(100% - 130.2px); width: 16.5px; height: 24.7px; }
.sp3  { left: calc(50% - 45.6px); top: calc(100% - 128.4px); width: 21.8px; height: 29.4px; }
.sp4  { left: calc(50% + 36.2px); top: calc(100% - 111.4px); width: 11.2px; height: 16.5px; }
.sp5  { left: calc(50% - 50.3px); top: calc(100% - 109.0px); width:  7.6px; height: 12.4px; }
.sp6  { left: calc(50% + 52.7px); top: calc(100% - 103.1px); width: 11.8px; height: 17.6px; }
.sp7  { left: calc(50% - 65.6px); top: calc(100% - 102.5px); width: 19.4px; height: 28.8px; }
.sp8  { left: calc(50% + 47.4px); top: calc(100% -  80.8px); width: 20.0px; height: 25.3px; }
.sp9  { left: calc(50% - 69.1px); top: calc(100% -  73.1px); width: 10.0px; height: 15.3px; }
.sp10 { left: calc(50% + 59.7px); top: calc(100% -  55.5px); width:  8.2px; height: 11.8px; }
.sp11 { left: calc(50% - 62.6px); top: calc(100% -  60.8px); width: 20.0px; height: 28.8px; }
.sp12 { left: calc(50% + 40.3px); top: calc(100% -  48.4px); width: 19.4px; height: 26.5px; }
.sp13 { left: calc(50% - 50.3px); top: calc(100% -  32.5px); width: 12.9px; height: 15.9px; }
.sp14 { left: calc(50% + 35.6px); top: calc(100% -  26.1px); width:  7.6px; height:  8.2px; }

/* The flyer's own lettering for all five blurbs, cut one by one off the poster:
   the categories' bottom text, which had been standing in as 17px Georgia. The
   flyer's face is the same typewriter slab as the lede, and at 1700 -> 1000 it
   lands at the size we already had - cap 12.4px against 12.2px at 17px Georgia -
   so this costs nothing in legibility and gains the right letterforms. Real text
   stays in the DOM, pushed out of view, so the blurbs still select and read. */
.card p {
  margin: 0 auto;
  background-repeat: no-repeat;
  background-size: 100% 100%;
  /* color:transparent, NOT text-indent:-9999px. text-indent only moves the FIRST
     line of a block, and every one of these blurbs is full of <br>s - so lines 2+
     were being painted in black ON TOP of the cut-out. That is exactly what made
     the categories look blurry. The images were always sharp. */
  color: transparent;
  overflow: hidden;
}
.card:nth-child(1) p { width: 111.2px; height: 51.2px; background-image: url("../icons/blurb1-flyer.webp"); }
.card:nth-child(2) p { width: 117.6px; height: 51.2px; background-image: url("../icons/blurb2-flyer.webp"); }
.card:nth-child(3) p { width: 103.5px; height: 70.6px; background-image: url("../icons/blurb3-flyer.webp"); }
.card:nth-child(4) p { width: 118.2px; height: 90.6px; background-image: url("../icons/blurb4-flyer.webp"); }
.card:nth-child(5) p { width: 134.7px; height: 108.2px; background-image: url("../icons/blurb5-flyer.webp"); }

/* ---------- LOWER BLOCKS ---------- */
/* The flyer's own lettering (ink 790x30 of 1700 -> 464.7 x 17.6), which carries
   the red "JUST US." in the same cut-out. Centred on the column; the real text
   stays in the DOM, pushed out of view. The 40px top margin keeps the ink where
   the 23px Oswald line had it. */
.shout {
  /* Brandon: "making the 'No third party...' and 'We answer our own phones...'
     much larger text". 1.5x: the cut's own ink was 464.7 wide, now 697.1. */
  width: 697.1px;
  height: 26.4px;
  margin: 14px auto 0;
  background-image: url("../icons/shout-flyer.webp");
  background-repeat: no-repeat;
  background-size: 100% 100%;
  text-indent: -9999px;
  white-space: nowrap;
  overflow: hidden;
}
.red { color: var(--red); }

/* The flyer's own lettering again (ink 779x29 of 1700 -> 458.2 x 17.1). Note
   this is 458.2 wide, not the 430 that 17px Georgia reached: the earlier 734px
   reading was clipped by the measuring window, so the flyer really does set this
   line a touch wider than we had it. */
.shout-sub {
  width: 687.3px;    /* 458.2 x 1.5, the same ratio as the line above */
  height: 25.7px;
  margin: 13.3px auto 0;
  background-image: url("../icons/shout-sub-flyer.webp");
  background-repeat: no-repeat;
  background-size: 100% 100%;
  text-indent: -9999px;
  white-space: nowrap;
  overflow: hidden;
}

.owned {
  text-align: center;
  color: var(--red);
  font-family: "Oswald", Georgia, serif;
  font-size: 21px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .05em;
  margin: 8px 0 8px;
}
.owned .ic-star { width: 15px; height: 15px; vertical-align: -2px; }
/* the flyer's ornament beside this line is a three-leaf sprig, not a sparkle -
   cut out of the flyer at flyer x503..546, y1603..1645 (44x43 -> 26x25 CSS).
   The sprig's centre sits on the cap-height centre (flyer y1624 vs the text's
   1625.5), so it is vertically centred on the caps, not on the baseline. */
.owned .ic-leaf { width: 26px; height: 25px; vertical-align: -4px; margin: 0 3px; }

.phonebar {
  position: relative;
  z-index: 0;
  background: transparent;
  color: var(--paper);
  text-align: center;
  padding: 20px 18px 16px 104px;
  font-size: 26px;
}
/* brush-stroke banner, matching the category titles */
.phonebar::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--ink);
  filter: url(#rough-chip);
  z-index: -1;
}
/* Pokes out above the banner the way the flyer's bottle does. The flyer prints
   it as a cream body with black contour lines and a black paw, so it needs two
   passes split on the banner's top edge:
     - on the paper  : the outline art in black (line art on cream)
     - on the banner : the evenodd knock-out, filled cream, so the body reads
                       cream, the contour lines read black, and the paw - a
                       hole - reads black too. */
.phonebar-spray {
  position: absolute;
  left: 20px;
  top: -34px;
  width: 58px;
  height: 118px;
  background-color: transparent;
  -webkit-mask-image: none;  mask-image: none;
  z-index: 1;
}
.phonebar-spray::before,
.phonebar-spray::after {
  content: "";
  position: absolute;
  inset: 0;
  -webkit-mask-repeat: no-repeat;  mask-repeat: no-repeat;
  -webkit-mask-position: center;   mask-position: center;
  -webkit-mask-size: contain;      mask-size: contain;
}
.phonebar-spray::before {
  background-color: var(--ink);
  -webkit-mask-image: url("../icons/spray-bottle.svg");
          mask-image: url("../icons/spray-bottle.svg");
  clip-path: inset(0 0 calc(100% - 34px) 0);
}
.phonebar-spray::after {
  background-color: var(--paper);
  -webkit-mask-image: url("../icons/spray-bottle-invert.svg");
          mask-image: url("../icons/spray-bottle-invert.svg");
  clip-path: inset(34px 0 0 0);
}
.phonebar strong { color: var(--red); font-weight: 800; }
/* One star asset for all three stars in the banner, at one size.
   The phone-bar one used to be a text glyph (a ★ character), whose ink is only
   ~21px inside a 26px em box, so it could never be matched to the masked ones.
   The URL pair was worse: the rule above named .ic-star while the markup carries
   ic-star5, so both were falling back to the .ic default of 46px.
   The flyer's own are 26.5px (phone) and 22.5px (URL), so 25px splits the
   difference and makes all three identical. The glyph inside the span is zeroed.
   overflow:hidden is NOT cosmetic: it moves the span's baseline from its stunted
   zero-height line box to its bottom margin edge, so vertical-align: -4px measures
   from the bottom of the star as intended. Without it the star hung ~14px low. */
.phonebar .st { font-size: 0; overflow: hidden; margin: 0 14px; vertical-align: -4px; }
.phonebar .st,
.phonebar .url .ic-star5 { width: 25px; height: 25px; }
/* Red rays leaving the NOZZLE and fanning right. FOUR of them, traced off the
   flyer by ring-scanning from their true convergence point - which sits ~6px
   INSIDE the nozzle, so the ink starts ~12px out and the rays read detached,
   as they do in print. Angles +39 / +10 / -19 / -47 deg. Drawn rather than cut
   out, since they are just straight tapered wedges (3-point polygons, thick at
   the inner end, pointed at the tip). user(0,0) is the convergence point. */
.spray-rays {
  position: absolute;
  left: 70px;
  top: -59px;
  width: 52px;
  height: 76px;
  overflow: visible;
  z-index: 1;
  pointer-events: none;
  color: var(--red);
}
.spray-rays polygon { fill: currentColor; }
/* The flyer's own lettering for the URL, cut off the banner and keyed on the
   LIGHT ink rather than the dark (574x49 of 1700 -> 337.6 x 28.8). Georgia cannot
   match this: the flyer's line is both much taller and much narrower than Georgia
   can be at any one size, so no font-size gets there. Laid out as a flex row with
   the two stars, so all three pieces share one centre line. */
.phonebar .url {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;        /* flyer: star ends x546, lettering starts x570 -> 14.1px */
  margin-top: 10px;
}
.url-text {
  width: 337.6px;
  height: 28.8px;
  background-image: url("../icons/url-flyer.webp");
  background-repeat: no-repeat;
  background-size: 100% 100%;
  text-indent: -9999px;
  white-space: nowrap;
  overflow: hidden;
}

.serving {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 20px;
  text-align: center;
  font-size: 14px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  line-height: 1.5;
  margin: 14px 0 0;
}
/* the flyer's own lettering for "SERVING ST. PAUL, MINNEAPOLIS / & THE TWIN
   CITIES METRO", cut as one piece (489x60 of 1700 -> 287.7 x 35.3). Same size as
   the 14px Georgia it replaces - the width came out 287.7 against 285.9 - but it
   is the right face now. Real text stays in the DOM. */
.serving-text {
  width: 287.7px;
  height: 35.3px;
  background-image: url("../icons/serving-flyer.webp");
  background-repeat: no-repeat;
  background-size: 100% 100%;
  /* same trap as the blurbs: this block has a <br>, so text-indent moved the
     first line out of view but left the second one painted over the cut-out.
     That overlay is the "double text line" Brandon saw. */
  color: transparent;
  overflow: hidden;
}
/* the flyer's own engraved red key, cut out of the poster (184x56 of 1700 ->
   108.2 x 32.9). We had been stretching our traced SVG to 110x24, which flattens
   the key's aspect from 3.29 to 4.58 - that is why it looked wrong next to the
   flyer. The right-hand key is this same cut, mirrored. */
.keydiv {
  width: 108.2px;
  height: 32.9px;
  background-image: url("../icons/key-red-flyer.webp");
  background-repeat: no-repeat;
  background-size: 100% 100%;
}
/* the two keys flanking the serving line are mirror images of each other, and
   they are red. The cut is the flyer's LEFT key, bow out to the left, so it is
   the RIGHT-hand one that gets mirrored: on the flyer both bows face OUTWARD.
   This had been flipping the first child, which turned both bows in to face the
   text - that was the wrong way round. */
.serving .keydiv:last-child { transform: scaleX(-1); }

/* ---------- PENDING-ASSET MARKERS ---------- */
.pending {
  display: inline-block;
  border: 1px dashed rgba(176,2,1,.65);
  color: var(--red);
  font-size: 12px;
  font-family: system-ui, sans-serif;
  padding: 2px 8px;
  border-radius: 3px;
  vertical-align: middle;
}

/* ============================================================
   RESPONSIVE — below the poster's own 1000px
   ============================================================
   The sheet is a 1000px poster and it has no smaller version: at
   768px the five cards collapse to 99px each and at 390px to 26px,
   while the mug overflows the masthead. So below 1000px the page
   reflows to a single column and every cut-out line falls back to
   the real text already sitting in the DOM behind it.

   Side effect, and the point of doing it this way: because the
   cut-out backgrounds are overridden here, a phone never fetches
   the 20 keyed images. It gets the paper, the headline, the
   script, the pet line, the icons and the font - about 150KB
   against the desktop's 380KB.

   Everything is inside a media query. Desktop (>=1000px) is
   byte-for-byte the poster it was.
   ============================================================ */
@media (max-width: 1019px) {
  body { background: var(--paper); }
  /* the band and its shadow are inset -4/-8 to sit ON the sheet's edge; on a
     full-bleed sheet that is 8px wider than the screen, so clip it */
  html { overflow-x: hidden; }

  .mode-paper .stage { max-width: none; }
  /* the sheet is full-bleed here: there is no page around it to cast onto, so
     the drop shadow goes and the band sits inside the screen instead of 4px
     outside it (which was 8px of horizontal scroll) */
  .mode-paper .edge-shadow { display: none; }
  .mode-paper .edge { inset: 0; border-width: 9px; filter: url(#rough-edge-sm); }
  .mode-paper .paper-bg { filter: url(#rough-paper-sm); }
  .mode-paper .poster {
    padding: 30px max(22px, env(safe-area-inset-right)) 26px max(22px, env(safe-area-inset-left));
  }

  /* the flyer's breaks are only right at the flyer's measure; the real text
     re-wraps, and every <br> now carries a space so nothing runs together */
  br { display: none; }

  /* ---- masthead ---- */
  .masthead { grid-template-columns: minmax(0, 1fr); gap: 0; }

  .brand-line1,
  .brand-line2 { line-height: 0; text-indent: -9999px; }
  .brand-line1 { width: 100%; height: auto; aspect-ratio: 897 / 124; margin: 2px 0 0; }
  .brand-line2 { width: 100%; height: auto; aspect-ratio: 880 / 133; margin: 9px 0 0; }

  .promise { font-size: 22px; line-height: 1.2; margin: 16px 0 0; }

  .lede {
    width: auto; height: auto; margin: 12px 0 0;
    background-image: none; text-indent: 0; white-space: normal;
    font-size: 17px; line-height: 1.45;
  }

  .script {
    width: 100%; height: auto; aspect-ratio: 500 / 79.8;
    margin: 20px 0 0; line-height: 0;
  }
  .pet {
    width: 84%; height: auto; aspect-ratio: 412 / 57;
    margin: 14px 0 0; line-height: 0;
  }

  /* the mug keeps the flyer's bottom-right flourish, sized to the sheet */
  .masthead-right { position: relative; height: 128px; margin-top: 14px; }
  .hero-illustration { top: auto; bottom: 0; right: 0; width: 108px; height: 127px; }
  .ic-cat-mug { filter: drop-shadow(-5px 6px 7px rgba(0,0,0,.45)); }
  .steam {
    top: 0; right: 0; height: auto; gap: 3px;
    transform: translateY(-96%) scale(.42);
    transform-origin: bottom right;
  }

  /* ---- cards: five columns become five rows ---- */
  .cards { grid-template-columns: minmax(0, 1fr); margin-top: 24px; }
  .card {
    display: grid;
    grid-template-columns: 76px minmax(0, 1fr);
    column-gap: 14px;
    row-gap: 3px;
    align-items: center;
    padding: 16px 2px;
    text-align: left;
  }
  /* the dividers were vertical rules between columns; in one column they are
     rules between rows */
  .card::after { top: auto; bottom: 0; right: 0; left: 0; width: auto; height: 1.5px; }
  .card-title { grid-column: 2; grid-row: 1; justify-self: start; font-size: 15px; padding: 4px 10px; }
  .card-icon { grid-column: 1; grid-row: 1 / span 2; height: 76px; margin: 0; }
  .card-icon .ic { width: 76px; height: 76px; }
  .card-icon .ic-bucket { width: 62px; height: 62px; }
  .spark { display: none; }
  /* same specificity as .card:nth-child(1) p, and later, so it wins */
  .card:nth-child(n) p {
    grid-column: 2; grid-row: 2;
    width: auto; height: auto; margin: 0;
    background-image: none;
    color: var(--ink);
    font-size: 15px; line-height: 1.42;
  }

  /* ---- the two shout lines, set in Oswald again ---- */
  .shout {
    width: auto; height: auto; margin: 30px 0 0;
    background-image: none; text-indent: 0; white-space: normal;
    font-family: "Oswald", Georgia, serif; font-weight: 600;
    font-size: 20px; line-height: 1.2; letter-spacing: .01em;
    text-transform: uppercase; text-align: center;
  }
  .shout-sub {
    width: auto; height: auto; margin: 12px 0 0;
    background-image: none; text-indent: 0; white-space: normal;
    font-size: 16px; line-height: 1.4; text-align: center;
  }

  .owned { font-size: 15px; margin: 20px 0 14px; }
  .owned .ic-leaf { width: 19px; height: 18px; vertical-align: -3px; margin: 0 2px; }

  /* ---- phone banner ---- */
  .phonebar {
    padding: 18px 14px 16px 46px;
    font-size: 17px; line-height: 1.45;
  }
  /* one name per line; the separator star only makes sense inline */
  .phonebar .ph { display: block; }
  .phonebar .st { display: none; }
  .phonebar-spray { width: 34px; height: 70px; left: 8px; top: -16px; }
  /* the two half-art clips are tied to the banner's height, so they move with it */
  .phonebar-spray::before { clip-path: inset(0 0 calc(100% - 21px) 0); }
  .phonebar-spray::after  { clip-path: inset(21px 0 0 0); }
  .spray-rays { left: 38px; top: -34px; width: 30px; height: 44px; }
  .phonebar .st { width: 15px; height: 15px; margin: 0 7px; vertical-align: -3px; }
  .phonebar .url { gap: 9px; margin-top: 9px; flex-wrap: wrap; }
  .url-text {
    width: auto; height: auto;
    background-image: none; text-indent: 0;
    font-size: 15px; letter-spacing: .05em;
  }
  .phonebar .url .ic-star5 { width: 15px; height: 15px; }

  /* ---- serving line ---- */
  .serving { gap: 9px; margin: 16px 0 0; }
  .serving-text {
    width: auto; height: auto;
    background-image: none;
    color: var(--ink);
    font-size: 13px; line-height: 1.45;
  }
  .keydiv { width: 46px; height: 14px; }
}

/* ---- tablet: enough room to stand the mug back up beside the masthead,
   and to run the cards two across ---- */
@media (min-width: 640px) and (max-width: 1019px) {
  .mode-paper .poster { padding: 44px 54px 38px; }

  .masthead { grid-template-columns: minmax(0, 1fr) 150px; column-gap: 26px; }
  .masthead-right { height: 0; margin: 0; }
  .hero-illustration { top: 0; bottom: auto; width: 150px; height: 176px; }
  .brand-line1, .brand-line2 { max-width: 528px; }
  .script { max-width: 500px; }

  .promise { font-size: 26px; }
  .lede { font-size: 18px; }

  .cards { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 26px; }
  .card:nth-child(n) p { font-size: 16px; }
  .card-title { font-size: 16px; }
  .card-icon, .card-icon .ic { height: 84px; }
  .card-icon .ic { width: 84px; }
  .card-icon .ic-bucket { width: 68px; height: 68px; }
  .card { grid-template-columns: 84px minmax(0, 1fr); }

  .shout { font-size: 24px; }
  .shout-sub { font-size: 17px; }
  .phonebar { font-size: 19px; }
  .serving-text { font-size: 14px; }
}
