/* NORTHBOUND RV & POWERSPORTS — "TRIP LOG"
   Ground: warm sand and dusty olive as real surface colors. Ink for text.
   One route-marker orange, used for waypoints and for the refusal.
   Bands run as segments of a route through a day: morning paper, midday sand,
   afternoon clay, dusty olive, shaded evening, night.
   No webfonts, no external anything, no photographs. System stacks only. */

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{margin:0}

:root{
  /* --- the route, hour by hour --- */
  --paper:#f5eddc;      /* the log sheet */
  --sand-lt:#ece2c8;    /* early, low sun */
  --sand:#dccfae;       /* midday */
  --sand-dk:#cdbb95;    /* kept: legacy name */
  --clay:#cbb28c;       /* afternoon, deeper ground */
  --sage:#c3c3a2;       /* dusty olive scrub */
  --dusk:#33291d;       /* shaded evening */
  --dusk-2:#3d3225;
  --olive:#4b5738;
  --olive-dk:#39432a;
  --olive-lt:#6d7a52;

  --ink:#241f16;
  --ink-2:#4b4335;
  --ink-3:#6d6250;
  /* ⭐ THE ONE ACCENT, RETUNED TO DESERT CLAY — 11 Sep 2026. It was #b8531a,
     a highway orange. Clay is the ground this whole site is drawn on, and the
     accent now comes out of it instead of sitting on top of it.
     ⚠️ The 76 hard-coded #b8531a fills in the enamel badge SVGs were swept to
     match in the same pass. ⛔ Never leave two oranges 3% apart on one site —
     that reads as a mistake, not a system. */
  --orange:#b8442b;
  --orange-dk:#9c3520;   /* small type on sand: --orange is 4.6:1, this is 6.1:1 */
  --orange-lt:#d05a38;
  --orange-pale:#eca580;   /* kicker on --olive: 3.7:1, up from the 3.6:1 it shipped at */
  --sign:#1b4f36;

  --rule:rgba(36,31,22,.30);
  --rule-soft:rgba(36,31,22,.16);
  --lite:#f1ecdc;             /* text on dark grounds */
  --lite-2:#d9d3bf;
  --lite-3:#a9a48d;

  --sans:"Avenir Next","Avenir","Futura","Trebuchet MS","Segoe UI",system-ui,-apple-system,"Helvetica Neue",Arial,sans-serif;
  --mono:ui-monospace,"SF Mono",SFMono-Regular,Menlo,Monaco,"Cascadia Mono","Roboto Mono",Consolas,"Courier New",monospace;

  --shell:1160px;
  --pad:clamp(18px,4vw,44px);

  /* one timing language for the whole site */
  --t-fast:150ms;
  --t:200ms;
  --t-slow:250ms;
  --ease:cubic-bezier(.2,.75,.25,1);

  --sy:0; /* scroll parallax hint, written by route.js */
}

body{
  font-family:var(--sans);
  color:var(--ink);
  background:var(--sand);
  font-size:1.0625rem;
  line-height:1.62;
  overflow-x:hidden;
}

img,svg{max-width:100%}
a{color:var(--ink);text-underline-offset:.18em;text-decoration-thickness:1px;
  transition:color var(--t) var(--ease)}
a:hover{color:var(--orange)}

.shell{width:100%;max-width:var(--shell);margin:0 auto;padding-left:var(--pad);padding-right:var(--pad)}

/* ---------- signage lettering ---------- */
h1,h2,h3,h4{font-family:var(--sans);margin:0;font-weight:700;line-height:1.03;
  letter-spacing:.055em;text-transform:uppercase;text-wrap:balance}
h1{font-size:clamp(1.9375rem,6.2vw,4rem);letter-spacing:.028em;line-height:.99}
h2{font-size:clamp(1.4375rem,3.9vw,2.375rem);letter-spacing:.045em;line-height:1.02}
h3{font-size:clamp(1.0625rem,2.2vw,1.375rem);letter-spacing:.08em;line-height:1.14}
h4{font-size:.84375rem;letter-spacing:.16em}
p{margin:0 0 1.05em}
p:last-child{margin-bottom:0}

