/* ============================================================
   African print backdrop.

   Lays the cream .frame card on a printed cloth: the print fills
   the body, and .shell's own cream fill is cleared so it shows
   through the gutter around the card and across the field beyond
   1200px on wide screens.

   Desktop and large tablet only. Below 1000px styles.css sets
   .shell{padding:0} and strips the frame's radius and shadow, so
   the card runs edge to edge and there is no gutter for a print
   to sit in.

   That scoping used to double as the reason a 360px Android never
   fetched this tile at all, since a background-image in an
   unmatched media query is never requested. That is no longer
   true: print.css uses the same file for accents that DO apply on
   mobile, so a phone now pulls it regardless. Which is why the
   tile was cut to 360px / 62KB — the weight is a phone's problem
   now, not just a desktop's.

   The tile is mirror-tiled (2x2: original, h-flip, v-flip, both)
   because the source scan does not wrap: its opposite edges differ
   as much as two unrelated interior columns, so a plain repeat
   drew hard grid lines down the gutter. Mirroring makes every
   outer edge identical to its opposite by construction.

   Nothing here changes markup, layout or the approved palette —
   it only paints the area outside the card. See CLAUDE.md Rule 1.
   ============================================================ */

@media (min-width:1001px){
  body{
    /* Sits under the tile so the gutter is never bare cream while
       the image loads, and stays correct if it fails outright. */
    background-color:var(--wine-deep);

    /* Wine wash over the print. The scan is high-saturation orange
       and red; at full strength it pulls the eye off the product
       photography and the wine/gold type. */
    /* The 360px derivative, not the 1024px master: 62KB instead of 205KB.
       It renders at 220px CSS below, so a 2x screen wants 440 and this is a
       1.2x upscale — imperceptible under the 66% wash above, which is the
       only reason a tile this small is enough. print.css uses the same file
       for its in-page accents, so the whole site pulls one orange tile
       rather than two, and a 360px phone pays 62KB for it rather than 109.
       The 1024px master stays on disk as the source it is generated from. */
    background-image:
      linear-gradient(rgba(42,16,20,.66),rgba(42,16,20,.66)),
      url("../img/brand/african-print-360.webp");
    background-repeat:repeat,repeat;
    background-position:center,center;
    /* Small repeat. The band is only 20px wide, so the 640px tile the
       first version used showed one meaningless sliver of a motif down
       the entire edge. At 220px the motifs are small enough that a
       20px slot still crosses recognisable pattern. */
    background-size:auto,220px 220px;

    /* Pinned to the viewport, so the card slides over stationary cloth
       instead of carrying it along. Owner's call, reversing the note that
       stood here — which argued the card "lies on the cloth, so the two
       should travel together". The bolt now reads as the fixed thing and
       the card as the thing moving across it.

       Both layers, not just the tile. The wash is a two-stop gradient of
       one colour, so it renders identically either way; pinning it too
       keeps the two layers in one coordinate space rather than leaving a
       reader to work out why they differ.

       html carries only scroll-behavior (styles.css:25) and no background,
       so this rule propagates to the canvas and anchors to the viewport —
       the tile keeps painting past the end of a short page.

       Two costs the old note was right about, both accepted:

       1. A fullPage screenshot paints one viewport of a fixed background
          and leaves the rest of the band bare, so the desktop baselines
          record something no visitor sees. Diffs still work — the artifact
          is deterministic — but the PNGs stop being an honest record.
          visual-baseline.mjs:99 is the fullPage:true this refers to.
       2. It repaints the background every scroll frame. One 220px tile
          under a flat wash, no blur or filter, so it composites cheaply,
          but it is not free the way `scroll` was. */
    background-attachment:fixed,fixed;
  }

  /* Overrides styles.css:47 (`width:1200px; padding:34px 40px 56px;
     background:var(--page)`) — the owner's own change, restored.

     The print is loud. Held back at 1200px it becomes a wide field either
     side of the card that competes with the product photography; pulled to
     the edge it reads as a decorative border, which is the intent.

     background — the cream fill is the only reason body is invisible.
     width      — card tracks the viewport so the print frames it.
     padding    — this IS the visible band, and one value keeps it even on
                  all four edges rather than 34 top / 40 side / 56 bottom.

     This is a deliberate Rule 1 departure, made by the owner. The visual
     baseline is re-captured to match rather than treated as drift. */
  .shell{
    background:transparent;
    width:auto;
    /* Capped rather than unbounded. Unbounded, the print collapsed to a 20px
       sliver on a wide monitor — it read as a mistake, not a border — and it
       let the hero's image column grow without limit, which is what cropped
       the photography (see below). At 1320 the band is ~300px each side at
       1920 and ~60px at 1440: a border, deliberately. styles.css:47 already
       sets margin:0 auto, so capping re-centres the card for free. */
    max-width:1320px;

    /* Scales instead of sitting at a flat 20px. Below the 1320 cap the card
       is as wide as the viewport allows, so a fixed 20px was the entire band
       — at 1024 that is a sliver, and a sliver reads as a mistake rather than
       a border, which is the same complaint that started this work. Above the
       cap the band grows on its own as the card stops widening, so the clamp
       only has to do the work in the 1001-1320 stretch. 40px is the ceiling:
       past that it takes width from the content without looking any more
       deliberate. */
    padding:clamp(20px,2.6vw,40px);
  }

  /* ---- keep photography framed as approved, at every width ----

     These two panels sit in `grid-template-columns:1fr 1fr`, so their width
     tracks the card. Both were given a FIXED height back when the card was
     pinned to 1200px (.hero-img min-height:560px at styles.css:109,
     .bespoke-img min-height:360px at :217), and both fill with
     `object-fit:cover`. A constant height under a growing width means the
     crop deepens as the screen widens — the wider the monitor, the more of
     the garment is cut away.

     The hero photos are 900x1125 (4:5) and no object-position is set
     anywhere, so the loss is split evenly top and bottom: at 1920 the
     full-bleed card cropped 52% of each photo, taking 26% off the model's
     head and 26% off her feet.

     Pinning the RATIO instead of the height makes the crop constant at every
     viewport, so this cannot regress with screen size again.

     Both are 4/5, because that is what the photographs actually are — the
     hero set is 900x1125 and the bespoke shot is 760x950. Matching the box
     to the source means object-fit:cover has nothing left to trim, so the
     whole garment is in frame at every width.

     This is also what mobile has always done: styles.css:561 already sets
     .hero-img{aspect-ratio:4/5}. Desktop was the odd one out.

     Earlier revisions of this file used 1/1 for the hero and 560/360 for the
     bespoke panel, reproducing the boxes the old fixed heights resolved to at
     the 1200px cap. Both cropped — 20% off the hero, 49% off the bespoke shot,
     which took the model's head. Reproducing an accidental crop faithfully is
     still a crop; the ratio now follows the photography instead.

     560/360 had a second failure worth recording: it is wider than the copy
     column beside it is tall, so the image could not fill its own grid row
     and sat above a band of dead cream. At 4/5 the image is the taller item,
     so it sets the row height and the panel closes up.

     min-height is zeroed so the ratio, not the old fixed height, decides.

     .ch-img is deliberately left alone: it holds "photography pending"
     placeholders on gradients (story.html:41, 78, 137), so there is nothing
     to crop. It will need the same treatment when real portraits land.

     Mobile is untouched — styles.css:561 and :586 already do exactly this
     with aspect-ratio, and this whole file is scoped to min-width:1001px.

     min-width:0 is load-bearing, not tidiness. A grid item's automatic
     minimum size is derived from its aspect-ratio and the row's height, and
     `1fr` is really `minmax(auto, 1fr)` — so an item with a ratio can demand
     more than its fair share and widen the whole track. .bespoke-img hit this
     exactly: the copy column beside it is 543px tall, so at 560/360 the image
     claimed 543 x 1.5556 = 845px and broke the 1fr/1fr split, identically at
     every viewport because the driver is the text height, not the card.
     min-width:0 lets the track fall back to its share, and the ratio then
     sets height from width, which is the direction we want. */
  .hero-img{aspect-ratio:4/5;min-height:0;min-width:0}
  .bespoke-img{aspect-ratio:4/5;min-height:0;min-width:0}

  /* The image column is now the taller of the two, so the copy beside it has
     room to spare. Centring it keeps the text optically level with the
     garment instead of stranded against the top edge with a long drop below.
     .bespoke-copy and .ch-copy already do exactly this (styles.css:219, 482);
     .hero-copy never needed it while the hero was short. .rail inside it is
     absolutely positioned and is unaffected. */
  .hero-copy{display:flex;flex-direction:column;justify-content:center}
}

