:root{
  --ink:#121415; --mut:#6E7478; --line:#D8DCDF; --bg:#F2F3F4; --paper:#FFFFFF;
  --dark:#0B0D0E; --dark-ink:#F2F3F4; --dark-mut:#9AA1A6; --dark-line:#242829;
  --sans:"Montserrat",system-ui,-apple-system,"Helvetica Neue",sans-serif;
  --serif:"Libre Baskerville",Georgia,"Times New Roman",serif;
}
*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{margin:0;background:var(--bg);color:var(--ink);font-size:15px;line-height:1.55;
     font-family:var(--sans);
     -webkit-font-smoothing:antialiased}
a{color:inherit}
img{max-width:100%}
:focus-visible{outline:2px solid currentColor;outline-offset:3px}
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}

.w{max-width:1000px;margin:0 auto;padding-inline:clamp(18px,4.5vw,42px)}
h1,h2,h3{margin:0}
h2,h3{font-weight:500;letter-spacing:-.012em;line-height:1.12}
h1{font-family:var(--serif);font-weight:400;letter-spacing:0;line-height:1.14}
h2{font-size:clamp(24px,3.3vw,34px);text-wrap:balance}
p{margin:14px 0 0;max-width:58ch;color:#3C4145}
.lbl{font-size:10.5px;letter-spacing:.22em;text-transform:uppercase;color:var(--mut)}
.fine{font-size:14px}
.rule{border:0;border-top:1px solid var(--line);margin:0}
/* Readable to a screen reader and to a crawler, invisible on screen. Not
   display:none, which removes it from both. */
.vh{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;
    clip-path:inset(50%);white-space:nowrap;border:0}
section.band{padding-block:clamp(48px,6.5vw,80px)}

/* ---- header nav ------------------------------------------------------- */
/* Written narrow first. The panel is a popover, so the browser handles opening,
   closing, Escape, light dismiss and announcing expanded or collapsed. No script,
   and deliberately no hand written aria-expanded. */
.nav{display:flex;align-items:center;flex-wrap:wrap;row-gap:12px;
     gap:clamp(12px,2.4vw,34px);padding-block:18px;border-bottom:1px solid var(--line)}
.logo{display:block;text-decoration:none;flex:0 0 auto;margin-right:auto}
.logo .wordmark{font-weight:600;font-size:13px;letter-spacing:.3em;text-transform:uppercase;
      white-space:nowrap}

/* 44px minimum target. It is a thumb, not a mouse pointer. */
.menubtn{display:inline-flex;align-items:center;gap:9px;min-height:44px;padding:0 15px;
         background:none;border:1px solid var(--line);border-radius:1px;cursor:pointer;
         font:inherit;font-size:11px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink)}
.menubtn .bars{display:block;width:17px;height:11px;position:relative;
               border-top:1.5px solid currentColor;border-bottom:1.5px solid currentColor}
.menubtn .bars::after{content:"";position:absolute;left:0;top:50%;width:100%;
                      border-top:1.5px solid currentColor;transform:translateY(-50%)}

#site-nav[popover]{position:fixed;inset:0 0 0 auto;width:min(300px,84vw);height:100dvh;
                   margin:0;border:0;border-left:1px solid var(--line);padding:26px 24px;
                   background:var(--paper);overflow-y:auto}
#site-nav::backdrop{background:rgba(11,13,14,.45)}
/* Escape and tapping outside already close it. This is for the people who look
   for an X. popovertargetaction keeps it script free. */
.menuclose{display:inline-flex;align-items:center;gap:7px;min-height:44px;margin-bottom:10px;
           padding:0 13px 0 0;background:none;border:0;cursor:pointer;font:inherit;
           font-size:11px;letter-spacing:.13em;text-transform:uppercase;color:var(--mut)}
.menuclose span{font-size:19px;line-height:1}
.menuclose:hover{color:var(--ink)}
#site-nav ul{display:flex;flex-direction:column;list-style:none;margin:0;padding:0}
#site-nav > ul > li{border-bottom:1px solid var(--line)}
#site-nav a{display:block;padding:15px 0;text-decoration:none;color:#43484C;
            font-size:13px;letter-spacing:.12em;text-transform:uppercase}
#site-nav a[aria-current="page"]{color:var(--ink)}

/* Submenus. In the narrow panel they are simply an indented list, always open,
   because a tap that only reveals more taps is a tax on a thumb and the parent
   is already a link to its own hub. */
#site-nav .sub{padding:0 0 14px 15px;border-left:1px solid var(--line);margin:0 0 14px}
#site-nav .sub li{border-bottom:0}
#site-nav .sub a{padding:9px 0;font-size:12px;letter-spacing:.06em;text-transform:none;
                 color:var(--mut)}
#site-nav .sub a:hover{color:var(--ink)}
/* The hub sits last and gets a rule above it, because it is the catch-all
   rather than one more destination of the same kind. */
#site-nav .sub li:last-child{border-top:1px solid var(--line);margin-top:6px;padding-top:2px}

.navcta{display:flex;gap:8px;align-items:center;flex:1 1 100%}
.navcta .btn{flex:1 1 0;text-align:center;padding:12px 10px;font-size:10.5px;letter-spacing:.1em}

/* Wide enough for the links to sit beside the logo and buttons. Measured at about
   920px, so 60em leaves headroom. Not a device width. */
