/* ============================================================
   RIG DAWGS SUPERVISION INC — site.css
   The one shared stylesheet. Every page loads this and nothing else.
   Palette, type and devices come straight off the wolf patch.
   One small site.js for the draw popup, no framework, no build step. Dark only, on purpose.
   ============================================================ */

:root{--surface:#1A1A1D;--surface-hi:#232327;
  --ink:#0B0B0C;          /* page ground */
  --coal:#141416;         /* raised surface: cards, header, fields */
  --steel:#3A3A40;        /* every 1px line, placeholder ground */
  --slate:#8B8B93;        /* banner grey: secondary text, labels */
  --bone:#ECE8E3;         /* logo cream: primary text */
  --crimson:#BC100A;--signal:#F25555;      /* the accent, from the logo verbatim */
  --crimson-deep:#8E0C07; /* hover / pressed */
  --white:#FFFFFF;        /* text on the accent fill; his red is dark so this goes back to white */
  --display:'Big Shoulders Display',Impact,'Arial Narrow',sans-serif;
  --body:Barlow,'Helvetica Neue',Arial,sans-serif;
  --utility:'Barlow Condensed','Arial Narrow',Impact,sans-serif;
  --gutter:16px;
  --wrap:1120px;
  --edge:max(var(--gutter),calc(50% - (var(--wrap) / 2) + var(--gutter)));
  --callbar:0px;
  --ease-out:cubic-bezier(.2,.7,.2,1);
  color-scheme:dark;
}
@media (min-width:768px){ :root{ --gutter:32px; } }

/* ---------- reset ---------- */
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
html{-webkit-text-size-adjust:100%;scroll-behavior:auto;scroll-padding-top:90px}
body{background:var(--ink);color:var(--bone);font:400 15.5px/1.5 var(--body);min-height:100vh;min-height:100svh;padding-bottom:var(--callbar)}
@media (min-width:768px){ body{font-size:18px;padding-bottom:0} }
img,svg{display:block;max-width:100%;height:auto}
a{color:var(--bone);text-decoration:none;transition:color 180ms var(--ease-out),background-color 180ms var(--ease-out),border-color 180ms var(--ease-out)}
a:hover{color:var(--signal)}
button,input,select,textarea{font:inherit;color:inherit}
:focus-visible{outline:2px solid var(--crimson);outline-offset:2px}
ul,ol{list-style:none}
p{max-width:62ch;color:rgba(236,232,223,.88)}
strong{font-weight:600;color:var(--bone)}
.lead{color:var(--bone);font-weight:600;font-size:1.06em}
.wrap{width:100%;max-width:var(--wrap);margin:0 auto;padding-left:var(--gutter);padding-right:var(--gutter)}
.nowrap{white-space:nowrap}
.stack{display:grid;gap:16px}
.mt{margin-top:28px}

/* ---------- type ---------- */
h1,h2,h3,.display{font-family:var(--display);font-weight:800;text-transform:uppercase;letter-spacing:.01em;line-height:.95;color:var(--bone)}
h1{font-size:clamp(34px,6.2vw,66px);font-weight:900;line-height:.9;letter-spacing:-.018em}
h2{font-size:clamp(25px,4.1vw,42px);letter-spacing:-.014em;line-height:.98}
h3{font-size:21px;font-weight:700;line-height:1.02;letter-spacing:-.008em}
.kicker{display:block;font:600 14px/1.2 var(--utility);text-transform:uppercase;letter-spacing:.08em;color:var(--slate);margin-bottom:12px;max-width:none}
.kicker--red{color:var(--signal)}
.util{font-family:var(--body);font-weight:500;font-size:15px;line-height:1.45;text-transform:none;letter-spacing:0;color:var(--slate);max-width:none}
.caption{font:500 14px/1.4 var(--body);text-transform:none;letter-spacing:0;color:var(--slate);max-width:none}
/* .ph = an open fact Jamie still has to confirm. Visibly unfinished, never a fake value. */
.ph{display:inline-block;font:600 .92em/1.2 var(--utility);text-transform:uppercase;letter-spacing:.06em;color:var(--slate);border:1px dashed var(--slate);padding:2px 8px;vertical-align:baseline}
.prose p{margin-bottom:1em}
.prose p:last-child{margin-bottom:0}
.sig{font:600 15px/1.3 var(--utility);text-transform:uppercase;letter-spacing:.08em;color:var(--slate)}

/* ---------- buttons ---------- */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:46px;padding:0 20px;font:700 16px/1 var(--display);text-transform:uppercase;letter-spacing:.03em;border:2px solid var(--crimson);border-radius:0;background:var(--crimson);color:var(--white);cursor:pointer;white-space:nowrap;text-align:center;transition:background-color 180ms var(--ease-out),border-color 180ms var(--ease-out),color 180ms var(--ease-out),transform 180ms var(--ease-out)}
.btn:hover{background:var(--crimson-deep);border-color:var(--crimson-deep);color:var(--white)}
.btn--ghost{background:transparent;border-color:var(--bone);color:var(--bone)}
.btn--ghost:hover{background:var(--bone);border-color:var(--bone);color:var(--ink)}
.btn--sm{min-height:44px;padding:0 18px;font-size:16px}
.btn[aria-disabled="true"]{cursor:default;background:transparent;border-color:var(--steel);color:var(--slate)}
.btn-row{display:flex;flex-wrap:wrap;gap:12px}

/* ---------- header (not sticky, no JS, no hamburger) ---------- */

/* ---------- THE DRAW BAR: sits above the topbar on every page, the one thing a visitor
   sees before anything else. Crimson so it reads as an offer, not chrome. The clock is
   hidden by default and site.js only reveals it once DRAW_DATE is a real date. ---------- */
.drawbar{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:4px 12px;
  padding:9px 14px;background:var(--crimson);color:var(--white);text-align:center;
  border-bottom:1px solid var(--crimson-deep);text-decoration:none}
.drawbar__label{font:700 11px/1 var(--utility);text-transform:uppercase;letter-spacing:.2em;
  padding:3px 8px;border:1px solid rgba(255,255,255,.55)}
.drawbar__clock{font:800 17px/1 var(--display);letter-spacing:.02em;font-variant-numeric:tabular-nums;
  display:inline-flex;align-items:baseline;gap:2px;min-width:132px;justify-content:center}
.drawbar__clock[hidden]{display:none}
.drawbar__clock b{font-weight:800;display:inline-block;min-width:1.15em;text-align:center;font-variant-numeric:tabular-nums}
.drawbar__clock i{font-style:normal;font-size:.62em;opacity:.8;margin-right:5px}
.drawbar__cta{font:700 12px/1.2 var(--utility);text-transform:uppercase;letter-spacing:.1em}
/* on phones the CTA sentence forced the bar onto two lines, costing 22px of permanently
   sticky screen. Label plus clock is enough there; the sentence returns when it fits. */
@media (max-width:519px){ .drawbar__cta{display:none} .drawbar{gap:0 10px;padding:8px 12px} }
@media (hover:hover){ .drawbar:hover{background:var(--crimson-deep)} }
@media (min-width:768px){
  .drawbar{gap:6px 18px;padding:10px 20px}
  .drawbar__clock{font-size:21px}
  .drawbar__cta{font-size:13px}
}
.topbar{background:var(--coal);min-height:38px;display:flex;align-items:center;font:500 14px/1 var(--body);text-transform:none;letter-spacing:0;color:var(--slate)}
.topbar .wrap{display:flex;justify-content:space-between;align-items:center;gap:12px}
.topbar a{color:var(--slate)}
.topbar a:hover{color:var(--bone)}
.topbar__where{display:none}
@media (min-width:768px){ .topbar__where{display:block} }
.header{background:var(--coal);border-bottom:1px solid var(--steel)}
.header .wrap{display:flex;flex-wrap:wrap;align-items:center;gap:12px 26px;min-height:80px;padding-top:15px;padding-bottom:12px}
.brand{display:flex;align-items:center;gap:20px;margin-right:auto;color:var(--bone)}
.brand:hover{color:var(--bone)}
.brand__name{font:800 24px/1 var(--display);text-transform:uppercase;letter-spacing:.02em;
  transition:font-size 260ms var(--ease-out)}
/* .patch = the logo, transparent PNG, floating straight on the ink or coal. No backing box (Kage, Sept 25). */
.patch{display:block;width:78px;height:78px;flex:none;
  transition:width 260ms var(--ease-out),height 260ms var(--ease-out)}
.patch img{width:100%;height:100%;object-fit:contain}
.patch--lg{width:96px;height:96px}
.nav{display:flex;flex-wrap:nowrap;gap:0 16px;width:100%;font:600 13px/1 var(--utility);text-transform:uppercase;letter-spacing:.08em}
/* nav links were 27px tall on phones; 44px is the accepted minimum tap target */
@media (max-width:767px){ .nav a{padding:11px 0;min-height:40px;display:inline-flex;align-items:center} }
.nav a{position:relative;display:block;color:var(--slate);padding:8px 0 6px}
.nav a::after{content:"";position:absolute;left:0;right:0;bottom:0;height:2px;background:var(--crimson);transform:scaleX(0);transition:transform 260ms var(--ease-out)}
.nav a:hover{color:var(--bone)}
.nav a:hover::after{transform:scaleX(1)}
.nav a[aria-current="page"]{color:var(--bone)}
.nav a[aria-current="page"]::after{transform:scaleX(1)}
.header__call{display:inline-flex;order:1;margin-left:auto}
.brand{order:0}
@media (max-width:767px){ .nav{order:2;flex-basis:100%;margin-top:10px} }
.header__call.btn--sm{min-height:42px;padding:0 15px;font-size:15px;letter-spacing:.04em}
/* phones get the short label, the number comes back when there is room */
.header__call .full{display:none}
@media (min-width:430px){ .header__call .full{display:inline} .header__call .short{display:none} }
@media (min-width:768px){
  .header .wrap{flex-wrap:nowrap;gap:8px 52px;min-height:104px}
  .nav{width:auto;font-size:15px;gap:0 42px;margin-left:auto}
  .header__call{margin-left:14px}
  .brand{margin-right:0}
  .brand__name{font-size:22px}
}
@media (min-width:1024px){
  .header .wrap{gap:8px 40px}
  .nav{gap:0 32px;font-size:15px}
  .header__call.btn--sm{min-height:56px;padding:0 32px;font-size:19px}
}

