/* One stylesheet for every brand on this engine. Mobile first, no
   framework, no build step.

   The palette and the product-shot blend mode arrive as custom properties
   from brand.json (see `theme` there and the inline <style> in base.html),
   so a new brand needs no CSS of its own. --red/--red-dark are kept as
   aliases because a lot of rules below were written against them. */
:root{
  --ink:#14171a; --ink-2:#3c444d; --muted:#6b747d;
  --paper:#ffffff; --paper-2:#f4f5f6; --line:#e2e5e8;
  --accent:#c8102e; --accent-dark:#9c0c23; --sea:#0e5a7a;
  --red:var(--accent); --red-dark:var(--accent-dark);
  /* multiply suits a cut-out product shot on an alpha background (Halco's
     whole catalogue); normal suits a photographed rod on white. */
  --shot-blend:multiply;
  /* Header logo height. A landscape lockup reads fine at 48px; a portrait
     one (Assassin's wordmark arcs over a caster) would be 29px wide there
     and unreadable, so the brand sets its own. */
  --logo-h:38px; --logo-h-wide:48px; --logo-h-foot:38px;
  /* The footer is dark and most marks are one-colour artwork with no
     reversed version, so they sit on a white chip. A disc-shaped mark
     brings its own and turns these off. */
  --foot-chip:#fff; --foot-chip-pad:8px 12px;
  --radius:10px; --wrap:1180px;
  --shadow:0 1px 2px rgba(20,23,26,.06), 0 6px 18px rgba(20,23,26,.06);
}
*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0; background:var(--paper); color:var(--ink);
  font:16px/1.55 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
}
img{max-width:100%; height:auto; display:block}
a{color:inherit}
h1,h2,h3{line-height:1.2; margin:0 0 .5rem}
h1{font-size:1.75rem; letter-spacing:-.02em}
h2{font-size:1.25rem}
p{margin:0 0 1rem}
.wrap{max-width:var(--wrap); margin:0 auto; padding:0 16px}
.muted{color:var(--muted)}
.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.skip{position:absolute;left:-9999px}
.skip:focus{left:8px;top:8px;background:#fff;padding:8px;z-index:99}

/* header — white, because Halco's mark is a red wordmark over a NAVY fish
   and there is no reversed version; on the old charcoal bar the fish
   disappeared. See static/ASSETS.md. */
.site-head{position:sticky;top:0;z-index:20;background:#fff;color:var(--ink);
  border-bottom:1px solid var(--line)}
.head-row{display:flex;align-items:center;gap:12px;min-height:64px;flex-wrap:wrap}
.brand{display:flex;align-items:center;gap:10px;text-decoration:none;min-width:0;
  flex-wrap:nowrap}
/* Capped, never scaled up: the source file is 448px wide and without a cap
   the header logo renders at its intrinsic size. */
.brand-logo{height:var(--logo-h);width:auto;flex:none}
.brand-nz{font-size:.72rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase;
  color:var(--muted);border-left:1px solid var(--line);padding-left:10px;white-space:nowrap}
.menu-btn{margin-left:auto;background:none;border:1px solid var(--line);border-radius:8px;
  width:42px;height:36px;display:grid;place-items:center;cursor:pointer}
.bars,.bars::before,.bars::after{display:block;width:18px;height:2px;background:var(--ink);content:""}
.bars{position:relative}
.bars::before{position:absolute;top:-6px}
.bars::after{position:absolute;top:6px}
.nav{display:none;width:100%;padding-bottom:10px}
.nav.open{display:block}
.nav > ul{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:2px}
.nav a{display:block;padding:10px 8px;color:var(--ink-2);text-decoration:none;border-radius:8px;font-weight:600}
.nav a:hover{background:var(--paper-2);color:var(--ink)}
.nav a.cta{background:var(--red);color:#fff;margin-top:6px;text-align:center}
.nav a.cta:hover{background:var(--red-dark);color:#fff}
@media (min-width:560px){.brand-logo{height:var(--logo-h-wide)}}
@media (min-width:900px){
  .menu-btn{display:none}
  .nav{display:block;width:auto;margin-left:auto;padding:0}
  .nav > ul{flex-direction:row;align-items:center;gap:4px}
  .nav a{padding:8px 12px}
  .nav a.cta{margin:0}
}

/* hero — a real photograph beside the copy, not a gradient */
.hero{background:var(--paper-2);border-bottom:1px solid var(--line);padding:28px 0 0}
.hero-grid{display:grid;gap:22px;align-items:center}
.hero h1{font-size:2rem;max-width:16ch}
.hero p{max-width:52ch;color:var(--ink-2);font-size:1.05rem}
.hero .btns{display:flex;gap:10px;flex-wrap:wrap;margin-top:18px}
.hero-shot{margin:0 -16px}
.hero-shot img{width:100%;height:auto;display:block;aspect-ratio:3/2;object-fit:cover}
@media (min-width:860px){
  .hero{padding:0}
  .hero-grid{grid-template-columns:1fr 1fr;gap:40px;min-height:420px}
  .hero-copy{padding:56px 0}
  .hero h1{font-size:2.9rem}
  .hero-shot{margin:0;height:100%}
  .hero-shot img{height:100%;aspect-ratio:auto;border-radius:0}
}
.hero .btn.ghost{border-color:var(--line);color:var(--ink)}
.hero .btn.ghost:hover{background:#fff}

.btn{display:inline-block;padding:11px 18px;border-radius:8px;text-decoration:none;font-weight:700;
  background:var(--red);color:#fff;border:1px solid transparent}
.btn:hover{background:var(--red-dark)}
.btn.ghost{background:transparent;border-color:#4a5761;color:#fff}
.btn.ghost:hover{background:rgba(255,255,255,.08)}
.btn.small{padding:8px 13px;font-size:.9rem}

section{padding:34px 0}
.section-head{display:flex;align-items:baseline;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-bottom:14px}
.section-head p{margin:0}

/* Ranges are the structure of a category page: page-title size, a clear gap
   above so each reads as a section break, and a rule under the heading
   separating it from its cards. Deliberately not styled as a link — the
   chip strip at the top of the page is what navigates. */
.home-section{margin-top:48px}
.home-section:last-of-type{margin-bottom:8px}
@media (min-width:760px){.home-section{margin-top:64px}}
.section-head.stacked{display:block;margin-bottom:18px;padding-bottom:12px;
  border-bottom:1px solid var(--line)}
.section-head.stacked p{margin:4px 0 0;font-size:.95rem}

.range-section{padding:0 0 10px}
.range-section .section-head{margin:0 0 18px;padding:0 0 12px;
  border-bottom:1px solid var(--line);align-items:flex-end}
.range-section{margin-top:48px}
.range-section:first-of-type{margin-top:16px}
.range-title{font-size:1.75rem;letter-spacing:-.02em;line-height:1.2;margin:0;
  text-decoration:none}
.range-title,.range-title a{color:var(--ink);text-decoration:none}
.range-title a:hover{text-decoration:none}
.range-more{font-size:.88rem;font-weight:600;white-space:nowrap}
.range-more a{color:var(--ink-2);text-decoration:none;border-bottom:1px solid var(--line)}
.range-more a:hover{color:var(--red);border-color:var(--red)}
@media (min-width:760px){
  .range-title{font-size:2rem}
  .range-section{margin-top:64px}
}

/* grids */
.grid{display:grid;gap:14px;grid-template-columns:repeat(2,1fr)}
@media (min-width:640px){.grid{grid-template-columns:repeat(3,1fr)}}
@media (min-width:1000px){.grid{grid-template-columns:repeat(4,1fr)}}
.grid.wide{grid-template-columns:1fr}
@media (min-width:640px){.grid.wide{grid-template-columns:repeat(2,1fr)}}
@media (min-width:1000px){.grid.wide{grid-template-columns:repeat(3,1fr)}}

.card{background:var(--paper);border:1px solid var(--line);border-radius:var(--radius);
  overflow:hidden;display:flex;flex-direction:column;text-decoration:none;box-shadow:var(--shadow)}
.card:hover{border-color:#c8ced4}
/* The image box is a FIXED FRAME and every product shot sits inside it,
   whatever shape the file is. `aspect-ratio` alone did not do that: the box
   is a grid container, a grid item's automatic minimum size is its content,
   and `height:100%` on the image resolves against an indefinite height and
   falls back to the file's intrinsic one — so a portrait shot pushed the row
   taller and `aspect-ratio`, which only sets a PREFERRED size, gave way.
   Hayabusa made it obvious: a 1/1 box measured 275x497 on the Float Rig and
   275x275 on the Snapper Adjustable Rig beside it, and the cards in a row
   came out different heights. `min-height:0` lets the item shrink below its
   content, which is what holds the ratio; `overflow:hidden` is the backstop.
   Nothing here crops — `object-fit:contain` still letterboxes the whole
   image inside the frame. */
.card .shot{aspect-ratio:1/1;background:var(--paper-2);display:grid;place-items:center;
  padding:8px;overflow:hidden}
.card .shot img{width:100%;height:100%;min-width:0;min-height:0;
  object-fit:contain;mix-blend-mode:var(--shot-blend)}
.card .body{padding:10px 12px 12px;display:flex;flex-direction:column;gap:4px;flex:1}
.card .name{font-weight:700;font-size:.98rem;line-height:1.25}
.card .meta{font-size:.82rem;color:var(--muted)}
.card .rrp{font-weight:700;font-size:.95rem;margin-top:auto}

.grid.tiles{grid-template-columns:repeat(2,1fr)}
@media (min-width:700px){.grid.tiles{grid-template-columns:repeat(3,1fr)}}
@media (min-width:1000px){.grid.tiles{grid-template-columns:repeat(5,1fr)}}
.cat-tile .name{font-size:1.02rem}
.cat-tile .shot{aspect-ratio:4/3}

/* badges */
.badge{display:inline-flex;align-items:center;gap:5px;font-size:.74rem;font-weight:700;
  letter-spacing:.03em;text-transform:uppercase;padding:3px 8px;border-radius:99px}
.badge.nz{background:#e7f4ea;color:#1c6b34;border:1px solid #bfe3c9}
.badge.na{background:var(--paper-2);color:var(--muted);border:1px solid var(--line)}

/* breadcrumbs + filter bar */
.crumbs{font-size:.85rem;color:var(--muted);padding:14px 0 0}
.crumbs a{text-decoration:none}
.crumbs a:hover{text-decoration:underline}
.filters{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin:12px 0 4px}
.chip{display:inline-block;padding:7px 13px;border:1px solid var(--line);border-radius:99px;
  text-decoration:none;font-size:.88rem;font-weight:600;background:#fff}
.chip.on{background:var(--ink);color:#fff;border-color:var(--ink)}

/* range strip */
.strip{display:flex;gap:8px;overflow-x:auto;padding:4px 0 10px;-webkit-overflow-scrolling:touch}
/* The region pills WRAP rather than scroll: a horizontal scroller hides
   half the regions behind a gesture nobody is told about, and on a desktop
   it draws a scrollbar under the row. Scoped to `.regions` so the category
   page's range strip — a short list where scrolling is fine — is untouched. */
.strip.regions{flex-wrap:wrap;overflow-x:visible;row-gap:8px}
/* Below this width the pills wrap to four or five rows and push the first
   shop off the screen, so a select does the same job in one line. Exactly
   one of the two is ever in the document flow. */
.region-jump{display:block;padding:4px 0 12px}
.region-jump select{width:100%;padding:10px 12px;font:inherit;font-size:.95rem;
  color:var(--ink);background:#fff;border:1px solid var(--line);
  border-radius:10px;-webkit-appearance:menulist}
@media (min-width:640px){
  .region-jump{display:none}
}
@media (max-width:639px){
  .strip.regions{display:none}
}
.strip a{white-space:nowrap;padding:7px 13px;border:1px solid var(--line);border-radius:99px;
  text-decoration:none;font-size:.88rem;font-weight:600;background:#fff}
.strip a:hover{border-color:var(--ink)}

/* product page */
.pdp{display:grid;gap:22px;padding-top:8px}
@media (min-width:900px){.pdp{grid-template-columns:1.1fr .9fr;gap:38px;align-items:start}}
.gallery .main{background:var(--paper-2);border-radius:var(--radius);aspect-ratio:1/1;
  display:grid;place-items:center;padding:14px;border:1px solid var(--line)}
.gallery .main img{width:100%;height:100%;object-fit:contain;mix-blend-mode:var(--shot-blend)}
.thumbs{display:grid;grid-template-columns:repeat(5,1fr);gap:8px;margin-top:8px}
@media (min-width:640px){.thumbs{grid-template-columns:repeat(8,1fr)}}
.thumbs button{padding:4px;background:var(--paper-2);border:1px solid var(--line);border-radius:8px;cursor:pointer;aspect-ratio:1/1}
.thumbs button[aria-current="true"]{border-color:var(--ink)}
.thumbs img{width:100%;height:100%;object-fit:contain;mix-blend-mode:var(--shot-blend)}

.pricebox{border:1px solid var(--line);border-radius:var(--radius);padding:14px;background:var(--paper-2);margin:14px 0}
.pricebox .amount{font-size:1.5rem;font-weight:800}
.pricebox .label{font-size:.8rem;text-transform:uppercase;letter-spacing:.05em;color:var(--muted);font-weight:700}

.colours{list-style:none;margin:0;padding:0;display:grid;gap:6px;grid-template-columns:1fr}
@media (min-width:480px){.colours{grid-template-columns:1fr 1fr}}
.colours li{display:block}
.colour{width:100%;display:flex;justify-content:flex-start;gap:9px;align-items:center;
  border:1px solid var(--line);border-radius:8px;padding:8px 10px;font-size:.9rem;
  background:#fff;cursor:pointer;text-align:left;font:inherit;font-size:.9rem;color:inherit}
.colour:hover{border-color:var(--ink-2)}
.colour[aria-current="true"]{border-color:var(--ink);box-shadow:inset 0 0 0 1px var(--ink)}
.colour.nz{border-color:#bfe3c9;background:#f6fbf7}
.colour.nz[aria-current="true"]{border-color:#2c8a4b;box-shadow:inset 0 0 0 1px #2c8a4b}
.colour .dot{width:8px;height:8px;border-radius:99px;background:#c9ced3;flex:none}
.colour.nz .dot{background:#2c8a4b}
.colour .cname{flex:1}
.colour .cprice{color:var(--muted);font-variant-numeric:tabular-nums}
.more-colours{margin-top:12px}
.more-colours summary{cursor:pointer;font-size:.88rem;color:var(--muted);padding:6px 0}
.more-colours summary:hover{color:var(--ink)}
.more-colours .colours{margin-top:8px}

.rte{max-width:68ch}
.rte img{border-radius:8px;margin:12px 0}
.rte h2,.rte h3{margin-top:1.2em}

.panel{background:var(--paper-2);border:1px solid var(--line);border-radius:var(--radius);padding:16px}
/* `section{padding:34px 0}` never reaches a `<section class="wrap">`: the
   class selector wins and its `padding:0 16px` zeroes the vertical padding,
   so the In-store heading sat flush against the Online cards — a measured
   0px, against 16px between the intro and "Online". Other pages space their
   sections with their own classes (.home-section, .range-section); this page
   had none. 1rem is exactly the gap it is matching: a paragraph's bottom
   margin, which is what separates the intro from "Online". */
.wtb-section{margin-top:1rem}

.stockist{display:flex;flex-direction:column;gap:6px;border:1px solid var(--line);border-radius:var(--radius);
  padding:16px;background:#fff;box-shadow:var(--shadow);height:100%}
.stockist h3{margin:0}
.stockist .region{font-size:.85rem;color:var(--muted)}
/* `margin-top:auto` is what stops the row staggering. The cards are already
   equal height (grid stretches them), but a card whose region line wraps to
   two lines pushed its link a line lower than its neighbours'. Pinning the
   link to the card's foot lines them all up. */
.stockist-go{margin:14px 0 0 !important;padding-top:2px;margin-top:auto !important}
/* A plain text link in the brand's own accent, not a button: three solid
   red blocks in a row read as three calls to action competing with each
   other, on a section whose job is to list places evenly. */
.stockist-link{color:var(--accent);font-weight:600;text-decoration:none;
  display:inline-flex;align-items:baseline;gap:.35em}
.stockist-link:hover,.stockist-link:focus-visible{text-decoration:underline}
.stockist-arrow{transition:transform .15s ease}
.stockist-link:hover .stockist-arrow{transform:translateX(2px)}

/* stockist regions */
.region-block{margin-top:26px}
.region-block h3{font-size:1.15rem;margin:0 0 10px;padding-bottom:8px;border-bottom:1px solid var(--line)}
/* One column. A multi-column grid read as "<town> <next store name>" down
   the column gutters, which is how "Kaitaia Mccoy and Thomas" happened. */
.shops{list-style:none;margin:0;padding:0}
.shops li{padding:10px 0;border-bottom:1px solid var(--paper-2)}
.shops li:last-child{border-bottom:0}
.shop-line{margin:0;line-height:1.35}
.shop-name{font-weight:600}
.shop-town{color:var(--ink-2)}
.shop-contact{margin:2px 0 0;font-size:.86rem;color:var(--muted);line-height:1.45}
.shop-contact a{color:var(--muted);text-decoration:none;border-bottom:1px solid var(--line)}
.shop-contact a:hover{color:var(--red);border-color:var(--red)}

/* Page intro: full content width, just a touch larger than body copy. The
   70ch .prose measure is right for an essay and wrong for one line above a
   directory. */
.lede{font-size:1.05rem;color:var(--ink-2);max-width:none}

.prose{max-width:70ch}
.prose h1{margin-bottom:.6rem}

/* footer */
.site-foot{background:var(--ink);color:#c9d1d8;margin-top:40px;padding:34px 0 22px;font-size:.92rem}
.foot-grid{display:grid;gap:22px;grid-template-columns:1fr}
@media (min-width:700px){.foot-grid{grid-template-columns:1.4fr 1fr 1fr 1fr}}
.site-foot h2{font-size:.8rem;text-transform:uppercase;letter-spacing:.06em;color:#8e9aa4}
.site-foot ul{list-style:none;margin:0;padding:0;display:grid;gap:6px}
.site-foot a{color:#dfe3e7;text-decoration:none}
.site-foot a:hover{text-decoration:underline}
.foot-logo{margin:0 0 12px}
.foot-logo img{height:var(--logo-h-foot);width:auto;background:var(--foot-chip);
  border-radius:8px;padding:var(--foot-chip-pad)}
.foot-logo{display:flex;align-items:center;gap:10px}
/* A brand's own knockout artwork already works on a dark ground; the white
   chip exists for marks that have none, and around one it draws a second
   edge. */
.foot-logo.reversed img{background:none;padding:0}
.foot-fine{border-top:1px solid #262d34;margin-top:26px;padding-top:16px;font-size:.82rem;color:#8e9aa4}
.foot-fine p{margin:0 0 .4rem}

/* warranty checklist */
.checklist{margin:0 0 1rem;padding:0;list-style:none;display:grid;gap:8px}
.checklist li{position:relative;padding-left:26px;line-height:1.5}
.checklist li::before{content:"";position:absolute;left:0;top:.45em;width:12px;height:7px;
  border-left:2px solid var(--red);border-bottom:2px solid var(--red);
  transform:rotate(-45deg)}

/* guide cards: a wide hero, a title and one line */
.card.guide{text-decoration:none}
.card.guide .shot.wide-shot{aspect-ratio:16/9;padding:0}
.card.guide .shot.wide-shot img{width:100%;height:100%;object-fit:cover;mix-blend-mode:normal}
.card.guide .name{font-size:1.02rem;line-height:1.3}
.card.guide .excerpt{font-size:.9rem;color:var(--ink-2);line-height:1.45}
.card.guide .meta{margin-top:auto;padding-top:4px}

/* Instagram strip — a square grid, same shape as Halco's own */
.social-grid{display:grid;gap:8px;grid-template-columns:repeat(3,1fr)}
@media (min-width:640px){.social-grid{grid-template-columns:repeat(4,1fr)}}
@media (min-width:900px){.social-grid{grid-template-columns:repeat(6,1fr)}}
.social-tile{position:relative;display:block;aspect-ratio:1/1;overflow:hidden;
  border-radius:8px;background:var(--paper-2)}
.social-tile img{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform .25s ease}
.social-tile:hover img{transform:scale(1.04)}
.social-tile .play{position:absolute;right:7px;top:7px;width:0;height:0;
  border-left:10px solid #fff;border-top:7px solid transparent;
  border-bottom:7px solid transparent;filter:drop-shadow(0 1px 2px rgba(0,0,0,.5))}
.trademark{color:#8e9aa4;margin:0 0 .4rem}


/* ── brand engine additions ────────────────────────────────────────────── */

/* A brand with no logo file sets its wordmark as type instead. Assassin
   arrived without artwork; a placeholder image would read as broken and
   another brand's mark would be worse. */
.wordmark{font-weight:800;letter-spacing:-.02em;font-size:1.45rem;
  text-transform:uppercase;color:var(--ink);white-space:nowrap;flex:none}
@media (min-width:560px){.wordmark{font-size:1.75rem}}
.foot-logo .wordmark{color:#fff;font-size:1.35rem}

/* A badge-shaped mark carries no readable brand name at header size, so the
   name is set beside it. Smaller than a wordmark standing on its own: here
   it is the second half of a lockup, not the whole mark. */
.wordmark-beside{font-size:1.25rem;letter-spacing:.01em}
@media (min-width:560px){.wordmark-beside{font-size:1.45rem}}
.foot-logo .wordmark-beside{font-size:1.2rem}

/* Only ever on a product the distributor does not carry, so it marks the
   exception rather than decorating every card. */
.card .shot{position:relative}
.flag{position:absolute;left:8px;top:8px;z-index:1;
  background:var(--ink);color:#fff;border-radius:999px;
  font-size:.66rem;font-weight:700;letter-spacing:.04em;text-transform:uppercase;
  padding:4px 9px;max-width:calc(100% - 16px);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

.panel.exclusive{background:var(--paper);border-left:3px solid var(--accent);
  margin:0 0 16px}
.panel.exclusive .label{font-size:.8rem;text-transform:uppercase;
  letter-spacing:.05em;color:var(--accent);font-weight:700}

/* A size on an exclusive page links straight to that size's page at the
   retailer — the product-level link can only be the collection when one
   model family maps to six listings. */
.at-retailer{display:inline-block;margin:2px 0 0 26px;font-size:.78rem;
  font-weight:600;letter-spacing:.01em;color:var(--accent);text-decoration:none}
.at-retailer:hover{text-decoration:underline}

/* The brand's published specification, one block per size. A definition list
   because that is what it is — a label and its value — and it keeps the
   run-on source text off the page. */
.specs{display:grid;gap:10px;margin:0 0 14px}
.spec{border:1px solid var(--line);border-radius:var(--radius);padding:12px 14px;
  background:var(--paper-2)}
.spec-head{margin:0;font-weight:700;display:flex;gap:10px;align-items:baseline;
  flex-wrap:wrap}
.spec-sku{font-weight:500;font-size:.78rem;color:var(--muted);letter-spacing:.02em}
.spec-lead{margin:2px 0 8px;font-size:.88rem;color:var(--ink-2)}
.spec dl{display:grid;grid-template-columns:auto 1fr;gap:2px 14px;margin:0;
  font-size:.88rem}
.spec dt{color:var(--muted)}
.spec dd{margin:0}
@media (max-width:480px){.spec dl{grid-template-columns:1fr}
  .spec dt{margin-top:6px}}


/* Product videos. A facade, not an iframe: the button carries our own
   mirrored still and is swapped for the player only when a reader clicks,
   so nothing of YouTube's loads — player, image or cookie — until asked. */
.videos{display:grid;gap:10px;margin:14px 0 0}
.video{position:relative;display:block;width:100%;padding:0;border:1px solid var(--line);
  border-radius:var(--radius);overflow:hidden;background:var(--paper-2);cursor:pointer;
  text-align:left;font:inherit;color:inherit}
.video img{width:100%;height:auto;display:block;aspect-ratio:16/9;object-fit:cover}
.video .play{position:absolute;left:50%;top:50%;width:54px;height:54px;margin:-27px 0 0 -27px;
  border-radius:50%;background:rgba(20,23,26,.72);pointer-events:none}
.video .play::after{content:"";position:absolute;left:21px;top:16px;border-style:solid;
  border-width:11px 0 11px 18px;border-color:transparent transparent transparent #fff}
.video:hover .play{background:var(--accent)}
.video-title{display:block;padding:9px 12px;font-weight:600;font-size:.9rem}
.video-frame{width:100%;aspect-ratio:16/9;border:0;border-radius:var(--radius);display:block}

/* ONE video is a section, not the first card of a row. Left in the grid so
   the card, the facade and the mirrored still are all the same component,
   but given a column of its own: at three columns a lone card sat a third
   of the way across with two empty columns beside it, which reads as a
   missing row rather than as a feature. Capped rather than stretched edge
   to edge — a 16:9 still at full page width is a banner, and this is a
   brand film under a heading. Only ever applied when the strip holds
   exactly one, so every other brand is untouched. */
/* `justify-content` and not `margin:auto` or `text-align`: the column is
   a grid track, so centring it is the container's job. The heading above
   stays left with every other section head on the page — it is the video
   that is centred, not the section. */
.video-grid.solo{grid-template-columns:minmax(0,560px);justify-content:center}
.video-grid .video-card{display:flex;flex-direction:column}
.video-grid .video{border:0;border-radius:0}
.video-grid .body{gap:4px}
.video-grid .meta a{color:var(--accent);text-decoration:none;font-weight:600}
.video-grid .meta a:hover{text-decoration:underline}

/* Guide pages — authored long-form copy for one brand. New classes only, so
   nothing here reaches a page that does not use them. */
/* Copy left, comparison table right. Capping the measure on the paragraphs
   alone left the right half of the page empty; the column does the capping
   now, and the table fills what it used to waste. */
.guide-layout{display:grid;gap:30px;align-items:start}
/* A grid item defaults to min-width:auto, so the table's min-width pushed the
   whole page sideways on a phone instead of scrolling inside its own box. */
.guide-layout>*{min-width:0}
@media (min-width:900px){
  .guide-layout{grid-template-columns:minmax(0,1.1fr) minmax(0,.9fr);gap:44px}
  .guide-side{position:sticky;top:88px}
}
.guide-body h2{margin:26px 0 8px;font-size:1.25rem}
.guide-body h2:first-child{margin-top:0}
.guide-body p{margin:0 0 14px;line-height:1.65;color:var(--ink-2)}
.guide-body .claim{margin-bottom:16px}
.guide-body .claim b{color:var(--ink)}
.guide-side h2{margin:0 0 12px;font-size:1.25rem}
.short-version{background:var(--paper-2);border-left:3px solid var(--accent);
  border-radius:0 var(--radius) var(--radius) 0;padding:14px 18px;margin:0 0 24px}
.short-version p{margin:0 0 6px;color:var(--ink);font-weight:600;line-height:1.5}
.short-version p:last-child{margin:0;font-weight:500;color:var(--ink-2)}
.sv-label{font-size:.72rem!important;text-transform:uppercase;letter-spacing:.1em;
  color:var(--muted)!important;font-weight:700!important;margin-bottom:8px!important}
.table-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch;margin:0 0 8px}
.compare{border-collapse:collapse;width:100%;min-width:430px;font-size:.9rem}
.compare th,.compare td{text-align:left;padding:9px 12px;border-bottom:1px solid var(--line);
  vertical-align:top}
.compare thead th{font-size:.78rem;text-transform:uppercase;letter-spacing:.06em;
  color:var(--muted);border-bottom-width:2px}
.compare tbody th{font-weight:600;color:var(--ink);width:34%}
.compare tbody tr:last-child th,.compare tbody tr:last-child td{border-bottom:none}
.guide-link{margin:0 0 4px;font-weight:600}

/* Assassin's header is a badge, a wordmark and nine nav entries, which wrapped
   the nav to a second line at every desktop width. Scoped with :has() to the
   badge-plus-wordmark lockup, so a brand with a single logo image keeps the
   roomier nav it fits in. */
@media (min-width:900px){
  .head-row:has(.wordmark-beside) .brand{gap:8px}
  .head-row:has(.wordmark-beside) .wordmark-beside{font-size:1.15rem}
  .head-row:has(.wordmark-beside) .brand-nz{padding-left:8px;font-size:.68rem}
  .head-row:has(.wordmark-beside) .nav ul{gap:2px}
  .head-row:has(.wordmark-beside) .nav a{padding:8px 9px}
}
/* Between 900 and 1200 the nav still does not fit. The location line goes
   rather than the nav links: it is repeated in the footer and the page title,
   and cramping nine tap targets to save it would be the wrong trade. */
@media (min-width:900px) and (max-width:1199px){
  .head-row:has(.wordmark-beside) .brand-nz{display:none}
}

/* Cross-links (lib/relations.py). A compatibility group is a labelled band
   of cards inside one section: the label is the brand's own row heading
   ("Mounts that fit it"), so it has to read as a sub-heading of "What fits
   this", not as another page section. Only brands that publish a
   compatibility model render these at all. */
.xlink-head{font-size:1rem;font-weight:600;letter-spacing:.01em;
  margin:22px 0 12px;color:var(--muted)}
.xlink-head:first-of-type{margin-top:4px}

/* ── grouped navigation (catalogue.nav_groups) ──────────────────────────────
   Ten flat categories wrapped to three rows on a laptop, so a brand with a
   deep range groups them the way its own header does: a handful of menus,
   each opening on the ranges beneath. One set of markup serves both widths —
   on mobile the panel is a block the chevron expands in place, on desktop it
   is absolutely positioned and opens on hover or keyboard focus as well.
   A brand with no groups declared renders no `.has-menu` at all. */

.nav .has-menu{display:flex;flex-wrap:wrap;align-items:center}
.nav .has-menu > a{flex:1 1 auto}

/* The chevron is a second control beside the link, not a replacement for it:
   the menu title still navigates to the category, which is what a reader
   tapping the word expects. Hit area is the full row height. */
.submenu-btn{flex:none;background:none;border:0;padding:10px;cursor:pointer;
  color:var(--ink-2);line-height:0;border-radius:8px}
.submenu-btn:hover{background:var(--paper-2)}
.chev{display:inline-block;width:8px;height:8px;border-right:2px solid currentColor;
  border-bottom:2px solid currentColor;transform:rotate(45deg) translate(-2px,-2px);
  transition:transform .15s ease}
.submenu-btn[aria-expanded="true"] .chev{transform:rotate(-135deg) translate(-2px,-2px)}

.submenu{display:none;width:100%}
.submenu-btn[aria-expanded="true"] + .submenu{display:block}
.submenu-inner{display:flex;flex-direction:column;gap:2px}
.submenu-col{min-width:auto}
.submenu-head{font-size:.78rem!important;letter-spacing:.08em;text-transform:uppercase;
  color:var(--muted)!important;padding-bottom:4px!important}
.submenu ul{list-style:none;margin:0;padding:0 0 6px 12px}
.submenu a{font-weight:500;padding:8px}

@media (min-width:900px){
  .nav .has-menu{position:relative;flex-wrap:nowrap}
  .nav .has-menu > a{flex:0 0 auto;padding-right:4px}
  .submenu-btn{padding:8px 8px 8px 0}
  .submenu-btn:hover{background:none}
  /* Opens on hover for a pointer, on focus-within for a keyboard, and on the
     button for a touch screen that reports neither. */
  .nav .has-menu:hover > .submenu,
  .nav .has-menu:focus-within > .submenu{display:block}
  /* `max-content`, not `auto`: an absolutely positioned box shrink-to-fits
     against its containing block, and the containing block here is the menu
     item — about 110px — so `auto` collapses a three-column panel into one
     very tall column. max-content asks for the full width, max-width clamps
     it, and the columns wrap inside that. */
  .submenu{position:absolute;top:100%;left:0;width:max-content;
    max-width:min(88vw,660px);min-width:230px;padding-top:6px;z-index:30}
  .submenu-inner{flex-direction:row;flex-wrap:wrap;gap:14px 26px;background:#fff;
    border:1px solid var(--line);border-radius:12px;padding:14px 18px;
    box-shadow:0 12px 28px rgba(0,0,0,.13)}
  /* The nav is right-aligned, so the last menu's panel would hang off the
     window if it opened leftwards like the others. Marked in the template
     rather than guessed with :nth-last-of-type, which would misfire the
     moment a brand's nav is a different length. */
  .submenu.align-right{left:auto;right:0}
  .submenu ul{padding:0}
  /* Fourteen ranges in one column is taller than most laptop screens. */
  .submenu ul.split{display:grid;grid-template-columns:repeat(2,max-content);
    gap:0 22px}
  .submenu a{white-space:nowrap;padding:6px 8px}
  .submenu-head{padding:0 8px 6px!important}
}

/* "Coming soon" (catalogue.coming_soon) — a range the distributor has taken
   on but cannot sell yet. Muted rather than loud: it is a statement of fact,
   not a promotion, and it sits where the price would be. */
.soon-panel{background:var(--paper-2);border:1px solid var(--line)}
.soon-panel .label{color:var(--ink-2)}
.flag.soon{background:var(--ink);color:#fff}
/* A dot beside the nav entry, because the word would not fit in a menu and
   the category page says it properly. title= carries it for a pointer, and
   the page itself for everyone else. */
.soon-dot{display:inline-block;width:6px;height:6px;border-radius:50%;
  background:var(--accent);margin-left:6px;vertical-align:middle}


/* Stockist tier badge (stockists.tiers) — shared by every brand that sets
   tiers, so nothing in here is Scotty-specific.

   A LABEL, not a number (see lib/stockists.apply_tiers). Outlined rather
   than filled and set in the brand red: a solid red pill in caps read as a
   sale sticker on a page whose whole job is naming other people's shops
   respectfully. No `text-transform` — the case is whatever the brand wrote
   in `premier_label`, because deciding a brand's own wording in CSS is how
   a config value stops meaning anything.

   `inline-flex` + `vertical-align:middle` centres the pill on the shop
   name's x-height rather than sitting it on the baseline; sizing is all in
   `em` so it tracks the name if the type scale ever changes. */
.shop-tier{display:inline-flex;align-items:center;gap:.34em;
  margin-left:8px;padding:.12em .6em .12em .5em;
  /* The outline follows the BRAND's accent, not a hardcoded red: Halco and
     Scotty are red but Assassin's is navy (#1d2a35), and a red ring round
     navy type would be nobody's mark. Softened with color-mix where it is
     supported; the fallback is the accent at full strength, which is right
     rather than merely tolerable. */
  border:1px solid var(--accent);border-radius:999px;
  color:var(--accent);background:none;
  font-size:.73rem;font-weight:500;letter-spacing:.005em;line-height:1.45;
  white-space:nowrap;vertical-align:middle}
@supports (color: color-mix(in srgb, red 50%, transparent)) {
  .shop-tier{border-color:color-mix(in srgb, var(--accent) 42%, transparent)}
}
.shop-tier-mark{width:.8em;height:.8em;fill:currentColor;flex:none;
  /* the star's own optical centre sits a shade high against the cap line */
  margin-top:-.04em}

/* The other Monster Distribution brand sites, under the footer. Greyscale so
   four other brands' marks sit quietly beneath this one's, and colour on
   hover so the row is plainly clickable. */
.network{background:var(--paper-2);border-top:1px solid var(--line);padding:16px 0}
.network-row{display:flex;align-items:center;gap:18px 26px;flex-wrap:wrap}
.network-label{font-size:.74rem;text-transform:uppercase;letter-spacing:.1em;
  color:var(--muted);font-weight:700;white-space:nowrap}
.network ul{list-style:none;margin:0;padding:0;display:flex;align-items:center;
  gap:14px 26px;flex-wrap:wrap}
.network a{display:block;line-height:0;border-radius:6px}
.network img{height:28px;width:auto;max-width:150px;object-fit:contain;
  filter:grayscale(1);opacity:.75;transition:filter .15s,opacity .15s}
.network a:hover img,.network a:focus-visible img{filter:none;opacity:1}
@media (prefers-reduced-motion:reduce){.network img{transition:none}}

/* ── technology explainers (lib/technology.py, templates/technology.html) ──
   A brand whose value is the technology in a part (Fuji) gets a /technology
   page, a section of it on the home page above the range, a panel on every
   product page and a link strip on every category. Nothing here is
   brand-specific: the accent, the paper and the line colours are the
   brand's own custom properties, the same as every other block. */
.tech-home .tech-intro{max-width:70ch;margin:0 0 18px}
.tech-home .tech-intro p{color:var(--ink-2);line-height:1.65}
.tech-code{margin:0 0 18px}
.tech-code-lead{margin:0 0 10px;font-weight:600}
.tech-chips{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:10px}
.tech-chips li{display:flex;flex-direction:column;gap:4px;min-width:96px}
.chip-code{display:inline-block;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  font-weight:700;font-size:1.05rem;letter-spacing:.04em;padding:4px 10px;border-radius:6px;
  background:var(--paper);border:1px solid var(--line);color:var(--accent);width:max-content}
.chip-meaning{font-size:.86rem;color:var(--ink-2);max-width:18ch;line-height:1.35}
.tech-code-foot{margin:12px 0 0;font-size:.86rem}
.tech-cards .tech-card{display:flex;flex-direction:column;gap:6px;text-decoration:none;color:inherit;
  transition:box-shadow .15s,border-color .15s}
.tech-cards .tech-card:hover{box-shadow:var(--shadow);border-color:var(--accent)}
.tech-card h3{margin:0;font-size:1.1rem}
.tech-card p{margin:0;color:var(--ink-2);font-size:.95rem;line-height:1.5}
.tech-kicker{font-size:.76rem;text-transform:uppercase;letter-spacing:.08em;color:var(--accent);font-weight:700}
.tech-more{margin-top:auto;padding-top:8px;font-weight:700;color:var(--accent);font-size:.9rem}
.tech-all{margin:18px 0 0}
/* the page */
.tech-head{padding-top:8px}
.tech-toc{margin:18px 0 8px;padding:12px 16px;background:var(--paper-2);border:1px solid var(--line);border-radius:var(--radius)}
.tech-toc ol{margin:0;padding:0 0 0 1.2em;columns:2;column-gap:24px;font-size:.95rem}
.tech-toc li{break-inside:avoid;padding:2px 0}
.tech-toc a{color:var(--ink);text-decoration:none;font-weight:600}
.tech-toc a:hover{color:var(--accent)}
.tech-section{padding:34px 0 8px;border-top:1px solid var(--line);margin-top:26px;scroll-margin-top:16px}
.tech-section:first-of-type{border-top:none;margin-top:8px}
.tech-body h2{font-size:1.6rem;letter-spacing:-.01em}
.tech-body h3{font-size:1.12rem;margin:22px 0 8px}
.tech-body p{line-height:1.65;color:var(--ink-2)}
.tech-body .claim b{color:var(--ink)}
.tech-body .lede{color:var(--ink);font-weight:500}
.tech-bullets{margin:0 0 1rem;padding-left:1.2em;color:var(--ink-2);line-height:1.6}
.tech-note{font-size:.88rem}
.codes{margin:6px 0 18px;display:grid;gap:10px}
.code-row{display:grid;gap:4px;padding:10px 12px;background:var(--paper-2);border:1px solid var(--line);border-radius:8px}
.code-row dt{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:0}
.code-name{font-weight:700}
.code-row dd{margin:0;color:var(--ink-2);line-height:1.55;font-size:.95rem}
@media (min-width:760px){
  .code-row{grid-template-columns:230px 1fr;align-items:start;gap:16px}
  .code-row dt{flex-direction:column;align-items:flex-start;gap:4px}
}
.tech-examples{margin-top:22px}
.tech-examples .range-title{font-size:1.05rem}
.tech-closing{padding:34px 0 8px;border-top:1px solid var(--line);margin-top:26px}
/* on product, category and card */
.tech-panel{margin:0 0 18px}
.tech-panel .label{font-size:.8rem;text-transform:uppercase;letter-spacing:.05em;color:var(--muted);font-weight:700;margin-bottom:8px}
.tech-list{list-style:none;margin:0;padding:0;display:grid;gap:8px}
.tech-list li{display:flex;flex-wrap:wrap;gap:4px 10px;align-items:baseline;line-height:1.4}
.tech-list a{text-decoration:none;color:var(--ink)}
.tech-list a b{color:var(--accent)}
.tech-list a:hover b{text-decoration:underline}
.tech-sec{font-size:.84rem}
.tech-strip{margin:0 0 14px;display:flex;flex-wrap:wrap;gap:6px 12px;align-items:baseline;font-size:.95rem}
.tech-strip a{font-weight:700;color:var(--accent);text-decoration:none}
.tech-strip a:hover{text-decoration:underline}
.card .tech{font-size:.8rem;color:var(--accent);font-weight:600;line-height:1.3}