/* ---------- demonstration strip ---------- */
.demostrip{
  background:linear-gradient(180deg,#414c31 0%,var(--olive-dk) 100%);
  color:#f0ead9;
  font-size:.84375rem;
  line-height:1.5;
  padding:10px var(--pad);
  display:flex;
  gap:10px;
  align-items:flex-start;
  border-bottom:2px solid var(--orange);
  position:relative;
}
.demostrip b{letter-spacing:.06em;text-transform:uppercase}
.demostrip a{color:#ffd9ac;font-weight:700;white-space:nowrap}
.demostrip a:hover{color:#fff}
.demostrip__dot{
  flex:0 0 auto;width:11px;height:11px;margin-top:6px;border-radius:50%;
  background:var(--orange-lt);box-shadow:0 0 0 3px rgba(208,90,56,.28);
}

/* route progress ribbon — inert until route.js runs, never carries content */
.routeprog{position:fixed;left:0;top:0;height:3px;width:100%;z-index:9500;pointer-events:none;
  background:rgba(36,31,22,.22)}
.routeprog span{display:block;height:100%;width:0;
  background:repeating-linear-gradient(90deg,var(--orange-lt) 0 13px,rgba(208,90,56,.30) 13px 22px);
  transition:width 90ms linear}
html:not(.rv-js) .routeprog{display:none}

/* ---------- header ---------- */
.top{background:linear-gradient(180deg,var(--dusk-2) 0%,var(--dusk) 70%,#291f15 100%);
  color:var(--lite);border-bottom:1px solid rgba(0,0,0,.28);position:relative}
.top::after{content:"";position:absolute;left:0;right:0;bottom:0;height:2px;
  background:repeating-linear-gradient(90deg,rgba(208,90,56,.85) 0 16px,transparent 16px 30px)}
.top__in{display:flex;align-items:center;gap:16px;padding-top:15px;padding-bottom:15px;flex-wrap:wrap}
.brand{display:flex;align-items:center;gap:12px;text-decoration:none;color:inherit;margin-right:auto}
.brand__mk{
  flex:0 0 auto;width:44px;height:44px;border-radius:8px;
  background:linear-gradient(160deg,#f4ecd8,var(--sand-dk));color:var(--olive-dk);
  display:grid;place-items:center;font-family:var(--mono);font-weight:700;font-size:.9375rem;
  letter-spacing:.02em;border:2px solid var(--orange);
  transition:transform var(--t) var(--ease),box-shadow var(--t) var(--ease);
}
.brand:hover .brand__mk{transform:translateY(-2px) rotate(-3deg);box-shadow:0 4px 0 rgba(0,0,0,.22)}
.brand__nm{display:block;font-weight:700;text-transform:uppercase;letter-spacing:.1em;font-size:.9375rem;line-height:1.15}
.brand__sub{display:block;font-family:var(--mono);font-size:.6875rem;letter-spacing:.13em;text-transform:uppercase;color:#c8ceb2;margin-top:3px}

.nav ul{list-style:none;display:flex;flex-wrap:wrap;gap:2px 4px;margin:0;padding:0}
.nav a{
  display:block;padding:7px 10px;text-decoration:none;color:#e9e4d2;position:relative;
  font-size:.75rem;letter-spacing:.13em;text-transform:uppercase;font-weight:600;border-radius:4px;
  transition:background var(--t) var(--ease),color var(--t) var(--ease);
}
.nav a::after{content:"";position:absolute;left:10px;right:10px;bottom:3px;height:2px;
  background:var(--orange-lt);transform:scaleX(0);transform-origin:left;
  transition:transform var(--t-slow) var(--ease)}
.nav a:hover{background:rgba(255,255,255,.13);color:#fff}
.nav a:hover::after{transform:scaleX(1)}
.nav a[aria-current="page"]{background:rgba(255,255,255,.15);color:#fff;box-shadow:inset 0 -2px 0 var(--orange-lt)}

.callnum{
  font-family:var(--mono);font-size:.875rem;font-weight:700;letter-spacing:.04em;
  background:linear-gradient(180deg,var(--orange-lt),var(--orange));color:#fff;
  padding:10px 14px;border-radius:6px;text-decoration:none;white-space:nowrap;
  border:2px solid rgba(0,0,0,.22);
  transition:transform var(--t) var(--ease),box-shadow var(--t) var(--ease),filter var(--t) var(--ease);
}
.callnum:hover{color:#fff;transform:translateY(-2px);filter:brightness(1.07);box-shadow:0 4px 0 rgba(0,0,0,.25)}
.callnum:active{transform:translateY(0);box-shadow:0 1px 0 rgba(0,0,0,.25)}

/* ---------- bands: segments of a route through a day ---------- */
.band{padding:clamp(46px,7vw,86px) 0;position:relative;isolation:isolate}
/* screen-printed grain: a fine halftone dot over every band */
.band::before{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background-image:radial-gradient(rgba(36,31,22,.075) .9px,transparent 1px);
  background-size:4px 4px;
  mix-blend-mode:multiply;
}
.band--olive::before,.band--dusk::before{
  background-image:radial-gradient(rgba(255,255,255,.055) .9px,transparent 1px);
  mix-blend-mode:screen;
}

.band--lt{background:linear-gradient(180deg,#f2e9d3 0%,var(--sand-lt) 55%,#e5d9bd 100%)}
.band--sand{background:linear-gradient(180deg,#e3d6b6 0%,var(--sand) 55%,#d3c4a1 100%)}
.band--dk{background:linear-gradient(180deg,#d5bf9c 0%,var(--clay) 58%,#bfa47c 100%)}
.band--sage{background:linear-gradient(180deg,#cbcbab 0%,var(--sage) 55%,#b3b494 100%)}
.band--paper{background:linear-gradient(180deg,#f8f1e2 0%,var(--paper) 100%)}
.band--dusk{background:linear-gradient(180deg,#3d3225 0%,var(--dusk) 55%,#2a2117 100%);color:var(--lite-2)}
.band--olive{background:linear-gradient(180deg,#55623f 0%,var(--olive) 55%,#3d4830 100%);color:var(--lite)}

.band--olive h2,.band--olive h3,.band--olive h4,
.band--dusk h1,.band--dusk h2,.band--dusk h3,.band--dusk h4{color:#fff}
.band--olive a,.band--dusk a{color:#ffd7a8}
.band--olive a:hover,.band--dusk a:hover{color:#fff}
.band--dusk .lede{color:var(--lite-2)}
.band--olive .lede{color:#ddd8c6}
/* light cards keep their own ink on a dark band */
.band--dusk .panel,.band--dusk .side,.band--dusk .refuse,.band--dusk .log,
.band--dusk .fig,.band--dusk .form,.band--dusk .empty,.band--dusk .slot__cap,
.band--olive .panel,.band--olive .side,.band--olive .refuse,.band--olive .log,
.band--olive .fig,.band--olive .form,.band--olive .empty,.band--olive .slot__cap{color:var(--ink)}

/* a dashed rule runs the join between one segment and the next */
.band + .band::after{
  content:"";position:absolute;left:0;right:0;top:0;height:0;
  border-top:2px dashed var(--rule);opacity:.55;pointer-events:none;
}
.band--dusk + .band::after,.band--olive + .band::after,
.band + .band--dusk::after,.band + .band--olive::after{border-top-color:rgba(255,255,255,.28)}

/* ---------- waypoint heading ---------- */
.wp{display:flex;flex-wrap:wrap;align-items:center;gap:10px 14px;margin:0 0 30px}
.wp__badge{
  flex:0 0 auto;font-family:var(--mono);font-size:.6875rem;font-weight:700;letter-spacing:.12em;
  background:var(--ink);color:var(--sand-lt);padding:6px 10px;border-radius:3px;text-transform:uppercase;
  box-shadow:2px 2px 0 rgba(36,31,22,.22);
}
.band--olive .wp__badge,.band--dusk .wp__badge{background:var(--orange);color:#fff;box-shadow:2px 2px 0 rgba(0,0,0,.3)}
.wp h2,.wp h3{flex:0 1 auto;min-width:0;overflow-wrap:break-word}
.wp__rule{flex:1 1 auto;height:0;border-top:2px dashed var(--rule);min-width:24px;
  transform:scaleX(1);transform-origin:left}
.band--olive .wp__rule,.band--dusk .wp__rule{border-top-color:rgba(255,255,255,.35)}
.wp__mk{
  flex:0 0 auto;width:13px;height:13px;background:var(--orange);
  transform:rotate(45deg);border-radius:2px;box-shadow:0 0 0 4px rgba(184,83,26,.18);
}

.lede{font-size:clamp(1.0625rem,2.1vw,1.28125rem);line-height:1.55;max-width:64ch;color:var(--ink-2)}
.prose{max-width:70ch}
.prose h3{margin:2em 0 .55em}
.prose ul{padding-left:1.15em;margin:0 0 1.05em}
.prose li{margin-bottom:.5em}
.band--dusk .prose,.band--dusk .side p,.band--dusk .side li{color:var(--lite-2)}
.kicker{font-family:var(--mono);font-size:.71875rem;letter-spacing:.2em;text-transform:uppercase;color:var(--orange);font-weight:700;margin:0 0 14px;
  display:inline-flex;align-items:center;gap:9px}
.kicker::before{content:"";width:22px;height:2px;background:var(--orange);flex:0 0 auto}
.band--olive .kicker,.band--dusk .kicker{color:var(--orange-pale)}
.band--olive .kicker::before,.band--dusk .kicker::before{background:var(--orange-pale)}

/* ---------- hero ---------- */
.hero,
.showcase{
  padding:clamp(38px,5.6vw,68px) 0 clamp(30px,4vw,52px);
  position:relative;overflow:hidden;isolation:isolate;
  background:linear-gradient(180deg,#f7f0de 0%,#f0e7d0 42%,var(--sand-lt) 72%,#e0d2b2 100%);
}
/* low horizon behind the badge */
.hero::before,
.showcase::before{
  content:"";position:absolute;z-index:-2;left:-6%;right:-6%;bottom:0;height:62%;
  background:
    radial-gradient(120% 78% at 72% 100%,rgba(184,83,26,.16) 0%,rgba(184,83,26,0) 62%),
    linear-gradient(180deg,rgba(196,182,148,0) 0%,rgba(190,174,138,.55) 58%,rgba(150,140,106,.55) 100%);
  transform:translateY(calc(var(--sy) * -0.06px));
}
.hero::after,
.showcase::after{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background-image:radial-gradient(rgba(36,31,22,.07) .9px,transparent 1px);
  background-size:4px 4px;mix-blend-mode:multiply;
}
.hero__grid{display:grid;gap:clamp(26px,4vw,50px);grid-template-columns:1fr}
@media(min-width:930px){.hero__grid{grid-template-columns:1.02fr .98fr;align-items:center}}
.hero__tag{
  display:inline-flex;align-items:center;gap:9px;font-family:var(--mono);font-size:.6875rem;
  letter-spacing:.18em;text-transform:uppercase;font-weight:700;color:var(--ink-2);
  border:2px solid var(--rule);border-radius:100px;padding:6px 14px;margin-bottom:20px;
  background:rgba(255,255,255,.34);
}
.hero__tag::before{content:"";width:9px;height:9px;background:var(--orange);transform:rotate(45deg)}
.hero h1{margin-bottom:20px}
.hero h1 em{font-style:normal;color:var(--orange);display:block}
.hero__sub{font-size:clamp(1.03125rem,2vw,1.21875rem);color:var(--ink-2);max-width:54ch;margin-bottom:26px}
.hero__cta{display:flex;flex-wrap:wrap;gap:11px}

/* ---------- buttons ---------- */
.btn{
  display:inline-block;text-decoration:none;font-size:.78125rem;font-weight:700;letter-spacing:.13em;
  text-transform:uppercase;padding:14px 22px;border-radius:6px;border:2px solid transparent;
  transition:transform var(--t) var(--ease),background var(--t) var(--ease),
             color var(--t) var(--ease),box-shadow var(--t) var(--ease);
}
.btn--go{background:linear-gradient(180deg,var(--orange-lt),var(--orange));color:#fff;
  border-color:rgba(0,0,0,.2);box-shadow:0 3px 0 rgba(36,31,22,.3)}
.btn--go:hover{color:#fff;transform:translateY(-2px);box-shadow:0 5px 0 rgba(36,31,22,.32)}
.btn--go:active{transform:translateY(1px);box-shadow:0 1px 0 rgba(36,31,22,.32)}
.btn--out{border-color:var(--ink);color:var(--ink);box-shadow:0 3px 0 rgba(36,31,22,.16)}
.btn--out:hover{background:var(--ink);color:var(--sand-lt);transform:translateY(-2px);box-shadow:0 5px 0 rgba(36,31,22,.26)}
.btn--out:active{transform:translateY(1px);box-shadow:0 1px 0 rgba(36,31,22,.26)}
.band--olive .btn--out,.band--dusk .btn--out{border-color:#e9e4d2;color:#e9e4d2;box-shadow:0 3px 0 rgba(0,0,0,.3)}
.band--olive .btn--out:hover{background:#e9e4d2;color:var(--olive)}
.band--dusk .btn--out:hover{background:#e9e4d2;color:var(--dusk)}

/* ---------- the hero rig badge ---------- */
.rigwrap{
  background:linear-gradient(180deg,#e5d8b9,var(--sand));
  border:2px solid var(--rule);border-radius:12px;padding:14px 14px 10px;
  box-shadow:0 10px 0 rgba(36,31,22,.10),0 2px 0 rgba(255,255,255,.5) inset;
}
.rigsvg{display:block;width:100%;height:auto}
.rigwrap__cap{
  font-family:var(--mono);font-size:.65625rem;letter-spacing:.13em;text-transform:uppercase;
  color:var(--ink-3);margin-top:10px;display:flex;justify-content:space-between;gap:10px;flex-wrap:wrap;
}

/* ---------- enamel badges (one per stop) ---------- */
.bdg{display:block;width:100%;height:auto}
.bdg--sm{width:54px;height:54px;flex:0 0 auto}
.bdg--lg{width:clamp(92px,15vw,124px);height:auto;flex:0 0 auto}
.bdgwrap{
  display:inline-flex;padding:7px;border-radius:14px;flex:0 0 auto;
  background:linear-gradient(160deg,var(--paper),var(--sand-dk));
  border:2px solid var(--ink);
  box-shadow:3px 3px 0 rgba(36,31,22,.24);
  transition:transform var(--t-slow) var(--ease),box-shadow var(--t-slow) var(--ease);
}
.band--olive .bdgwrap,.band--dusk .bdgwrap{border-color:rgba(255,255,255,.45);box-shadow:3px 3px 0 rgba(0,0,0,.34)}

/* the hero of a service page: big badge beside the heading */
.pagehd{display:flex;gap:clamp(16px,3vw,28px);align-items:flex-start;flex-wrap:wrap}
.pagehd__tx{flex:1 1 320px;min-width:0}

/* ---------- diagrams ---------- */
.fig{
  background:linear-gradient(180deg,#f9f2e2,var(--paper));
  border:2px solid var(--ink);border-radius:10px;padding:16px 16px 12px;
  box-shadow:5px 5px 0 rgba(36,31,22,.16);
  margin:0 0 20px;
}
.band--dusk .fig,.band--olive .fig{box-shadow:5px 5px 0 rgba(0,0,0,.28)}
.fig svg{display:block;width:100%;height:auto}
/* a wide diagram scrolls inside its own frame rather than pushing the page.
   Grid children need min-width:0 or the scroller's content width blows the
   track out and the whole page gains a horizontal scrollbar. */
.two>*,.panels>*,.hero__grid>*,.foot__grid>*,.prose,.fig,.fig__vp{min-width:0}
.fig__vp{overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch}
@media(max-width:760px){
  .fig__vp svg{width:600px;max-width:none}
  .fig__cap{border-top:1px dashed var(--rule-soft);padding-top:9px}
  .fig__cap::after{content:"Scroll the diagram sideways";display:block;flex:1 1 100%;
    color:var(--ink-3);letter-spacing:.1em}
}
.fig--md{max-width:800px}
.fig--wide{max-width:100%;margin-bottom:30px}
.prose .fig{margin-top:8px}
.prose .slot{max-width:100%}
.fig__cap{
  font-family:var(--mono);font-size:.65625rem;letter-spacing:.13em;text-transform:uppercase;
  color:var(--ink-3);margin:10px 0 0;display:flex;justify-content:space-between;gap:10px;flex-wrap:wrap;
}
.fig__cap b{color:var(--ink);font-weight:700}

/* ---------- photograph slots (frames waiting for real photographs) ---------- */
.slot{
  border:2px solid var(--ink);border-radius:10px;overflow:hidden;
  background:linear-gradient(180deg,#e9dfc4,var(--sand-dk));
  box-shadow:6px 6px 0 rgba(36,31,22,.18);
  margin:0 0 22px;
}
.band--dusk .slot,.band--olive .slot{box-shadow:6px 6px 0 rgba(0,0,0,.3)}
.slot__art{position:relative;display:block;width:100%;aspect-ratio:3/2;
  background:linear-gradient(180deg,#efe6cd 0%,#ddceac 58%,#c8b58e 100%)}
.slot__art svg{position:absolute;inset:0;width:100%;height:100%;display:block}
.slot__tag{
  position:absolute;left:10px;top:10px;z-index:2;
  font-family:var(--mono);font-size:.59375rem;font-weight:700;letter-spacing:.16em;text-transform:uppercase;
  background:var(--ink);color:var(--sand-lt);padding:5px 8px;border-radius:3px;
}
.slot__cap{
  font-family:var(--mono);font-size:.6875rem;line-height:1.55;letter-spacing:.05em;
  color:var(--ink-2);background:var(--paper);border-top:2px solid var(--ink);padding:11px 13px;
}
.slot__cap b{display:block;text-transform:uppercase;letter-spacing:.12em;font-size:.65625rem;color:var(--ink);margin-bottom:3px}
.slot--wide{max-width:760px}

/* ---------- the log sheet: a real ruled sheet ---------- */
.log{
  background:
    linear-gradient(90deg,transparent 0 40px,rgba(184,83,26,.16) 40px 41.5px,transparent 41.5px),
    linear-gradient(180deg,#f9f2e3,var(--paper));
  border:2px solid var(--ink);
  border-radius:7px;
  box-shadow:9px 9px 0 rgba(36,31,22,.20);
  overflow:hidden;
  max-width:920px;
}
.log__hd{
  background:linear-gradient(180deg,#312a1e,var(--ink));color:var(--sand-lt);padding:15px 18px;
  display:flex;flex-wrap:wrap;gap:6px 26px;align-items:baseline;
  border-bottom:2px solid var(--ink);
}
.log__ttl{font-family:var(--sans);font-weight:700;text-transform:uppercase;letter-spacing:.14em;font-size:.84375rem}
.log__meta{font-family:var(--mono);font-size:.71875rem;letter-spacing:.06em;color:#c9bfa2}
.log__meta b{color:#fff;font-weight:700}
.log__rows{font-family:var(--mono);font-size:.8125rem}
.row{
  display:grid;
  grid-template-columns:34px 1fr 96px;
  gap:4px 12px;
  padding:12px 16px 12px 14px;
  border-top:1px dashed var(--rule-soft);
  align-items:baseline;
  position:relative;
  transition:background var(--t) var(--ease);
}
.row:nth-child(even){background:rgba(36,31,22,.028)}
.row:hover{background:rgba(184,83,26,.07)}
.log__rows .row:first-child{border-top:0}
.row__n{color:var(--ink-3);font-size:.71875rem}
.row__it{font-weight:700;letter-spacing:.02em;text-transform:uppercase;font-size:.78125rem}
.row__st{display:block;font-weight:400;text-transform:none;letter-spacing:0;color:var(--ink-2);font-size:.78125rem;margin-top:3px}
.row__c{text-align:right;font-weight:700;font-size:.78125rem;white-space:nowrap}
.row__note{grid-column:2/-1;font-family:var(--sans);font-size:.875rem;line-height:1.5;color:var(--ink-2);margin-top:7px;
  border-left:2px solid rgba(184,83,26,.35);padding-left:11px}
.row--zero .row__c{color:var(--olive-lt)}
.row--nosold{
  background:linear-gradient(90deg,rgba(184,83,26,.16),rgba(184,83,26,.07));
  border-left:5px solid var(--orange);
  padding-left:9px;
}
.row--nosold:hover{background:linear-gradient(90deg,rgba(184,83,26,.22),rgba(184,83,26,.10))}
.row--nosold .row__it{color:var(--orange)}
.row--nosold .row__c{color:var(--orange);font-size:.875rem}
.log__ft{
  border-top:2px solid var(--ink);padding:14px 16px;font-family:var(--mono);font-size:.78125rem;
  display:flex;justify-content:space-between;gap:12px;flex-wrap:wrap;background:rgba(36,31,22,.06);
}
.log__ft b{letter-spacing:.06em}
.log__sig{font-family:var(--mono);font-size:.6875rem;color:var(--ink-3);padding:11px 16px;border-top:1px dashed var(--rule-soft)}
@media(max-width:520px){
  .log{background:linear-gradient(180deg,#f9f2e3,var(--paper))}
  .row{grid-template-columns:26px 1fr;gap:2px 9px;padding:11px 12px}
  .row__c{grid-column:2;text-align:left;margin-top:4px}
  .row--nosold{padding-left:7px}
}

/* ---------- the refusal ---------- */
.refuse{
  border:2px solid var(--orange);
  background:linear-gradient(180deg,#f9f1e1,var(--paper));
  border-radius:9px;
  padding:clamp(20px,3.4vw,32px);
  max-width:780px;
  position:relative;
  box-shadow:7px 7px 0 rgba(184,83,26,.20);
}
.refuse::after{
  content:"";position:absolute;left:0;right:0;top:0;height:5px;border-radius:7px 7px 0 0;
  background:repeating-linear-gradient(90deg,var(--orange) 0 15px,var(--orange-pale) 15px 26px);
}
.refuse__hd{
  font-family:var(--mono);font-size:.75rem;font-weight:700;letter-spacing:.14em;text-transform:uppercase;
  color:var(--orange);margin:0 0 14px;display:flex;align-items:center;gap:10px;flex-wrap:wrap;
}
.refuse__hd span{background:var(--orange);color:#fff;padding:5px 9px;border-radius:3px;letter-spacing:.1em;
  box-shadow:2px 2px 0 rgba(184,83,26,.32)}
.refuse p{font-size:clamp(1.03125rem,2.1vw,1.25rem);line-height:1.55;color:var(--ink)}
.refuse__side{display:flex;gap:18px;align-items:center;flex-wrap:wrap;margin-top:20px;padding-top:18px;border-top:2px dashed var(--rule)}
.refuse__side p{font-size:.90625rem;color:var(--ink-2);flex:1 1 240px;margin:0}
.band--dusk .refuse p,.band--olive .refuse p{color:var(--ink)}
.band--dusk .refuse a,.band--olive .refuse a{color:var(--orange)}

/* ---------- stops along the route ---------- */
.stops{list-style:none;margin:0;padding:0;position:relative}
.stop{position:relative;padding:0 0 34px 52px}
.stop::before{
  content:"";position:absolute;left:14px;top:30px;bottom:-4px;width:0;
  border-left:2px dashed var(--rule);
  transform:scaleY(1);transform-origin:top;
}
.stop:last-child{padding-bottom:0}
.stop:last-child::before{display:none}
.stop__mk{
  position:absolute;left:0;top:4px;width:30px;height:30px;border-radius:50%;
  background:linear-gradient(160deg,var(--paper),var(--sand-dk));border:2px solid var(--ink);
  display:grid;place-items:center;font-family:var(--mono);font-size:.6875rem;font-weight:700;color:var(--ink);
  box-shadow:2px 2px 0 rgba(36,31,22,.22);
  transition:transform var(--t-slow) var(--ease),background var(--t-slow) var(--ease),color var(--t-slow) var(--ease);
}
.stop:hover .stop__mk{background:var(--orange);border-color:var(--orange);color:#fff;transform:scale(1.1)}
.stop--on .stop__mk{background:var(--orange);border-color:var(--orange);color:#fff}
.band--olive .stop__mk,.band--dusk .stop__mk{background:linear-gradient(160deg,#4a5636,#333d25);border-color:#cfd6b8;color:var(--lite)}
.band--olive .stop::before,.band--dusk .stop::before{border-left-color:rgba(255,255,255,.3)}
.stop__hd{display:flex;align-items:center;gap:14px;margin-bottom:9px}
.stop__hd h3{margin:0;min-width:0}
.stop:hover .bdgwrap{transform:translateY(-3px) rotate(-2deg);box-shadow:5px 5px 0 rgba(36,31,22,.26)}
.stop h3{margin-bottom:7px}
.stop h3 a{text-decoration:none;border-bottom:2px solid rgba(184,83,26,.5);
  transition:border-color var(--t) var(--ease),color var(--t) var(--ease)}
.stop h3 a:hover{border-bottom-color:var(--orange)}
.stop p{font-size:.96875rem;color:var(--ink-2);max-width:62ch;margin-bottom:7px}
.band--olive .stop p,.band--dusk .stop p{color:var(--lite-2)}
.stop__mi{font-family:var(--mono);font-size:.6875rem;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3)}
.band--olive .stop__mi,.band--dusk .stop__mi{color:#b3b79a}
@media(min-width:820px){
  .stops--two{columns:2;column-gap:44px}
  .stops--two .stop{break-inside:avoid}
}

/* ---------- number panels ---------- */
.panels{display:grid;gap:20px;grid-template-columns:1fr}
@media(min-width:760px){.panels{grid-template-columns:repeat(3,1fr)}}
.panel{
  background:linear-gradient(180deg,#f9f2e2,var(--paper));
  border:2px solid var(--ink);border-radius:9px;padding:24px 22px;
  border-top:7px solid var(--orange);
  box-shadow:5px 5px 0 rgba(36,31,22,.18);
  transition:transform var(--t-slow) var(--ease),box-shadow var(--t-slow) var(--ease);
}
.band--dusk .panel,.band--olive .panel{box-shadow:5px 5px 0 rgba(0,0,0,.32)}
.panel:hover{transform:translateY(-3px);box-shadow:7px 9px 0 rgba(36,31,22,.22)}
.band--dusk .panel:hover,.band--olive .panel:hover{box-shadow:7px 9px 0 rgba(0,0,0,.36)}
.panel h3{margin-bottom:12px;font-size:1.03125rem;color:var(--ink)}
.panel p{font-size:.9375rem;color:var(--ink-2)}
.panel .code{
  font-family:var(--mono);font-weight:700;font-size:1.1875rem;letter-spacing:.08em;color:var(--ink);
  background:linear-gradient(180deg,var(--sand-lt),var(--sand));display:inline-block;padding:3px 9px;
  border-radius:3px;margin:0 1px;box-shadow:0 0 0 1px var(--rule-soft) inset;
}
.panel__fig{margin:0 0 14px}
.panel__fig svg{display:block;width:100%;height:auto}

/* generic two column */
.two{display:grid;gap:clamp(22px,3.6vw,48px);grid-template-columns:1fr}
@media(min-width:860px){.two{grid-template-columns:1.1fr .9fr}}
.side{
  background:linear-gradient(180deg,#f9f2e2,var(--paper));
  border:2px solid var(--ink);border-radius:9px;padding:24px 22px;align-self:start;
  box-shadow:5px 5px 0 rgba(36,31,22,.16);
}
.band--dusk .side,.band--olive .side{box-shadow:5px 5px 0 rgba(0,0,0,.3)}
.side h3{margin-bottom:14px;font-size:.9375rem;color:var(--ink)}
.side p,.side li{font-size:.90625rem;color:var(--ink-2)}
.band--dusk .side p,.band--dusk .side li{color:var(--ink-2)}
.side ul{margin:0;padding-left:1.05em}
.side li{margin-bottom:.5em}
.side a{color:var(--ink)}

/* mono facts list */
.facts{list-style:none;margin:0;padding:0;font-family:var(--mono);font-size:.8125rem}
.facts li{
  display:flex;justify-content:space-between;gap:14px;padding:10px 0;
  border-bottom:1px dashed var(--rule-soft);
  transition:padding-left var(--t) var(--ease),background var(--t) var(--ease);
}
.facts li:hover{background:rgba(184,83,26,.07);padding-left:5px}
.facts li b{font-weight:700;text-align:right}
.facts li:last-child{border-bottom:0}

/* faq */
.qa{border-top:2px dashed var(--rule);padding:26px 0;transition:background var(--t) var(--ease)}
.qa:last-of-type{border-bottom:2px dashed var(--rule)}
.qa h3{margin-bottom:9px}
.qa p{max-width:72ch;color:var(--ink-2)}
.band--dusk .qa p{color:var(--lite-2)}

/* reviews empty state */
.empty{
  border:2px dashed var(--rule);border-radius:9px;
  background:linear-gradient(180deg,#f9f2e2,var(--paper));
  padding:clamp(26px,4vw,46px);text-align:center;max-width:740px;
}
.empty__mk{
  width:56px;height:56px;margin:0 auto 18px;border:2px solid var(--rule);border-radius:50%;
  display:grid;place-items:center;font-family:var(--mono);font-size:1.25rem;color:var(--ink-3);
}
.empty h3{margin-bottom:11px}
.empty p{color:var(--ink-2);max-width:56ch;margin-left:auto;margin-right:auto;font-size:.96875rem}

/* form */
.form{background:linear-gradient(180deg,#f9f2e2,var(--paper));border:2px solid var(--ink);border-radius:9px;
  padding:clamp(20px,3.2vw,32px);max-width:740px;box-shadow:8px 8px 0 rgba(36,31,22,.18)}
.fld{margin-bottom:17px}
.fld label{display:block;font-family:var(--mono);font-size:.6875rem;letter-spacing:.14em;text-transform:uppercase;font-weight:700;margin-bottom:7px}
.fld input,.fld select,.fld textarea{
  width:100%;font-family:var(--sans);font-size:1rem;color:var(--ink);
  background:var(--sand-lt);border:2px solid var(--rule);border-radius:6px;padding:12px 13px;
  transition:border-color var(--t) var(--ease),background var(--t) var(--ease),box-shadow var(--t) var(--ease);
}
.fld input:hover,.fld select:hover,.fld textarea:hover{border-color:var(--ink-3)}
.fld input:focus,.fld select:focus,.fld textarea:focus{outline:3px solid var(--orange-lt);outline-offset:1px;background:#fff}
.fld textarea{min-height:120px;resize:vertical}
.fld__hint{font-size:.8125rem;color:var(--ink-3);margin-top:6px}
.formnote{
  font-family:var(--mono);font-size:.75rem;line-height:1.55;letter-spacing:.02em;
  background:linear-gradient(180deg,#312a1e,var(--ink));color:var(--sand-lt);
  padding:13px 15px;border-radius:6px;margin-bottom:22px;border-left:5px solid var(--orange);
}

/* footer */
.foot{background:linear-gradient(180deg,#3f4a2f,#2c3421);color:#d9d5c2;padding:52px 0 30px;font-size:.90625rem;position:relative}
.foot::before{content:"";position:absolute;left:0;right:0;top:0;height:3px;
  background:repeating-linear-gradient(90deg,var(--orange) 0 16px,rgba(184,83,26,.25) 16px 30px)}
.foot a{color:#efe9d7}
.foot a:hover{color:#ffd7a8}
.foot__grid{display:grid;gap:28px;grid-template-columns:1fr}
@media(min-width:760px){.foot__grid{grid-template-columns:1.3fr 1fr 1fr}}
.foot h4{color:#fff;margin-bottom:14px;font-size:.75rem;letter-spacing:.16em}
.foot ul{list-style:none;margin:0;padding:0}
.foot li{margin-bottom:7px}
.foot__rule{border:0;border-top:2px dashed rgba(255,255,255,.22);margin:32px 0 18px}
.foot__fine{font-family:var(--mono);font-size:.71875rem;line-height:1.6;color:#a9a892;letter-spacing:.02em}

/* ---------- chat launcher (bottom-LEFT: the host page owns bottom-right) ---------- */
.nbchat{position:fixed;left:16px;bottom:16px;z-index:9000;font-family:var(--sans);max-width:calc(100vw - 32px)}
.nbchat__btn{
  display:flex;align-items:center;gap:9px;background:linear-gradient(180deg,#312a1e,var(--ink));color:var(--sand-lt);
  border:2px solid var(--orange);border-radius:100px;padding:12px 18px;cursor:pointer;
  font-family:var(--sans);font-size:.78125rem;font-weight:700;letter-spacing:.11em;text-transform:uppercase;
  box-shadow:0 6px 18px rgba(0,0,0,.28);
  transition:transform var(--t) var(--ease),background var(--t) var(--ease),box-shadow var(--t) var(--ease);
}
.nbchat__btn:hover{background:linear-gradient(180deg,#48533a,var(--olive-dk));transform:translateY(-2px);box-shadow:0 9px 22px rgba(0,0,0,.32)}
.nbchat__btn i{width:9px;height:9px;background:var(--orange-lt);transform:rotate(45deg);display:block}
.nbchat__win{
  display:none;width:min(340px,calc(100vw - 32px));background:var(--paper);
  border:2px solid var(--ink);border-radius:11px;overflow:hidden;box-shadow:0 14px 34px rgba(0,0,0,.32);
}
.nbchat.is-open .nbchat__win{display:block}
.nbchat.is-open .nbchat__btn{display:none}
.nbchat__hd{background:linear-gradient(180deg,#312a1e,var(--ink));color:var(--sand-lt);padding:12px 13px;display:flex;align-items:center;gap:9px}
.nbchat__hd b{font-size:.75rem;letter-spacing:.12em;text-transform:uppercase}
.nbchat__hd small{font-family:var(--mono);font-size:.625rem;color:#bdb49a;display:block;letter-spacing:.08em}
.nbchat__x{margin-left:auto;background:none;border:0;color:#cfc7ae;font-size:1.1875rem;line-height:1;cursor:pointer;padding:2px 4px;
  transition:color var(--t) var(--ease)}
.nbchat__x:hover{color:#fff}
.nbchat__body{padding:13px;max-height:min(56vh,380px);overflow-y:auto}
.nbmsg{font-size:.90625rem;line-height:1.5;margin-bottom:11px;padding:10px 12px;border-radius:9px;max-width:92%}
.nbmsg--bot{background:var(--sand);color:var(--ink);border:1px solid var(--rule-soft)}
.nbmsg--me{background:var(--olive);color:#f1ecdc;margin-left:auto}
.nbopt{display:block;width:100%;text-align:left;margin-bottom:7px;background:var(--sand-lt);
  border:2px solid var(--rule);border-radius:8px;padding:10px 12px;font-family:var(--sans);
  font-size:.875rem;color:var(--ink);cursor:pointer;
  transition:border-color var(--t) var(--ease),background var(--t) var(--ease),transform var(--t) var(--ease)}
.nbopt:hover{border-color:var(--orange);background:#fff;transform:translateX(2px)}
.nbchat__form{display:flex;gap:6px;margin-bottom:8px}
.nbchat__form input{flex:1;min-width:0;font-size:.9375rem;padding:10px 11px;border:2px solid var(--rule);border-radius:8px;background:var(--sand-lt);color:var(--ink);font-family:var(--sans)}
.nbchat__form button{background:var(--orange);color:#fff;border:0;border-radius:8px;padding:0 15px;font-weight:700;font-size:.75rem;letter-spacing:.1em;text-transform:uppercase;cursor:pointer;font-family:var(--sans);
  transition:background var(--t) var(--ease)}
.nbchat__form button:hover{background:var(--orange-lt)}
.nbchat__ft{font-family:var(--mono);font-size:.625rem;letter-spacing:.06em;color:var(--ink-3);padding:0 13px 11px}
@media(max-width:430px){.nbchat{left:10px;bottom:10px;max-width:calc(100vw - 20px)}}

.skip{position:absolute;left:-9999px}
.skip:focus{left:8px;top:8px;position:fixed;z-index:99;background:var(--orange);color:#fff;padding:9px 13px;border-radius:4px}

/* =====================================================================
   MOTION
   Rule: the default state of every element is VISIBLE. Nothing below
   hides content. Animations only run once route.js has set .rv-js on
   <html> AND the element has been marked .is-in, and every one of them
   uses animation-fill-mode: backwards so the element is on screen the
   instant the animation is removed. If the script never runs, the page
   is simply the finished page.
   ===================================================================== */

@keyframes rvRise{from{opacity:0;transform:translateY(16px)}to{opacity:1;transform:none}}
@keyframes rvBadge{from{opacity:0;transform:translateY(-8px) scale(.86)}to{opacity:1;transform:none}}
@keyframes rvPin{
  0%{opacity:0;transform:translateY(-14px) rotate(-9deg) scale(.7)}
  62%{opacity:1;transform:translateY(2px) rotate(3deg) scale(1.05)}
  100%{opacity:1;transform:none}
}
@keyframes rvDrawX{from{transform:scaleX(0)}to{transform:scaleX(1)}}
@keyframes rvDrawY{from{transform:scaleY(0)}to{transform:scaleY(1)}}
@keyframes rvRoll{to{transform:rotate(360deg)}}
@keyframes rvSway{0%,100%{transform:translateX(0) rotate(0)}50%{transform:translateX(1.6px) rotate(1.1deg)}}
@keyframes rvBreathe{0%,100%{transform:scaleY(1)}50%{transform:scaleY(1.14)}}
@keyframes rvPulse{0%,100%{opacity:.55;transform:scale(1)}50%{opacity:1;transform:scale(1.16)}}

@media (prefers-reduced-motion: no-preference){

  /* waypoint headings: the badge drops in, then the dashed rule draws
     across to the next marker */
  .rv-js .wp.is-in .wp__badge{animation:rvBadge 420ms var(--ease) backwards}
  .rv-js .wp.is-in .wp__rule{animation:rvDrawX 620ms 120ms var(--ease) backwards}
  .rv-js .wp.is-in .wp__mk{animation:rvPin 460ms 480ms var(--ease) backwards}

  /* stops arrive one after the other, and the dashed route draws
     down from each waypoint to the next */
  .rv-js .stop.is-in .stop__mk{animation:rvPin 480ms var(--ease) backwards}
  .rv-js .stop.is-in .bdgwrap{animation:rvPin 520ms 90ms var(--ease) backwards}
  .rv-js .stop.is-in::before{animation:rvDrawY 700ms 200ms var(--ease) backwards}
  .rv-js .stop.is-in .stop__hd h3,
  .rv-js .stop.is-in p{animation:rvRise 460ms 130ms var(--ease) backwards}

  /* cards and figures ease up as their band arrives */
  .rv-js .panel.is-in,
  .rv-js .side.is-in,
  .rv-js .fig.is-in,
  .rv-js .slot.is-in,
  .rv-js .log.is-in,
  .rv-js .refuse.is-in,
  .rv-js .empty.is-in,
  .rv-js .form.is-in{animation:rvRise 560ms var(--ease) backwards}
  .rv-js .panel.is-in:nth-child(2){animation-delay:110ms}
  .rv-js .panel.is-in:nth-child(3){animation-delay:220ms}

  /* the log rows fill in top to bottom, like a sheet being written */
  .rv-js .log.is-in .row{animation:rvRise 340ms var(--ease) backwards}
  .rv-js .log.is-in .row:nth-child(1){animation-delay:180ms}
  .rv-js .log.is-in .row:nth-child(2){animation-delay:220ms}
  .rv-js .log.is-in .row:nth-child(3){animation-delay:260ms}
  .rv-js .log.is-in .row:nth-child(4){animation-delay:300ms}
  .rv-js .log.is-in .row:nth-child(5){animation-delay:340ms}
  .rv-js .log.is-in .row:nth-child(6){animation-delay:380ms}
  .rv-js .log.is-in .row:nth-child(n+7){animation-delay:420ms}

  /* ambient life in the hero badge — a parked rig, not a moving one */
  .rig-wheel{transform-box:fill-box;transform-origin:center;animation:rvRoll 26s linear infinite}
  .rig-grass{transform-box:fill-box;transform-origin:bottom center;animation:rvSway 7s ease-in-out infinite}
  .rig-grass--b{animation-duration:9.5s;animation-delay:-2.5s}
  .rig-awning{transform-box:fill-box;transform-origin:top center;animation:rvBreathe 6.5s ease-in-out infinite}
  .rig-dot{transform-box:fill-box;transform-origin:center;animation:rvPulse 3.6s ease-in-out infinite}
}

@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{
    animation-duration:.001ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.001ms !important;
    scroll-behavior:auto !important;
  }
  .routeprog{display:none}
  .hero::before{transform:none}
}


/* ═══ 📱 MOBILE MENU — added 8 Sep 2026. See tools/navfix notes.
   ⛔ Do not give this a colour. The panel IS this site's own <nav>, so it
   keeps this site's own paper and rules; the button rides on currentColor.
   ⛔ Do not raise the breakpoint without re-measuring — 860 is where these
   nav rows start wrapping, which is the thing being fixed. */
.navbtn { display: none; }
.navq { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
        overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
@media (max-width: 860px) {
  .navbtn {
    display: inline-flex; align-items: center; gap: .55rem;
    padding: .5rem .8rem; border-radius: .5rem; cursor: pointer;
    font: inherit; font-size: .82rem; letter-spacing: .06em; text-transform: uppercase;
    color: currentColor;
    border: 1px solid currentColor;
    background: transparent;
    opacity: .85;
  }
  .navbtn__ico { position: relative; width: 15px; height: 2px; background: currentColor; }
  .navbtn__ico::before, .navbtn__ico::after {
    content: ""; position: absolute; left: 0; width: 15px; height: 2px; background: currentColor;
  }
  .navbtn__ico::before { top: -5px; }
  .navbtn__ico::after  { top:  5px; }
  .navq:focus-visible + .navbtn { outline: 2px solid currentColor; outline-offset: 2px; }

  /* the demo's own nav, closed */
  nav[aria-label="Main"], nav[aria-label="Primary"] { display: none; }
  .navq:checked ~ nav[aria-label="Main"],
  .navq:checked ~ nav[aria-label="Primary"] { display: block; width: 100%; }

  /* ⚠️ the lists inside are flex rows on every one of these sites; they have to
     stack, and the row gap has to become a tap target. */
  nav[aria-label="Main"] ul, nav[aria-label="Primary"] ul {
    display: block; margin: 0; padding: 0; list-style: none;
  }
  nav[aria-label="Main"] li, nav[aria-label="Primary"] li { display: block; }
  nav[aria-label="Main"] li a, nav[aria-label="Primary"] li a,
  nav[aria-label="Main"] > a, nav[aria-label="Primary"] > a {
    display: block; padding: .7rem .2rem; line-height: 1.2;
  }
  nav[aria-label="Main"] li + li, nav[aria-label="Primary"] li + li {
    border-top: 1px solid currentColor;
  }
  nav[aria-label="Main"] li + li, nav[aria-label="Primary"] li + li { border-top-color: color-mix(in srgb, currentColor 18%, transparent); }
}


/* ═══ 🔤 NAV TYPE PASS 9 Sep 2026 — size and tracking only.
   ⛔ Do not add colour, family, case or weight here: those are what keep these
   twelve sites from converging, and converging is the thing that was fixed
   once already. Measured before: 11–12.5px with tracking wide enough that
   the label read as separate letters rather than a word. */
nav[aria-label="Main"] a,
nav[aria-label="Primary"] a {
  font-size: .8125rem;
  letter-spacing: .1em;
}

/* ══════════════════════════════════════════════════════════════════════════
   ⭐ THE PROFESSIONAL PASS — 11 Sep 2026.
   Measured against the reference client rebuild, this demo was missing four things:
     1. no brand MARK — the plate in the header held the letters "NB", which
        is a wordmark shrunk down, not a mark
     2. no offer strip, so nothing said what you actually get before scroll
     3. the accent was a highway orange floating over a clay-and-sand page
     4. no real shadow under the hero rig — it sat ON the page, not IN it
   ⚠️ LIGHT GROUND. The roofing template's strip and button are dark
   gradients; both are re-derived here over sand. Small accent type uses
   --orange-dk, never --orange: on this paper --orange is 4.6:1 and the strip
   tag is 10.5px mono.
   ⛔ No photograph closes this gap. Every badge on this site is drawn.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── the mark ─────────────────────────────────────────────────────────── */
/* A route shield with a dashed enamel keyline and a compass needle pointing
   north, because the shop is called Northbound. currentColor throughout, so
   the enamel plate recolours it with one property. */
.brand__mk{color:var(--orange-dk);border-color:var(--orange)}
.nav__mark{display:block;width:26px;height:26px;flex:0 0 auto;color:inherit}
.brand:hover .brand__mk{color:var(--orange)}

/* ── the headline carries the colour ──────────────────────────────────── */
/* ⚠️ `.hero h1 em` upstream is 0,1,2 and sets both the colour and the block
   display that gives the second line its own row. `.hero h1 .hl` is 0,2,2, so
   it wins the colour — and it has to REPEAT display:block or the line rejoins
   the first one and the sentence loses its beat. */
h1 .hl{font-style:normal;color:var(--orange)}
.hero h1 .hl{font-style:normal;color:var(--orange);display:block}

/* ── the offer strip ──────────────────────────────────────────────────── */
/* ⭐ the reference site's coupon bar in this shop's own words. Both clauses are lifted: the
   first off the home page hero, the second off the services page. ⛔ It must
   never carry a price, a rating or a count this demo has not published. */
.offerbar{
  border-bottom:1px solid var(--rule-soft);
  background-image:linear-gradient(180deg,
    color-mix(in srgb, var(--orange) 7%, var(--paper)),
    color-mix(in srgb, var(--orange) 13%, var(--sand-lt)));
}
.offerbar__in{display:flex;align-items:center;gap:14px;flex-wrap:wrap;padding-top:10px;padding-bottom:10px}
.offerbar__tag{
  font-family:var(--mono);font-size:.65625rem;text-transform:uppercase;letter-spacing:.14em;
  color:var(--orange-dk);background:var(--paper);
  border:1px solid color-mix(in srgb, var(--orange) 45%, transparent);
  border-radius:999px;padding:3px 9px;flex:0 0 auto;
}
.offerbar__msg{margin:0;font-size:.84375rem;line-height:1.45;color:var(--ink-2);flex:1 1 340px;min-width:0}
.offerbar__msg b{color:var(--ink);font-weight:700}
.offerbar__go{
  flex:0 0 auto;font-family:var(--mono);font-size:.71875rem;text-transform:uppercase;
  letter-spacing:.09em;color:var(--orange-dk);text-decoration:none;white-space:nowrap;
  border-bottom:1px solid color-mix(in srgb, var(--orange) 55%, transparent);padding-bottom:2px;
}
.offerbar__go:hover{color:var(--orange);border-bottom-color:var(--orange)}
@media (max-width:640px){
  .offerbar__go{display:none}        /* the hero button is a screen below it */
  .offerbar__msg{font-size:.78125rem}
}

/* ── the primary button is the accent ─────────────────────────────────── */
/* ⚠️ THE GRADIENT IS WHAT DECIDES THE CONTRAST, NOT THE TOKEN. White on
   --orange is 5.4:1 but white on --orange-lt is only 4.0:1, and the old button
   put --orange-lt at the TOP — so the first rows of a 12.5px uppercase label
   failed AA while the swatch it was "made of" passed. Start the ramp lower.
   Hover goes DARKER, not lighter, for the same reason; the lift and the
   shadow on .btn--go:hover upstream are what signal the hover. */
.btn--go{
  background:linear-gradient(180deg,#c55032,var(--orange));   /* 4.6:1 → 5.4:1 */
  border-color:rgba(0,0,0,.22);color:#fff;
}
.btn--go:hover{
  background:linear-gradient(180deg,var(--orange),var(--orange-dk));  /* 5.4 → 6.1 */
  color:#fff;
}

/* ── depth on the drawn hero ──────────────────────────────────────────── */
/* ⭐ The plate had a flat 10px offset, which is a sticker. A cast shadow plus
   a touch of contrast is what separates the reference site's rendered instrument from a
   vector pasted onto a page. */
.rigwrap{
  box-shadow:0 10px 0 rgba(36,31,22,.10),
             0 2px 0 rgba(255,255,255,.5) inset,
             0 30px 50px -26px rgba(36,31,22,.55);
}
.rigsvg{filter:contrast(1.04) saturate(1.05)}

/* 🔴 AND THE GHOST HAS TO BE RESTATED AFTER IT. `.btn--out` is declared ~460
   lines above; the `.btn--go` rule in this block is the SAME specificity and
   LATER in an unlayered file, so anything they share is decided by source
   order alone. Restating the outline here is what keeps ONE primary on the
   page. ⛔ Any future `.btn`/`.btn--go` rule appended below must restate it
   again. ⚠️ `.band--olive .btn--out` and `.band--dusk .btn--out` upstream are
   0,2,0 and still win on the dark bands — that is correct, leave them. */
.btn--out{
  background:transparent;border-color:var(--ink);color:var(--ink);
  box-shadow:0 3px 0 rgba(36,31,22,.16);
}
.btn--out:hover{
  background:var(--ink);color:var(--sand-lt);box-shadow:0 5px 0 rgba(36,31,22,.26);
}

@media (prefers-reduced-motion:reduce){
  .brand:hover .brand__mk{transform:none}
}

/* ── 🛞 THE DAY, AS THE CUSTOMER HAS IT — 11 Sep 2026 ─────────────────────
   ⭐ The old h1 led with the LOG — our proof, and the best thing about this
   shop, but a log is not what anybody wakes up wanting. What a person buys from
   an RV shop is the trip they do not have to cancel; the log is how they know
   the trip is safe. So the headline names the trade and the town, the accent
   carries the trip, and this section walks the pre-trip day hour by hour.
   ⛔ Every beat is something three bays and a van could really do in a day, and
   every reading in it is already on the example log further down this page.
   Nothing here says a slot is held — this shop's own "what we will not do" list
   ends with "tell you a slot is held before it is written on the board", and
   that sentence governs this section too.
   10:35 is the REFUSAL: line 03, six tires, not sold, $0.00.
   ⭐ GROUND. The bands run as a route through a day — morning paper, midday
   sand, afternoon clay, scrub, evening, night — and this one is inserted at the
   very start of it, so it is drawn on --paper: the log sheet itself, brighter
   than the sand that follows, which is what makes it read as a step and not a
   repeat of the band below. */
.band--day{background:linear-gradient(180deg,#f9f3e5 0%,var(--paper) 56%,#ece2c9 100%)}
.band--day .wp__badge{background:var(--orange);color:#fff}

.day{list-style:none;margin:0;padding:0;display:grid;gap:0}
.day__i{
  display:grid;grid-template-columns:4.5rem 1fr;gap:0 1.5rem;
  padding:18px 0;border-top:2px dashed var(--rule-soft);align-items:start;
}
.day__i:first-child{border-top:2px solid var(--rule)}
.day__t{
  font-family:var(--mono);font-size:.78125rem;font-weight:700;letter-spacing:.12em;
  color:var(--ink-3);padding-top:3px;font-variant-numeric:tabular-nums;
}
.day__i h3{font-size:clamp(1.0625rem,2.1vw,1.25rem);line-height:1.25;margin:0 0 7px;color:var(--ink)}
.day__i p{margin:0;font-size:.96875rem;line-height:1.62;color:var(--ink-2);max-width:64ch}
/* ⛔ the route-marker orange is this site's refusal colour as well as its
   waypoint colour — the declined line gets it, and so does the one marked beat */
.day__i--no .day__t{color:var(--orange-dk)}
.day__i--no h3{color:var(--orange-dk)}
/* ⭐ ONE marked beat, and it is the tow-out: the moment "the trip you do not
   cancel" stops being a headline and becomes a rig on the hitch. */
.day__i--live .day__t{color:var(--orange-dk)}
.day__i--live .day__t::after{
  content:"";display:block;width:9px;height:9px;background:var(--orange);
  transform:rotate(45deg);border-radius:2px;margin:9px 0 0 1px;
  box-shadow:0 0 0 3px rgba(184,68,43,.18);
}
.day__foot{
  margin:0;padding-top:18px;border-top:2px solid var(--rule);
  font-size:.96875rem;line-height:1.62;color:var(--ink-2);max-width:68ch;
}
.day__foot b{color:var(--ink)}
@media (max-width:560px){
  .day__i{grid-template-columns:1fr;gap:5px}
  .day__t{padding-top:0}
  .day__i--live .day__t::after{display:inline-block;margin:0 0 -1px 9px;vertical-align:middle}
}

/* 🔴 THE GRID HAD THREE CHILDREN AND TWO COLUMNS. `.day__i` holds a timestamp,
   an <h3> and a <p>. Auto-placement puts the timestamp at 1/1, the heading at
   1/2 and then wraps the PARAGRAPH back to 2/1 — the timestamp column — so every
   beat's prose rendered in an 84px ribbon one or two words wide and ~330px tall.
   It looked like a layout, so nothing about it read as an error.
   ⛔ Both text children must be pinned to column 2 explicitly. Never rely on
   auto-placement to keep a two-column row on one row. */
.day__i h3,.day__i p{grid-column:2}
@media (max-width:560px){ .day__i h3,.day__i p{grid-column:1} }


/* ── 📷 REVIEWED PHOTOGRAPHS ──────────────────────────────────────────────
   Fetched under commercial-use licences, culled BY EYE from a contact sheet,
   downloaded locally (the sync guard refuses an external <img>, and a remote
   image inside an iframe fails as a blank box with no error).
   ⚠️ Any CC-BY image carries its credit in the frame. Attribution is a licence
   term, not a courtesy. */
.photoband{position:relative;margin:0;line-height:0}
.photoband img{width:100%;height:clamp(190px,25vw,320px);object-fit:cover;display:block;filter:saturate(1.02) contrast(1.02)}
.photoband__cr{position:absolute;right:8px;bottom:8px;font-size:.625rem;line-height:1.4;color:rgba(255,255,255,.82);background:rgba(0,0,0,.55);padding:3px 7px;border-radius:3px}
.photoband__cr a{color:inherit}

/* ── 📷 PHOTOGRAPHS ───────────────────────────────────────────────────────
   🔴 11 Sep 2026. Owner: "need photos!!" and "no stick diagrams". This demo
   shipped with none, and a page of line drawings reads as a prototype rather
   than as a business's site.

   ⭐ PORTABLE ON PURPOSE. Thirteen demos, thirteen different token names —
   --soil/--panel/--hair here, --paper/--rule/--gr there, light and dark both.
   A component written against one demo's variables is a component that has to
   be rewritten twelve times and will be wrong in four of them. So this uses
   `currentColor` and plain rgba, and inherits the page's own ink.

   ⛔ Every CC BY / CC BY-SA frame carries its credit IN the frame. Attribution
   is a licence term, not a courtesy, and "we'll add the credits later" is
   exactly how a licence gets breached. */
.photo{position:relative;margin:0;line-height:0;border-radius:4px;overflow:hidden;
  border:1px solid rgba(128,128,128,.28)}
.photo img{width:100%;display:block;object-fit:cover;filter:saturate(1.03) contrast(1.02)}
.photo--hero img{height:clamp(260px,34vw,430px)}
.photo--band img{height:clamp(190px,26vw,320px)}
.photo--tall img{height:clamp(240px,30vw,380px)}
/* ⚠️ the badge carries its OWN scrim rather than the frame carrying a gradient.
   A gradient tuned for a dark ground turns a light photo muddy along the bottom,
   and half these demos are light. */
.photo__cr{position:absolute;right:8px;bottom:8px;z-index:2;
  font-size:.59375rem;letter-spacing:.04em;line-height:1.45;font-weight:500;
  color:rgba(255,255,255,.88);background:rgba(0,0,0,.52);padding:3px 7px;border-radius:2px;
  text-shadow:0 1px 2px rgba(0,0,0,.5)}
.photo__cr a{color:inherit;text-decoration:underline;text-underline-offset:2px}
.photo__cap{line-height:1.55;font-size:.78125rem;opacity:.72;padding-top:9px}

/* ── 🚪 THE WAY OUT STAYS ON SCREEN ───────────────────────────────────────
   🔴 11 Sep 2026, owner: "need to be able and x out of all the demo sites if
   you view on mobile dont let people get stuck somewher with out easy exit."

   This banner is the only route from a demo back to us, and it sat at the top
   of the document as a static block. On a phone, two swipes down a service page
   and it is gone — a visitor who arrived on a shared link has no way back and
   no reason to think one exists. ⚠️ The link was always there and was always
   unreachable, which is the same shape as the embed's close button being parked
   off-screen above the iframe.

   ⭐ Sticky on phones only. On a desktop the banner is in view at the top of a
   page people can see all of, and pinning it would just spend vertical room. */
@media (max-width: 640px) {
  .demostrip {
    position: sticky;
    top: 0;
    z-index: 90;
  }
  /* ⚠️ AND THE LINK HAS TO BE HITTABLE, NOT MERELY PRESENT. It is inline text
     inside a sentence, so on a 375px screen it wrapped into two fragments 15px
     tall — measured, both genuinely tappable, and both far under the 44px a
     thumb needs. ⭐ Make it a control: one line, real padding, no wrap. */
  .demostrip a {
    display: inline-block;
    margin-top: 4px;
    padding: 11px 12px;
    white-space: nowrap;
    font-weight: 700;
  }
}


/* 🔴 INSIDE OUR OWN FRAME THE BANNER IS DUPLICATE — 11 Sep 2026. Owner, looking
   at the embed on the home page: "take all of this off this is awfull they know
   that". He is right about that surface: our own chrome prints a disclosure
   directly under the frame, in our voice, so the demo's banner made two stacked
   notices — which reads as nervous rather than as honest.
   ⛔ A STANDALONE PAGE KEEPS IT. There the banner is the ONLY notice, and these
   pages carry a live telephone line: an invented business with a working number
   and nothing saying so is a trap, not a demo.
   ⚠️ Fails in the honest direction — with JavaScript off, nothing is hidden.
   ⛔ If the note under the frame is ever removed, delete this rule first. */
html[data-embedded] .demostrip { display: none !important; }


/* ── 🧭 THE UTILITY BAR — 15 Sep 2026 ─────────────────────────────────
   Written by tools/demo-utilbar.mjs. See that file for why the disclosure
   banner became a chip and why hours are absent on the demos that publish none.
   ⛔ Self-contained colour on purpose: every demo means something different by
   --ink, and borrowing it painted this a different thing on each site. */
.utilbar{background:#0f1b2a;color:rgba(255,255,255,.92);
  border-bottom:1px solid rgba(255,255,255,.14);font-size:.78rem;line-height:1.4;
  font-family:system-ui,-apple-system,"Segoe UI",sans-serif}
.utilbar__in{display:flex;align-items:center;justify-content:space-between;
  gap:.9rem;min-height:38px;padding:.3rem 20px;flex-wrap:wrap;
  max-width:1180px;margin:0 auto}
.utilbar__hours{margin:0;display:flex;align-items:center;gap:.45rem;min-width:0}
.utilbar__hours b{font-weight:600;color:#fff}
.utilbar__sep{opacity:.45}
.utilbar__hours>span:last-child{opacity:.72}
.utilbar__right{display:flex;align-items:center;gap:.9rem;flex-wrap:wrap;min-width:0}
.utilbar__lnk{color:rgba(255,255,255,.88);text-decoration:none;
  border-bottom:1px solid rgba(255,255,255,.26);padding-bottom:1px}
.utilbar__lnk:hover{color:#fff;border-bottom-color:#fff}
/* ⭐ colour is never the only carrier — the words say Open or Closed outright */
.utilbar__dot{width:8px;height:8px;border-radius:50%;flex:0 0 auto;background:#7fe0a8}
.utilbar__hours[data-state="open"] .utilbar__dot{background:#7fe0a8;animation:utilpulse 3s ease-out infinite}
.utilbar__hours[data-state="soon"] .utilbar__dot{background:#ffc861}
.utilbar__hours[data-state="shut"] .utilbar__dot{background:#9aa6b1}
@keyframes utilpulse{0%{box-shadow:0 0 0 0 rgba(127,224,168,.5)}
  70%{box-shadow:0 0 0 6px rgba(127,224,168,0)}100%{box-shadow:0 0 0 0 rgba(127,224,168,0)}}
@media (prefers-reduced-motion:reduce){.utilbar__dot{animation:none !important}}
.utilbar .demostrip{display:inline-flex;align-items:center;gap:.4rem;
  padding:.16rem .55rem;border-radius:999px;background:rgba(255,255,255,.10);
  border:1px solid rgba(255,255,255,.22);font-size:.72rem;color:#fff;
  text-decoration:none;cursor:pointer}
.utilbar .demostrip:hover{background:rgba(255,255,255,.18);border-color:rgba(255,255,255,.38)}
.utilbar .demostrip b{text-transform:uppercase;letter-spacing:.08em;font-size:.68rem;font-weight:700}
.utilbar .demostrip__dot{width:7px;height:7px;border-radius:50%;background:#ff6a55;display:block}
@media (max-width:860px){
  /* ⛔ the TAIL hides, never the notice — and the chip becomes the link to it */
  .utilbar__demotail{display:none}
  .utilbar__in{gap:.55rem}
  .utilbar__right{gap:.7rem}
  .utilbar .demostrip{min-height:30px}
}
@media (max-width:560px){
  .utilbar{font-size:.72rem}
  .utilbar__hours>span:last-child,.utilbar__sep{display:none}
  .utilbar .demostrip{min-height:34px;padding-inline:.7rem}
}
/* ⛔ Inside our own iframe the surrounding chrome carries the disclosure, so the
   chip is hidden there and ONLY there. A standalone page always keeps it. */
html[data-embedded] .utilbar .demostrip{display:none !important}

/* 🔴 NO STATUS LIGHT WITHOUT A STATUS — 15 Sep 2026. Six of these demos publish
   no hours at all, and one publishes "by appointment". The dot is a status
   light: green, beside a company name with nothing behind it, it silently says
   OPEN NOW about a business whose hours nobody ever wrote. It only appears once
   the script has decided a real state from real published hours.
   ⚠️ This shipped for one sync because the fix was written into a script that
   died on an assertion BEFORE the file was saved — the edit was reported and
   never landed. Verify the artefact, not the log line. */
.utilbar__hours:not([data-state]) .utilbar__dot{display:none}


/* ── 🖼️ THE PHOTOGRAPH IS THE HERO — 15 Sep 2026 ─────────────────────────
   Written by tools/demo-photo-hero.mjs; the reasoning lives there. */
.lanaihero{position:relative;isolation:isolate;display:flex;flex-direction:column;justify-content:center;
  min-height:clamp(330px,62vh,600px);overflow:hidden;background:#07182a}
.lanaihero>img{position:absolute;inset:0;z-index:0;width:100%;height:100%;
  object-fit:cover;object-position:center 58%}
/* 🔴 TWO GRADIENTS, BOTH LOAD-BEARING. The horizontal one carries the headline;
   the vertical one holds the eyebrow and the buttons, which sit where the
   horizontal scrim has already thinned out. */
.lanaihero__scrim{position:absolute;inset:0;z-index:1;
  background:
    linear-gradient(90deg, rgba(5,18,32,.93) 0%, rgba(5,18,32,.86) 38%,
                           rgba(5,18,32,.46) 70%, rgba(5,18,32,.24) 100%),
    linear-gradient(0deg,  rgba(5,18,32,.42) 0%, rgba(5,18,32,.30) 50%,
                           rgba(5,18,32,.14) 100%)}
/* ⛔ padding-block, never the shorthand — a `padding: X 0 Y` here wipes the
   horizontal gutter the wrap class contributes and every line goes flush to the
   edge of the screen. That shipped once. */
.lanaihero__in{position:relative;z-index:2;
  padding-block:clamp(2rem,5vw,3.4rem) clamp(1.9rem,4.5vw,3rem)}
.lanaihero h1{color:#fff;max-width:20ch;text-wrap:balance}
.lanaihero .h1__where{color:#fff}
.lanaihero .hl{color:rgba(255,255,255,.74)}
.lanaihero .eyebrow,.lanaihero .lbl,.lanaihero .kicker{color:rgba(255,255,255,.88)}
.lanaihero .btnrow,.lanaihero .hero__act{margin-top:1.4rem;display:flex;flex-wrap:wrap;gap:.7rem}
/* ⛔ A ghost/outline button is a hairline on paper; over a photograph it
   disappears. WCAG 2.2 asks 3:1 for the control's own boundary, not just its
   label. */
.lanaihero .btn--ghost,.lanaihero .btn--line,.lanaihero .btn--out{
  border-color:rgba(255,255,255,.62);color:#fff;background:rgba(7,22,38,.42);
  -webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}
.lanaihero .btn--ghost:hover,.lanaihero .btn--line:hover,.lanaihero .btn--out:hover{
  background:rgba(7,22,38,.66);border-color:#fff}
.lanaihero .photo__cr{position:absolute;right:10px;bottom:9px;z-index:3;
  font-size:.625rem;color:rgba(255,255,255,.8);background:rgba(0,0,0,.5);
  padding:3px 7px;border-radius:3px}
.lanaihero .photo__cr a{color:inherit}
@media (max-width:640px){
  /* ⚠️ At phone width the headline spans the full column, so a left-weighted
     gradient leaves its right-hand words over bright sky. Mostly vertical here. */
  .lanaihero{min-height:clamp(300px,52vh,420px)}
  .lanaihero__scrim{background:
    linear-gradient(0deg, rgba(5,18,32,.80) 0%, rgba(5,18,32,.72) 50%,
                          rgba(5,18,32,.55) 100%),
    linear-gradient(90deg, rgba(5,18,32,.55) 0%, rgba(5,18,32,.30) 100%)}
  .lanaihero h1{max-width:none}
}




/* 🔴 THE HERO BUTTONS — 15 Sep 2026. Owner: "make sure the buttons are spread
   out and even across heros", "not sqished into the tiltles".
   Measured at 1280 before touching anything: rv-powersports had its buttons
   touching the headline at a gap of ZERO, because its row is `.hero__cta` and
   the rule only named `.btnrow` and `.hero__act`. The rest sat at 22px with an
   11px gap between them and heights running 40 to 53.
   ⭐ One rule, all three row names, and a floor under the height so a row of
   buttons reads as a row rather than as two different controls. */
.lanaihero .btnrow,
.lanaihero .hero__act,
.lanaihero .hero__cta{
  margin-top:clamp(1.6rem,2.6vw,2.2rem);
  display:flex; flex-wrap:wrap; align-items:center;
  gap:.85rem;
}
.lanaihero .btn{
  min-height:48px;
  display:inline-flex; align-items:center; justify-content:center;
  padding-inline:1.25rem;
}
@media (max-width:560px){
  /* ⚠️ Full width and stacked on a phone — two half-width buttons side by side
     put both under the 48px the thumb needs in the direction that matters. */
  .lanaihero .btnrow,.lanaihero .hero__act,.lanaihero .hero__cta{gap:.65rem}
  .lanaihero .btn{width:100%}
}


/* ── 👥 THE SOCIAL MARKS — 15 Sep 2026. Owner: "put fake no link social on the
   headers", after twice being told there is nowhere honest to point them.
   ⛔ THEY ARE NOT LINKS, AND THAT IS THE POINT. These companies are invented,
   so a social icon could only lead to an invented profile, to somebody else's
   real account, or to nothing — and a control that goes nowhere is worse than
   no control. They are `<span>` marks, `aria-hidden`, not focusable and not
   clickable: an illustration of where a real client's profiles sit in the bar,
   on a page that already says it is a demonstration.
   ⛔ Do not turn these into <a> on a real build without real profiles behind
   them. Bots On Staff's own Facebook and Instagram have never published once. */
.utilbar__social{display:inline-flex;align-items:center;gap:.55rem;opacity:.62}
.utilbar__social svg{width:15px;height:15px;display:block}
@media (max-width:560px){ .utilbar__social{display:none} }


/* 🔴 THE GHOST BUTTON, RESTATED BELOW `.btn` — 15 Sep 2026.
   The polish gate refused four demos for this and it was right: adding a
   `.lanaihero .btn` block after the ghost rules puts the outline variant at the
   mercy of source order in unlayered CSS. It happens that the block above sets
   no background, so nothing rendered wrong — but "it happens to be fine" is not
   a property anyone can rely on while editing this file later.
   ⛔ Any new `.btn` rule goes ABOVE this, or this moves below it. */
.lanaihero .btn--ghost,
.lanaihero .btn--line,
.lanaihero .btn--out{
  border-color:rgba(255,255,255,.62);
  color:#fff;
  background:rgba(7,22,38,.42);
  -webkit-backdrop-filter:blur(3px); backdrop-filter:blur(3px);
}
.lanaihero .btn--ghost:hover,
.lanaihero .btn--line:hover,
.lanaihero .btn--out:hover{background:rgba(7,22,38,.66);border-color:#fff}

.lanaihero .btn--ghost{
  border-color:rgba(255,255,255,.62);
  color:#fff;
  background:rgba(7,22,38,.42);
}


/* ── 📣 THE OFFER BAND, ON THE PHOTOGRAPH — 15 Sep 2026 ──────────────────────
   Owner: "i dont think it needs the white section evry vist", then "figure it
   out in a great spot dont just throw it somewhere be creative".
   🔴 IT CANNOT SIMPLY GO. The polish gate requires an offer strip on every page
   and it is right to — it is the one line on a demonstration site that says what
   the shop actually promises. But as a white slab wedged between the header and
   the hero it interrupted the only picture on the page before anyone had seen it.
   ⭐ So it is pinned to the FOOT of the hero, over the photograph, on the same
   dark glass as the scrim. The promise now reads as part of the image instead of
   as an announcement above it, and the page opens header -> photograph -> story
   with nothing cutting across.
   ⛔ Its own backdrop is near-opaque on purpose: type over a photograph is the
   one thing on this estate that has been measured wrong twice, and a band that
   carries its own ground cannot drift when the picture changes. */
.lanaihero{padding-bottom:0}
.lanaihero .offerbar{
  position:absolute; left:0; right:0; bottom:0; z-index:3;
  background:rgba(6,19,34,.86);
  -webkit-backdrop-filter:blur(10px); backdrop-filter:blur(10px);
  border-top:1px solid rgba(255,255,255,.16);
  border-bottom:0;
}
.lanaihero .offerbar__in{
  display:flex; align-items:center; gap:1rem; flex-wrap:wrap;
  padding-block:.7rem;
}
.lanaihero .offerbar__tag{
  color:#fff; border-color:rgba(255,255,255,.45); background:rgba(255,255,255,.10);
}
.lanaihero .offerbar__msg{color:rgba(255,255,255,.92); margin:0}
.lanaihero .offerbar__msg b{color:#fff}
.lanaihero .offerbar__go{color:#fff; border-color:rgba(255,255,255,.5)}
/* ⚠️ the hero's own content must clear the band, or the buttons sit under it */
.lanaihero__in{padding-bottom:clamp(5.5rem,9vw,7rem)}
@media (max-width:860px){
  /* ⛔ On a phone the band would eat the picture. It goes back into the flow
     directly beneath the hero — still out from between the header and the photo,
     which is the thing that was wrong. */
  .lanaihero .offerbar{position:static;backdrop-filter:none;-webkit-backdrop-filter:none}
  .lanaihero__in{padding-bottom:clamp(1.9rem,4.5vw,3rem)}
}


/* 🎨 THE HEADER IS NO LONGER OLIVE — 15 Sep 2026. Owner: "no green header make
   it a nicer color". ⭐ The replacement comes out of this site's OWN palette
   rather than off a colour wheel: --dusk / --dusk-2, the deep warm brown that
   already sits under the sand and clay. It reads as leather and dusk rather than
   as army surplus, and it is the ground the orange was mixed for — #b8442b on
   olive was two mid-tones arguing; on dusk it is the only bright thing there. */
.top{border-bottom:1px solid rgba(0,0,0,.4)}
.top .callnum{background:var(--orange);border-color:var(--orange-dk);color:#fff}
.top .callnum:hover{background:var(--orange-lt)}


/* ══ 🧭 THE HEADER, 2026 — 15 Sep 2026 ══════════════════════════════════════
   Owner: "the header need to be way better on each site look like proper 2026
   header trends", "make sure everyting looks as goos as outr customer sites".
   🔴 MEASURED FIRST, ALL TWELVE AT 1280: heights ran from 62px to 223px, only
   one was sticky, and eleven carried a telephone number that the new utility bar
   was already showing a few pixels above it.
   ⭐ This layer is keyed on the `header` ELEMENT, not on a class, because these
   demos call it .site, .top, .mast, .nav and .masthead — five names for one
   thing. Anything that needs a class name is done per demo.
   ⛔ It is deliberately visual-only: sticky, glass, a hairline that appears on
   scroll, and honest focus rings. It does not re-order anybody's markup. */
header{
  position:sticky; top:0; z-index:60;
  -webkit-backdrop-filter:saturate(1.3) blur(10px);
  backdrop-filter:saturate(1.3) blur(10px);
  transition:box-shadow .22s ease, border-color .22s ease;
}
/* ⭐ The rule under the header only appears once you have scrolled — a border
   that is always there is chrome, a border that arrives is depth. */
header::after{
  content:""; position:absolute; left:0; right:0; bottom:-1px; height:1px;
  background:currentColor; opacity:0; transition:opacity .22s ease;
  pointer-events:none;
}
html[data-scrolled] header::after{opacity:.16}
html[data-scrolled] header{box-shadow:0 10px 30px -22px rgba(0,0,0,.55)}

/* ⛔ 44px is not decoration. WCAG 2.2 §2.5.8, and on a phone this is the only
   navigation there is. */
@media (max-width:900px){
  header nav a{min-height:44px;display:flex;align-items:center}
}
/* a focus ring that is visible on both a light and a dark header */
header a:focus-visible, header button:focus-visible, header label:focus-visible{
  outline:2px solid currentColor; outline-offset:3px; border-radius:6px;
}


/* 🔴 STICKY WAS LOSING ON SPECIFICITY — 15 Sep 2026. `header{position:sticky}`
   is (0,0,1) and these demos set `.top{position:relative}` at (0,1,0), so five
   of twelve silently stayed put while the other seven pinned. Measured, not
   assumed: auto-detailing, drain-cleaning, mobile-repair, plumbing-hvac and
   rv-powersports all read `relative` after the layer went in.
   ⭐ `header[class]` is (0,1,1) and beats a single class without reaching for
   !important, which would then have to be fought later. */
header[class]{position:sticky;top:0;z-index:60}

/* 🔴 THE OFF-CANVAS MENU WAS WIDENING THE PAGE. Parked at translateX(102%) the
   panel still counted toward scrollWidth — 700px against a 371px viewport — so
   the whole site scrolled sideways on a phone with nothing visible to scroll to.
   ⛔ `overflow-x:hidden` would fix it and break `position:sticky` in the same
   stroke; `clip` does not create a scroll container, so the header still pins. */
html{overflow-x:clip}


/* 🔴 THE NAV WAS WRAPPING ONTO ITS OWN ROW — 15 Sep 2026, measured at 1280.
   These headers are flex rows that ran out of width, so the navigation dropped
   beneath the brand and the header doubled in height: 134, 138, 104, 223.
   A sticky header that tall eats a quarter of a laptop screen, and it is the
   clearest difference between these and the client sites.
   ⭐ One row, and the NAV is the part allowed to give — `min-width:0` lets it
   shrink, and if it still will not fit it scrolls sideways within itself rather
   than pushing the whole header down. ⛔ `scrollbar-width:none` hides the bar,
   not the ability to scroll; the items remain reachable by wheel, trackpad,
   touch and keyboard. */
@media (min-width:901px){
  header .top__in,
  header .masthead__row,
  header .brandline{flex-wrap:nowrap}
  header nav{min-width:0}
}
@media (min-width:901px){
  header nav ul{flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none;-ms-overflow-style:none}
  header nav ul::-webkit-scrollbar{display:none}
  header nav a{white-space:nowrap}
}

@media (min-width:901px){
  header .brand{flex:0 1 auto;min-width:0}
  header nav.nav{flex:1 1 auto;min-width:0}
  header .callnum{flex:0 0 auto}
}



/* 🔴 ONE HERO WAS 83vh BECAUSE ITS HEADLINE WAS 104px — 15 Sep 2026.
   Owner: "make sure desktop hero are proper sixe". Measured at 1280: nine
   heroes sat at 62-66vh and auto-detailing at 83vh, and the cause was not the
   hero box at all — its <h1> renders at 104px over three lines, 306px of type.
   That size was tuned for a hero made ONLY of words; over a photograph it is
   shouting. ⭐ Capped to the size the rest already use, so the set reads as one
   family. ⛔ Still large text for contrast purposes (>=24px), so the 3:1
   threshold the probe applies is unchanged. */
.lanaihero h1{font-size:clamp(2rem,4.4vw,3.5rem);line-height:1.06}


/* ══════════════════════════════════════════════════════════════════════════
   ⚠️ HAND-EDITED — THIS SHEET NOW DIVERGES FROM ITS GENERATOR. 23 Sep 2026.
   The header at the top of this file says this demo is written out of
   ~/Desktop/demo-rv/dist by tools/sync-demo.mjs and must not be edited by
   hand. Everything below this line was written BY HAND anyway, on the owner's
   instruction, and the generator knows nothing about it.
   ⛔ DO NOT RUN tools/sync-demo.mjs OR build.py FOR THIS DEMO. A sync would
   revert every rule below without printing a word — the exact failure the
   estate has already paid for once ("a hand-edit to a generated file reverts
   silently — build green, fix gone").
   ⭐ WHY THIS IS THE RIGHT WAY ROUND ANYWAY: the generator source lives outside
   this repo, is untracked and unbacked, and at least one of these demos
   provably no longer reproduces its published copy. public/demo IS in git. So
   public/demo is the authority now. If the generator is ever restored, port
   these blocks into it FIRST and diff its output before syncing anything.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── 1. ONE HERO, NOT TWO ─────────────────────────────────────────────────
   🔴 This page opened with <section class="lanaihero"> and then a SECOND
   <section class="hero"> immediately underneath. Ten of the thirteen demos
   did. Two hero bands is a stack, and a stack has no first thing to look at —
   the same defect the Cut Above home page was rebuilt six times for.
   ⭐ The second band is now `.showcase`: a content band that keeps its ground,
   its drawing and its photograph, and has no headline, no eyebrow and no lede
   restating what the h1 already said. The rules it needs were added to the
   `.hero` selectors above rather than duplicated, so the two cannot drift. */

/* ── 2. THE HEADLINE IS AT LEAST 3.0x BODY AT EVERY WIDTH ─────────────────
   🔴 Measured before this pass: the hero headline fell to **1.88x** body on a
   phone. `.lanaihero h1` capped it at 2rem — correctly, because 104px over
   three lines had made one hero 83vh — but the floor went with the ceiling.
   A headline under 2x body is not a headline, it is a bold paragraph.
   ⭐ THE FIX IS ARITHMETIC, NOT TASTE, and it is this pair:
        body  1rem (16px) up to 740px, 1.0625rem above it
        h1    clamp(3rem, 7vw, …)
   The worst point is 741px, where body jumps to 17px while 7vw is only
   51.87px — 3.05x, the tightest the whole range gets. At 320px it is 48/16 =
   3.00x exactly. ⛔ Do not lower either number without recomputing 741px.
   ⚠️ The 3.5rem ceiling on the hero headline is deliberately unchanged: that
   number was measured, and raising it is how a hero became 83vh tall. */
@media (max-width:740px){ body{font-size:1rem} }

/* ── 3. THE HERO IS THE DOCUMENT ──────────────────────────────────────────
   ⭐ The most persuasive object this business has is a job it turned DOWN: one
   real line on a real document, at $0.00, with a reason a customer can go and
   check. It was buried mid-page behind two hundred words of lede. It is now
   the offer strip itself, at the fold, and **$0.00 is a literal in the
   markup** — not a badge, not a rounded claim, not a rating. There are no
   ratings, stars or review counts anywhere on this site and there never will
   be; this is the honest version of the same job.
   ⛔ THE WRAPPER KEEPS `offerbar` IN ITS CLASS LIST ON PURPOSE.
   tools/check-demo-polish.mjs requires an offer strip on every page of every
   demo. Renaming the class here would strip it from the gate's view.
   ⚠️ COLOUR, AND WHY NOTHING COLOURED CARRIES TEXT. This band is
   rgba(6,19,34,.86) over a photograph, so with a white photo behind it it
   composites to roughly #293340 — dark, but not as dark as it looks in a
   screenshot of a dark picture. Every foreground below is white or near-white
   against that. The one coloured thing is the 3px flag rule, which carries no
   glyphs and so answers to the 3:1 non-text floor, not 4.5:1. */
.lanaihero .herodoc{ box-shadow:inset 0 3px 0 var(--doc-flag); }
.herodoc__in{
  display:grid;
  grid-template-columns:auto minmax(0,1fr) auto;
  align-items:center;
  column-gap:clamp(.8rem,2vw,1.5rem);
  row-gap:.5rem;
  padding-block:clamp(.8rem,1.7vw,1.1rem);
}
.herodoc__tag{
  grid-column:1; grid-row:1;
  font-family:var(--mono); font-size:.625rem; font-weight:700;
  letter-spacing:.2em; text-transform:uppercase; white-space:nowrap;
  color:#fff; background:rgba(255,255,255,.12);
  border:1px solid rgba(255,255,255,.42); border-radius:2px;
  padding:.3rem .55rem; align-self:center;
}
.herodoc__it{
  grid-column:2; grid-row:1;
  font-weight:600; line-height:1.25; color:#fff;
  font-size:clamp(.9375rem,1.5vw,1.0625rem);
  text-shadow:0 1px 2px rgba(0,0,0,.70);
}
/* ⛔ Not a muted grey. Over a picture the picture is already doing the
   de-emphasising, and a dimmed foreground on a busy ground is just an
   unreadable foreground. Near-full ink, plus a shadow that travels with the
   glyphs rather than a panel that darkens the photograph. */
.herodoc__why{
  display:block; margin-top:.22rem; max-width:52ch;
  font-family:var(--mono); font-style:normal; font-weight:400;
  font-size:.75rem; line-height:1.5; letter-spacing:.01em;
  color:rgba(255,255,255,.93);
  text-shadow:0 1px 2px rgba(0,0,0,.70);
}
/* ⭐ tabular figures, so the amount reads as money in a column rather than as
   a word in a sentence. That is what makes it look like a document. */
.herodoc__amt{
  grid-column:3; grid-row:1;
  font-family:var(--mono); font-weight:700; color:#fff; white-space:nowrap;
  font-size:clamp(1.25rem,2.4vw,1.6rem); letter-spacing:-.01em;
  font-variant-numeric:tabular-nums;
  text-shadow:0 1px 2px rgba(0,0,0,.70);
}
/* ⛔ At 640px three columns stop fitting and the reason column collapses to a
   word per line. The flag and the amount stay together on the first row —
   they are the two things that must be read as one statement — and the line
   itself wraps underneath at full width. Nothing is lost at 320px. */
@media (max-width:640px){
  .herodoc__in{ grid-template-columns:auto minmax(0,1fr); }
  .herodoc__amt{ grid-column:2; grid-row:1; justify-self:end; }
  .herodoc__it{ grid-column:1 / -1; grid-row:2; }
}

/* ── 4. THE MOST DATED THING IN THE SET ───────────────────────────────────
   🔴 The h1 was set UPPERCASE at weight 700 with POSITIVE tracking (+.028em).
   That combination is the single strongest "this was designed in 2018" tell on
   this estate. Taken off award-standard work frame by frame, the display pair
   is **weight 500, tracked −0.07em**, sentence case — and that one pair of
   numbers is most of what separates "looks like the reference" from "looks
   generic".
   ⚠️ h2/h3/h4 keep the uppercase signage lettering ON PURPOSE. This site's
   whole idea is enamel signage and route furniture; the defect was the
   headline wearing the furniture's clothes, not the furniture. */
h1{
  font-size:clamp(3rem,7vw,4rem);
  font-weight:500;
  letter-spacing:-.07em;
  text-transform:none;
  line-height:1.02;
}
.lanaihero h1{ font-size:clamp(3rem,7vw,3.5rem); line-height:1.04; }

/* the flag rule's colour: --orange-pale, the tint this site already tuned for type on dark grounds */
:root{ --doc-flag:#eca580; }

/* ── 5. NOTHING STRANDED AT THE END OF THE DOCUMENT ───────────────────────
   🔴 Measured at 375px with the page scrolled to the bottom: the "Bots On
   Staff" credit link in the footer was **35% covered** by the .nbchat
   launcher. At the bottom of the document there is nothing left to scroll, so
   unlike every other overlap a fixed element causes, this one the reader
   cannot escape. (The three sister demos clear it; this one does not, because
   its launcher is bottom-LEFT and so is the credit.)
   ⭐ One rule, and it reserves the launcher's height from the launcher's OWN
   tokens rather than a measured number: 16px offset + 2x12px padding + 2x2px
   border + the cap line, plus the iOS home indicator.
   ⛔ Do not hard-code the gap. A reader at 200% text gets a bigger button, and
   a number copied from the site next door still buries the link. */
.foot{
  padding-bottom:calc(30px + 1rem + 16px + 24px + 4px + 1.6em + env(safe-area-inset-bottom,0px));
}

/* ── 6. THE SHIELD IS ITS OWN CONTAINER ───────────────────────────────────
   The mark was a monoline shield sitting INSIDE a cream rounded plate — a
   container drawn twice. The enamel shield is now two real fills and is the
   container, so the plate goes. ⚠️ It is portrait (26x32), deliberately: every
   other mark on this estate is square, and a different aspect ratio is half of
   why two marks read as two companies. */
.brand__mk{background:none;border:0;border-radius:0;width:auto;height:auto}
.brand:hover .brand__mk{transform:translateY(-2px);box-shadow:none}
.nav__mark{width:27px;height:33px}

/* ── 7. GLASS — A FROSTED ENAMEL CHIP ─────────────────────────────────────
   Owner, 23 Sep 2026: "use glass buttons all the newest elements".
   ⛔ See the long note in the auto-detailing sheet. The alpha below clears
   4.5:1 with NO blur; the blur is an enhancement, not the contrast mechanism.
   Measured by tools/check-hero-button-contrast.mjs at three widths, both states.

   ⭐ THE MATERIAL IS THIS SITE'S ENAMEL. A full pill with a 2px pale edge —
   the same object as the badges and the route furniture, in glass. ⛔ The
   stacked `0 3px 0` hard shadow goes: on a photograph it reads as a sticker,
   and depth here is the pale edge plus the blur. */
.lanaihero .btn--go{
  border-radius:100px;
  /* ⛔ --orange-dk, NOT --orange, and the site's own palette says why: its
     comment reads "small type on sand: --orange is 4.6:1, this is 6.1:1".
     White on --orange at 90% alpha bounds to 4.52:1 over a white sky — it
     PASSES, and 0.02 over the floor is not a margin, it is a coincidence.
     At 92% of --orange-dk the same label bounds to 8.0:1. */
  background:color-mix(in srgb, var(--orange-dk) 92%, transparent);
  border:2px solid color-mix(in srgb, var(--orange-pale) 72%, transparent);
  color:#fff;
  box-shadow:none;
  -webkit-backdrop-filter:blur(16px) saturate(1.35);
  backdrop-filter:blur(16px) saturate(1.35);
}
.lanaihero .btn--go:hover{
  background:color-mix(in srgb, var(--orange) 96%, transparent);
  border-color:var(--orange-pale); transform:translateY(-2px); box-shadow:none;
}
.lanaihero .btn--go:active{transform:translateY(1px);box-shadow:none}
.lanaihero .btn:focus-visible{
  outline:2px solid #fff; outline-offset:3px; box-shadow:0 0 0 5px rgba(36,31,22,.72);
}