/* ---------- mobile-only fixed call bar ---------- */
.callbar{display:none}
.callbar:hover{background:var(--crimson-deep);color:var(--white)}
@media (min-width:768px){ .callbar{display:none} }

/* ---------- bands: every section is a black band with a seam rule + crimson tick ---------- */
.band{position:relative;padding:54px 0}

.band--coal{background:var(--coal)}
.band--tight{padding:34px 0}
@media (min-width:768px){ .band{padding:88px 0} .band--tight{padding:48px 0} }
.band__head{margin-bottom:32px}
@media (min-width:768px){ .band__head{margin-bottom:40px} }
.band__head h2{margin-bottom:8px}
.band__head p:not(.kicker){margin-top:10px}

/* ---------- page head (inner pages): swallowtail ribbon h1, one per page ---------- */
.page-head{padding-top:40px;padding-bottom:24px}
.page-head p{margin-top:18px}
.ribbon{display:inline-block;padding:10px 34px;background:var(--slate);color:var(--ink);font:800 clamp(28px,5.8vw,50px)/1 var(--display);text-transform:uppercase;letter-spacing:.02em;clip-path:polygon(0 0,100% 0,calc(100% - 16px) 50%,100% 100%,0 100%,16px 50%)}
@media (min-width:768px){ .page-head{padding-top:56px;padding-bottom:24px} }

/* ---------- hero ---------- */
.hero{position:relative;min-height:56vh;min-height:56svh;display:flex;align-items:flex-end;overflow:hidden;background:var(--coal)}
.hero__img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:24% 72%;filter:saturate(.90) contrast(1.02) brightness(1.24)}
/* Lightened twice now at Kage's request. The bottom stop stays heavy enough to keep the
   headline legible; everything above it is pulled back so the photo reads. */
.hero::before{content:"";position:absolute;inset:0;z-index:1;background:linear-gradient(to top,rgba(14,18,23,.88) 0%,rgba(14,18,23,.34) 40%,rgba(14,18,23,.02) 74%,rgba(14,18,23,0) 100%)}
.hero::after{content:"";position:absolute;inset:0;z-index:1;background:none}
.hero__patch{display:none}
.hero__body{position:relative;z-index:2;width:100%;max-width:var(--wrap);margin:0 auto;padding:24px var(--gutter) 28px}
.hero .kicker{margin-bottom:14px;color:rgba(236,232,223,.82);letter-spacing:.14em;font-size:13px}
.hero h1{max-width:14ch;margin-bottom:16px}
.hero__sub{font-size:16.5px;max-width:34ch;margin-bottom:24px}
@media (max-width:599px){ .hero::before{background:linear-gradient(to top,rgba(14,18,23,.91) 0%,rgba(14,18,23,.40) 50%,rgba(14,18,23,0) 80%)} }
@media (min-width:600px){ .hero__img{object-position:62% 58%} }
@media (min-width:768px){
  .hero::after{background:linear-gradient(to right,rgba(14,18,23,.55) 0%,rgba(14,18,23,0) 60%)}
  .hero__sub{font-size:18px}
}
@media (min-width:1024px){
  /* Patch is absolute at the top, body is flex-end at the bottom. On a short window the
     body climbed into it (Kage caught this Sept 27). Reserve the patch height as padding
     so the two can never touch, whatever the window height. */
  .hero{min-height:64vh;min-height:64svh;padding-top:206px}
  .hero__body{padding:40px var(--gutter)}
  .hero__patch{display:block;position:absolute;z-index:2;top:28px;left:var(--edge);width:148px;height:148px;filter:drop-shadow(0 2px 10px rgba(14,18,23,.6))}
}
.hero-cap{padding-top:8px}