@media (min-width:60em){
  .nav{flex-wrap:nowrap;row-gap:0}
  .menubtn,.menuclose{display:none}
  /* An author rule outranks the browser default display:none on a closed popover. */
  #site-nav[popover]{display:block;position:static;inset:auto;width:auto;height:auto;
                     border:0;padding:0;background:none;overflow:visible;flex:1 1 auto}
  #site-nav > ul{flex-direction:row;gap:clamp(14px,1.7vw,24px);justify-content:flex-end}
  #site-nav > ul > li{border-bottom:0}
  #site-nav a{padding:0;font-size:12px;letter-spacing:.07em;white-space:nowrap}
  #site-nav a:hover{color:var(--ink)}
  /* Hover and focus-within, so a keyboard reaches it without a script. The
     ::after is an invisible bridge across the gap between the link and the
     panel, or the menu closes while the pointer is still travelling to it. */
  #site-nav li.has-sub{position:relative}
  #site-nav li.has-sub::after{content:"";position:absolute;left:0;right:0;top:100%;height:24px}
  #site-nav .sub{position:absolute;top:calc(100% + 24px);left:-18px;z-index:5;display:none;
                 flex-direction:column;gap:0;min-width:236px;margin:0;padding:14px 18px 8px;
                 border:1px solid var(--line);background:var(--paper);
                 box-shadow:0 14px 34px rgba(11,13,14,.10)}
  #site-nav li.has-sub:hover > .sub,
  #site-nav li.has-sub:focus-within > .sub{display:flex}
  #site-nav .sub a{padding:8px 0;font-size:12.5px;white-space:nowrap}
  .navcta{flex:0 0 auto}
  .navcta .btn{flex:0 0 auto;padding:11px 16px;font-size:11px;letter-spacing:.13em}
}

/* Without popover support the button would do nothing, so show the links instead. */
@supports not selector(:popover-open){
  .menubtn,.menuclose{display:none}
  #site-nav .sub{display:none}
  #site-nav > ul{flex-direction:row;flex-wrap:wrap;gap:14px}
  #site-nav[popover]{display:block;position:static;inset:auto;width:auto;height:auto;
                     border:0;padding:0;background:none}
  #site-nav > ul > li{border-bottom:0}
  #site-nav a{padding:0}
}
.btn{font-size:11px;letter-spacing:.13em;text-transform:uppercase;padding:11px 16px;
     white-space:nowrap;display:inline-block;border-radius:1px;font-weight:500;text-decoration:none}