/* ---- the same backdrop, still, for anyone who asked for still ----

   A pinned background is background motion: nothing animates, but the cloth
   moves against the card at scroll speed, and that kind of uncommanded
   parallax drift is a common vestibular trigger. The stated goal above is
   for it to "feel animated", which is precisely why it needs an opt-out.

   `scroll` is a complete fallback rather than a degraded one — it is the
   card-on-cloth behaviour this file shipped with, so a visitor with the
   preference set gets the previous design intact, not a broken version of
   the new one.

   Written as one combined query rather than nested inside the block above
   so it reads at a glance which two conditions have to hold. Same
   specificity, declared later, so it wins.

   styles.css:657 kills animation and transition globally under this
   preference, but background-attachment is neither, so it is untouched
   there and has to be handled here. */
@media (min-width:1001px) and (prefers-reduced-motion:reduce){
  body{background-attachment:scroll,scroll}
}

/* ---- the same photograph, uncropped on a phone ----

   Everything above is desktop. This one rule is not, because the crop it
   fixes is mobile-only: styles.css:586 gives .bespoke-img aspect-ratio:16/10
   below 1000px, and the shot behind it (760x950) is portrait. A landscape box
   on a portrait photo threw away half the garment and took the model's head,
   measured at 50.1% visible on a 390px screen.

   4/5 is the file's own ratio, so nothing is trimmed. It also matches what
   the rest of the mobile layout already does — .hero-img at styles.css:561
   and .ch-img at :621 are both 4/5 — so the bespoke panel was the single
   exception rather than the rule. */
@media (max-width:1000px){
  .bespoke-img{aspect-ratio:4/5}
}