/* ---------- badges: the four facts, as sewn patches, X-sign icon from the logo ---------- */
.badges{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.badge{display:flex;align-items:center;gap:11px;min-height:80px;padding:14px 16px;background:var(--surface);border:0;border-radius:8px;font:700 16px/1.05 var(--display);text-transform:uppercase;letter-spacing:-.005em;color:var(--bone)}
.badge svg{flex:none;width:34px;height:22px}
@media (min-width:768px){
  .badges{grid-template-columns:repeat(4,1fr);gap:22px}
  .badge{gap:12px;padding:16px 18px;font-size:18px}
}

/* ---------- cards (services) ---------- */
.cards{display:grid;gap:18px}
@media (min-width:640px){ .cards{grid-template-columns:1fr 1fr} }
@media (min-width:1024px){ .cards{grid-template-columns:repeat(4,1fr);gap:26px} }
.card{display:flex;flex-direction:column;background:var(--surface);border:0;border-radius:8px;color:var(--bone);overflow:hidden;transition:transform 220ms var(--ease-out),background-color 220ms var(--ease-out)}
a.card:hover{color:var(--bone)}
@media (hover:hover){ a.card:hover{transform:translateY(-3px);background:var(--surface-hi)} }
.card__body{display:flex;flex-direction:column;gap:11px;padding:26px 24px 28px;flex:1}
.tick{display:block;width:24px;height:4px;background:var(--crimson)}
.card h3{margin-top:2px}
.card p{font-size:16px}
.card__more{margin-top:auto;padding-top:8px;font:600 13px/1 var(--utility);text-transform:uppercase;letter-spacing:.08em;color:var(--signal)}

/* ---------- split: two columns from 768 (who we are, contact) ---------- */
.split{display:grid;gap:28px;align-items:start}
.split > *{min-width:0}
@media (min-width:768px){ .split{grid-template-columns:1fr 1fr;gap:72px;align-items:center} .split--top{align-items:start} }
.split__media img{width:100%;aspect-ratio:1;object-fit:cover;object-position:50% 50%;border:0;border-radius:10px}

/* ---------- figures and photo bands ---------- */
.figure{margin:0}
.figure img{width:100%;border:0;border-radius:10px}
.figure figcaption{margin-top:8px}
.banner{aspect-ratio:3/1;overflow:hidden;border:0;border-radius:10px}
.banner img{width:100%;height:100%;object-fit:cover;object-position:60% 50%}

/* ---------- the draw: one crimson strip (the only crimson band) + the stitched block ---------- */
.strip{display:flex;align-items:center;justify-content:center;gap:10px;min-height:44px;padding:10px var(--gutter);background:var(--crimson);color:var(--white);font:600 14px/1.2 var(--utility);text-transform:uppercase;letter-spacing:.08em;text-align:center}
.strip:hover{background:var(--crimson-deep);color:var(--white)}
.draw{padding:28px 22px 32px;background:var(--surface);border:0;border-radius:10px}
.draw h2{margin-bottom:14px}
.draw p{margin-bottom:8px}
.draw .btn{margin-top:16px}
@media (min-width:768px){ .draw{padding:44px 40px 48px} }


/* ---------- THE GIVEAWAY BAND: sits directly under the hero so the draw is the first
   thing after the headline, not something you find at the bottom. The clock is driven
   by data-draw on .gw__clock; with no date set it shows dashes and says so, because a
   fake countdown on a real giveaway is worse than no countdown at all. ---------- */
.gw{background:var(--coal);border-top:3px solid var(--crimson);border-bottom:3px solid var(--crimson);padding:20px 0 22px}
.gw .wrap{text-align:center}
.gw__kicker{font:700 12px/1 var(--utility);text-transform:uppercase;letter-spacing:.2em;color:var(--signal);margin-bottom:8px}
.gw__title{font:800 clamp(23px,5.9vw,38px)/1.02 var(--display);text-transform:uppercase;letter-spacing:.01em;color:var(--bone);margin-bottom:14px}
.gw__title .ph{font-size:.5em;vertical-align:middle}
.gw__clock{display:flex;justify-content:center;gap:8px;margin-bottom:14px}
.gw__cell{flex:0 1 78px;background:var(--surface);border:0;border-radius:8px;padding:10px 4px 8px}
.gw__num{display:block;font:800 clamp(21px,5.9vw,33px)/1 var(--display);color:var(--bone);font-variant-numeric:tabular-nums;min-height:1em}
.gw__lab{display:block;margin-top:4px;font:600 10px/1 var(--utility);text-transform:uppercase;letter-spacing:.14em;color:var(--slate)}
.gw__clock.is-unset .gw__num{color:var(--steel)}
.gw__note{font:600 14px/1.3 var(--utility);text-transform:uppercase;letter-spacing:.1em;color:var(--bone);margin-bottom:14px}
.gw__unset{margin-bottom:14px}
.gw__unset[hidden]{display:none}
.gw .btn{min-height:48px}
@media (min-width:768px){
  .gw{padding:30px 0 34px}
  .gw__clock{gap:14px}
  .gw__cell{flex:0 1 116px;padding:13px 8px 10px}
  .gw__note{font-size:16px}
}

/* the popup's prize photo is what made it 69% of a phone screen */
.draw-modal__panel .kicker{font-size:10px;margin-bottom:5px}
.draw-modal__panel h2{font-size:19px;line-height:1.06;margin-bottom:7px;padding-right:34px}
.draw-modal__panel .lead{font-size:14.5px;line-height:1.4;margin-bottom:9px}
.draw-modal__panel .prize{margin:0 0 3px}
.draw-modal__panel .prize__img{max-height:96px}
.draw-modal__panel .prize__img strong{font-size:17px}
.draw-modal__panel .prize__img span{font-size:9px}
.draw-modal__panel .prize__cap{font-size:11.5px;line-height:1.35}
.draw-modal__panel .ph{font-size:.88em;padding:1px 5px}
.draw-modal__panel .btn{min-height:44px;font-size:16px;margin-top:9px}
@media (min-width:640px){
  .draw-modal__panel{padding:30px 28px 32px;max-height:86vh;max-height:86dvh}
  .draw-modal__panel .kicker{font-size:13px;margin-bottom:10px}
  .draw-modal__panel h2{font-size:27px;margin-bottom:11px}
  .draw-modal__panel .lead{font-size:17px;margin-bottom:14px}
  .draw-modal__panel .prize__img{max-height:none}
  .draw-modal__panel .prize__cap{font-size:14px}
  .draw-modal__panel .btn{min-height:50px;font-size:17px}
}


/* ---------- The popup is deliberately LIGHT in every theme. Cream card on a dark scrim
   reads as a separate moment rather than another panel of the page, and it keeps the
   contrast strong whichever colourway is running. Literal values, not tokens, so the
   Bone theme cannot invert it. ---------- */
.draw-modal__panel{background:#f4f1ea;color:#14181d;border:0;
  box-shadow:0 18px 50px rgba(0,0,0,.55)}
.draw-modal__panel .kicker{color:#A8120C}
.draw-modal__panel h2,.draw-modal__panel .lead{color:#14181d}
.draw-modal__panel .lead{opacity:.88}
.draw-modal__panel .prize__img{border-color:#b9b2a4;
  background:repeating-linear-gradient(135deg,rgba(20,24,29,.07) 0 9px,transparent 9px 18px)}
.draw-modal__panel .prize__img strong{color:#14181d}
.draw-modal__panel .prize__img span{color:rgba(20,24,29,.6)}
.draw-modal__panel .prize__cap{color:#5d6670}
.draw-modal__panel .ph{color:#5d6670;border-color:#b9b2a4}
.draw-modal__panel .draw-modal__close{color:#8b93a0}
@media (hover:hover){ .draw-modal__panel .draw-modal__close:hover{color:#A8120C} }

/* ---------- the draw popup: same stitched .draw block, as a bottom sheet on phones and a centred panel from 640. Opened by site.js. ---------- */
.draw-modal{position:fixed;inset:0;z-index:50;display:flex;align-items:center;justify-content:center;padding:26px 22px;background:rgba(14,18,23,.86);opacity:0;transition:opacity 180ms}
.draw-modal[hidden]{display:none}
.draw-modal.is-open{opacity:1}
.draw-modal__panel{position:relative;width:100%;max-width:330px;max-height:66vh;max-height:66dvh;overflow:auto;padding:15px 15px 17px;border-radius:0}
.draw-modal__panel .kicker,.draw-modal__panel h2{padding-right:44px}
/* The X reads small and quiet, but the button underneath stays 44px so it is still
   an easy tap on a phone. Shrink the glyph, never the hit area. */
.draw-modal__close{position:sticky;top:0;float:right;z-index:3;width:38px;height:34px;margin:-6px -8px 0 0;display:flex;align-items:flex-start;justify-content:flex-end;padding:2px 4px 0 0;background:transparent;border:0;color:var(--slate);font:400 19px/1 var(--body);cursor:pointer}
.draw-modal__close:hover{color:var(--signal)}
.draw-modal__panel:focus{outline:none} /* it is focused on open so the dialog reads to a screen reader, but it is not a control */
html.modal-open{overflow:hidden}
html.modal-open body{position:fixed;left:0;right:0;width:100%}
@media (min-width:640px){
  .draw-modal{padding:var(--gutter)}
  .draw-modal__panel{max-width:480px;max-height:86vh;max-height:86dvh;padding:36px 32px 40px}
}
@media (prefers-reduced-motion:reduce){ .draw-modal{transition:none} }

/* ---------- price (shop) ---------- */
.price{font:600 17px/1 var(--utility);letter-spacing:.02em;color:var(--signal)}
@media (min-width:600px){ .price{font-size:24px} }

/* ---------- shop: product cards + the Shopify slot ---------- */
/* Four equal cards. One per row on a phone, then a 2x2 that keeps them large.
   No hero card: a full-width one at the top read as odd and stretched. */
/* Shop grid. Two big tiles per row read as a "shelf" -- one hoodie was 515px wide on a
   laptop. Every colourway is its own tile now (16), so the row count carries the range
   and the tiles stay small enough to take in at a glance. */
.products{display:grid;grid-template-columns:repeat(2,1fr);gap:10px}
@media (min-width:560px){ .products{grid-template-columns:repeat(3,1fr);gap:14px} }
@media (min-width:900px){ .products{grid-template-columns:repeat(4,1fr);gap:16px} }
@media (min-width:1024px){ .products{gap:18px} }
.product{display:flex;flex-direction:column;background:transparent;border:0;border-radius:0;padding:0 0 4px;transition:transform 220ms var(--ease-out)}
@media (min-width:600px){ .product{padding-bottom:8px} }
@media (hover:hover){ .product:hover{transform:translateY(-3px)} }
/* .hatch = honest placeholder ground. Product name + PHOTO COMING, never a fake product shot. */
.hatch{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;text-align:center;padding:12px;background:var(--steel) repeating-linear-gradient(135deg,transparent 0 10px,rgba(125,139,147,.35) 10px 12px)}
.product__img{aspect-ratio:1;border-radius:8px;border:0;background:var(--surface)}
.product__img strong{font:700 clamp(14px,3.6vw,26px)/1 var(--display);text-transform:uppercase;color:var(--bone)}
.product__img span{font:600 9px/1.3 var(--utility);text-transform:uppercase;letter-spacing:.06em;color:rgba(236,232,223,.72);text-align:center;padding:0 6px}
@media (min-width:600px){ .product__img span{font-size:12px;padding:0} }
.product__body{display:flex;flex-direction:column;gap:4px;flex:1;padding:10px 2px 0}
@media (min-width:600px){ .product__body{gap:6px;padding:14px 2px 0} }
.product h3{font-size:16px;line-height:1.15}
@media (min-width:600px){ .product h3{font-size:24px} }
.sizes{font:600 13px/1.3 var(--utility);text-transform:uppercase;letter-spacing:.08em;color:var(--slate)}
.sizes--note{display:block;margin-top:5px;font-size:12px;letter-spacing:.05em;text-transform:none;color:#9b9891}
/* Big sizes cost Printful more (hoodie runs +$1.45 at 2XL to +$6.25 at 5XL, USD),
   so the surcharge is stated on the card instead of surprising anyone at checkout.
   These are RETAIL numbers, rounded up to cover the cost -- change them here and in
   the Shopify variant prices together, they are two copies of the same decision. */
.sizes--fee{display:block;margin-top:3px;font-size:11.5px;letter-spacing:.05em;text-transform:none;color:#7d7a74}
/* ---------- colour picker: real garment colours, tap to swap the photo ---------- */
/* gap must exceed the ::before overflow or the tap targets overlap and the later
   sibling steals the click -- that is the "black selects grey" bug (Kage, Sept 28).
   Rule: gap > 2 * |inset|. Here 14 > 12. */
.colours{display:flex;align-items:center;gap:14px;margin-top:10px;flex-wrap:wrap}
.sw{width:22px;height:22px;padding:0;border-radius:50%;background:var(--c);
  border:1px solid var(--steel);flex:none;cursor:pointer;position:relative;
  transition:transform 160ms var(--ease-out),border-color 160ms var(--ease-out)}
.sw::after{content:"";position:absolute;inset:-4px;border-radius:50%;border:1.5px solid transparent;
  transition:border-color 160ms var(--ease-out)}
/* invisible 44px tap target on touch -- the dot stays 22px, the finger gets the full area */
.sw::before{content:"";position:absolute;inset:-6px;border-radius:50%}
.colours--mini .sw::before{inset:-5px}
.sw.is-on{border-color:var(--bone)}
.sw.is-on::after{border-color:var(--crimson)}
.sw:focus-visible{outline:2px solid var(--signal);outline-offset:3px}
@media (hover:hover){ .sw:hover{transform:scale(1.14)} }
.colours--mini{gap:12px;padding:0 10px 11px;margin-top:2px}
.colours--mini .sw{width:18px;height:18px}
.colours--mini .sw::after{inset:-3px;border-width:1.2px}

/* ---------- the product shot: cut-out garment on a lit stage, not a white box ---------- */
/* A LIT BACKDROP, not a dark card. A cut-out black hoodie on the old near-black stage
   measured 1.00:1 against it -- the same luminance, i.e. invisible, and black is the
   colour the page opens on. The pool behind the garment is #646470 (3.1:1 vs a black
   garment, 2.7:1 vs navy); the corners stay dark so the tile still reads as the brand. */
.product__shot,.sitem__img{position:relative;display:grid;place-items:center;aspect-ratio:1;overflow:hidden}
/* Home and shop both show the concrete composites now. The slab is baked INTO the
   700x700 image, so the tile needs no background of its own -- and the photo must
   COVER the square, not letterbox inside it. */
.sitem__img{background:#1a1a1d}
.product__shot{border:1px solid var(--steel);border-radius:2px;background:#1a1a1d}
/* the accent lives in a rule that wipes in on hover, not in a wash over everything */
.product__shot::before{content:"";position:absolute;left:0;right:0;top:0;height:3px;z-index:2;
  background:var(--crimson);transform:scaleX(0);transform-origin:left;
  transition:transform 320ms var(--ease-out)}
@media (hover:hover){ .product:hover .product__shot::before{transform:scaleX(1)} }
.product__shot img,.sitem__img img{width:100%;height:100%;object-fit:cover;
  padding:0;filter:none;display:block;
  transition:transform 320ms var(--ease-out),opacity 200ms linear}
.product__shot img.is-swapping,.sitem__img img.is-swapping{opacity:.25}
@media (hover:hover){ .product:hover .product__shot img{transform:scale(1.04)} }
/* Tile text. Small tiles, so the name carries and the colour is a quiet second line. */
.products .product__body{gap:2px;padding:8px 2px 0}
.products .product h3{font-size:clamp(15px,1.5vw,18px);line-height:1}
.product__col{font:600 11.5px/1.2 var(--utility);text-transform:uppercase;letter-spacing:.07em;color:var(--slate)}
.products .price{font-size:14px}
@media (hover:hover){
  .products .product{transition:transform 220ms var(--ease-out)}
  .products .product:hover{transform:translateY(-4px)}
  .products .product:hover .product__shot{border-color:var(--crimson)}
}
.buy-slot{margin-top:auto;padding-top:18px;padding-bottom:4px}
.btn-buy{width:100%;min-height:54px;font-size:17px;padding:0 12px;white-space:normal}
.policy{display:grid;gap:8px;font-size:16px}

.urgent{padding:18px 20px;margin-bottom:26px;background:var(--coal);border:1px solid var(--steel);border-left:3px solid var(--crimson);border-radius:6px}
.urgent .util{margin-bottom:12px;color:var(--bone)}

/* ---------- forms ---------- */
.form{display:grid;gap:16px}
.field{display:grid;gap:6px}
.field label{font:600 13px/1 var(--utility);text-transform:uppercase;letter-spacing:.08em;color:var(--slate)}
.field input,.field textarea,.field select{width:100%;min-height:48px;padding:10px 12px;background:var(--coal);border:1px solid var(--steel);border-radius:0;color:var(--bone);transition:border-color 180ms var(--ease-out),background-color 180ms var(--ease-out)}
.field input::placeholder,.field textarea::placeholder{color:var(--steel)}
.field textarea{min-height:120px;resize:vertical}
.field input:focus,.field textarea:focus,.field select:focus{outline:2px solid var(--crimson);outline-offset:0;border-color:var(--crimson)}
/* Tap-to-pick answers. The radio is the real control — kept in the flow, laid over its own
   chip at zero opacity — so keyboard and screen readers get a normal radio group and the whole
   chip is the tap target. Nothing here depends on JS. */
.field--choices{border:0;padding:0;margin:0;display:grid;gap:8px}
.field--choices legend{padding:0;font:600 13px/1 var(--utility);text-transform:uppercase;letter-spacing:.08em;color:var(--slate)}
.choices{display:flex;flex-wrap:wrap;gap:10px}
.choice{position:relative;display:block}
.choice input{position:absolute;inset:0;width:100%;height:100%;min-height:0;margin:0;padding:0;border:0;opacity:0;cursor:pointer;-webkit-appearance:none;appearance:none}
.choice span{display:block;padding:14px 16px;background:var(--coal);border:1px solid var(--steel);color:var(--bone);font:600 14px/1 var(--utility);text-transform:uppercase;letter-spacing:.06em;transition:background-color 200ms var(--ease-out),border-color 200ms var(--ease-out),color 200ms var(--ease-out)}
.choice input:checked+span{background:var(--crimson);border-color:var(--crimson);color:var(--white)}
.choice input:focus-visible+span{outline:2px solid var(--bone);outline-offset:2px}
@media (hover:hover){ .choice:hover input:not(:checked)+span{border-color:var(--bone)} }
/* color-scheme makes the browser draw its own calendar button light-on-dark instead of
   invisible. The reveal is a class site.js toggles; with no JS the field just stays open. */
.field input[type="date"]{color-scheme:dark;cursor:pointer}
/* ---------- date picker (site.js datePicker) ----------
   Square corners and the brand amber, to match everything else. The native
   input stays in the form so the value and the no-JS path are unchanged. */
.dp{position:relative}
/* The native date input stays in the DOM so the form still submits a real date, but it
   must be visually hidden. `.field input` (0,1,1) was beating a bare `.dp__native` (0,1,0),
   so width:100% + min-height:48px won and the input rendered 1470px wide at left:771px --
   which pushed the contact page to 2241px and made the whole page scroll sideways.
   `.field .dp__native` (0,2,0) wins, and left/top pin it instead of its static position. */
.field .dp__native,.dp__native{position:absolute;left:0;top:0;opacity:0;pointer-events:none;
  width:1px;height:1px;min-height:0;padding:0;border:0;margin:0;clip-path:inset(50%)}
.dp__trigger{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;min-height:46px;
  padding:8px 13px;background:var(--coal);border:1px solid var(--steel);border-radius:10px;color:var(--slate);
  font:600 14px/1 var(--utility);text-transform:uppercase;letter-spacing:.06em;cursor:pointer;text-align:left;
  transition:border-color 180ms var(--ease-out),color 180ms var(--ease-out)}
.dp__trigger.is-set{color:var(--bone)}
.dp__trigger:focus-visible{outline:2px solid var(--crimson);outline-offset:0}
@media (hover:hover){ .dp__trigger:hover{border-color:var(--bone)} }
.dp.is-open .dp__trigger{border-color:var(--crimson);color:var(--bone)}
.dp__ico{width:17px;height:17px;flex:none;color:var(--crimson)}

.dp__panel{margin-top:7px;padding:10px 9px 8px;max-width:292px;background:var(--surface);border:1px solid var(--steel);border-radius:14px}
.dp__panel[hidden]{display:none}
html.js .dp.is-open .dp__panel{animation:dpIn 200ms var(--ease-out) both}
@keyframes dpIn{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:none}}

.dp__head{display:flex;align-items:center;justify-content:space-between;gap:6px;margin-bottom:7px}
.dp__month{font:800 14px/1 var(--display);text-transform:uppercase;letter-spacing:.01em;color:var(--bone)}
.dp__nav{width:30px;height:30px;display:grid;place-items:center;background:transparent;border:1px solid var(--steel);
  border-radius:8px;color:var(--bone);cursor:pointer;transition:border-color 160ms var(--ease-out),background-color 160ms var(--ease-out)}
.dp__nav svg{width:14px;height:14px}
@media (hover:hover){ .dp__nav:hover{border-color:var(--crimson);background:var(--surface-hi)} }
.dp__nav:focus-visible{outline:2px solid var(--crimson);outline-offset:1px}

.dp__dow{display:grid;grid-template-columns:repeat(7,1fr);gap:1px;margin-bottom:2px}
.dp__dow span{text-align:center;font:600 9.5px/1 var(--utility);text-transform:uppercase;letter-spacing:.06em;color:var(--slate);padding:2px 0}
.dp__grid{display:grid;grid-template-columns:repeat(7,1fr);gap:1px}
.dp__pad{display:block}
.dp__day{aspect-ratio:1;min-height:32px;display:grid;place-items:center;background:transparent;border:1px solid transparent;
  border-radius:8px;color:var(--bone);font:600 13px/1 var(--utility);cursor:pointer;
  transition:background-color 140ms var(--ease-out),border-color 140ms var(--ease-out),color 140ms var(--ease-out)}
@media (hover:hover){ .dp__day:not([disabled]):hover{background:var(--surface-hi);border-color:var(--steel)} }
.dp__day:focus-visible{outline:2px solid var(--crimson);outline-offset:-1px}
.dp__day[disabled]{color:var(--steel);cursor:default}
.dp__day.is-today{border-color:var(--steel);color:var(--signal)}
.dp__day.is-selected{background:var(--crimson);border-color:var(--crimson);color:var(--white)}

.dp__foot{display:flex;gap:14px;margin-top:7px;padding-top:7px;border-top:1px solid var(--steel)}
.dp__link{background:none;border:0;padding:3px 0;color:var(--signal);cursor:pointer;
  font:600 10.5px/1 var(--utility);text-transform:uppercase;letter-spacing:.08em}
@media (hover:hover){ .dp__link:hover{color:var(--bone)} }
.dp__link:focus-visible{outline:2px solid var(--crimson);outline-offset:2px}
@media (min-width:480px){ .dp__day{min-height:34px;font-size:13.5px} .dp__month{font-size:15px} }
.field.is-hidden{display:none}
/* The date field used to display:none / display:grid, which snapped the whole page when you
   tapped "On A Date" (Kage, Sept 27). grid-template-rows 0fr->1fr is the one way to animate
   to an auto height without JS measuring, so it now slides. With JS off it is simply open,
   which is why the closed state is scoped to html.js. */
.field--reveal{display:grid;gap:0}
.field--reveal>.field__inner{display:grid;gap:6px;min-height:0;overflow:hidden}
html.js .field--reveal{grid-template-rows:0fr;opacity:0;
  transition:grid-template-rows 300ms var(--ease-out),opacity 200ms var(--ease-out)}
html.js .field--reveal.is-open{grid-template-rows:1fr;opacity:1}
html.js .field--reveal>.field__inner{padding-top:1px}
.form .btn{justify-self:start}
.form__note{font-size:15px}

/* ---------- contact: big display links ---------- */
.biglinks{display:grid;gap:22px}
.biglink{display:block;font:800 clamp(24px,5.9vw,39px)/1 var(--display);text-transform:uppercase;color:var(--bone);overflow-wrap:anywhere}
.biglink--sm{font-size:clamp(18px,3.9vw,25px)}
.biglink small{display:block;font:600 13px/1 var(--utility);letter-spacing:.08em;color:var(--slate);margin-bottom:6px}
.biglink:hover{color:var(--signal)}

/* ---------- closing call band ---------- */
.cta-band h2{max-width:18ch;margin-bottom:20px}

/* ---------- footer ---------- */
.footer{background:var(--coal);border-top:0;padding:56px 0 40px;font-size:15px;color:var(--slate)}
.footer .wrap{display:grid;gap:24px}
@media (min-width:768px){ .footer .wrap{grid-template-columns:auto 1fr auto;align-items:start;gap:40px} }
.footer__logo{width:96px;height:96px}
.footer .footer__brand{font:800 18px/1 var(--display);text-transform:uppercase;color:var(--bone);margin-bottom:6px}
.footer .footer__tag{font:600 13px/1 var(--utility);text-transform:uppercase;letter-spacing:.08em;color:var(--signal);margin-bottom:12px}
.footer p{max-width:none;color:var(--slate)}
.footer a{color:var(--bone)}
.footer a:hover{color:var(--signal)}

/* social icons in the footer: 44px tap targets, icon inherits colour so it picks up the hover */
.social{display:flex;gap:6px;list-style:none;margin:14px 0 0;padding:0}
.social a{display:flex;align-items:center;justify-content:center;width:42px;height:42px;
  border-radius:8px;background:var(--surface);color:var(--bone);
  transition:background-color 200ms var(--ease-out),color 200ms var(--ease-out),transform 200ms var(--ease-out)}
.social svg{width:20px;height:20px;display:block}
@media (hover:hover){ .social a:hover{background:var(--crimson);color:var(--white);transform:translateY(-2px)} }
.social a:focus-visible{outline:2px solid var(--signal);outline-offset:2px}
.footer__nav{display:flex;flex-wrap:wrap;gap:8px 16px;font:600 13px/1 var(--utility);text-transform:uppercase;letter-spacing:.08em}
.footer__nav a{color:var(--slate)}
.footer__fine{margin-top:20px;font-size:13px}
/* ---------- built-by bar. Its own strip under the footer on every page. ---------- */
.madeby{background:var(--ink);border-top:1px solid var(--steel);padding:22px 0}
.madeby p{max-width:none;text-align:center;margin:0;font:600 clamp(15px,3.6vw,18px)/1.4 var(--utility);text-transform:uppercase;letter-spacing:.12em;color:var(--slate)}
.madeby a{color:var(--bone);border-bottom:2px solid var(--crimson);padding-bottom:3px}
.madeby a:hover{color:var(--signal)}

/* ============================================================
   MOTION. Every rule here hangs off html.js, which a one-line inline
   script in <head> sets before first paint. No JS: none of this applies
   and the page is plain and fully visible. Reduced motion: switched off
   at the bottom of this block. Transform and opacity only.
   ============================================================ */
:root{--ease-pop:cubic-bezier(.16,1.02,.3,1.18)}
@keyframes rise{from{opacity:0;transform:translateY(18px)}to{opacity:1;transform:none}}
@keyframes wipeUp{from{opacity:0;clip-path:inset(100% 0 0 0);transform:translateY(.28em)}to{opacity:1;clip-path:inset(-20% 0 -20% 0);transform:none}}
@keyframes stamp{0%{opacity:0;transform:scale(1.06)}70%{opacity:1;transform:scale(.985)}100%{opacity:1;transform:none}}
@keyframes kburns{from{transform:scale(1.06)}to{transform:scale(1)}}
@keyframes tickLine{to{transform:scaleX(1)}}
@keyframes introOut{to{transform:translateY(-100%);visibility:hidden}}
@keyframes ticker{to{transform:translateX(-50%)}}
@keyframes hatchDrift{to{background-position:8.5px 8.5px}}


/* ---------- hero entrance: kicker, the three lines one after another, sub, buttons. The photo eases in from a 6% crop over 14s. ---------- */
.hero h1 span{display:block}
html.js .hero .kicker{--d:.1s}
html.js .hero h1 span:nth-child(1){--d:.2s}
html.js .hero h1 span:nth-child(2){--d:.3s}
html.js .hero h1 span:nth-child(3){--d:.4s}
html.js .hero__patch{--d:.3s}
html.js .hero__sub{--d:.55s}
html.js .hero .btn-row{--d:.65s}
html.js .hero :is(.kicker,.hero__sub,.btn-row),html.js .hero__patch{animation:rise .7s var(--ease-out) both;animation-delay:var(--d,0s)}
html.js .hero h1 span{animation:wipeUp .8s var(--ease-out) both;animation-delay:var(--d,0s)}
/* Hero slideshow. Four slides stacked, cross-fading on a 24s loop, each also drifting
   in slowly so it never looks like a static photo. Pure CSS, no JS, no library.
   Slide 1 sits visible underneath at all times, so there is never a blank frame. */
.hero__img + .hero__img{opacity:0}
/* Five slides, 6s each. The percentages ARE the 6s slot: 20% of 30s. Change the
   slide count and all four numbers move -- duration, the two hold stops, and the
   last delay. Six slides would be 36s with holds at ~2%/16.7%/19%. */
@keyframes heroCycle{
  0%{opacity:0}   2.5%{opacity:1}   20%{opacity:1}   23%{opacity:0}   100%{opacity:0}
}
html.js .hero__img:nth-of-type(n+2){animation:heroCycle 30s ease-in-out infinite}
html.js .hero__img:nth-of-type(2){animation-delay:6s}
html.js .hero__img:nth-of-type(3){animation-delay:12s}
html.js .hero__img:nth-of-type(4){animation-delay:18s}
html.js .hero__img:nth-of-type(5){animation-delay:24s}
html.js .hero__img:nth-of-type(1){animation:kburns 14s ease-out both}
html.js .ribbon,html.js .page-head p{animation:rise .6s var(--ease-out) both;animation-delay:.1s}
html.js .page-head p{animation-delay:.25s}

/* ---------- scroll reveals: .rv rises as a block, .rv-stagger rises its children in turn, .rv-stamp stamps the badges. site.js adds .in. ---------- */
html.js .rv,html.js .rv-stagger>*{opacity:0;transform:translateY(16px);transition:opacity .6s var(--ease-out),transform .6s var(--ease-out)}
html.js .band.rv::before{transform:scaleX(0);transform-origin:left;transition:transform .55s var(--ease-out) .12s}
html.js .band.rv.in::before{transform:scaleX(1)}
html.js .rv.in,html.js .rv-stagger.in>*{opacity:1;transform:none}
html.js .rv-stagger.in>:nth-child(2){transition-delay:.08s}
html.js .rv-stagger.in>:nth-child(3){transition-delay:.16s}
html.js .rv-stagger.in>:nth-child(4){transition-delay:.24s}
html.js .rv-stagger.in>:nth-child(5){transition-delay:.32s}
html.js .rv-stagger.in>:nth-child(6){transition-delay:.4s}
/* The shop grid is 16 tiles, and the delays above stop at 6 -- the last ten would all
   land at once. Smaller steps so the whole wall cascades in about .6s instead. */
html.js .products.rv-stagger.in>*{transition-delay:calc(var(--i,0) * .04s)}
html.js .products.rv-stagger.in>:nth-child(1){--i:0}  html.js .products.rv-stagger.in>:nth-child(2){--i:1}
html.js .products.rv-stagger.in>:nth-child(3){--i:2}  html.js .products.rv-stagger.in>:nth-child(4){--i:3}
html.js .products.rv-stagger.in>:nth-child(5){--i:4}  html.js .products.rv-stagger.in>:nth-child(6){--i:5}
html.js .products.rv-stagger.in>:nth-child(7){--i:6}  html.js .products.rv-stagger.in>:nth-child(8){--i:7}
html.js .products.rv-stagger.in>:nth-child(9){--i:8}  html.js .products.rv-stagger.in>:nth-child(10){--i:9}
html.js .products.rv-stagger.in>:nth-child(11){--i:10} html.js .products.rv-stagger.in>:nth-child(12){--i:11}
html.js .products.rv-stagger.in>:nth-child(13){--i:12} html.js .products.rv-stagger.in>:nth-child(14){--i:13}
html.js .products.rv-stagger.in>:nth-child(15){--i:14} html.js .products.rv-stagger.in>:nth-child(16){--i:15}
html.js .rv-stamp>*{opacity:0}
html.js .rv-stamp.in>*{animation:stamp .5s var(--ease-out) both}
html.js .rv-stamp.in>:nth-child(2){animation-delay:.1s}
html.js .rv-stamp.in>:nth-child(3){animation-delay:.2s}
html.js .rv-stamp.in>:nth-child(4){animation-delay:.3s}

/* ---------- the strip runs like the LED board on a pilot truck. Pauses on hover and keyboard focus. Two identical sets, so -50% loops clean. ---------- */
.strip{overflow:hidden;justify-content:flex-start;padding-left:0;padding-right:0}
.strip__track{display:flex;width:max-content;white-space:nowrap}
.strip__set{display:inline-block}
.strip__word{display:inline-block;padding:0 1.6em}
html.js .strip__track{animation:ticker 30s linear infinite}
.strip:hover .strip__track,.strip:focus-visible .strip__track{animation-play-state:paused}

/* ---------- small stuff: buttons press, arrows nudge, cards lift, the placeholder hatch crawls so "photo coming" reads as in progress ---------- */
.btn{transition:background-color 120ms,border-color 120ms,color 120ms,transform 150ms var(--ease-out)}
.btn:not([aria-disabled="true"]):active{transform:translateY(1px)}
.card__more{display:inline-block;transition:transform 200ms var(--ease-out)}
.product{transition:border-color 120ms,transform 200ms var(--ease-out)}
@media (hover:hover){
  .btn:not([aria-disabled="true"]):hover{transform:translateY(-1px)}
  a.card:hover .card__more{transform:translateX(4px)}
  .product:hover{transform:translateY(-3px)}
}
html.js .hatch{animation:hatchDrift 3s linear infinite}

/* ---------- images settle in rather than snapping in when they decode. html.js only,
     so with no JS every picture is simply visible. site.js adds .ready on load. ---------- */
html.js :is(.figure,.split__media,.banner,.shot) img{opacity:0;transition:opacity 600ms var(--ease-out)}
html.js :is(.figure,.split__media,.banner,.shot) img.ready{opacity:1}
/* the hero is deliberately left out: its slides already own their own opacity via heroCycle */

/* ---------- work.html: the photo grid. One column on a phone, two from 640, three from 1024, with two shots running full width for rhythm. ---------- */
/* One size for every photo, no spans, no captions. Uneven tiles made the page read
   as a broken layout rather than a gallery, so the grid is deliberately uniform and the
   gaps are tight enough that nine photos read as one block of work. */
/* 2-up from the smallest screen (Kage, 30 Sept). One photo per row ate the whole
   phone screen, so six shots meant six full screens of scrolling. */
.shots{display:grid;grid-template-columns:1fr 1fr;gap:10px}
@media (min-width:640px){ .shots{gap:14px} }
@media (min-width:1024px){ .shots{grid-template-columns:repeat(3,1fr);gap:16px} }
/* Square corners. 10px rounded was the odd one out -- every other edge on this site is
   0-3px. Kage asked for sharp lines on the photos. */
.shot{margin:0;overflow:hidden;border:0;border-radius:0}
.shot img{display:block;width:100%;aspect-ratio:4/3;object-fit:cover}
/* The zoom was choppy (Kage, Sept 27): a 1200px photo re-rasterised every frame inside a
   rounded overflow clip. translateZ(0) hands it to the GPU as its own layer, so the scale
   is a compositor transform instead of a repaint. Only on pointer devices, so phones carry
   neither the layers nor the transition. */
@media (hover:hover){
  .shot{transform:translateZ(0)}
  .shot img{transform:translateZ(0);backface-visibility:hidden;transition:transform 420ms var(--ease-out)}
  .shot:hover img{transform:scale(1.045) translateZ(0)}
}

/* the best seller flag, a stamped corner tag */
.product{position:relative}
.flag{position:absolute;top:0;left:0;z-index:2;background:var(--crimson);color:var(--white);font:700 10px/1 var(--display);text-transform:uppercase;letter-spacing:.07em;padding:6px 9px;border-bottom-right-radius:6px}
@media (min-width:600px){ .flag{font-size:13px;padding:9px 14px;letter-spacing:.08em} }

/* ---------- the prize: big picture area, the thing that actually sells the draw ---------- */
.prize{margin:20px 0 4px}
.prize__img{aspect-ratio:16/10;border:2px dashed var(--slate);border-radius:0}
/* --photo = the slot now holds a real image. The dashed border is placeholder language, so it
   goes; the img covers whatever aspect-ratio the context sets (16/10, 3/2 and 16/9 all occur). */
.prize__img--photo{border:0;overflow:hidden;padding:0;background:var(--steel)}
.prize__img--photo img{display:block;width:100%;height:100%;object-fit:cover}
.prize__img strong{font:800 clamp(19px,4.2vw,28px)/1 var(--display);text-transform:uppercase;color:var(--bone)}
.prize__img span{font:600 12px/1.2 var(--utility);text-transform:uppercase;letter-spacing:.08em;color:rgba(236,232,223,.72);text-align:center}
.prize__cap{margin-top:10px;font-size:15px}
.draw-modal__panel .prize{margin:16px 0 4px}

/* Jamie offered this unprompted — "created by kage… try to help yah out get more work".
   Kage's call 3 Oct: use his name, point the link at the business, not a personal mobile.
   Deliberately quiet: it is Jamie's site, the credit earns its place by not shouting. */
.footer__credit{margin-top:6px;font:500 12px/1.4 var(--body);color:var(--slate)}
.footer__credit a{color:var(--slate);text-decoration:underline;text-underline-offset:2px}
.footer__credit a:hover,.footer__credit a:focus-visible{color:var(--bone)}

/* ===== DRAW POPUP, one screen (4 Oct 2026) ===============================
   Was a two-pane quiz: one question, then the shop CTA. Removed because the answer
   was never stored anywhere -- no backend, nothing reading it -- so it bought nothing
   and cost a tap between the prize and the only button that matters. The quiz-only
   rules (.draw__q, .draw__opts, .draw__opt, .draw__ack) went with the markup. */
.dstep[hidden]{display:none}
.draw__rule{margin:0 0 4px;font:800 clamp(17px,4vw,21px)/1.25 var(--display);
  text-transform:uppercase;letter-spacing:.01em;color:var(--bone)}
.draw__no{display:block;width:100%;margin-top:10px;padding:9px;background:transparent;
  border:0;color:var(--slate);font:600 12.5px/1 var(--body);text-decoration:underline;
  text-underline-offset:3px;cursor:pointer}
.draw__no:hover{color:var(--bone)}
/* light panel variant, matching the existing .draw-modal__panel overrides */
.draw-modal__panel .draw__rule{color:#14181d}
.draw-modal__panel .draw__no{color:#5d6670}
.draw-modal__panel .draw__no:hover{color:#14181d}
.draw-modal__panel .prize__img{aspect-ratio:16/9}

/* ---------- popup: pops in. Scale plus a small overshoot, so it lands rather than slides. ---------- */
.draw-modal{transition:opacity 220ms}
.draw-modal__panel{transform:translateY(16px) scale(.92);opacity:0;transition:transform .42s cubic-bezier(.16,1.02,.3,1.18),opacity .24s ease-out}
@media (min-width:640px){ .draw-modal__panel{transform:translateY(20px) scale(.9)} }
.draw-modal.is-open .draw-modal__panel{transform:none;opacity:1}
/* the stitched border flashes crimson as it lands */
/* This used to animate box-shadow spread 0->26px, which repaints the whole panel every
   frame (Kage: "the pop-up's bad", Sept 27). The panel scrolls, so a scaling ring inside it
   would be clipped; a border-colour flash repaints only the 2px edge instead. */
@keyframes drawFlash{0%{border-color:var(--crimson)}100%{border-color:transparent}}
html.js .draw-modal.is-open .draw-modal__panel{border:2px solid transparent;animation:drawFlash .75s ease-out .12s 1}

/* ---------- confetti: a canvas inside the modal, over the scrim but BEHIND the panel so it never sits on the words. Drawn by site.js, removed when it settles. ---------- */
.confetti{position:absolute;inset:0;z-index:1;pointer-events:none}
.draw-modal__panel{z-index:2}

/* ---------- reduced motion: all of the above, off ---------- */
@media (prefers-reduced-motion:reduce){
    html.js .rv,html.js .rv-stagger>*,html.js .rv-stamp>*{opacity:1;transform:none;transition:none;animation:none}
  html.js .hero :is(.kicker,h1 span,.hero__sub,.btn-row),html.js .hero__patch,html.js .hero__img,html.js .ribbon,html.js .page-head p,html.js .strip__track,html.js .hatch{animation:none;clip-path:none}
  /* no slideshow under reduced motion: slide one only, the rest stay hidden */
  .hero__img + .hero__img{opacity:0}
  html.js .band.rv::before{transform:none;transition:none}
  html.js .draw-modal.is-open .draw-modal__panel{animation:none}
  .confetti{display:none}
  .draw-modal,.draw-modal__panel,.btn,.card__more,.product,.card,.nav a::after,html.js .field--reveal,.dp__trigger,.dp__day,.dp__nav{transition:none}
  html.js .dp.is-open .dp__panel{animation:none}
  html.js :is(.figure,.split__media,.banner,.shot) img{opacity:1;transition:none}
  .nav a[aria-current="page"]::after{transform:scaleX(1)}
  .draw-modal__panel{transform:none}
}

/* ============================================================
   SHOPIFY BUY BUTTON — theming targets for whoever embeds it
   The embed goes inside each <div class="buy-slot" data-product="...">
   on shop.html, replacing the placeholder <span class="btn btn-buy">.
   Theme the generated button to match .btn-buy exactly:
     font-family: 'Big Shoulders Display', Impact, 'Arial Narrow', sans-serif
     font-weight: 700; font-size: 16px; text-transform: uppercase
     background: #BC100A; color: #FFFFFF; border: 2px solid #BC100A
     border-radius: 0; width: 100%; min-height: 48px
     hover: background #8E0C07, border-color #8E0C07
   Variant (size) dropdown: background #141416, color #ECE8E3,
     border 1px solid #3A3A40, radius 0, font Barlow Condensed 600 13px.
   Only one cart per page. Keep prices in the accent (#EE3B3B).
   ============================================================ */

/* ============================================================
   MOTION, SECOND PASS. Brought up to the level of the Mr Home Improvement
   build, which is the one the client said he liked, but in this brand's
   language: crimson, hard edges, beacon pulses, nothing bouncy.
   ============================================================ */

/* ---------- page transitions. The page lifts in on arrival and drops out on the
     way to the next one, so moving around the site feels continuous. ---------- */
/* The slide lives on <main>, never on <body>. A transform animation on body makes it a
   containing block and the sticky header stops sticking. Body only ever fades. */
@keyframes pageFadeIn{from{opacity:0}to{opacity:1}}
@keyframes pageFadeOut{to{opacity:0}}
@keyframes mainIn{from{transform:translateY(16px)}to{transform:none}}
@keyframes mainOut{to{transform:translateY(-10px)}}
html.js body{animation:pageFadeIn .5s var(--ease-out) both}
/* fill-mode is "backwards", NOT "both". With "both" the browser keeps applying the
   final keyframe after the animation ends, and transform:none resolves to the
   IDENTITY MATRIX rather than clearing - which still makes <main> a containing
   block for position:fixed descendants. That silently broke .stickybuy on every
   product page: it was pinned to main, not the viewport. "backwards" covers the
   pre-start frame and then gets out of the way. */
html.js main{animation:mainIn .5s var(--ease-out) backwards}
html.js body.leaving{animation:pageFadeOut .22s ease-in both}
html.js body.leaving main{animation:mainOut .22s ease-in both}

/* ---------- scroll progress. A crimson rule across the very top, filled by site.js. ---------- */
.progress{position:fixed;top:0;left:0;height:3px;width:0;z-index:60;background:var(--crimson);box-shadow:0 0 10px rgba(188,16,10,.55);pointer-events:none;transition:width 90ms linear}

/* ---------- the header tightens and darkens once you leave the top ---------- */
/* The draw bar rides along with the header. Its height is measured by site.js into
   --drawbar-h, because the clock wraps to a second line on narrow phones and a hard-coded
   offset would leave a gap or overlap. Falls back to a sane number if JS never runs. */
html.js .drawbar{position:sticky;top:0;z-index:31}
html.js .header{position:sticky;top:var(--drawbar-h,38px);z-index:30;transition:box-shadow 260ms var(--ease-out),background-color 260ms var(--ease-out)}
html.js .header .wrap{transition:min-height 260ms var(--ease-out),padding 260ms var(--ease-out)}
html.js .header.scrolled{background:rgba(14,18,23,.94);box-shadow:0 10px 30px rgba(0,0,0,.45);backdrop-filter:saturate(1.2) blur(8px)}
html.js .header.scrolled .wrap{min-height:62px;padding-top:6px;padding-bottom:6px;gap:10px 26px}
html.js .header.scrolled .header__call.btn--sm{min-height:44px;font-size:17px;padding:0 22px}
html.js .header.scrolled .patch{width:50px;height:50px}
html.js .header.scrolled .brand{gap:14px}
html.js .header.scrolled .brand__name{font-size:19px}
html.js .header.scrolled .nav{font-size:12px;gap:0 14px;margin-top:0}
html.js .header .wrap,html.js .header .brand{transition:min-height 260ms var(--ease-out),gap 260ms var(--ease-out),padding 260ms var(--ease-out)}
html.js .header .nav{transition:font-size 260ms var(--ease-out),gap 260ms var(--ease-out)}
/* Everything the .scrolled state resizes needs its own transition or the header
   SNAPS to the small size mid-scroll (Kage, Sept 29: "does like a glitch").
   .wrap/.brand/.nav had one; the logo, wordmark, cart and call button did not. */
html.js .header .patch{transition:width 260ms var(--ease-out),height 260ms var(--ease-out)}
html.js .header .brand__name{transition:font-size 260ms var(--ease-out)}
html.js .header .cartbtn{transition:width 260ms var(--ease-out),height 260ms var(--ease-out),
  border-color 200ms var(--ease-out)}
html.js .header .cartbtn svg{transition:width 260ms var(--ease-out),height 260ms var(--ease-out)}
html.js .header .header__call.btn--sm{transition:min-height 260ms var(--ease-out),
  font-size 260ms var(--ease-out),padding 260ms var(--ease-out)}
html.js .header .header__fb{transition:width 260ms var(--ease-out),height 260ms var(--ease-out),
  opacity 180ms var(--ease-out),margin 260ms var(--ease-out)}
@media(prefers-reduced-motion:reduce){
  html.js .header,html.js .header *{transition-duration:1ms !important}
}
@media(min-width:768px){ html.js .header.scrolled .nav{font-size:14px;gap:0 30px} }

/* ---------- reveals with more travel and a touch of blur, the thing that made the
     other site feel expensive. Overrides the lighter first-pass rule above. ---------- */
html.js .rv,html.js .rv-stagger>*{opacity:0;transform:translateY(38px) scale(.985);filter:blur(5px);transition:opacity .85s var(--ease-out),transform .9s var(--ease-out),filter .7s var(--ease-out)}
html.js .rv.in,html.js .rv-stagger.in>*{opacity:1;transform:none;filter:blur(0)}

/* ---------- the hero photo drifts further, so it reads as a moving picture ---------- */
@keyframes heroDrift{0%{transform:scale(1.04) translate(0,0)}100%{transform:scale(1.14) translate(-2.5%,-1.5%)}}
html.js .hero__img:nth-of-type(1){animation:kburns 14s ease-out both,heroDrift 26s ease-out both}

/* ---------- a light sweeps across a button as you hover it ---------- */
.btn{position:relative;overflow:hidden}
.btn::after{content:"";position:absolute;top:0;bottom:0;left:-60%;width:40%;background:linear-gradient(90deg,transparent,rgba(255,255,255,.28),transparent);transform:skewX(-18deg);opacity:0}
@keyframes btnShine{from{left:-60%;opacity:1}to{left:130%;opacity:0}}
@media (hover:hover){ html.js .btn:not([aria-disabled="true"]):hover::after{animation:btnShine 620ms var(--ease-out)} }

/* ---------- the phone button breathes like a beacon, because the phone is the
     whole point of the hire side ---------- */
/* Same problem, and this one ran forever: an infinite box-shadow spread on the hero's Call
   button repainted it every frame for as long as the page was open. Now it is a ring on a
   pseudo-element moving with transform + opacity only, which the compositor handles. */
@keyframes beacon{0%{transform:scale(1);opacity:.6}70%{transform:scale(1.13);opacity:0}100%{transform:scale(1.13);opacity:0}}
html.js .hero .btn-row .btn:first-child,html.js .callbar{position:relative}
html.js .hero .btn-row .btn:first-child::after,html.js .callbar::after{
  content:"";position:absolute;inset:-2px;pointer-events:none;border:2px solid var(--crimson);
  opacity:0;will-change:transform,opacity}
html.js .hero .btn-row .btn:first-child::after{animation:beacon 3.2s ease-out 2.4s infinite}
html.js .callbar::after{animation:beacon 3.2s ease-out 3s infinite}

/* ---------- section headings slide their kicker in just ahead of the heading ---------- */
html.js .rv .band__head .kicker{opacity:0;transform:translateX(-10px);transition:opacity .6s var(--ease-out) .1s,transform .6s var(--ease-out) .1s}
html.js .rv.in .band__head .kicker{opacity:1;transform:none}

@media (prefers-reduced-motion:reduce){
  html.js body,html.js body.leaving,html.js main,html.js body.leaving main{animation:none}
  .progress{display:none}
  html.js .header{position:static;transition:none}
  html.js .rv,html.js .rv-stagger>*{filter:none;transform:none;opacity:1;transition:none}
  html.js .rv .band__head .kicker{opacity:1;transform:none;transition:none}
  html.js .hero__img:nth-of-type(1),html.js .hero .btn-row .btn:first-child,html.js .callbar,
  html.js .hero .btn-row .btn:first-child::after,html.js .callbar::after{animation:none}
  html.js .hero .btn-row .btn:first-child::after,html.js .callbar::after{display:none}
  .btn::after{display:none}
}


/* ---------- STYLE SWITCHER. Only ever rendered when ?preview=1 has been used,
   so this is invisible on the client-facing site. ---------- */
#style-switch{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:5px;
  padding:8px 10px;background:#0a0c0f;border-bottom:1px solid #39404a}
#style-switch b{padding:0 7px;font:700 10px/1 var(--utility);letter-spacing:.16em;
  text-transform:uppercase;color:#7d8b93}
#style-switch a{padding:7px 12px;border-radius:999px;background:#1A1A1D;color:#ECE8E3;
  font:700 12px/1 var(--utility);letter-spacing:.07em;text-transform:uppercase;text-decoration:none}
#style-switch a.on{background:#ECE8E3;color:#0B0B0C}
@media (hover:hover){ #style-switch a:hover{background:#2a323d} #style-switch a.on:hover{background:#fff;color:#11151a} }

/* ---------- shop strip (index) — Jamie's #1: gear noticed first ---------- */
.shopstrip{background:var(--coal);border-top:2px solid var(--crimson);padding:26px 0 28px}
.shopstrip__head{display:flex;align-items:baseline;justify-content:space-between;gap:12px;margin-bottom:14px}
/* was a 61x13px tap target -- padding brings it to a thumb-sized box without moving it,
   the negative margin keeps the header row laid out exactly as before */
.shopstrip__all{font:600 13px/1 var(--utility);text-transform:uppercase;letter-spacing:.08em;
  color:var(--signal);white-space:nowrap;display:inline-flex;align-items:center;min-height:44px;
  padding:0 4px;margin:-15px -4px}
@media (hover:hover){ .shopstrip__all:hover{color:var(--bone)} }
.shopstrip__row{display:grid;grid-template-columns:repeat(2,1fr);gap:10px}
@media(min-width:720px){ .shopstrip__row{grid-template-columns:repeat(4,1fr);gap:14px} }
/* The four pieces were ~270px each inside the 1120px wrap, which read small. Let the
   strip run wider than the text column so the photos carry. Kage: "make them bigger". */
@media(min-width:1180px){ .shopstrip>.wrap{max-width:1440px} .shopstrip__row{gap:18px} }
.sitem{display:flex;flex-direction:column;background:var(--surface);border:1px solid var(--steel);
  border-radius:8px;overflow:hidden;color:var(--bone);
  transition:border-color 180ms var(--ease-out),transform 180ms var(--ease-out)}
@media (hover:hover){ .sitem:hover{border-color:var(--crimson);transform:translateY(-3px);color:var(--bone)} }
.sitem__img{border-bottom:1px solid var(--steel)}
@media (hover:hover){ .sitem:hover .sitem__img img{transform:scale(1.06)} }
.sitem__link{display:flex;flex-direction:column;color:inherit;text-decoration:none}
.sitem__name{padding:9px 10px 0;font:800 15px/1 var(--display);text-transform:uppercase;letter-spacing:-.005em}
.sitem__price{padding:4px 10px 10px;font:600 14px/1 var(--utility);color:var(--signal)}
@media(min-width:720px){ .sitem__name{font-size:17px} }

/* ---------- brand hero (index only). Jamie is far more invested in the clothing than the
   trucking, so the homepage opens on the brand, not a pilot truck. The truck photos still
   carry the Work page and the services band. ---------- */
/* photos are back but crushed almost black, with his red glowing out from behind the patch.
   When product photos arrive they swap straight into .hero__img and the treatment still works. */
.hero--brand{position:relative;display:block;background:var(--ink);min-height:auto;padding:30px 0 34px;overflow:hidden}
/* Lightened at Kage's request (twice). This is the rule that actually governs the home hero --
   the base .hero__img rule is overridden here, which is why an earlier edit to it did nothing.
   brightness .324 -> .55 and grayscale .55 -> .30 so the dusk colour and the lit rig read;
   the overlay is pulled back but the bottom stop stays heavy to keep the headline legible. */
.hero--brand .hero__img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  filter:grayscale(.30) brightness(.55) contrast(1.08)}
.hero--brand::before{content:"";position:absolute;inset:0;z-index:1;display:block;
  background:linear-gradient(to bottom,rgba(11,11,12,.72) 0%,rgba(11,11,12,.48) 45%,rgba(11,11,12,.88) 100%)}
.hero--brand::after{content:"";position:absolute;z-index:1;display:block;
  left:50%;top:clamp(80px,17vw,150px);width:min(78vw,540px);aspect-ratio:1;transform:translate(-50%,-50%);
  background:radial-gradient(circle,rgba(188,16,10,.55) 0%,rgba(188,16,10,.22) 42%,rgba(188,16,10,0) 70%);
  pointer-events:none}
.hero--brand .hero__body{position:relative;z-index:2}
.hero--brand .hero__body{padding:0 var(--gutter);text-align:center;max-width:var(--wrap);margin:0 auto}
.hero--brand .hero__patch{display:block;position:relative;left:auto;top:auto;z-index:2;width:140px;height:140px;
  margin:0 auto 18px;filter:drop-shadow(0 4px 22px rgba(0,0,0,.75))}
.hero--brand h1{max-width:none;margin:0 auto 14px;font-size:clamp(40px,10vw,84px)}
.hero--brand .hero__sub{margin:0 auto 22px;max-width:36ch}
.hero--brand .btn-row{justify-content:center;flex-wrap:wrap;gap:10px}
.hero--brand .kicker{display:block;margin-bottom:12px}
@media(min-width:1024px){
  .hero--brand{padding:46px 0 50px}
  .hero--brand .hero__patch{width:172px;height:172px;margin-bottom:22px}
}
/* the red hairline under the hero now reads as one block with the gear strip */
.hero--brand + .shopstrip{border-top-width:2px}

/* prize photo now lives inside the draw band, between WIN and the clock.
   Smaller than the old standalone band so the countdown stays the focus. */
.prize--gw{margin:14px auto 18px;max-width:440px;width:100%}
.prize--gw .prize__img{aspect-ratio:3/2;max-height:none;border-width:2px;border-radius:0}
.prize--gw .prize__img strong{font-size:clamp(16px,3.6vw,22px)}
.prize--gw .prize__img span{font-size:10.5px}
@media(min-width:768px){
  .prize--gw{max-width:520px;margin:18px auto 22px}
  .prize--gw .prize__img{max-height:250px}
}

/* WIN on its own centred line, the prize name centred beneath it */
.gw__title{text-align:center}
.gw__prizename{text-align:center;margin:0 0 4px;max-width:none}
.gw__prizename .ph{font-size:clamp(13px,3.4vw,17px)}
/* prize photo 25% bigger */
.prize--gw{max-width:550px}
.prize--gw .prize__img{max-height:none}
@media(min-width:768px){
  .prize--gw{max-width:650px}
  .prize--gw .prize__img{aspect-ratio:16/9;max-height:312px}
}

/* the draw band was half centred, half left — everything in it centres now */
.gw .wrap{text-align:center}
.gw__kicker,.gw__unset,.gw__note,.gw__prizename{text-align:center;margin-left:auto;margin-right:auto}
.gw__unset,.gw__note{max-width:none}
.gw .btn{margin-left:auto;margin-right:auto}

/* a max-height + aspect-ratio box goes narrower than its parent — auto margins or it drifts left */
.prize--gw .prize__img{margin-left:auto;margin-right:auto}
/* shop.html closing band had kicker+lead left while the button centred */
#call .wrap,.cta-band .wrap{text-align:center}
#call .wrap>*,.cta-band .wrap>*{margin-left:auto;margin-right:auto}

/* #policy on shop.html had kicker+lead left while its button centred */
#policy .wrap{text-align:center}
#policy .wrap>*,#policy .wrap p{margin-left:auto;margin-right:auto}

/* facebook in the header, beside the call button */
.header__fb{display:inline-flex;align-items:center;justify-content:center;order:1;
  width:44px;height:44px;flex:none;border:1px solid var(--steel);border-radius:8px;color:var(--slate);
  transition:color 180ms var(--ease-out),border-color 180ms var(--ease-out)}
.header__fb svg{width:21px;height:21px}
@media (hover:hover){ .header__fb:hover{color:var(--bone);border-color:var(--bone)} }
html.js .header.scrolled .header__fb{width:38px;height:38px}
html.js .header.scrolled .header__fb svg{width:18px;height:18px}
html.js .header__fb{transition:width 260ms var(--ease-out),height 260ms var(--ease-out),
  color 180ms var(--ease-out),border-color 180ms var(--ease-out)}

/* roomier desktop header */
@media(min-width:768px){
  .header .wrap{gap:8px 34px;min-height:116px;padding-top:20px;padding-bottom:18px}
  .nav{gap:0 30px;font-size:15px}
  .brand{gap:18px}
  .brand__name{white-space:nowrap}
  .patch{width:84px;height:84px}
  .brand__name{font-size:24px}
  .header__fb{width:48px;height:48px;margin-left:6px}
  .header__fb svg{width:23px;height:23px}
  html.js .header.scrolled .wrap{min-height:70px;gap:8px 40px}
  html.js .header.scrolled .patch{width:54px;height:54px}
}

/* shop cards now carry his real artwork instead of hatched placeholders */
.product__img--art{display:grid;place-items:center;background:var(--ink);border:1px solid var(--steel);
  border-radius:0;aspect-ratio:1;padding:13% 15%;overflow:hidden}
.product__img--art img{max-width:100%;max-height:100%;width:auto;height:auto;object-fit:contain;
  transition:transform 320ms var(--ease-out)}
@media (hover:hover){ .product:hover .product__img--art img{transform:scale(1.05)} }

/* ---------- shop ranges, the full kit, and the hover second shot (Sept 28) ---------- */
.band__blurb{max-width:52ch;margin-top:8px;color:var(--slate);font:400 15px/1.5 var(--body)}
/* Each tile can carry a second photo (worn or zoomed). It is swapped in on hover by
   site.js, which preloads it first so the tile never flashes empty. */
.product__shot img.is-alt{transform:scale(1.02)}
.kit{display:grid;gap:18px}
@media (min-width:860px){ .kit{grid-template-columns:1.35fr 1fr;align-items:center;gap:30px} }
.kit__row{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;list-style:none;margin:0;padding:0}
.kit__row img{width:100%;aspect-ratio:1;object-fit:cover;border:1px solid var(--steel);border-radius:2px;display:block}
.kit__body p{margin:0 0 10px}
.kit__price{font:800 34px/1 var(--display);color:var(--bone);letter-spacing:-.01em}
.kit__price s{font-size:20px;color:var(--slate);margin-left:8px;font-weight:600}
.kit__entries{font:600 13px/1.4 var(--utility);text-transform:uppercase;letter-spacing:.07em;color:var(--signal)}
.kit__entries strong{color:var(--signal)}

/* Full-bleed page banner. Contact had no photo at all above the fold -- Kage: "big nice
   photo in contact its empty". Square corners on purpose, the site has no rounded imagery. */
.pagebanner{margin:0 0 4px;position:relative;overflow:hidden;background:var(--coal);
  border-top:2px solid var(--crimson);border-bottom:1px solid var(--steel)}
.pagebanner img{display:block;width:100%;height:clamp(220px,34vw,420px);object-fit:cover;
  object-position:50% 58%;filter:saturate(.92) contrast(1.06) brightness(1.04)}

/* ===== PHONE HEADER: get the chrome out of the way =========================
   Measured before: drawbar 36 + topbar 38 + header 222 = 296px of a 812px
   screen, 36% gone before a single word of content. Jamie reviews this on a
   phone, so this is the first thing he judges.

   Three causes, all fixed here:
   1. .topbar showed ONLY the phone number on mobile (.topbar__where is already
      display:none under 768px) - sitting directly above a CALL button that is
      the same number. 38px to say a thing twice.
   2. The logo patch was 78x78 with a 24px wordmark beside it.
   3. .header__call carries margin-left:auto, which at this width computed to
      284px and threw Call onto a row of its own, pushing the nav to a third.
   ========================================================================= */
@media (max-width:767px){
  /* 1. the number is already a tap away on the Call button */
  .topbar{display:none}

  /* 2. brand down to something a phone can carry */
  .patch{width:44px;height:44px}
  .brand{gap:10px}
  .brand__name{font-size:18px}
  /* the scrolled state shrinks to 19px, which is BIGGER than the above and
     would make the header grow on scroll. Match it to the resting size. */
  html.js .header.scrolled .brand__name{font-size:18px}

  /* 3. let Call sit on the first row instead of claiming its own */
  .header__call{margin-left:0}
  .header .wrap{gap:8px 12px;min-height:0;padding-top:10px;padding-bottom:8px}
  .header__fb{width:40px;height:40px}
  /* .cartbtn sizing lives in store.css - it loads after this file */
  .header__call.btn--sm{min-height:40px;padding:0 13px;font-size:14px}

  /* nav keeps its 40px tap targets, just loses the dead space around them */
  .nav{gap:0 13px;font-size:12px}
  .nav a{padding:9px 0;min-height:38px}
}
@media (max-width:767px){ .nav{margin-top:4px} }

/* Policy links in the footer. The checklist item is that a shopper can read the
   returns policy BEFORE buying - Shopify's copies only appear at checkout. */
.footer__legal{margin:0 0 6px;font:500 14px/1.6 var(--body);color:var(--slate)}
.footer__legal a{color:var(--slate);text-decoration:underline;text-underline-offset:3px}
.footer__legal a:hover{color:var(--bone)}
.footer__legal span{opacity:.5;padding:0 4px}

/* the policies page itself */
.pol h2{font:800 clamp(26px,5vw,38px)/1 var(--display);text-transform:uppercase;margin-bottom:14px}
.pol p{max-width:68ch;margin:0 0 14px;font:400 16px/1.65 var(--body);color:var(--slate)}
.pol p strong{color:var(--bone)}
.pol a{color:var(--signal);text-decoration:underline;text-underline-offset:3px}
.pol a:hover{color:var(--bone)}
/* anchor links from the footer must not land under the sticky header */
.pol{scroll-margin-top:170px}

/* Quote form: the "did your email not open?" fallback. mailto is a request to the
   visitor's own device, so on a phone with no mail account it does nothing and the
   lead vanishes. This puts the composed message on screen with a text/copy route. */
.fallback[hidden]{display:none}
.fallback{margin-top:18px;padding:16px;background:var(--coal);border:1px solid var(--crimson)}
.fallback__h{margin:0 0 4px;font:800 20px/1.1 var(--display);text-transform:uppercase;color:var(--bone)}
.fallback__p{margin:0 0 12px;font:400 14px/1.5 var(--body);color:var(--slate)}
.fallback__box{margin:0 0 14px;padding:12px;background:var(--ink);border:1px solid var(--steel);
  color:var(--bone);font:400 13px/1.55 ui-monospace,SFMono-Regular,Menlo,monospace;
  white-space:pre-wrap;word-break:break-word;max-height:240px;overflow:auto}
.fallback__row{display:flex;flex-wrap:wrap;gap:8px}
.field__opt{font:500 12px/1 var(--utility);text-transform:uppercase;letter-spacing:.06em;
  color:var(--slate);margin-left:6px}

/* ===== BUILT BY KAGE: the small web-dev enquiry block on contact.html ======================
   Everything here is tuned DOWN. Jamie's quote form owns that page -- this one has to be
   findable without competing, so: narrower column, smaller type, a hairline box instead of a
   filled card, and btn--sm so the only crimson in here is a button half the size of Jamie's.
   If it ever reads as loud as the form above it, the balance is wrong, not the copy. */
.bf__box{max-width:620px;border:1px solid var(--steel);padding:22px}
.bf__kicker{font:600 12px/1.2 var(--utility);text-transform:uppercase;letter-spacing:.14em;
  color:var(--slate);margin:0 0 8px}
.bf__lead{font-family:var(--body);font-size:15px;line-height:1.5;color:var(--bone);
  margin:0 0 18px;max-width:52ch}
.bf__form{display:grid;gap:12px}
/* Name and phone sit together from 520px. Below that they stack -- two 48px inputs side by
   side on a phone leaves neither one wide enough to read what you typed. */
.bf__row{display:grid;gap:12px}
@media (min-width:520px){.bf__row{grid-template-columns:1fr 1fr}}
.bf__form .field label{font-size:12px;letter-spacing:.1em}
.bf__form .field input,.bf__form .field textarea{min-height:44px;font-size:15px}
.bf__form .field textarea{min-height:66px}
.bf__foot{display:flex;flex-wrap:wrap;align-items:center;gap:12px 16px;margin-top:4px}
.bf__note{font-family:var(--body);font-size:13px;line-height:1.4;color:var(--slate);margin:0}
/* Honeypot. Off-screen rather than display:none -- a bot that respects display:none skips it,
   which is the opposite of what a trap is for. */
.bf__trap{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
.bf__msg{font-family:var(--body);font-size:14px;line-height:1.45;margin:4px 0 0;
  padding:10px 12px;border:1px solid var(--steel);background:var(--coal);color:var(--bone)}
.bf__msg--bad{border-color:var(--signal);color:var(--signal)}
.bf__form.is-sending{opacity:.6;pointer-events:none}
/* ⛔ The browser's own [hidden]{display:none} is a UA rule, so ANY author display wins over it
   -- .field{display:grid} and .bf__foot{display:flex} both do. Without this the send succeeds,
   the thank-you prints, and the filled-in boxes just sit there looking like nothing happened.
   Scoped to this form and specific enough (0,2,0) to beat .field without !important. */
.bf__form [hidden]{display:none}
