:root{--ink:#18191b;--paper:#f3eee5;--panel:#fbf8f2;--line:#ddd3c2;--muted:#595349;--accent:#7b2323;--accent-dark:#5e1a1a;--accent-light:#c9a25e;--gold:#b08a4a;--radius:12px;--display-weight:600;--display-font:'Fraunces';--body-font:'IBM Plex Sans';}
/* lwkit base.css: the Loomwest site standard, tokenised. Every colour, font and radius is a variable set
   by the build from the site's theme; nothing brand-specific lives here. Components: the header with the
   hamburger on the LEFT on desktop and on the RIGHT on a phone, pill navigation, the slide-in panel of pill
   links that opens from the hamburger's own side, the sticky action bar on phones, buttons, sections, cards,
   the service menu with search and category chips, the gallery with a lightbox, the before/after slider,
   the contact form, the footer, and the scroll reveal. */
*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth}
html,body{overflow-x:clip}
body{font-family:var(--body-font),system-ui,sans-serif;color:var(--ink);background:var(--paper);line-height:1.6;font-size:16.5px;-webkit-font-smoothing:antialiased}
h1,h2,h3,.display{font-family:var(--display-font),Georgia,serif;font-weight:var(--display-weight,700);line-height:1.1;letter-spacing:-.01em}
h1{font-size:clamp(38px,5.6vw,68px)} h2{font-size:clamp(28px,3.6vw,44px)} h3{font-size:clamp(20px,2.2vw,26px)}
a{color:inherit;text-decoration:none}
img{max-width:100%;height:auto;display:block}
.wrap{width:min(1120px,92vw);margin:0 auto}
:focus-visible{outline:3px solid var(--accent);outline-offset:3px}
.skip{position:absolute;left:8px;top:-70px;z-index:100;background:var(--accent);color:#fff;padding:10px 16px;border-radius:6px} .skip:focus{top:8px}
section[id]{scroll-margin-top:84px}

/* header: hamburger left, wordmark, pills across the top, one action on the right */
header.site{position:sticky;top:0;z-index:60;background:color-mix(in srgb,var(--paper) 90%,transparent);backdrop-filter:blur(12px);border-bottom:1px solid var(--line)}
header.site .wrap{display:flex;align-items:center;height:70px;gap:14px}
.logo{display:flex;align-items:center;gap:10px;font-family:var(--display-font),Georgia,serif;font-size:22px;font-weight:700;letter-spacing:.02em;color:var(--ink);white-space:nowrap;min-width:0;overflow:hidden;text-overflow:ellipsis}
.logo img{height:38px;width:auto}
.logo .short,.hdr-cta .short{display:none} @media(max-width:560px){.logo .full,.hdr-cta .full{display:none} .logo .short,.hdr-cta .short{display:inline}}
/* The hamburger glyph is placed, not centred (2026-09-17). The old build centred three 2px arms in a flex
   column, so their position was (content height - glyph height) / 2: a division whose inputs changed with the
   button size, the header height and the 1px border, and which could land a hairline on a half pixel. That
   renders faint or eaten on a real phone while looking perfect in an emulator, which is what Andre saw. Now
   each arm states its own whole-pixel offset from the button's top edge, so there is no division left to
   round: no gap, no justify-content, no border inside the box, and appearance:none so no UA button padding
   can creep back in. The arms sit at 10/18/26 in a 44px box, which is 2px higher than centred and leaves 16px
   of clear button beneath the bottom arm: Andre's "slide it up a little". Travel for the X is 8px because the
   arm tops are 8px apart; if those offsets ever change, the travel changes with them or the X misses centre.
   Parity rule: the button height must match the header row height in parity or align-items:center puts the
   whole button on a half pixel. 44 against rows of 70 and 64 gives whole 13px and 10px offsets. */
.tog{position:relative;display:block;width:44px;height:44px;overflow:visible;line-height:0;background:none;border:0;border-radius:12px;cursor:pointer;padding:0;order:-1;flex:none;-webkit-appearance:none;appearance:none}
.tog:hover{background:color-mix(in srgb,var(--ink) 6%,transparent)}
.tog span{position:absolute;left:11px;right:11px;height:2px;border-radius:2px;background:var(--ink);transition:transform .35s ease,opacity .3s ease;transform-origin:center}
.tog span:nth-child(1){top:10px} .tog span:nth-child(2){top:18px;background:var(--accent)} .tog span:nth-child(3){top:26px}
.tog[aria-expanded="true"] span:nth-child(1){transform:translateY(8px) rotate(45deg)} .tog[aria-expanded="true"] span:nth-child(2){opacity:0;transform:scaleX(.2)} .tog[aria-expanded="true"] span:nth-child(3){transform:translateY(-8px) rotate(-45deg)}
.pills{display:flex;gap:6px;margin:0 auto;align-items:center;justify-content:center;flex-wrap:wrap}
.pills a{padding:8px 15px;border-radius:999px;border:1px solid var(--line);font-size:13px;letter-spacing:.04em;color:var(--ink);background:color-mix(in srgb,var(--panel) 60%,transparent);transition:.25s;white-space:nowrap}
.pills a:hover{border-color:var(--accent);color:var(--accent)} .pills a.on{background:var(--ink);color:var(--paper);border-color:var(--ink)}
.hdr-cta{margin-left:auto;white-space:nowrap;flex:none}
@media(max-width:980px){.pills{display:none}}
@media(max-width:560px){header.site .wrap{height:64px;gap:10px} .logo{font-size:18px} .logo img{height:32px} .hdr-cta{padding:9px 14px;font-size:12.5px}}
/* the narrow-screen override is width only: the arms stay 22px wide and keep their whole-pixel offsets */
@media(max-width:400px){.logo{font-size:16px} .hdr-cta{padding:8px 12px;font-size:12px} .tog{width:40px} .tog span{left:9px;right:9px}}

/* the slide-in panel: pages, sections of this page, the actions, the hours */
#menu-scrim{position:fixed;inset:0;background:color-mix(in srgb,var(--ink) 45%,transparent);z-index:64;opacity:0;pointer-events:none;transition:opacity .35s} #menu-scrim.open{opacity:1;pointer-events:auto}
#menu-panel{position:fixed;top:0;left:0;bottom:0;width:min(330px,86vw);background:var(--paper);border-right:1px solid var(--line);z-index:65;padding:88px 22px 30px;transform:translateX(-103%);transition:transform .42s cubic-bezier(.33,.02,.2,1);overflow-y:auto}
#menu-panel.open{transform:translateX(0)}
#menu-panel .sub{font-size:11px;letter-spacing:.22em;text-transform:uppercase;color:var(--accent);margin:22px 0 10px;padding-left:16px} #menu-panel .sub:first-child{margin-top:0}
#menu-panel a{display:flex;align-items:center;justify-content:space-between;padding:12px 18px;margin:0 0 8px;border-radius:999px;border:1px solid var(--line);background:color-mix(in srgb,var(--panel) 60%,transparent);font-family:var(--display-font),Georgia,serif;font-size:18px;line-height:1.1;color:var(--ink);opacity:0;transform:translateX(-8px);transition:opacity .3s ease .08s,transform .3s ease .08s,background .2s,border-color .2s,color .2s}
#menu-panel.open a{opacity:1;transform:none} #menu-panel a:hover{border-color:var(--accent);color:var(--accent)} #menu-panel a.here{background:var(--ink);color:var(--paper);border-color:var(--ink)}
#menu-panel a.small{font-family:var(--body-font),sans-serif;font-size:14px;letter-spacing:.02em;padding:11px 18px;margin-bottom:6px}
#menu-panel a.small.go{background:var(--accent);color:#fff;border-color:var(--accent)} #menu-panel a.small.go:hover{background:var(--accent-dark);border-color:var(--accent-dark)}
#menu-panel .mh{margin-top:22px;padding-top:16px;border-top:1px solid var(--line);font-size:13.5px;color:var(--muted)} #menu-panel .mh b{display:block;font-size:11px;letter-spacing:2.2px;text-transform:uppercase;color:var(--accent);margin-bottom:8px} #menu-panel .mh span{display:block;padding:2px 0}
/* The scroll lock while the menu is open sits on the ROOT, never on body (2026-10-08). html and body are both
   overflow-x:clip, so the old body.menu-open{overflow:hidden} made body a scroll container of its own: the sticky
   header then stuck to body, which never scrolls, and slid out of view behind the panel on a menu opened mid-page,
   while the page itself still scrolled under the scrim. Hidden on html is carried to the viewport, which stays the
   scroll container: the header stays stuck where it was, the scroll position is never touched (nothing saved or
   restored, so nothing jumps on open or close), and the page behind cannot be scrolled (desktop, Android Chrome,
   iOS Safari 16 and later). base.js sets both classes; body.menu-open stays for site styles that key off it.
   .menu-gutter (set only when the page had a classic scrollbar) keeps its width reserved, so a desktop page does not
   shift sideways when the scrollbar goes. A gesture that starts on the scrim never pans the page, and a panel
   scrolled to its end does not hand the scroll on to the page behind it. */
html.menu-open{overflow:hidden} html.menu-open.menu-gutter{scrollbar-gutter:stable}
#menu-scrim{touch-action:none} #menu-panel{overscroll-behavior:contain}
/* Mobile right-hand navigation (Andre 2026-09-17, amending the 9/7 nav standard). A phone is held in one hand
   and the thumb reaches the right side, so below the width where the top pill row stops showing, the
   hamburger and its panel move to the right. The breakpoint is tied to .pills going away rather than to a
   guessed phone width, so the button moves on exactly the screens where it is the whole navigation and the
   two can never drift apart. Desktop does not move. This is order and CSS only; the button stays first in the
   DOM so keyboard and screen-reader order still meet the menu before the wordmark.
   This block MUST stay after the #menu-panel rules above: the specificity is identical, so source order is
   the only thing deciding which wins. The header's free space is handed to the logo here rather than relying
   on .hdr-cta's auto margin, because the header CTA is optional in a built site and without it order:1 alone
   would leave the toggle sitting next to the wordmark. No sideways scroll: #menu-panel is position:fixed, so
   its off-screen transform adds nothing to the document's scrollable width. */
@media(max-width:980px){
  .tog{order:1}
  .logo{margin-right:auto} .hdr-cta{margin-left:0}
  #menu-panel{left:auto;right:0;border-right:0;border-left:1px solid var(--line);transform:translateX(103%)}
  #menu-panel.open{transform:translateX(0)}
  #menu-panel a{transform:translateX(8px)} #menu-panel.open a{transform:none}
}

/* the sticky action bar on phones: never covers a hero, always reachable */
#stickybar{display:none;position:fixed;left:0;right:0;bottom:0;z-index:50;gap:10px;padding:10px 12px calc(10px + env(safe-area-inset-bottom));background:color-mix(in srgb,var(--paper) 96%,transparent);border-top:1px solid var(--line);box-shadow:0 -6px 18px color-mix(in srgb,var(--ink) 10%,transparent)}
#stickybar a{flex:1 1 0;min-height:44px;display:flex;align-items:center;justify-content:center;font:700 16px var(--display-font),Georgia,serif;border-radius:10px}
#stickybar .sb-main{background:var(--accent);color:#fff} #stickybar .sb-call{color:var(--accent-dark);border:2px solid var(--accent-dark)}
/* the search pill (Karson's idea, 2026-09-12): a third pill that opens the site's service search from anywhere */
#stickybar .sb-search{flex:0 0 auto;min-width:48px;padding:0 12px;color:var(--ink);border:2px solid var(--line);background:var(--panel)} #stickybar .sb-search svg{width:18px;height:18px}
@media(max-width:820px){#stickybar{display:flex} body{padding-bottom:74px}}

/* buttons, sections, cards */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:10px;padding:14px 24px;border-radius:var(--radius-pill,999px);font-weight:600;font-size:15px;letter-spacing:.02em;transition:.25s;border:1px solid transparent;cursor:pointer;min-height:44px}
.btn.solid{background:var(--accent);color:#fff} .btn.solid:hover{background:var(--accent-dark)}
.btn.ghost{border-color:var(--ink);color:var(--ink)} .btn.ghost:hover{background:var(--ink);color:var(--paper)}
.btn.sm{padding:9px 16px;font-size:13px;min-height:0}
section{padding:88px 0} @media(max-width:820px){section{padding:60px 0}}
section.alt{background:var(--panel);border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
section.band{background:var(--ink);color:var(--paper)} section.band .kick{color:var(--accent-light,var(--accent))} section.band .lede{color:color-mix(in srgb,var(--paper) 82%,transparent)}
/* ghost buttons on the dark band (2026-09-15): ink on ink was invisible; paper border and text, as in the hero */
section.band .btn.ghost{border-color:color-mix(in srgb,var(--paper) 70%,transparent);color:var(--paper)} section.band .btn.ghost:hover{background:var(--paper);color:var(--ink)}
/* heading rhythm (2026-09-15, Andre, from his phone): the kick, the heading and the paragraph under it each get room to breathe, the same few
   pixels at every width. These used to be inline styles in the build (14px under a heading, 16 or 18px above the copy); they live here now so a
   site's extra_css can tune them. The hero keeps its own spacing, and the menu's category heads keep theirs (.cathead, further down). */
.kick{font-size:12px;letter-spacing:.22em;text-transform:uppercase;color:var(--accent);margin-bottom:18px;font-weight:700} .hero .kick{margin-bottom:14px}
.lede{font-size:clamp(17px,1.5vw,20px);color:var(--muted);max-width:62ch} h2+.lede,h3+.lede{margin-top:18px}
.copy{margin-top:22px} .copy:first-child{margin-top:0} .copy p{max-width:68ch;margin-bottom:14px;color:var(--muted)} .copy p:last-child{margin-bottom:0}
/* .sec-head, a bespoke heading block inside an html section (a span.kick, the h2, then a paragraph, as the Pastelaria pages use it): the same rhythm */
.sec-head .kick{display:block} .sec-head h2{margin-bottom:18px}

/* The heading underline gauge (Andre's spec, 2026-08-27, from South County; into the kit 2026-09-17).
   Every section heading carries an underline that draws itself in on load and then tracks scroll: the
   further a heading has climbed the screen, the fuller its own line. The selector is written once in
   lwkit/__init__.py (ULINE_PARTS) and substituted into this file and into base.js, so the look and the
   driver cannot drift apart and no heading needs a hand-added class. The colour is the theme's, never a
   hard-coded one, and only a transform ever changes, so scrolling costs no layout and no text repaint. */
:root{--uline-a:var(--accent);--uline-b:color-mix(in srgb,var(--accent) 28%,transparent)}
/* on ink (the dark band) and over a hero photo, the light end of the accent carries instead */
section.band,.hero:not(.plain){--uline-a:var(--accent-light,var(--accent));--uline-b:color-mix(in srgb,var(--accent-light,var(--accent)) 26%,transparent)}
/* the line ends where the words end, never at the column edge; a heading too long for its column still
   wraps as normal and the line then spans the column, which is the two-line case, not a broken one */
section>.wrap>h1:not(.no-uline),section>.wrap>h2:not(.no-uline),section>.wrap>h3:not(.no-uline),section>.wrap>.fold>h2:not(.no-uline),section>.wrap>.fold>h3:not(.no-uline),section>.wrap>.ctr>h1:not(.no-uline),section>.wrap>.ctr>h2:not(.no-uline),section>.wrap>.ctr>h3:not(.no-uline),section>.wrap>.grid2>div>h1:not(.no-uline),section>.wrap>.grid2>div>h2:not(.no-uline),section>.wrap>.grid2>div>h3:not(.no-uline),.cathead>h2:not(.no-uline),.cathead>h3:not(.no-uline),.sec-head>h1:not(.no-uline),.sec-head>h2:not(.no-uline),.sec-head>h3:not(.no-uline),.uline:not(.no-uline){width:max-content;max-width:100%}
/* the hero keeps its own line length: the rule above is more specific than .hero h1, so re-assert it */
section.hero>.wrap>h1{max-width:min(14ch,100%)}
/* the h1 now has a line under it, so the lede needs the same room beneath a heading that h2 and h3 already had */
h1+.lede{margin-top:18px}
/* A text column beside a photo must be allowed to shrink below the heading's max-content width, or the
   heading's column swallows the row and the photo column collapses to nothing (Max's site, 2026-08-27). */
.grid2>*,.sec-head,.copy{min-width:0}
/* a centred set (the cta) centres the words, so the line has to be centred under them as well */
.ctr>h1,.ctr>h2,.ctr>h3{margin-inline:auto}
section>.wrap>h1:not(.no-uline)::after,section>.wrap>h2:not(.no-uline)::after,section>.wrap>h3:not(.no-uline)::after,section>.wrap>.fold>h2:not(.no-uline)::after,section>.wrap>.fold>h3:not(.no-uline)::after,section>.wrap>.ctr>h1:not(.no-uline)::after,section>.wrap>.ctr>h2:not(.no-uline)::after,section>.wrap>.ctr>h3:not(.no-uline)::after,section>.wrap>.grid2>div>h1:not(.no-uline)::after,section>.wrap>.grid2>div>h2:not(.no-uline)::after,section>.wrap>.grid2>div>h3:not(.no-uline)::after,.cathead>h2:not(.no-uline)::after,.cathead>h3:not(.no-uline)::after,.sec-head>h1:not(.no-uline)::after,.sec-head>h2:not(.no-uline)::after,.sec-head>h3:not(.no-uline)::after,.uline:not(.no-uline)::after{content:"";display:block;width:100%;height:3px;margin-top:14px;border-radius:2px;background:linear-gradient(90deg,var(--uline-a),var(--uline-b));transform:scaleX(var(--up,0));transform-origin:left;transition:transform .16s linear}
/* asked for nothing to move: the underline is simply there, complete and still */
@media(prefers-reduced-motion:reduce){section>.wrap>h1:not(.no-uline)::after,section>.wrap>h2:not(.no-uline)::after,section>.wrap>h3:not(.no-uline)::after,section>.wrap>.fold>h2:not(.no-uline)::after,section>.wrap>.fold>h3:not(.no-uline)::after,section>.wrap>.ctr>h1:not(.no-uline)::after,section>.wrap>.ctr>h2:not(.no-uline)::after,section>.wrap>.ctr>h3:not(.no-uline)::after,section>.wrap>.grid2>div>h1:not(.no-uline)::after,section>.wrap>.grid2>div>h2:not(.no-uline)::after,section>.wrap>.grid2>div>h3:not(.no-uline)::after,.cathead>h2:not(.no-uline)::after,.cathead>h3:not(.no-uline)::after,.sec-head>h1:not(.no-uline)::after,.sec-head>h2:not(.no-uline)::after,.sec-head>h3:not(.no-uline)::after,.uline:not(.no-uline)::after{transform:scaleX(1);transition:none}}
.hero{position:relative;min-height:78vh;display:grid;align-items:end;color:#fff;overflow:hidden;padding:0}
.hero.plain{min-height:0;color:var(--ink);align-items:start}
.hero .bg{position:absolute;inset:0;background:var(--ink) center/cover no-repeat}
.hero .bg::after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,color-mix(in srgb,var(--ink) 15%,transparent),color-mix(in srgb,var(--ink) 72%,transparent) 70%,color-mix(in srgb,var(--ink) 92%,transparent))}
.hero .wrap{position:relative;padding:110px 0 70px} .hero.plain .wrap{padding:70px 0 20px}
.hero h1{max-width:14ch;text-wrap:balance} .hero .lede{color:color-mix(in srgb,#fff 88%,transparent)} .hero.plain .lede{color:var(--muted)}
.hero .row{display:flex;gap:12px;flex-wrap:wrap;margin-top:28px}
.hero .btn.ghost{border-color:color-mix(in srgb,#fff 70%,transparent);color:#fff} .hero .btn.ghost:hover{background:#fff;color:var(--ink)}
.hero.plain .btn.ghost{border-color:var(--ink);color:var(--ink)}
.hero .note{margin-top:22px;font-size:14px;opacity:.85}
/* the cta set, centred (2026-09-15): the lede's 62ch box needs auto margins under a centred heading, and the button row is a flex row here */
.ctr{text-align:center} .ctr .lede{margin-left:auto;margin-right:auto} .ctr .row{display:flex;flex-wrap:wrap;gap:12px;justify-content:center;margin-top:28px}
.cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:20px;margin-top:36px}
.card{display:flex;flex-direction:column;background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;box-shadow:0 10px 30px color-mix(in srgb,var(--ink) 8%,transparent);transition:transform .4s ease,box-shadow .4s ease}
a.card:hover{transform:translateY(-4px);box-shadow:0 18px 40px color-mix(in srgb,var(--ink) 16%,transparent)}
.card .imgbox{aspect-ratio:4/3;overflow:hidden;background:var(--line)} .card .imgbox img{width:100%;height:100%;object-fit:cover}
.card .t{padding:20px 22px 24px} .card h3{margin-bottom:6px} .card p{font-size:15px;color:var(--muted)}
.grid2{display:grid;grid-template-columns:1.05fr .95fr;gap:52px;align-items:center} @media(max-width:900px){.grid2{grid-template-columns:1fr;gap:28px}}
.ph{border-radius:var(--radius);overflow:hidden;background:var(--line);box-shadow:0 24px 60px color-mix(in srgb,var(--ink) 18%,transparent);line-height:0}
.facts{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:22px;margin-top:36px}
.fact{border-top:1px solid color-mix(in srgb,currentColor 25%,transparent);padding-top:16px} .fact b{display:block;font-family:var(--display-font),Georgia,serif;font-size:40px;color:var(--accent-light,var(--accent))} .fact span{font-size:14px;opacity:.8}
.reviews{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:20px;margin-top:36px}
.rev{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);padding:24px} .rev .stars{color:var(--gold,#c9a45c);letter-spacing:2px;margin-bottom:10px} .rev p{font-size:15.5px} .rev .who{margin-top:12px;font-size:13px;color:var(--muted)}
.info{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:20px;margin-top:36px}
.info div{padding:22px;border:1px solid var(--line);border-radius:var(--radius);background:var(--panel)} .info b{display:block;font-family:var(--display-font),Georgia,serif;font-size:22px;margin-bottom:6px} .info p{font-size:15px;color:var(--muted);overflow-wrap:anywhere}
/* map links (2026-09-15): the street address opens Google Maps, the small link beside it opens Apple Maps; underlined so they read as links inside text */
.maplink{text-decoration:underline;text-underline-offset:3px;text-decoration-thickness:1px} .maplink:not(.alt){margin-right:6px}
.maplink.alt{font-size:12px;letter-spacing:.08em;text-transform:uppercase;white-space:nowrap}
/* the gap sits on the address's trailing edge, not the Apple link's leading edge: a start margin indented the link by 6px whenever it wrapped onto its
   own line, and mid-line after the zip it read as offset (Andre, on his phone, 2026-09-15). On phones the Apple link takes its own line, flush with the
   address above and the line below; the <br> the build puts after it is dropped there, or it would leave a blank line. */
@media(max-width:560px){.maplink.alt{display:block;margin-top:2px} .maplink.alt+br{display:none}}

/* the service menu with search, predictive suggestions and category chips */
.svc-search{margin-top:28px;display:flex;gap:14px;align-items:center;flex-wrap:wrap}
.svc-box{position:relative;flex:1;min-width:260px}
.svc-box input{width:100%;padding:14px 20px;border:1px solid var(--line);border-radius:999px;background:var(--panel);font:inherit;font-size:15px;color:var(--ink);box-shadow:0 8px 24px color-mix(in srgb,var(--ink) 6%,transparent)}
.svc-count{font-size:13px;color:var(--muted);letter-spacing:.04em}
.svc-sug{position:absolute;left:0;right:0;top:calc(100% + 8px);background:var(--panel);border:1px solid var(--line);border-radius:18px;box-shadow:0 18px 50px color-mix(in srgb,var(--ink) 16%,transparent);list-style:none;margin:0;padding:8px;z-index:30;max-height:340px;overflow:auto}
.svc-sug[hidden]{display:none}
.svc-sug li{display:grid;grid-template-columns:1fr auto;gap:2px 12px;padding:10px 12px;border-radius:12px;cursor:pointer;align-items:baseline} .svc-sug li:hover,.svc-sug li.sel{background:color-mix(in srgb,var(--accent) 12%,transparent)}
.svc-sug .n{font-family:var(--display-font),Georgia,serif;font-size:18px} .svc-sug .n mark{background:color-mix(in srgb,var(--accent) 30%,transparent);color:inherit;border-radius:3px;padding:0 1px}
.svc-sug .c{font-size:12px;color:var(--muted);letter-spacing:.04em} .svc-sug .p{font-family:var(--display-font),Georgia,serif;font-size:17px;color:var(--accent-dark)}
.svc-cats{display:flex;gap:8px;flex-wrap:wrap;margin-top:14px}
.chip{padding:8px 14px;border-radius:999px;border:1px solid var(--line);background:color-mix(in srgb,var(--panel) 60%,transparent);font:inherit;font-size:13px;color:var(--ink);cursor:pointer;letter-spacing:.03em;transition:.2s} .chip:hover{border-color:var(--accent);color:var(--accent)} .chip.on{background:var(--ink);color:var(--paper);border-color:var(--ink)}
.svc-empty{padding:40px 0;color:var(--muted);font-size:17px}
.cathead{margin:60px 0 18px} .cathead:first-of-type{margin-top:0} .cathead h2{margin-bottom:8px} .cathead .lede{margin-top:0}
.menu{display:grid;grid-template-columns:1fr}
.mrow{display:grid;grid-template-columns:1fr auto auto;gap:18px;align-items:baseline;padding:16px 0;border-top:1px solid var(--line)}
.mrow .n{font-family:var(--display-font),Georgia,serif;font-size:21px} .mrow .d{font-size:14px;color:var(--muted);grid-column:1/-1;margin-top:-6px;max-width:70ch}
.mrow .m{font-size:13px;color:var(--muted);letter-spacing:.04em} .mrow .p{font-family:var(--display-font),Georgia,serif;font-size:21px;color:var(--accent-dark)}
@media(max-width:620px){.mrow{grid-template-columns:1fr auto} .mrow .m{display:none}}
/* menu thumbnails (2026-09-15): a 58px picture slot per row when the section has thumbs; a blank slot shows the item's initial on a tint */
.menu.thumbs .mrow{grid-template-columns:58px 1fr auto auto;align-items:center} .menu.thumbs .mrow .d{grid-column:2/-1}
.mrow .th{grid-row:1/2;width:58px;height:58px;border-radius:12px;border:1px solid var(--line);overflow:hidden;background:var(--panel);display:grid;place-items:center;user-select:none} .mrow .th img{width:100%;height:100%;object-fit:cover}
.mrow .th.blank{background:color-mix(in srgb,var(--accent) 12%,var(--panel));color:var(--accent-dark);font-family:var(--display-font),Georgia,serif;font-weight:var(--display-weight,700);font-size:24px;line-height:1}
@media(max-width:620px){.menu.thumbs .mrow{grid-template-columns:58px 1fr auto}}
.mrow.hit{background:color-mix(in srgb,var(--accent) 18%,transparent);border-radius:12px;box-shadow:0 0 0 8px color-mix(in srgb,var(--accent) 18%,transparent);animation:hitfade 3s ease forwards} @keyframes hitfade{to{background:transparent;box-shadow:none}}
.hide{display:none!important}

/* gallery and lightbox */
.gal{display:grid;grid-template-columns:repeat(3,1fr);gap:18px;margin-top:30px}
@media(max-width:900px){.gal{grid-template-columns:repeat(2,1fr);gap:14px}} @media(max-width:520px){.gal{grid-template-columns:1fr}}
.gal .shot{position:relative;aspect-ratio:1;border-radius:var(--radius);overflow:hidden;background:var(--line);box-shadow:0 16px 42px color-mix(in srgb,var(--ink) 12%,transparent)}
.gal .shot img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.zoom{cursor:zoom-in}
.lb{position:fixed;inset:0;z-index:200;background:color-mix(in srgb,var(--ink) 93%,transparent);backdrop-filter:blur(8px);display:none;align-items:center;justify-content:center;padding:34px 22px 64px} .lb.on{display:flex}
.lb img{max-width:min(1120px,94vw);max-height:84vh;width:auto;height:auto;border-radius:var(--radius);box-shadow:0 40px 110px rgba(0,0,0,.55)}
.lb .x{position:absolute;top:18px;right:20px;width:46px;height:46px;border-radius:999px;border:1px solid rgba(255,255,255,.4);background:rgba(255,255,255,.14);color:#fff;font:400 26px/1 sans-serif;cursor:pointer}
.lb .cap{position:absolute;left:0;right:0;bottom:24px;text-align:center;color:rgba(255,255,255,.78);font-size:13.5px;padding:0 26px}

/* before / after slider: pointer-driven, no loop, native on touch */
.ba{position:relative;aspect-ratio:16/10;border-radius:var(--radius);overflow:hidden;border:1px solid var(--line);box-shadow:0 10px 30px color-mix(in srgb,var(--ink) 16%,transparent);touch-action:none;cursor:ew-resize;--cut:50%;margin-top:30px}
.ba img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;pointer-events:none}
.ba .before{clip-path:inset(0 calc(100% - var(--cut)) 0 0)}
.ba .handle{position:absolute;top:0;bottom:0;left:var(--cut);width:0;pointer-events:none}
.ba .handle::before{content:"";position:absolute;top:0;bottom:0;left:-1.5px;width:3px;background:var(--accent);box-shadow:0 0 0 1px rgba(255,255,255,.5)}
.ba .grip{position:absolute;top:50%;left:0;transform:translate(-50%,-50%);width:46px;height:46px;border-radius:50%;background:var(--accent);color:#fff;display:flex;align-items:center;justify-content:center;box-shadow:0 6px 18px color-mix(in srgb,var(--ink) 32%,transparent)}
.ba .tag{position:absolute;top:12px;font-size:11px;letter-spacing:1.5px;text-transform:uppercase;padding:4px 9px;border-radius:5px;background:color-mix(in srgb,var(--ink) 62%,transparent);color:#fff;pointer-events:none} .ba .tag.b{left:12px} .ba .tag.a{right:12px}

/* the contact form */
.form{max-width:720px;margin-top:30px} .fgrid{display:grid;grid-template-columns:1fr 1fr;gap:14px 16px;margin-bottom:18px} .fgrid .wide{grid-column:1/-1}
.form label{display:block;font-size:12.5px;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);font-weight:700} .form label span{display:block;margin-bottom:6px}
.form input,.form textarea{width:100%;padding:13px 14px;border-radius:10px;border:1px solid var(--line);background:var(--panel);color:var(--ink);font:inherit;font-size:16px;outline:none}
.form input:focus,.form textarea:focus{border-color:var(--accent);box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 28%,transparent)}
.form textarea{min-height:120px;resize:vertical}
.form .hp{position:absolute;left:-9999px;width:1px;height:1px;opacity:0}
.form .status{margin-top:14px;font-size:15px;min-height:1.3em;color:var(--muted)} .form.sent .fgrid,.form.sent .btn{display:none} .form.sent .status{font-size:17px;color:var(--ink)}
.form .consent{margin-top:14px;font-size:13.5px;line-height:1.55;color:var(--muted);max-width:62ch} .form .consent a{color:var(--accent-dark);text-decoration:underline} .form.sent .consent{display:none}
@media(max-width:640px){.fgrid{grid-template-columns:1fr}}

/* footer */
footer.site{background:var(--ink);color:color-mix(in srgb,var(--paper) 80%,transparent);padding:56px 0 40px;font-size:14px}
footer.site .wrap{display:grid;grid-template-columns:1.4fr 1fr 1fr 1fr;gap:30px} @media(max-width:900px){footer.site .wrap{grid-template-columns:1fr 1fr}} @media(max-width:520px){footer.site .wrap{grid-template-columns:1fr}}
footer.site h4{color:var(--paper);font-family:var(--display-font),Georgia,serif;font-size:20px;margin-bottom:10px} footer.site a:hover{color:var(--accent-light,var(--accent))} footer.site .tag{letter-spacing:.2em;text-transform:uppercase;font-size:11px;color:var(--accent-light,var(--accent));margin-top:14px}
footer.site .credit{grid-column:1/-1;margin-top:20px;padding-top:16px;border-top:1px solid color-mix(in srgb,var(--paper) 15%,transparent);font-size:12.5px;opacity:.7}

/* scroll reveal, and nothing moves for people who asked for nothing to move */
.rv{opacity:0;transform:translateY(16px);transition:opacity .9s ease,transform .9s ease} .rv.in{opacity:1;transform:none}
@media(prefers-reduced-motion:reduce){*,*::before,*::after{animation:none!important;transition:none!important} .rv{opacity:1;transform:none} html{scroll-behavior:auto}}

/* fold.css (shared, tools/lwkit/fold.css) */
/* fold v2: plus-minus (2026-10-01) */
/* fold.css: styles for the Loomwest fold standard (fold.js). Colours inherit from the site; override the custom
   properties per site if needed. Open by default; the button reads as part of the heading, with a small "Fold" or
   "Open" hint and a plus or minus at the right.
   v2 (Andre 2026-10-01 morning): the chevron became a plus and minus in a small rounded square, the look of the
   Command Center's "Records out of sync" toggle: a minus while the section is open (the hint reads "Fold"), a plus
   while it is folded (the hint reads "Open"). The button's aria-expanded drives it; the icon itself is aria-hidden. */
.fold-head { margin: 0; }
.fold-btn {
  all: unset; box-sizing: border-box; display: flex; align-items: center; gap: 12px; width: 100%;
  min-height: 44px; cursor: pointer; font: inherit; color: inherit; text-align: left;
}
.fold-btn:focus-visible { outline: 3px solid var(--fold-focus, currentColor); outline-offset: 4px; border-radius: 4px; }
.fold-label { flex: 1 1 auto; }
.fold-hint {
  flex: 0 0 auto; font-size: .8rem; font-weight: 600; letter-spacing: .02em; opacity: .75;
  font-family: var(--fold-hint-font, inherit); text-transform: none;
}
/* the plus and minus: a 24px square with a 1px border (so the 22px inside centres a 2px bar on whole pixels) and two
   bars drawn in the icon's own colour; the upright bar is there only while folded */
.fold-icon {
  flex: 0 0 auto; position: relative; box-sizing: border-box; width: 24px; height: 24px; margin-right: 2px;
  border: 1px solid currentColor; border-color: color-mix(in srgb, currentColor 55%, transparent); border-radius: 7px;
}
.fold-icon::before, .fold-icon::after {
  content: ""; position: absolute; left: 6px; top: 10px; width: 10px; height: 2px; border-radius: 1px;
  background: currentColor; transition: transform .2s ease;
}
.fold-icon::after { transform: rotate(90deg) scaleX(0); }
.fold-btn[aria-expanded="false"] .fold-icon::after { transform: rotate(90deg); }
.fold-btn:hover .fold-icon { background: color-mix(in srgb, currentColor 10%, transparent); }
.fold-summary { margin: 6px 0 0; opacity: .8; font-size: .95em; }
.fold-all-wrap { display: flex; justify-content: flex-end; margin: 0 0 10px; }
.fold-all {
  all: unset; box-sizing: border-box; cursor: pointer; min-height: 44px; display: inline-flex; align-items: center;
  padding: 0 14px; border: 1.5px solid currentColor; border-radius: 999px; font: inherit; font-size: .9rem; font-weight: 600;
}
.fold-all:focus-visible { outline: 3px solid var(--fold-focus, currentColor); outline-offset: 3px; }
@media (prefers-reduced-motion: reduce) { .fold-icon::after { transition: none; } }
@media print { .fold-body[hidden] { display: block !important; } .fold-btn .fold-hint, .fold-btn .fold-icon, .fold-all-wrap { display: none; } }

/* lwkit fold skin (2026-10-01): the shared fold.css above, in the theme's colours and fonts */
:root{--fold-focus:var(--accent)}
.fold-head .fold-btn{gap:14px}
.fold-head .fold-hint{margin-left:auto;font-family:var(--body-font),system-ui,sans-serif;font-size:13px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);opacity:1}
.fold-head .fold-icon{color:var(--accent);margin-right:6px}
section.band .fold-head .fold-hint{color:color-mix(in srgb,var(--paper) 80%,transparent)} section.band .fold-head .fold-icon{color:var(--accent-light,var(--accent))}
.fold-summary{max-width:62ch;margin:14px 0 0;color:var(--muted);font-size:16px;opacity:1}
section.band .fold-summary{color:color-mix(in srgb,var(--paper) 82%,transparent)}
.fold-body>.lede:first-child{margin-top:18px}
.fold-all-wrap{margin:0 0 18px}
.fold-all{font-family:var(--body-font),system-ui,sans-serif;font-size:14px;color:var(--ink)} section.band .fold-all{color:var(--paper)}
section>.wrap>h1.fold-head:not(.no-uline),section>.wrap>h2.fold-head:not(.no-uline),section>.wrap>h3.fold-head:not(.no-uline),section>.wrap>.fold>h2.fold-head:not(.no-uline),section>.wrap>.fold>h3.fold-head:not(.no-uline),section>.wrap>.ctr>h1.fold-head:not(.no-uline),section>.wrap>.ctr>h2.fold-head:not(.no-uline),section>.wrap>.ctr>h3.fold-head:not(.no-uline),section>.wrap>.grid2>div>h1.fold-head:not(.no-uline),section>.wrap>.grid2>div>h2.fold-head:not(.no-uline),section>.wrap>.grid2>div>h3.fold-head:not(.no-uline),.cathead>h2.fold-head:not(.no-uline),.cathead>h3.fold-head:not(.no-uline),.sec-head>h1.fold-head:not(.no-uline),.sec-head>h2.fold-head:not(.no-uline),.sec-head>h3.fold-head:not(.no-uline),.uline.fold-head:not(.no-uline){width:auto}
section>.wrap>h1.fold-head:not(.no-uline)::after,section>.wrap>h2.fold-head:not(.no-uline)::after,section>.wrap>h3.fold-head:not(.no-uline)::after,section>.wrap>.fold>h2.fold-head:not(.no-uline)::after,section>.wrap>.fold>h3.fold-head:not(.no-uline)::after,section>.wrap>.ctr>h1.fold-head:not(.no-uline)::after,section>.wrap>.ctr>h2.fold-head:not(.no-uline)::after,section>.wrap>.ctr>h3.fold-head:not(.no-uline)::after,section>.wrap>.grid2>div>h1.fold-head:not(.no-uline)::after,section>.wrap>.grid2>div>h2.fold-head:not(.no-uline)::after,section>.wrap>.grid2>div>h3.fold-head:not(.no-uline)::after,.cathead>h2.fold-head:not(.no-uline)::after,.cathead>h3.fold-head:not(.no-uline)::after,.sec-head>h1.fold-head:not(.no-uline)::after,.sec-head>h2.fold-head:not(.no-uline)::after,.sec-head>h3.fold-head:not(.no-uline)::after,.uline.fold-head:not(.no-uline)::after{content:none}
section>.wrap>h1.fold-head:not(.no-uline)>.fold-btn>.fold-label,section>.wrap>h2.fold-head:not(.no-uline)>.fold-btn>.fold-label,section>.wrap>h3.fold-head:not(.no-uline)>.fold-btn>.fold-label,section>.wrap>.fold>h2.fold-head:not(.no-uline)>.fold-btn>.fold-label,section>.wrap>.fold>h3.fold-head:not(.no-uline)>.fold-btn>.fold-label,section>.wrap>.ctr>h1.fold-head:not(.no-uline)>.fold-btn>.fold-label,section>.wrap>.ctr>h2.fold-head:not(.no-uline)>.fold-btn>.fold-label,section>.wrap>.ctr>h3.fold-head:not(.no-uline)>.fold-btn>.fold-label,section>.wrap>.grid2>div>h1.fold-head:not(.no-uline)>.fold-btn>.fold-label,section>.wrap>.grid2>div>h2.fold-head:not(.no-uline)>.fold-btn>.fold-label,section>.wrap>.grid2>div>h3.fold-head:not(.no-uline)>.fold-btn>.fold-label,.cathead>h2.fold-head:not(.no-uline)>.fold-btn>.fold-label,.cathead>h3.fold-head:not(.no-uline)>.fold-btn>.fold-label,.sec-head>h1.fold-head:not(.no-uline)>.fold-btn>.fold-label,.sec-head>h2.fold-head:not(.no-uline)>.fold-btn>.fold-label,.sec-head>h3.fold-head:not(.no-uline)>.fold-btn>.fold-label,.uline.fold-head:not(.no-uline)>.fold-btn>.fold-label{display:block;flex:0 1 auto;min-width:0}
section>.wrap>h1.fold-head:not(.no-uline)>.fold-btn>.fold-label::after,section>.wrap>h2.fold-head:not(.no-uline)>.fold-btn>.fold-label::after,section>.wrap>h3.fold-head:not(.no-uline)>.fold-btn>.fold-label::after,section>.wrap>.fold>h2.fold-head:not(.no-uline)>.fold-btn>.fold-label::after,section>.wrap>.fold>h3.fold-head:not(.no-uline)>.fold-btn>.fold-label::after,section>.wrap>.ctr>h1.fold-head:not(.no-uline)>.fold-btn>.fold-label::after,section>.wrap>.ctr>h2.fold-head:not(.no-uline)>.fold-btn>.fold-label::after,section>.wrap>.ctr>h3.fold-head:not(.no-uline)>.fold-btn>.fold-label::after,section>.wrap>.grid2>div>h1.fold-head:not(.no-uline)>.fold-btn>.fold-label::after,section>.wrap>.grid2>div>h2.fold-head:not(.no-uline)>.fold-btn>.fold-label::after,section>.wrap>.grid2>div>h3.fold-head:not(.no-uline)>.fold-btn>.fold-label::after,.cathead>h2.fold-head:not(.no-uline)>.fold-btn>.fold-label::after,.cathead>h3.fold-head:not(.no-uline)>.fold-btn>.fold-label::after,.sec-head>h1.fold-head:not(.no-uline)>.fold-btn>.fold-label::after,.sec-head>h2.fold-head:not(.no-uline)>.fold-btn>.fold-label::after,.sec-head>h3.fold-head:not(.no-uline)>.fold-btn>.fold-label::after,.uline.fold-head:not(.no-uline)>.fold-btn>.fold-label::after{content:"";display:block;width:100%;height:3px;margin-top:14px;border-radius:2px;background:linear-gradient(90deg,var(--uline-a),var(--uline-b));transform:scaleX(var(--up,0));transform-origin:left;transition:transform .16s linear}
@media(prefers-reduced-motion:reduce){section>.wrap>h1.fold-head:not(.no-uline)>.fold-btn>.fold-label::after,section>.wrap>h2.fold-head:not(.no-uline)>.fold-btn>.fold-label::after,section>.wrap>h3.fold-head:not(.no-uline)>.fold-btn>.fold-label::after,section>.wrap>.fold>h2.fold-head:not(.no-uline)>.fold-btn>.fold-label::after,section>.wrap>.fold>h3.fold-head:not(.no-uline)>.fold-btn>.fold-label::after,section>.wrap>.ctr>h1.fold-head:not(.no-uline)>.fold-btn>.fold-label::after,section>.wrap>.ctr>h2.fold-head:not(.no-uline)>.fold-btn>.fold-label::after,section>.wrap>.ctr>h3.fold-head:not(.no-uline)>.fold-btn>.fold-label::after,section>.wrap>.grid2>div>h1.fold-head:not(.no-uline)>.fold-btn>.fold-label::after,section>.wrap>.grid2>div>h2.fold-head:not(.no-uline)>.fold-btn>.fold-label::after,section>.wrap>.grid2>div>h3.fold-head:not(.no-uline)>.fold-btn>.fold-label::after,.cathead>h2.fold-head:not(.no-uline)>.fold-btn>.fold-label::after,.cathead>h3.fold-head:not(.no-uline)>.fold-btn>.fold-label::after,.sec-head>h1.fold-head:not(.no-uline)>.fold-btn>.fold-label::after,.sec-head>h2.fold-head:not(.no-uline)>.fold-btn>.fold-label::after,.sec-head>h3.fold-head:not(.no-uline)>.fold-btn>.fold-label::after,.uline.fold-head:not(.no-uline)>.fold-btn>.fold-label::after{transform:scaleX(1);transition:none}}

/* theme */
.hero{min-height:88vh} .hero .bg{animation:drift 26s ease-in-out infinite alternate;transform:scale(1.04)} @keyframes drift{from{transform:scale(1.04) translate3d(0,0,0)}to{transform:scale(1.1) translate3d(-1.5%,-1%,0)}} .hero .bg.fade{transition:opacity 1.4s ease} @media(prefers-reduced-motion:reduce){.hero .bg{animation:none}}
/* site */
/* Longhand Barber Co. (a Loomwest sample site): the Balanced preset tuned for a barbershop.
   Deep charcoal and warm off-white, oxblood for actions on paper, brass for actions on charcoal. */
:root{--brass:var(--accent-light);--brass-hi:#dcbb7e;--char:#0f1011;--on-dark:rgba(243,238,229,.78)}
section{padding:clamp(64px,8.5vw,116px) 0}
.row{display:flex;flex-wrap:wrap;gap:12px;margin-top:28px}
h1,h2,h3{letter-spacing:-.015em}
/* a hyphenated word ("line-up", "Walk-ins") never breaks at its hyphen: postbuild wraps every visible one, and the script
   wraps the text it writes later */
.nw{white-space:nowrap}
@media(max-width:560px){.wrap{width:calc(100% - 32px)}}

/* header: charcoal over the film, brass action */
header.site{background:color-mix(in srgb,var(--ink) 94%,transparent);border-bottom-color:rgba(255,255,255,.08)}
header.site .logo{color:var(--paper);letter-spacing:.01em}
header.site .tog span{background:var(--paper)} header.site .tog span:nth-child(2){background:var(--brass)}
header.site .tog:hover{background:rgba(255,255,255,.08)}
header.site .pills a{color:var(--paper);border-color:rgba(255,255,255,.18);background:transparent}
header.site .pills a:hover{border-color:var(--brass);color:var(--brass)}
header.site .pills a.on{background:var(--paper);color:var(--ink);border-color:var(--paper)}
header.site .hdr-cta{background:var(--brass);color:var(--ink)} header.site .hdr-cta:hover{background:var(--brass-hi)}
header.site :focus-visible,.hero :focus-visible,section.band :focus-visible,.bk-sum :focus-visible,footer.site :focus-visible,.sample-tab:focus-visible{outline-color:var(--brass)}
@media(max-width:1100px){.pills a{padding:8px 11px}}
/* 320 to 360: the wordmark, the Book pill and the menu button share 288 to 328px, and at 16px the wordmark needs 172,
   so the Book pill cut it to "Longhand Barber C". The gaps tighten by 2px, the pill's sides by 3px, and the wordmark
   scales with the screen (15px at 320, back to 16px at 360), which leaves it clear at every width. Wider is unchanged. */
@media(max-width:360px){
  header.site .wrap{gap:8px}
  header.site .logo{font-size:clamp(15px,4.45vw,16px);letter-spacing:0}
  header.site .hdr-cta{padding-left:13px;padding-right:13px}
}
/* the open menu: the header, with its menu button now drawn as an X, stays above the scrim and the panel, so the button
   that opened the menu is the visible 44px control that closes it (the panel used to slide over it, on the right on
   phones and on the left on desktop). Opaque while open, so the panel sliding under it never shows through. */
body.menu-open header.site{z-index:66;background:var(--ink)}

/* the film hero: a looping Higgsfield film under a charcoal scrim; poster only for reduced motion */
.hero.film{min-height:calc(100vh - 70px);min-height:calc(100svh - 70px);background:var(--char);grid-template-columns:minmax(0,1fr)}
.hero.film .bg{animation:none;transform:none;background:var(--char) url(assets/hero-poster.jpg?v=aac2ba32) center/cover no-repeat}
@media(max-aspect-ratio:3/4){.hero.film .bg{background-image:url(assets/hero-poster-portrait.jpg?v=6c09a6d2)}}
.hero.film video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block}
.hero.film .bg::after{z-index:1;background:
  linear-gradient(180deg,rgba(15,16,17,.42) 0%,rgba(15,16,17,.12) 26%,rgba(15,16,17,.5) 55%,rgba(15,16,17,.86) 78%,rgba(15,16,17,.94) 100%),
  linear-gradient(90deg,rgba(15,16,17,.62) 0%,rgba(15,16,17,.28) 45%,rgba(15,16,17,0) 72%)}
.hero.film .wrap{z-index:2;padding:120px 0 clamp(56px,9vh,96px)}
/* the kick says the shop is fictional, in the hero itself, in two even lines broken at the comma on every screen. On one
   line it reached past the side scrim into the beam (3.4:1 on the brightest frames at 900 x 700); in two it stays over
   the darker left of the picture, where the shop's old, shorter kick sat. The lighter brass keeps it well clear of 4.5:1. */
.hero.film .kick{color:var(--brass-hi);letter-spacing:.24em;max-width:25em;text-wrap:balance}
.hero.film h1{font-size:clamp(46px,7.2vw,96px);line-height:1.02;text-shadow:0 2px 24px rgba(0,0,0,.35)}
.hero.film .lede{font-size:clamp(19px,1.9vw,24px);color:rgba(255,255,255,.92);max-width:34ch}
.hero.film .btn.solid{background:var(--brass);color:var(--ink)} .hero.film .btn.solid:hover{background:var(--brass-hi)}
.hero.film .note{opacity:1;color:rgba(255,255,255,.8)}
/* portrait: the words sit over the chair's brass frame, so the scrim is heavier there and the kick turns off-white
   (measured over the whole loop: brass on brass dropped to 1.75:1; the words now clear 4.5:1 on every frame) */
@media(max-aspect-ratio:3/4){
  .hero.film .bg::after{background:linear-gradient(180deg,rgba(15,16,17,.42) 0%,rgba(15,16,17,.1) 18%,rgba(15,16,17,.36) 32%,rgba(15,16,17,.8) 44%,rgba(15,16,17,.9) 60%,rgba(15,16,17,.95) 100%)}
  .hero.film .kick{color:rgba(243,238,229,.94)}
}
/* short screens (a 375 x 667 or 360 x 740 phone, a phone on its side, a short laptop window): the words outgrow the space
   under the header and the call bar and ride up over the lamps and the beam, where the scrim is light (the kick came to
   1.3:1 there, the shop's old kick to 1.4:1), so a band of scrim rises with them, fading in over the 88px above the kick.
   Portrait gets it across the width; wider screens behind the words' side only. Taller screens are left as they are. */
@media (max-aspect-ratio:3/4) and (max-height:780px),(min-aspect-ratio:751/1000) and (max-height:620px){
  .hero.film .wrap::before{content:"";position:absolute;z-index:-1;top:0;bottom:0;left:calc(50% - 50vw);right:calc(50% - 50vw);pointer-events:none;
    background:rgba(15,16,17,.72);-webkit-mask-image:linear-gradient(180deg,transparent 0,#000 88px);mask-image:linear-gradient(180deg,transparent 0,#000 88px)}
}
@media (min-aspect-ratio:751/1000) and (max-height:620px){
  .hero.film .wrap::before{background:linear-gradient(90deg,rgba(15,16,17,.72) 0,rgba(15,16,17,.72) 50%,rgba(15,16,17,0) 80%)}
}
/* the air in the film (extra.js): a canvas over the film and under the scrim, never a pointer target; it fades in once
   the film plays and is not drawn at all under reduced motion */
.hero.film canvas.air{position:absolute;inset:0;width:100%;height:100%;display:block;pointer-events:none;opacity:0;transition:opacity 1.2s ease}
.hero.film canvas.air.on{opacity:1}
@media(prefers-reduced-motion:reduce){.hero.film video,.hero.film canvas.air{display:none}}
/* the scroll cue (extra.js): a button drawn as one dashed brass line with a single loop and a downward arrowhead, in the
   stroke of Loomwest's paper-plane carousel. extra.js places it (by transform, so the layout never moves), sizes it to the
   drawing (at least 44 px each way) and draws it; without scripts it stays hidden, since a button needs them to work.
   Nothing drawn yet (it is waiting for the film's strokes, or has undrawn on the way down): not a pointer target, but still
   in the Tab order, and focused it shows the whole arrow. canvas.cue-air carries the falling hair above the scrim. */
.hero.film .cue{position:absolute;left:0;top:0;z-index:3;margin:0;padding:0;border:0;border-radius:10px;background:transparent;color:var(--brass-hi);cursor:pointer;-webkit-tap-highlight-color:transparent;touch-action:manipulation}
.hero.film .cue[hidden]{display:none}
.hero.film .cue .cw,.hero.film .cue svg{display:block;overflow:visible;pointer-events:none}
.hero.film .cue path{fill:none;stroke:currentColor;stroke-width:var(--cw,1.5px);stroke-linecap:round;stroke-linejoin:round;visibility:hidden}
.hero.film .cue path.cp{stroke:#fff3dc;stroke-width:calc(var(--cw,1.5px) + .5px)}
.hero.film .cue.blank{pointer-events:none}
.hero.film .cue:hover{color:#ecd3a0}
.hero.film .cue:focus-visible{outline:2px solid var(--brass);outline-offset:2px}
/* the bob (extra.js) moves a plain box round the drawing, on a layer of its own, so a step of it is never a repaint */
.hero.film .cue.bob .cw{will-change:transform}
.hero.film canvas.cue-air{position:absolute;left:0;top:0;z-index:1;display:block;pointer-events:none}
@media(prefers-reduced-motion:reduce){.hero.film canvas.cue-air{display:none}.hero.film .cue .cw{transform:none!important}}
/* the services, reached from the cue, take the keyboard's place without a ring round the whole section */
#services:focus{outline:none}
@media(max-width:820px){.hero.film{min-height:calc(100vh - 64px - 84px);min-height:calc(100svh - 64px - 84px)} .hero.film .wrap{padding:96px 0 34px}}
/* phones held upright: the words run the width of the screen, so the scroll cue gets a lane of its own at the foot, under
   the last line and over the call bar (the bottom padding: the cue's 44 to 52 px with its focus ring and 12 px clear of the
   words and of the bar). The gaps between the lede, the buttons and the note close up a little to pay for most of it, so
   the kick hardly moves. Where the words would not all fit above the bar (a 360 x 640 or a 375 x 667 phone) the space
   above the kick gives way first (the band of scrim that rises with them reaches 56 px higher to match), and under 390
   the two buttons keep to one row. */
@media (max-width:560px) and (max-aspect-ratio:3/4){
  .hero.film .wrap{padding:40px 0 78px}
  .hero.film .wrap::before{top:-56px}
  .hero.film .lede{margin-top:12px}
  .hero.film .row{margin-top:20px}
  .hero.film .note{margin-top:14px}
}
@media (max-width:389px) and (max-aspect-ratio:3/4){
  .hero.film .row{gap:10px}
  .hero.film .row .btn{padding-left:18px;padding-right:18px}
}

/* the menu: a little more air between rows */
.mrow{padding:18px 0} .svc-search{margin-top:32px}
#services .row{margin-top:40px}
/* phones keep the durations (the kit hides them under 620px): a small line under the service name */
@media(max-width:620px){
  .mrow .m{display:block;grid-column:1/-1;grid-row:2;margin-top:-12px;font-size:12.5px;letter-spacing:.08em;text-transform:uppercase;font-weight:600}
  .mrow .d{grid-row:3;margin-top:-10px}
}

/* tap targets: every control is at least 44px on both axes (the kit's small pills, chips and panel links run 39 to 41) */
.chip{min-height:44px;display:inline-flex;align-items:center}
header.site .hdr-cta,header.site .logo{min-height:44px}
header.site .pills a{min-height:44px;display:inline-flex;align-items:center}
#menu-panel a,#menu-panel a.small{min-height:44px}
@media(max-width:400px){header.site .tog{width:44px} header.site .tog span{left:11px;right:11px}}

/* book a chair: the demo picker */
.book .sec-head{max-width:760px}
.bk{display:grid;grid-template-columns:minmax(0,1fr) 340px;gap:36px;margin-top:40px;align-items:start}
@media(max-width:960px){.bk{grid-template-columns:1fr;gap:28px}}
.bk-steps{min-width:0}
.bk-step{border:0;margin:0 0 30px;padding:0;min-width:0}
.bk-step legend{display:flex;align-items:center;gap:12px;font-family:var(--display-font),Georgia,serif;font-weight:var(--display-weight,600);font-size:22px;line-height:1.2;margin-bottom:14px;padding:0}
.bk-step legend .n{flex:none;width:30px;height:30px;border-radius:50%;background:var(--ink);color:var(--paper);display:grid;place-items:center;font:700 14px/1 var(--body-font),sans-serif}
.bk-grid{display:grid;gap:10px}
.bk-grid.svc{grid-template-columns:repeat(auto-fill,minmax(270px,1fr))}
.bk-grid.who{grid-template-columns:repeat(2,minmax(0,1fr))}
@media(max-width:560px){.bk-grid.who{grid-template-columns:1fr}}
.bk-grid.days{grid-template-columns:repeat(auto-fill,minmax(80px,1fr))}
.bk-grid.times{grid-template-columns:repeat(auto-fill,minmax(100px,1fr))}
.bk-hint{grid-column:1/-1;color:var(--muted);font-size:15px;padding:6px 0} .bk-hint a{text-decoration:underline;text-underline-offset:3px}
.bk-opt{position:relative;display:block;cursor:pointer;min-width:0}
.bk-opt input{position:absolute;inset:0;width:100%;height:100%;margin:0;opacity:0;cursor:pointer;z-index:1}
.bk-opt .box{display:flex;align-items:center;gap:12px;min-height:56px;height:100%;padding:12px 16px;border:1px solid var(--line);border-radius:12px;background:var(--panel);transition:border-color .2s,background .2s,box-shadow .2s}
.bk-opt:hover .box{border-color:color-mix(in srgb,var(--ink) 55%,var(--line))}
.bk-opt input:checked+.box{border-color:var(--accent);background:color-mix(in srgb,var(--accent) 8%,var(--panel));box-shadow:inset 0 0 0 2px var(--accent)}
.bk-opt input:focus-visible+.box{outline:3px solid var(--accent);outline-offset:3px}
.bk-opt input:disabled{cursor:not-allowed} .bk-opt input:disabled+.box{background:transparent;border-style:dashed;color:var(--muted);cursor:not-allowed}
.bk-opt input:disabled+.box .t{text-decoration:line-through;text-decoration-thickness:1px}
.bk-opt .tm{display:flex;flex-direction:column;min-width:0;line-height:1.3}
.bk-opt .t{font-weight:600;font-size:15.5px} .bk-opt .m{font-size:13px;color:var(--muted)}
.bk-opt .p{margin-left:auto;padding-left:8px;font-family:var(--display-font),Georgia,serif;font-size:20px;color:var(--accent-dark)}
.bk-opt .av{flex:none;width:40px;height:40px;border-radius:50%;object-fit:cover;display:grid;place-items:center;background:var(--ink);color:var(--brass)}
.bk-grid.days .box,.bk-grid.times .box{flex-direction:column;justify-content:center;gap:2px;text-align:center;padding:10px 8px}
.bk-grid.days .box{min-height:66px} .bk-grid.times .box{min-height:48px}
.bk-grid.days .dw{font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);font-weight:700} .bk-grid.days .dn{font-family:var(--display-font),Georgia,serif;font-size:19px;line-height:1.1}
.bk-grid.days input:checked+.box .dw{color:var(--accent-dark)}
.bk-grid.days .m{font-size:12px;line-height:1.2}
.bk-grid.times .t{font-size:15px} .bk-grid.times .m{font-size:11.5px}
.bk-sum{position:sticky;top:94px;background:var(--ink);color:var(--paper);border-radius:var(--radius);padding:26px 24px 22px;box-shadow:0 24px 60px color-mix(in srgb,var(--ink) 22%,transparent)}
@media(max-width:960px){.bk-sum{position:static}}
.bk-sum h3{color:var(--paper);font-size:26px;margin-bottom:14px}
.bk-sum dl div{display:flex;justify-content:space-between;align-items:baseline;gap:14px;padding:11px 0;border-top:1px solid rgba(255,255,255,.12)}
.bk-sum dt{color:var(--on-dark);font-size:14px;flex:none} .bk-sum dd{text-align:right;font-weight:600;font-size:15px;overflow-wrap:anywhere}
.bk-sum dd.empty{color:var(--on-dark);font-weight:400}
.bk-sum .tot dd{font-family:var(--display-font),Georgia,serif;font-size:26px;color:var(--brass)}
.bk-sum .bk-go{width:100%;margin-top:18px;background:var(--brass);color:var(--ink);font-size:16px} .bk-sum .bk-go:hover{background:var(--brass-hi)}
.bk-msg{margin-top:12px;font-size:14px;color:var(--on-dark);min-height:1.3em}
.bk-done{margin-top:6px;padding:16px 16px 18px;border-radius:12px;background:rgba(255,255,255,.06);border:1px solid color-mix(in srgb,var(--brass) 60%,transparent)}
.bk-done:focus{outline:none} .bk-done:focus-visible{outline:3px solid var(--brass);outline-offset:3px}
.bk-done-t{font-size:16px;line-height:1.5} .bk-done-t strong{color:var(--brass)} .bk-done-s{margin-top:8px;font-size:13.5px;color:var(--on-dark)}
.bk-done .btn{margin-top:14px;min-height:44px;background:transparent;border-color:rgba(243,238,229,.6);color:var(--paper)} .bk-done .btn:hover{background:var(--paper);color:var(--ink)}
.bk-note{margin-top:14px;padding-top:14px;border-top:1px solid rgba(255,255,255,.12);font-size:12.5px;color:var(--on-dark)}

/* the barbers: tall portraits, the whole card books that barber */
#barbers .card .imgbox{aspect-ratio:4/5}
#barbers .card .imgbox img{transition:transform .8s ease}
#barbers a.card:hover .imgbox img{transform:scale(1.03)}
#barbers .card h3{font-size:28px}
#barbers .card .t p{font-size:15.5px}
#barbers .card .t::after{content:"Book with this barber";display:inline-block;margin-top:14px;font-size:13px;font-weight:600;letter-spacing:.06em;color:var(--accent);border-bottom:1px solid currentColor;padding-bottom:2px}
/* on a phone the three portraits become compact rows, so the section is one screen instead of three */
@media(max-width:560px){
  #barbers .cards{gap:14px}
  #barbers .card{flex-direction:row;align-items:stretch}
  #barbers .card .imgbox{flex:0 0 38%;aspect-ratio:4/5}
  #barbers .card .t{padding:16px 16px 18px;align-self:center;min-width:0}
  #barbers .card h3{font-size:24px}
  #barbers .card .t p{font-size:14.5px}
  #barbers .card .t::after{margin-top:10px}
}

/* the gallery on the charcoal band */
section.band{background:var(--ink)}
section.band .gal .shot{box-shadow:none;background:#222326}
section.band .gal .shot img{transition:transform .8s ease,opacity .3s} section.band .gal .shot:hover img{transform:scale(1.03)}
@media(max-width:520px){.gal{grid-template-columns:1fr 1fr;gap:10px}}

/* walk-ins and hours */
.visit .grid2{align-items:center}
.open-now{display:inline-flex;align-items:center;gap:10px;margin-top:22px;padding:8px 14px;border-radius:999px;background:var(--panel);border:1px solid var(--line);font-size:14px;font-weight:600}
.open-now::before{content:"";width:9px;height:9px;border-radius:50%;background:var(--muted)} .open-now.is-open::before{background:#2f7a4b}
.hours{margin-top:22px;max-width:440px}
.hours div{display:flex;justify-content:space-between;gap:16px;padding:12px 0;border-top:1px solid var(--line)} .hours div:last-child{border-bottom:1px solid var(--line)}
.hours dt{color:var(--muted)} .hours dd{font-weight:600}
.hours div.today dt,.hours div.today dd{color:var(--accent)} .hours div.today dt::after{content:" (today)";font-weight:400}
.where{margin-top:22px;color:var(--muted);max-width:44ch} .where b{display:block;font-family:var(--display-font),Georgia,serif;font-size:22px;color:var(--ink);font-weight:var(--display-weight,600);margin-bottom:2px}
.visit .ph img,#story .ph img{width:100%;height:auto}
/* the map beside the address (the Loomwest map standard, Andre 2026-10-01; the component is the kit's map.js?v=6ea7e669 and
   map.css?v=236ccd11, copied in by postbuild.py). Desktop: the details on the left with the map filling the column beside them,
   the buttons and the storefront photo underneath. Phone: one column in source order, so the map comes right after
   the address, then the buttons, then the photo. The two-column rules live only above 900px (the kit's own breakpoint
   for .grid2), so the phone needs no overrides. The shop is fictional, so the map shows the town, never a street. */
.where-links{display:block;margin-top:8px}
.visit .grid2.vis{align-items:start}
@media(min-width:901px){
  .vis{grid-template-columns:minmax(0,1fr) minmax(0,1fr);row-gap:40px}
  .vis>.vis-a{grid-column:1;grid-row:1}
  .vis>.vis-map{grid-column:2;grid-row:1;align-self:stretch;display:flex;flex-direction:column}
  .vis>.vis-map>.lw-map-box{flex:1 1 auto;display:flex;flex-direction:column}
  .vis>.vis-map .lw-map{flex:1 1 auto;height:auto;min-height:420px}
  .vis>.vis-b{grid-column:1;grid-row:2;align-self:start}
  .vis>.vis-b>.row{margin-top:0}
  .vis>.vis-ph{grid-column:2;grid-row:2;aspect-ratio:16/9}
  .vis>.vis-ph img{width:100%;height:100%;object-fit:cover;object-position:50% 55%}
}

/* the story: a square frame, reserved before the photo loads */
#story .copy p{font-size:17.5px}
#story .ph{aspect-ratio:1/1} #story .ph img{width:100%;height:100%;object-fit:cover;object-position:50% 60%}

/* footer: the column titles are h2 for a clean heading order, drawn exactly as the kit's footer h4 */
footer.site .credit a{text-decoration:underline;text-underline-offset:3px}
footer.site h2.fh{color:var(--paper);font-family:var(--display-font),Georgia,serif;font-size:20px;line-height:1.2;letter-spacing:0;margin-bottom:10px}
/* footer links are 44px rows, not 18px lines stacked with <br> */
footer.site .fnav{list-style:none;margin:-10px 0 0;padding:0}
footer.site .fnav a{display:flex;align-items:center;min-height:44px}
footer.site a.ftel{display:inline-flex;align-items:center;min-height:44px;margin-top:-12px}

/* the fictional-shop marks, one system: the house disclosure at the foot (the Contour demo's "DEMO BUILD" tag, what is
   fictional, and "Example site by Loomwest"), a small "Demo" line where the page shows people, photographs, the phone
   and the location, and the sample-site tab and call-bar caption below */
footer.site .demo-note{opacity:1;font-size:13px;line-height:1.6;color:color-mix(in srgb,var(--paper) 76%,transparent)}
footer.site .demo-note p+p{margin-top:6px}
footer.site .demo-note .demo{font-size:11.5px;font-weight:700;letter-spacing:.14em;color:var(--brass);margin-bottom:8px}
.fict{display:flex;align-items:baseline;gap:10px;margin-top:24px;max-width:62ch;font-size:13.5px;line-height:1.55;color:var(--muted)}
.fict .ft{flex:none;padding:3px 8px 2px;border:1px solid color-mix(in srgb,var(--accent) 45%,transparent);border-radius:999px;font-size:10.5px;line-height:1.2;font-weight:700;letter-spacing:.16em;text-transform:uppercase;color:var(--accent)}
section.band .fict{color:var(--on-dark)}
section.band .fict .ft{color:var(--brass);border-color:color-mix(in srgb,var(--brass) 50%,transparent)}

/* the sample-site marks: a tab in the left margin on wide screens, a caption in the call bar on phones */
/* the tab is a full 44px target; from 821px up the page margins are at least 52px so it never sits over
   content (the kit's 92vw leaves 33 to 48px up to 1216px). Under 821px the call bar carries the caption instead. */
@media(min-width:821px){.wrap{width:min(1120px,calc(100% - 104px))}}
.sample-tab{position:fixed;left:0;top:50%;z-index:55;transform:translateY(-50%) rotate(180deg);writing-mode:vertical-rl;display:flex;align-items:center;justify-content:center;padding:16px 0;width:44px;min-height:44px;border-radius:8px 0 0 8px;background:var(--ink);color:var(--brass);border:1px solid color-mix(in srgb,var(--brass) 45%,transparent);border-right:0;font:700 10.5px/1 var(--body-font),sans-serif;letter-spacing:.2em;text-transform:uppercase}
footer.site .sample-tab:hover{color:var(--paper)}
#stickybar .sb-note{display:none}
@media(max-width:820px){
  .sample-tab{display:none}
  #stickybar{flex-wrap:wrap;row-gap:6px;padding-top:7px}
  #stickybar .sb-note{display:block;flex:0 0 100%;text-align:center;font-size:10.5px;line-height:1;letter-spacing:.16em;text-transform:uppercase;color:var(--muted);font-weight:700}
  body{padding-bottom:86px}
}
/* Text highlight (Andre 2026-10-14: a custom, ADA-compliant highlight from the site's own colorway): barber-pole oxblood under the cream.
   Text on it is 8.63:1 (WCAG AA needs 4.5:1); checked with tools/selection_color.py. */
::selection{background:#7b2323;color:#f3eee5}