.btn-fill{background:var(--ink);color:#fff}
.btn-fill.invert{background:var(--dark-ink);color:var(--dark)}
.btn-line{border:1px solid currentColor}

.hero{display:grid;grid-template-columns:1.05fr .95fr;gap:clamp(26px,5vw,60px);align-items:stretch;
      padding-block:clamp(48px,7vw,84px) clamp(30px,4vw,44px)}
.hero>div:first-child{display:flex;flex-direction:column;justify-content:flex-end}
.hero h1{font-size:clamp(27px,4.4vw,46px);line-height:1.14;letter-spacing:0;margin:16px 0 0;
         max-width:15ch;text-wrap:balance}
.say{font-size:17px;line-height:1.5;margin-top:22px;max-width:52ch}
.hero .say{max-width:44ch}
.acts{display:flex;gap:10px;margin-top:30px;flex-wrap:wrap;align-items:center}

.facts{display:grid;grid-template-columns:repeat(3,1fr);border-top:1px solid var(--line);
       border-bottom:1px solid var(--line)}
.facts>div{padding:20px clamp(16px,2.4vw,26px) 20px 0;border-left:1px solid var(--line)}
.facts>div+div{padding-left:clamp(16px,2.4vw,26px)}
.facts>div:first-child{border-left:0}
.facts .k{font-size:10.5px;letter-spacing:.2em;text-transform:uppercase;color:var(--mut)}
.facts .v{font-size:17px;font-weight:500;margin-top:5px;letter-spacing:-.01em}
/* Gold, not ink. Grey stars read as switched off, which is a strange thing for a
   five star rating to look like. Sized in em so they track the number beside them. */
.stars{display:inline-flex;gap:2px;color:#C8A02C;margin-right:9px;vertical-align:-.02em;font-size:.88em}
.stars svg{display:block;fill:currentColor}
.dark .stars{color:#D9B443}

.panel{background:linear-gradient(145deg,#E2E5E7,#C6CBCF 45%,#EDEFF0 62%,#BFC5C9);
       aspect-ratio:4/5;display:grid;place-items:center;color:#5A6165;padding:20px;max-width:100%}
.panel.wide{aspect-ratio:21/9}
.panel span{font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;text-align:center;
            line-height:1.6;border:1px solid currentColor;padding:7px 13px;max-width:90%}

.dark{background:var(--dark);color:var(--dark-ink)}
.dark p{color:var(--dark-mut)}
.dark .lbl{color:var(--dark-mut)}
.corp{display:grid;grid-template-columns:1fr 1fr;gap:clamp(26px,5vw,64px);align-items:start}
.steps{list-style:none;margin:28px 0 0;padding:0;counter-reset:s}
.steps li{counter-increment:s;display:grid;grid-template-columns:34px 1fr;gap:14px;padding:15px 0;
          border-top:1px solid var(--line);font-size:14.5px}
.steps li::before{content:counter(s,decimal-leading-zero);color:var(--mut);font-size:11px;
                  letter-spacing:.1em;padding-top:3px}
.dark .steps li{border-top-color:var(--dark-line)}
.dark .steps li::before{color:var(--dark-mut)}
.dests{margin:14px 0 0;font-size:14px;color:var(--dark-mut);line-height:2}
.quiet{font-size:13.5px;color:var(--dark-mut);margin-top:22px;
       border-left:1px solid var(--dark-line);padding-left:16px}

.tbl-wrap{overflow-x:auto;margin-top:26px}
table{border-collapse:collapse;width:100%;min-width:430px;font-variant-numeric:tabular-nums}
th,td{text-align:left;padding:13px 14px 13px 0;border-bottom:1px solid var(--line);font-size:14.5px}
th{font-size:10.5px;letter-spacing:.18em;text-transform:uppercase;color:var(--mut);font-weight:500;
   border-bottom:1px solid var(--ink)}
td.n,th.n{text-align:right;padding-right:0}
tr.rowgrp td{font-size:10.5px;letter-spacing:.2em;text-transform:uppercase;color:var(--ink);
          padding-top:26px;border-bottom:1px solid var(--ink)}
td .yes{color:#2F7D32;font-size:15px}
td .no{color:var(--mut)}
/* The schedule table's marks carry the answer the reader came for, so they are
   set larger and darker than the fleet table's feature ticks, which only ever
   support a label beside them. */
td.c .yes,td.c .gone{font-size:19px;line-height:1}
table td:first-child{color:var(--mut)}

/* ---- Fleet comparison table ------------------------------------------- */
table.cmp{table-layout:fixed;min-width:560px}
table.cmp th:first-child,table.cmp td:first-child{width:27%;text-align:left;padding-right:12px}
table.cmp th:not(:first-child),table.cmp td:not(:first-child){width:24.33%;text-align:center;
     padding-left:7px;padding-right:7px}
table th:not(:first-child){color:var(--ink)}

/* ---- Rideshare comparison table (/milwaukee-uber-and-lyft-prices/) ----- */
/* Every cell is a sentence rather than a figure, so this table is left aligned
   and top aligned throughout, and it must not be the one table on the site that
   forces a horizontal scroll on a phone. Below 700px it stops being a table and
   becomes stacked blocks, with each cell labelled from data-lbl, because a three
   column sentence table at 390px is unreadable however wide you let it scroll. */
table.vs{table-layout:fixed;min-width:0}
table.vs th,table.vs td{vertical-align:top;padding-right:16px}
table.vs th:first-child,table.vs td:first-child{width:20%}
table.vs th:not(:first-child),table.vs td:not(:first-child){width:40%}
table.vs th:last-child,table.vs td:last-child{padding-right:0}
table.vs td:first-child{color:var(--ink)}

@media (max-width:700px){
  table.vs,table.vs tbody,table.vs tr,table.vs td{display:block;width:auto}
  table.vs thead{display:none}
  table.vs tr{padding:24px 0 6px;border-bottom:1px solid var(--ink)}
  table.vs tr:first-child{padding-top:0}
  table.vs td{border-bottom:0;padding:0 0 14px}
  table.vs td:last-child{padding-bottom:2px}
  table.vs td:first-child{font-size:10.5px;letter-spacing:.18em;text-transform:uppercase;
       color:var(--mut);padding-bottom:12px}
  table.vs td[data-lbl]::before{content:attr(data-lbl) "  ";display:block;font-size:10.5px;
       letter-spacing:.14em;text-transform:uppercase;color:var(--mut);margin-bottom:5px}
}

/* ---- Schedule table (Packers) ----------------------------------------- */
/* The row header is the date and the opponent, stacked, because at 430px the
   two will not sit on one line and a wrapped date reads as two dates. */
td.c,th.c{text-align:center}
table th[scope=row]{font-size:14.5px;letter-spacing:0;text-transform:none;font-weight:400;
                    color:var(--ink);border-bottom:1px solid var(--line);white-space:nowrap}
table th[scope=row] .op{display:block;font-weight:500;margin-top:3px}
table th[scope=row] .op a{color:inherit;text-decoration:none}
table th[scope=row] .op a:hover{text-decoration:underline}
table th[scope=row] .op .fine{margin:0 0 0 7px;display:inline;font-weight:400;
                             font-size:13px;color:var(--mut)}
table th[scope=row] .tbd{color:var(--mut)}
table th[scope=row] abbr{text-decoration:none;color:var(--mut)}
td .gone{color:#A33A37;font-size:15px}
/* Where all three service levels agree the row carries one word instead of
   three identical marks. The word is visible here and screen reader only in the
   per-tier cells, so the fact is stated exactly once either way. */
td.all .mk{margin-left:9px;font-size:15px;color:var(--ink);letter-spacing:0}
/* A count is the one per tier state that renders visibly. The plain available
   mark says nothing a reader needs beyond the tick; a number does. */
td.c .ct{display:block;font-size:13.5px;color:var(--ink);margin-top:3px;letter-spacing:0;
         white-space:nowrap}
/* Played games are separated as a block, not marked row by row. Opacity failed
   because it asked the reader to compare every date against today's, and a small
   tag per row failed because five faint tags down a column of grey text read as
   more grey text rather than as a boundary. A divider plus a tint reads as one
   group at a glance, and nothing inside it is dimmed, so the run of Fully booked
   marks that the rows exist for stays at full strength. */
tr.past th[scope=row],tr.past td{background:rgba(18,20,21,.038)}
tr.past th[scope=row]{padding-left:12px}
tr.rowgrp + tr.past th[scope=row],tr.rowgrp + tr.past td{padding-top:17px}
/* On a phone the table's own min-width plus three tier columns pushed the
   availability label off the right edge, so the single word the reader came
   for was behind a horizontal scroll. Under 560px the row header wraps, the
   table drops its min-width, and the column headers shrink to fit. */
@media (max-width:560px){
  /* Too narrow for a label column beside the value, so the label sits above it. */
  .spec div{grid-template-columns:1fr;gap:3px}
  .tbl-wrap table{min-width:0}
  table th[scope=row]{white-space:normal;padding-right:10px}
  table th[scope=row] .op .fine{display:block;margin:2px 0 0}
  th.c{font-size:9.5px;letter-spacing:.08em;padding-left:2px;padding-right:2px}
  td.c{padding-left:2px;padding-right:2px}
  td.all .mk{display:block;margin:2px 0 0}
}

/* ---- Sample itinerary -------------------------------------------------- */
.itin{list-style:none;margin:22px 0 0;padding:0;counter-reset:none}
.itin li{display:grid;grid-template-columns:86px 1fr;gap:16px;padding:11px 0;
         border-top:1px solid var(--line);font-size:14.5px;align-items:baseline}
.itin .t{color:var(--mut);font-variant-numeric:tabular-nums}
.itin .d{color:var(--ink)}

/* Wide variant: the left column carries a phrase rather than a time, so it gets
   real width and the row aligns to the top instead of the baseline. Used by the
   services hub sorter and the add-ons list. */
.itin.wide li{grid-template-columns:minmax(0,14rem) 1fr;align-items:start;padding:14px 0}
.itin.wide strong{font-weight:500;color:var(--ink)}
.itin.wide span{color:#4A4F53}
.dark .itin li{border-top-color:var(--dark-line)}
.dark .itin.wide strong{color:var(--paper)}
.dark .itin.wide span{color:var(--dark-mut)}
/* Global a{color:inherit} would leave these routing links the same muted grey as
   the sentence around them. On the services hub they ARE the point of the row, so
   they carry the ink colour and an underline. */
.itin.wide span a{color:var(--ink);text-decoration:underline;text-underline-offset:3px}
.dark .itin.wide span a{color:var(--paper)}
@media (max-width:640px){.itin.wide li{grid-template-columns:1fr;gap:5px}}

/* ---- Sample rates, three across --------------------------------------- */
/* Stacked label-and-figure rows read as an invoice: subtotal, extras, total.
   These are three alternatives, so they sit side by side and stay side by side
   on a phone, where stacking them would put the invoice shape back. */
.rates{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(10px,2vw,22px);margin:26px 0 0}
.rates div{border-top:1px solid var(--ink);padding-top:14px}
.rates dt{font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--mut)}
.rates dd{margin:7px 0 0;font-size:clamp(21px,2.5vw,27px);letter-spacing:-.015em;
          font-variant-numeric:tabular-nums}
@media (max-width:420px){
  .rates{gap:9px}
  .rates dt{font-size:9.5px;letter-spacing:.09em}
}

.verify{font-size:12px;color:var(--mut);margin-top:12px}
.verify code{font-size:11.5px}

.pair{display:grid;grid-template-columns:1fr 1fr;gap:clamp(10px,1.6vw,18px);margin:26px 0 0}
.pair .shot{display:block}
.pair .shot img{aspect-ratio:4/3;height:auto}
.pair figcaption{grid-column:1/-1;font-size:12.5px;color:var(--mut);margin-top:2px}
.pair.trio{grid-template-columns:repeat(3,1fr)}
.pair.trio .shot img{aspect-ratio:4/5}
@media (max-width:40em){ .pair.trio{grid-template-columns:1fr 1fr} .pair.trio .shot:first-child{grid-column:1/-1} }
@media (max-width:40em){ .pair{grid-template-columns:1fr} }

.spec{display:grid;grid-template-columns:repeat(2,1fr);gap:0 clamp(20px,4vw,50px);margin-top:24px}
/* Grid, not flex with space-between. Under space-between a short value shrank
   to its content and was pushed hard right while a long value filled the row and
   started at the left, so a list of both read as ragged rather than as a table.
   A fixed label column gives every value the same left edge whether it is one
   word or three lines. Caught by Jonathan on the Kohler, hourly and city tours
   pages, 27 Sep 2026. */
.spec div{display:grid;grid-template-columns:minmax(84px,.3fr) 1fr;gap:4px 16px;
          align-items:baseline;padding:12px 0;
          border-top:1px solid var(--line);font-size:14px}
.spec dt{color:var(--mut)}
.spec dd{margin:0;font-weight:500;font-variant-numeric:tabular-nums}

.svc{list-style:none;margin:28px 0 0;padding:0}
.svc li{display:grid;grid-template-columns:minmax(150px,.34fr) 1fr;gap:clamp(14px,3vw,40px);
        padding:17px 0;border-top:1px solid var(--line);align-items:baseline}
.svc .nm{font-weight:500;font-size:15px;text-decoration:none}
.svc a.nm:hover{text-decoration:underline}
.svc .ds{font-size:14px;color:#4A4F53}

.areas{display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));
       gap:clamp(18px,3vw,40px);margin-top:28px}
.areas h3{font-size:10.5px;letter-spacing:.2em;text-transform:uppercase;color:var(--mut);
          font-weight:500;margin:0 0 10px;padding-bottom:9px;border-bottom:1px solid var(--line)}
.areas ul{list-style:none;margin:0;padding:0;font-size:14px;line-height:2;color:#43484C}

.areas .quietline{color:var(--mut);font-size:13px;line-height:1.45}
.areas li strong{font-weight:500;color:var(--ink)}
.areas .covers{display:block;font-size:12.5px;line-height:1.4;color:var(--mut);margin:-4px 0 6px}
.dark .areas h3,.dark .areas .quietline{color:var(--dark-mut)}
.dark .areas li strong{color:var(--paper)}
.dark .areas li{margin-bottom:14px;line-height:1.35}

/* Multi-column rather than a grid. A grid forces items of very different lengths
   into rows, which leaves a gap under every short review and an empty cell at the
   end when the count is odd. Columns flow independently, so both disappear and the
   number of reviews stops mattering.
   white-space:pre-wrap is load bearing. The originals contain double spaces, a
   missing space after a full stop and a curly apostrophe, and the page claims the
   reviews are reproduced word for word. Collapsing their whitespace would quietly
   make that claim false.
   The quote is set in the serif because that face is already the voice of the page
   in h1, so the customer and the site never read as the same speaker. */
.revs{columns:2;column-gap:clamp(22px,4vw,54px);margin-top:28px;list-style:none;padding:0}
.rev{break-inside:avoid;margin:0 0 clamp(24px,3.2vw,38px)}
.rev q{display:block;font-family:var(--serif);font-size:17px;line-height:1.55;quotes:none;
       white-space:pre-wrap;color:var(--ink)}
.rev .src{font-size:12px;color:var(--mut);margin-top:12px}
.rev .who{display:block;font-size:12px;letter-spacing:.1em;text-transform:uppercase;
          color:var(--ink);margin-bottom:4px}
.rev .stars{color:var(--ink);letter-spacing:.14em;margin-right:8px}

.close .mail{font-size:clamp(20px,3vw,27px);font-weight:500;letter-spacing:-.018em;
             margin-top:16px;display:inline-block;text-decoration:none}

.foot{background:var(--dark);color:var(--dark-mut);font-size:12px;letter-spacing:.06em}
.foot .w{display:flex;gap:clamp(16px,2.6vw,34px);flex-wrap:wrap;align-items:center;
         justify-content:space-between;padding-block:30px}
.foot-meta{display:flex;flex-direction:column;gap:7px;text-align:right;align-items:flex-end}

@media (max-width:860px){
  /* The homepage hero and the corporate two-up never collapsed, because this
     rule had been merged with the quietline rule below it and lost its own
     declaration. Jonathan caught the homepage at 440px on 26 Sep 2026: the
     headline was wrapping to five lines beside a thumbnail. Same breakpoint
     as .lochero and .pagehero, which were collapsing correctly all along. */
  .hero,.corp{grid-template-columns:1fr}
  .areas .quietline{color:var(--mut);font-size:13px;line-height:1.45}
.areas li strong{font-weight:500;color:var(--ink)}
.dark .areas h3,.dark .areas .quietline{color:var(--dark-mut)}
.dark .areas li strong{color:var(--paper)}
.dark .areas li{margin-bottom:14px;line-height:1.35}

.revs{columns:1}
  .facts{grid-template-columns:1fr}
  .facts>div{border-left:0;border-top:1px solid var(--line);padding-left:0}
  .facts>div+div{padding-left:0}
  .facts>div:first-child{border-top:0}
  .areas,.spec{grid-template-columns:1fr}
  .logo img{height:50px}
  .foot .w{justify-content:flex-start}
  .foot-meta{text-align:left;align-items:flex-start}
  .svc li{grid-template-columns:1fr;gap:4px}
}

.crumbs{font-size:12px;letter-spacing:.06em;color:var(--mut);padding-block:16px 0}
.band.pagehero,.band.lochero{padding-block:clamp(22px,3vw,34px) clamp(48px,6.5vw,80px)}
.crumbs a{color:inherit}
.crumbs span{margin-inline:6px}
.copy{max-width:none;margin:0;padding:14px 0 26px;text-align:center;font-size:11.5px;color:var(--mut);background:var(--dark)}

/* ---- logo ------------------------------------------------------------- */
/* The badge carries two tiers of detail. Below about 44px the SUV RIDES line
   and the star row stop resolving, so this floor is legibility, not taste. */
.logo img{display:block;height:clamp(48px,5vw,58px);width:auto}
.foot-logo{display:block;flex:0 0 auto}
.foot-logo img{display:block;height:52px;width:auto}

/* ---- photographs ------------------------------------------------------ */
.shot{margin:0}
.shot img{display:block;width:100%;height:100%;object-fit:cover;aspect-ratio:4/3;background:var(--line)}
.shot.wide img{aspect-ratio:21/9}
.shot.band-photo{margin-top:26px}
.shot figcaption{font-size:12.5px;color:var(--mut);margin-top:9px;line-height:1.45;max-width:62ch}
.dark .shot figcaption{color:var(--dark-mut)}

/* ---- facts strip ------------------------------------------------------ */
.facts .v{line-height:1.3}
.facts .v .codes{font-variant-numeric:tabular-nums;letter-spacing:.03em;white-space:nowrap}

/* ---- section headings inside a band ----------------------------------- */
h2.sub{margin-top:clamp(38px,5vw,56px);font-size:clamp(20px,2.4vw,26px)}
h2.sub + .tbl-wrap,h2.sub + .svc,h2.sub + .faqs{margin-top:20px}

/* ---- section groups --------------------------------------------------- */
/* A heading with its prose beside it rather than above it.
   The 58ch measure on p is not the problem and does not change: that is what
   makes a paragraph readable, and widening it would only look tidier while
   reading worse. The problem is what was left over. A 58ch column inside the
   1000px grid leaves roughly a third of every row empty, and once six or seven
   of those stack up the eye stops reading it as a measure and starts reading it
   as a layout that failed. Moving the heading into that empty third gives the
   row two things to balance and costs the prose nothing.
   Exactly two children, .hd and .bd. Not a flat list of headings and
   paragraphs: with a flat list every child is its own grid row, so a tall
   heading forces a matching gap in the body column beside it. */
.grp{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.92fr);
     gap:0 clamp(22px,3.6vw,54px);align-items:start;
     margin-top:clamp(36px,4.6vw,60px)}
.grp:first-child{margin-top:0}
.grp .hd{min-width:0}
.grp .bd{min-width:0}
/* The heading column is narrow, so the type steps down and breaks evenly. */
.grp .hd :is(h2,h3){margin-top:0;font-size:clamp(20px,2.5vw,27px);text-wrap:balance}
.grp .hd .lbl{margin-bottom:9px}
.grp .bd > :first-child{margin-top:0}
.grp .bd .tbl-wrap,.grp .bd .svc,.grp .bd .spec,.grp .bd .faqs,.grp .bd .shot,.grp .bd .pair{margin-top:22px}
/* One spec per row in the body column. Two columns of 280px put a long label and
   a long value in the same flex row and both wrap, which reads as broken rather
   than dense. Full width rows keep every label and value on one line. */
.grp .bd .spec{grid-template-columns:1fr}

@media (max-width:860px){
  .grp{grid-template-columns:1fr;margin-top:clamp(32px,6vw,44px)}
  .grp .hd{margin-bottom:14px}
}

/* ---- FAQ tiles -------------------------------------------------------- */
/* Left as open text, not collapsed: visible copy is what earns the ranking. */
.faqs{margin-top:22px;border-top:1px solid var(--ink)}
.faq{padding:20px 0;border-bottom:1px solid var(--line)}
.faq h3{font-size:15.5px;font-weight:500;letter-spacing:-.012em;line-height:1.35;max-width:62ch}
.faq p{margin-top:9px;max-width:72ch;color:#4A4F53}

/* ---- trust strip ------------------------------------------------------ */
/* Four marks on one line, sized to a shared height rather than dropped into
   equal cells. Equal cells were the mistake: a mark is centred in its cell, so
   the outer edges of the row are set by the two outermost marks' own widths,
   and NLA is nearly twice the width of the Visit Milwaukee mark. The row could
   never line up with the page above it. space-between puts the first mark flush
   to the left content edge and the last flush to the right, which is the only
   arrangement that does line up, and it lets each mark take the width its own
   proportions ask for instead of being squeezed to a common box.
   The dividers went with the cells. They were drawing a grid that was not
   really there. */
.trust{border-top:1px solid var(--line);border-bottom:1px solid var(--line);background:var(--paper)}
.trust ul{display:flex;align-items:center;justify-content:space-between;
          gap:clamp(16px,2.6vw,40px);list-style:none;margin:0;padding:0}
.trust li{display:flex;align-items:center;justify-content:center;padding-block:24px}
.trust a{display:flex;align-items:center;justify-content:center;text-decoration:none}
.trust a:hover .cl{text-decoration:underline}
/* A shared height, then a per mark correction on top of it. Equal height is a
   better starting point than an equal box, but it is still only a starting
   point: these marks are drawn to different conventions, and the NLA monogram
   carries far more ink at a given height than a thin gold ring and a serif
   wordmark do. heightScale in data/business.json is the dial, applied as a
   multiplier so the whole row still scales together as the viewport narrows. */
.trust img.cred{display:block;width:auto;max-width:100%;
                height:calc(var(--hs,1) * clamp(54px,7.3vw,76px))}
/* The BBB seal is a filmstrip: one image holding every state of the mark side by
   side, shown through a window one frame wide. BBB ship this as a script that
   does nothing but document.write a stylesheet, and a blocking third party
   script on every page of the site is a real cost for four CSS rules, so the
   rules live here instead. The image still comes from BBB, so the rating stays
   theirs to update or withdraw. --bw, --bh and --frames are written by PHP from
   data/business.json; a different seal is a data change, not a CSS change.
   It is run near native size, because the A+ BBB print inside it does not
   survive being scaled down to match a wordmark, and the A+ is the credential.
   That is also why it alone does not shrink with the others.
   If BBB ever reissue the artwork with a different frame count the worst case
   is that the hover stops advancing, because frame one is the resting state. */
.trust .seal{display:block;position:relative;overflow:hidden;width:var(--bw);height:var(--bh)}
.trust .seal img{display:block;position:absolute;top:0;left:0;max-width:none;height:100%;
                 width:calc(100% * var(--frames))}
.trust a:hover .seal img,.trust a:focus-visible .seal img{left:calc(-100% * (var(--frames) - 1))}
/* Text fallback, for a credential with no artwork on file. */
.trust .cl{display:block;font-size:11.5px;font-weight:500;letter-spacing:.11em;
            text-transform:uppercase;line-height:1.3}
.trust .cd{display:block;font-size:12px;color:var(--mut);margin-top:4px;max-width:20ch}
.trust li.unverified .cl::after{content:" ?";color:#B04A3A}

.trust + .w .band:first-child,.trust + .w > .band{padding-top:clamp(34px,4vw,48px)}

/* ---- plain lists (landmarks) ------------------------------------------ */
/* .svc is a two column name/description grid. A bare list of pick-up points
   has no description, so it gets its own two up layout instead. */
.plain{list-style:none;margin:20px 0 0;padding:0;display:grid;grid-template-columns:1fr 1fr;
       gap:0 clamp(20px,4vw,50px);border-top:1px solid var(--line)}
.plain li{padding:13px 0;border-bottom:1px solid var(--line);font-size:14.5px}
@media (max-width:640px){.plain{grid-template-columns:1fr}}
/* Two columns only work while the items are short enough to sit on one line.
   A list of full sentences in two columns wraps to three lines beside one, and
   the ragged pairing reads as a bug rather than as density. */
.plain.wide{grid-template-columns:1fr}

/* ---- location hero ---------------------------------------------------- */
.lochero,.pagehero{display:grid;grid-template-columns:1fr 1fr;gap:clamp(24px,4.5vw,52px);align-items:stretch}
/* A venue or location page whose own photograph does not exist yet. The rule in
   claude/luxsuv-photography-standard.md is that these pages need the vehicle AT
   that place, and nothing else satisfies it: a licensed frame or a manufacturer
   render is the templated filler the standard exists to prevent, and it would
   sit on the page indefinitely once it looked finished. So the hero becomes a
   deliberate single column rather than wearing a photograph that proves nothing,
   and the missing picture stays visible as missing. */
.pagehero.noshot{grid-template-columns:minmax(0,1fr);gap:0}
/* A photo-less hero on a page whose trust strip sits lower down has nothing
   filling the space beneath it, so it keeps its own bottom padding short. Only
   /licensing-permitting-insurance/ needs this: everywhere else the strip
   follows the hero and .trust + .w > .band does the work. */
.band.pagehero.noshot.tight{padding-bottom:clamp(10px,1.4vw,16px)}
.pagehero.noshot > div{max-width:46rem}
.pagehero.noshot h1{font-size:clamp(28px,4.4vw,44px)}
.pagehero.noshot .say{font-size:clamp(17px,1.65vw,20px);max-width:38rem}
/* HERO PHOTOGRAPHY IS 4:3 ON EVERY PAGE. Do not make it fill the column.
   It used to: aspect-ratio:auto with height:100% inside a stretch grid, which made
   the photograph's height a function of how much hero copy the page happened to
   carry. Two things were wrong with that. The obvious one is that no two heroes
   were the same size and editing a sentence resized the picture. The worse one is
   that object-fit:cover then cropped to whatever shape that produced, so a short
   page cropped the top and bottom off a 4:3 source and a long page cropped the
   sides in. The vehicle was framed differently on every page, and on a short one
   the roofline clipped. Every source frame is 1400x1050, so 4:3 crops nothing at
   all and matches .shot img everywhere else on the site. Changed 22 Sep 2026 at
   Jonathan's request. If a shallower hero is ever wanted, change the ratio here
   and it changes everywhere, which is the point. */
.hero .shot,.lochero .shot,.pagehero .shot{display:block;align-self:start}
.hero .shot img,.lochero .shot img,.pagehero .shot img{aspect-ratio:4/3;height:auto;
                                                       width:100%;object-position:center}
.lochero h1,.pagehero h1{font-size:clamp(25px,3.6vw,36px);line-height:1.14;letter-spacing:0;margin:14px 0 0;
            max-width:16ch;text-wrap:balance}

@media (max-width:860px){
  .lochero,.pagehero{grid-template-columns:1fr}
  .trust ul{display:grid;grid-template-columns:1fr 1fr;gap:clamp(16px,3.2vw,30px)}
  .trust li{padding-block:22px}
  .trust img.cred{height:auto;max-width:100%;max-height:72px}
}



/* ---- contact form ------------------------------------------------------ */
/* Four fields, on purpose. See the header comment in html/contact/index.html:
   the inquiry that became an $1,800 Packers booking was one sentence long, and
   every field added here is a field that might have lost it. */
.cform{margin:26px 0 0;max-width:34rem}
.f{margin:0 0 20px}
.f label{display:block;font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;
         color:var(--mut);margin:0 0 8px}
.f .opt{letter-spacing:0;text-transform:none;font-size:11.5px;color:var(--mut);margin-left:6px}
.f input[type=text],.f input[type=email],.f input[type=tel],.f textarea{
  width:100%;font:inherit;font-size:15.5px;color:var(--ink);background:transparent;
  border:1px solid var(--line);border-radius:0;padding:12px 13px;
  transition:border-color .15s ease}
.f textarea{resize:vertical;min-height:120px;line-height:1.5}
.f input:focus,.f textarea:focus{outline:none;border-color:var(--ink)}
.f .fine{display:block;margin-top:8px}
.f.check label{display:flex;gap:11px;align-items:flex-start;text-transform:none;
               letter-spacing:0;font-size:13.5px;color:#4A4F53;line-height:1.5}
.f.check input{margin-top:3px;flex:0 0 auto}

/* The honeypot. Not display:none, because some bots skip hidden fields and some
   password managers ignore them: off-canvas is filled by a bot that is reading
   the markup rather than the layout, which is the one we are catching. Also
   aria-hidden and tabindex -1 in the markup, so no screen reader or keyboard
   user ever meets it. */
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

.note{border-left:2px solid var(--ink);padding:16px 0 16px 18px;margin:0 0 24px}
.note h3{margin:0 0 6px;font-size:16px;letter-spacing:-.01em}
.note p{margin:0}
.note.ok{border-left-color:#2E7D52}
.note.bad{border-left-color:#9A3B3B}
.dark .note{border-left-color:var(--paper)}

.addr{font-size:15px;line-height:1.7;margin:0}

/* A portrait is not a landscape frame with a person in it. The sitewide .shot
   rule forces aspect-ratio:4/3 with object-fit:cover, which crops a headshot
   top and bottom and then scales it to the full body column. .shot.portrait
   lets the file keep its own proportions and caps its width, and it belongs in
   .hd rather than .bd so the narrow heading column does the sizing. Added
   25 Sep 2026 for the About page. */
.shot.portrait img{aspect-ratio:auto;height:auto;max-width:260px}
.grp .hd .shot.portrait{margin-top:18px}


/* ---- processor list (privacy policy) ---------------------------------- */
/* Not .spec. That is a two column label and value list built for short pairs
   like an email address and a phone number, and it right-aligns the value.
   Feed it sentences and every description ends ragged against the right edge.
   This is a label plus prose, which is the .svc shape rather than the .spec
   shape, so it borrows those proportions and stays left aligned. */
.procs{margin-top:22px}
.procs > div{display:grid;grid-template-columns:minmax(120px,.3fr) 1fr;
             gap:5px clamp(16px,3vw,34px);padding:13px 0;border-top:1px solid var(--line)}
.procs > div:first-child{border-top:0;padding-top:4px}
.procs dt{font-size:13px;color:var(--ink)}
.procs dd{margin:0;font-size:14px;line-height:1.5;color:#3C4145}
@media (max-width:560px){
  .procs > div{grid-template-columns:1fr;gap:3px}
  .procs dt{font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:var(--mut)}
}

.pull{margin:24px 0 0;padding:2px 0 2px clamp(16px,3vw,26px);border-left:2px solid var(--ink)}
.pull q{display:block;font-family:var(--serif);font-size:16.5px;line-height:1.55;quotes:none;color:var(--ink)}
.pull .src{font-size:12px;color:var(--mut);margin-top:10px}

/* ---- service area map -------------------------------------------------- */
/* Hand-built inline SVG rather than an embedded map. The old page loaded a
   Google map tied to the Business Profile, which is a third party script, a
   cookie, another processor in the privacy policy, and nothing a crawler can
   read. This is 21KB of geometry with real text in it.
   Geometry: US Census county boundaries, public domain. Places: data/areas.json,
   the same file the lists below the map render from, so the two cannot disagree.
   Regenerate with bin/build-service-map.py. Sizes inside the SVG are user units
   against a 1000 wide viewBox, so they land at roughly 0.6 of their number. */
.map{display:block;width:100%;height:auto;margin:0 0 20px}
.c-wi{fill:#E4E7E9;stroke:var(--bg);stroke-width:1}
.c-core{fill:#CDD2D6;stroke:var(--bg);stroke-width:1}
.c-il{fill:#ECEEEF;stroke:var(--bg);stroke-width:1}
.map .p{fill:var(--ink);stroke:var(--bg);stroke-width:2.5}
.map .p-min{fill:#8B9196}
.map .p-route{fill:none;stroke:var(--mut);stroke-width:2.4}
.map .pl{fill:var(--ink);font-size:21px;letter-spacing:.01em}
.map .pl-route{fill:var(--mut)}
.map .lake{fill:#9AA1A6;font-family:var(--serif);font-style:italic;font-size:24px;letter-spacing:.06em}
.map .water{fill:#E2EAEF}
.map .ap{fill:var(--ink);stroke:var(--bg);stroke-width:2;paint-order:stroke}
.map .ap-route{fill:var(--mut);stroke:var(--bg);stroke-width:2;paint-order:stroke}
.map .apl{fill:var(--ink);font-size:18px;letter-spacing:.1em}
.map .apl-route{fill:var(--mut)}
.map a{cursor:pointer}
.map a text{text-decoration:underline;text-underline-offset:3px;text-decoration-thickness:1.5px;
            text-decoration-color:var(--line)}
.map a:hover text,.map a:focus-visible text{text-decoration-color:currentColor}

/* A hub entry whose page is not built yet. See link_for() in includes/init.php:
   it renders as plain text rather than a broken link, and becomes a link on its
   own the day the page lands. Muted so the gap is visible in review without
   looking like an error to a visitor. */
.pending{color:var(--mut)}
.svc li .nm.pending{font-weight:inherit}

/* Working agreement rule 6: anything unconfirmed renders a VISIBLE review flag,
   so an unevidenced claim cannot ship silently. Deliberately loud enough to find
   on a page and quiet enough not to alarm a visitor who reaches one before it is
   cleared. */
.reviewflag{border-left:2px solid #B04A3A;padding-left:12px;margin-top:10px}
