/*
Theme Name: Off The Hood
Theme URI: https://othdetail.com/
Author: Webified Services
Description: Mobile detailing site for Off The Hood (Springfield / 417). Shared design system; page content is edited in WordPress.
Version: 4.2.0
Requires at least: 6.0
Tested up to: 7.0
Requires PHP: 7.4
License: GNU General Public License v2 or later
Text Domain: othdetail
*/

/* ==========================================================================
   OFF THE HOOD DETAIL — SHARED DESIGN SYSTEM
   Loaded on every page. Page-specific CSS (hero, honeycomb grid, gallery
   slider, reviews marquee, quote calculator, etc.) lives in a small local
   <style> block on the pages that actually use it — see WORDPRESS-NOTES.md
   for how this maps onto a WP theme's style.css + template parts.
   ========================================================================== */

:root{
  --black:#171A1F;
  --graphite:#1D2127;
  --graphite-2:#262B32;
  --graphite-light:#343B45;
  --accent:#4682B4;
  --accent-bright:#6FA3D0;
  --cta-pink:#E8556E;
  --cta-pink-bright:#F27186;
  --ivory:#F2F4F6;
  --steel:#8B95A3;
  --line:#333A44;
  --radius:2px;
}
*{box-sizing:border-box; margin:0; padding:0;}
html{scroll-behavior:smooth;}
@media (prefers-reduced-motion: reduce){
  html{scroll-behavior:auto;}
  *{animation-duration:0.001ms !important; transition-duration:0.001ms !important;}
}
body{
  background:var(--black); color:var(--ivory);
  font-family:'Inter',sans-serif; line-height:1.5; -webkit-font-smoothing:antialiased;
}
h1,h2,h3,.display{font-family:'Oswald',sans-serif; text-transform:uppercase; letter-spacing:0.02em; font-weight:600;}
.mono{font-family:'JetBrains Mono',monospace;}
a{color:inherit; text-decoration:none;}
img{max-width:100%; display:block;}
.wrap{max-width:1200px; margin:0 auto; padding:0 32px;}
button{font-family:inherit; cursor:pointer;}
button:focus-visible, a:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible{
  outline:2px solid var(--accent-bright); outline-offset:2px;
}

/* ---------- NAV ---------- */
.nav{
  position:sticky; top:0; z-index:50;
  background:rgba(23,26,31,0.92); backdrop-filter:blur(8px);
  border-bottom:1px solid var(--line);
}
.nav .wrap{display:flex; align-items:center; justify-content:space-between; height:76px;}
.logo{display:flex; align-items:center; gap:12px; font-family:'Oswald',sans-serif; font-weight:700; font-size:19px; letter-spacing:0.04em;}
.logo-mark{width:44px; height:44px; border-radius:50%; display:block; object-fit:cover;}
.nav-links{display:flex; align-items:center; gap:36px; font-size:14px; letter-spacing:0.03em; text-transform:uppercase; font-weight:500;}
.nav-links a{color:var(--steel); transition:color .2s;}
.nav-links a:hover{color:var(--ivory);}
.nav-right{display:flex; align-items:center; gap:24px;}
a.phone-link{display:none;}
@media (min-width:900px){ a.phone-link{display:inline-flex;} }
@media (max-width:520px){
  .nav-right{gap:8px; flex-shrink:0;}
  .nav-right .btn{padding:13px 9px; font-size:10px; letter-spacing:0.03em; white-space:nowrap; flex-shrink:0;}
  .logo{font-size:15px; gap:8px;}
}
@media (max-width:380px){ .logo{gap:6px;} .logo-mark{width:36px; height:36px;} }

/* ---------- NAV "AREAS" DROPDOWN (desktop) ---------- */
.nav-dropdown{position:relative;}
/* Padded so the hover target is the full height of the nav bar rather than the
   17px of text. The nav is a fixed 76px and the links are centre-aligned, so
   this changes the target without moving anything visually. */
.nav-dropdown-trigger{
  background:none; border:none; padding:14px 0; cursor:pointer;
  font:inherit; font-size:14px; letter-spacing:0.03em; text-transform:uppercase; font-weight:500;
  color:var(--steel); display:flex; align-items:center; gap:5px; transition:color .2s;
}
.nav-dropdown-trigger:hover{color:var(--ivory);}
.nav-caret{width:9px; height:9px; flex-shrink:0; transition:transform .25s ease;}
.nav-dropdown:hover .nav-dropdown-trigger,
.nav-dropdown.is-open .nav-dropdown-trigger{color:var(--ivory);}
.nav-dropdown:hover .nav-caret,
.nav-dropdown:focus-within .nav-caret,
.nav-dropdown.is-open .nav-caret{transform:rotate(180deg);}

.nav-dropdown-panel{
  position:absolute; top:calc(100% + 6px); left:50%;
  transform:translateX(-50%) translateY(-6px);
  width:460px; max-width:min(90vw, 460px);
  background:var(--graphite-2); border:1px solid var(--line);
  box-shadow:0 30px 70px -20px rgba(0,0,0,0.65);
  padding:22px 24px; display:grid; grid-template-columns:1fr 1fr; gap:0 28px;
  opacity:0; visibility:hidden; pointer-events:none;
  transition:opacity .22s ease, transform .22s ease, visibility 0s linear .22s;
  z-index:60;
}
.nav-dropdown:hover .nav-dropdown-panel,
.nav-dropdown:focus-within .nav-dropdown-panel,
.nav-dropdown.is-open .nav-dropdown-panel{
  opacity:1; visibility:visible; pointer-events:auto;
  transform:translateX(-50%) translateY(0);
  transition:opacity .22s ease, transform .22s ease;
}
/* An invisible strip spanning the gap between the trigger and the panel. The
   pointer used to cross bare nav background on the way down, where neither
   element is hovered, so the panel closed before it could be reached — which is
   why it only really worked by clicking. The strip belongs to the panel, so
   travelling across it keeps .nav-dropdown:hover true. It inherits the panel's
   pointer-events, so while the menu is closed it catches nothing. */
.nav-dropdown-panel::before{
  content:""; position:absolute; left:0; right:0; top:-14px; height:14px;
}
.nav-dropdown-col{display:flex; flex-direction:column;}
.nav-dropdown-heading{
  font-family:'JetBrains Mono',monospace; font-size:10.5px; color:var(--accent-bright);
  text-transform:uppercase; letter-spacing:0.06em; margin-bottom:10px;
}
.nav-dropdown-panel a{font-size:13px; color:var(--ivory); padding:5px 0; transition:color .15s ease;}
.nav-dropdown-panel a:hover{color:var(--accent-bright);}
.nav-dropdown-all{
  grid-column:1/-1; margin-top:14px; padding-top:14px; border-top:1px dashed var(--line);
  font-family:'JetBrains Mono',monospace; font-size:11.5px; color:var(--accent-bright) !important;
  text-transform:uppercase; letter-spacing:0.04em;
}

/* ---------- MOBILE HAMBURGER + MENU ---------- */
.nav-burger{
  display:none; flex-direction:column; justify-content:center; align-items:flex-end; gap:5px;
  width:44px; height:44px; background:none; border:none; cursor:pointer; padding:6px; flex-shrink:0;
}
.nav-burger span{display:block; width:100%; height:2px; background:var(--ivory); transition:transform .25s ease, opacity .2s ease, width .25s ease;}
.nav-burger.is-open span{width:100%;}
.nav-burger.is-open span:nth-child(1){transform:translateY(7px) rotate(45deg);}
.nav-burger.is-open span:nth-child(2){opacity:0;}
.nav-burger.is-open span:nth-child(3){transform:translateY(-7px) rotate(-45deg);}

.mobile-menu{
  display:none; max-height:0; overflow:hidden;
  background:var(--graphite); border-top:0 solid var(--line);
  flex-direction:column;
  transition:max-height .38s ease;
}
.mobile-menu.is-open{max-height:1200px; border-top-width:1px;}
.mobile-menu > a, .mobile-menu-cta{padding-left:32px; padding-right:32px;}
.mobile-menu > a{
  display:block; font-size:15px; color:var(--ivory); padding-top:16px; padding-bottom:16px;
  border-bottom:1px solid var(--line); text-transform:uppercase; letter-spacing:0.03em; font-weight:500;
}
.mobile-menu-areas{border-bottom:1px solid var(--line);}
.mobile-areas-trigger{
  width:100%; display:flex; align-items:center; justify-content:space-between;
  background:none; border:none; padding:16px 32px; font:inherit; font-size:15px; color:var(--ivory);
  text-transform:uppercase; letter-spacing:0.03em; font-weight:500; cursor:pointer;
}
.mobile-areas-panel{max-height:0; overflow:hidden; transition:max-height .35s ease;}
.mobile-areas-panel.is-open{max-height:900px;}
.mobile-areas-heading{
  font-family:'JetBrains Mono',monospace; font-size:10.5px; color:var(--accent-bright);
  text-transform:uppercase; letter-spacing:0.06em; margin:6px 32px 6px;
}
.mobile-areas-heading:first-child{margin-top:0;}
.mobile-areas-panel a{
  display:block; padding:8px 32px; font-size:14px; color:var(--steel); font-weight:400;
}
.mobile-areas-panel a:hover{color:var(--ivory);}
.mobile-areas-panel .nav-dropdown-all{
  display:block; margin:10px 32px 4px; padding:12px 0 0; border-top:1px dashed var(--line);
}
.mobile-menu-cta{display:flex; flex-direction:column; gap:10px; padding-top:20px; padding-bottom:24px;}

@media (max-width:900px){
  .nav-links{display:none;}
  .nav-burger{display:flex;}
  .mobile-menu{display:flex;}
}

.btn{
  display:inline-flex; align-items:center; justify-content:center;
  padding:13px 26px; font-size:13px; font-weight:600; text-transform:uppercase; letter-spacing:0.06em;
  border-radius:var(--radius); cursor:pointer; border:1px solid transparent;
  transition:transform .15s ease, box-shadow .15s ease, background .15s ease;
}
.btn-accent{background:var(--accent); color:var(--black);}
.btn-accent:hover{background:var(--accent-bright); transform:translateY(-1px); box-shadow:0 6px 20px -6px rgba(70,130,180,0.6);}
.btn-pink{background:var(--cta-pink); color:#fff;}
.btn-pink:hover{background:var(--cta-pink-bright); transform:translateY(-1px); box-shadow:0 6px 20px -6px rgba(232,85,110,0.6);}
.btn-ghost{border-color:var(--line); color:var(--ivory); background:none;}
.btn-ghost:hover{border-color:var(--accent); color:var(--accent);}
.btn:disabled{opacity:0.5; cursor:not-allowed;}
.btn-full{width:100%;}

/* ---------- BREADCRUMB ---------- */
.crumb{padding:18px 0 0; font-family:'JetBrains Mono',monospace; font-size:12px; color:var(--steel);}
.crumb a{color:var(--steel);}
.crumb a:hover{color:var(--accent-bright);}
.crumb span{margin:0 8px; opacity:0.6;}
.crumb .current{color:var(--ivory);}

/* ---------- PAGE HEADER (service pages, quote, apply, city pages) ---------- */
/* Closed by the same angled blue line art the homepage hero uses to hand off to the next
   section, in place of the flat 1px rule that used to sit here. The header and the section
   below it share a background, so only the lines are drawn — no fill wedge is needed. The
   extra bottom padding keeps the buttons clear of the angle. */
.page-header{position:relative; padding:28px 0 72px;}
.header-divider{
  position:absolute; left:0; right:0; bottom:-1px; height:56px;
  line-height:0; pointer-events:none;
}
/* Optional photo behind a page header — opt in with .has-hero-img on the header. */
.page-header.has-hero-img{position:relative;}
.page-header-media{
  position:absolute; inset:0; z-index:0; pointer-events:none; overflow:hidden;
  /* The bottom edge traces the blue divider line exactly: that polyline sits 4.6px above
     the header's bottom edge on the left and 38.2px above it on the right. */
  clip-path:polygon(0 0, 100% 0, 100% calc(100% - 38.2px), 0 calc(100% - 4.6px));
}
.page-header-media img{width:100%; height:100%; object-fit:cover; object-position:46% 55%; display:block;}
/* Scrim for headline legibility — weighted left on desktop, where the text column sits. */
.page-header-media::after{
  content:""; position:absolute; inset:0;
  background:linear-gradient(90deg,
    rgba(23,26,31,0.92) 0%, rgba(23,26,31,0.78) 40%,
    rgba(23,26,31,0.50) 74%, rgba(23,26,31,0.30) 100%);
}
@media (min-width:861px){
  /* The photo itself dissolves into the page on the left rather than just being darkened,
     so a shot that doesn't fill the width edge-to-edge has nowhere awkward to end. Left is
     also where the headline sits, so this buys legibility as well as a cleaner join. */
  .page-header-media img{
    -webkit-mask-image:linear-gradient(90deg, transparent 0%, rgba(0,0,0,0.45) 16%, #000 46%);
    mask-image:linear-gradient(90deg, transparent 0%, rgba(0,0,0,0.45) 16%, #000 46%);
  }
  /* --full: show the whole photo instead of cropping it to fill. It sits against the right
     edge and its own left side is already faded to the page colour in the file, so whatever
     space is left over reads as part of the image rather than a letterbox. No CSS mask here —
     the fade is baked in, and doubling them would wash the photo out. */
  .page-header-media--full img{
    object-fit:contain; object-position:right center;
    -webkit-mask-image:none; mask-image:none;
  }
}
@media (max-width:860px){
  /* Text runs full width on a phone, so the scrim has to cover evenly instead. */
  .page-header-media::after{
    background:linear-gradient(180deg,
      rgba(23,26,31,0.90) 0%, rgba(23,26,31,0.82) 55%, rgba(23,26,31,0.88) 100%);
  }
}
.page-header.has-hero-img .wrap{position:relative; z-index:1;}
/* Sitting over a photo, the lede gets the same frosted panel the homepage hero uses, and
   steps up from steel to ivory so it holds its own against the image behind it. */
.page-header.has-hero-img .lede{
  display:inline-block; color:var(--ivory);
  background:rgba(23,26,31,0.55);
  backdrop-filter:blur(3px); -webkit-backdrop-filter:blur(3px);
  padding:12px 16px; border-radius:10px;
}
.header-divider svg{display:block; width:100%; height:100%;}
.header-divider-line{
  fill:none; stroke:var(--accent-bright); stroke-width:2.5; vector-effect:non-scaling-stroke;
}
.header-divider-line-soft{
  fill:none; stroke:var(--accent); stroke-width:1.5; opacity:0.55; vector-effect:non-scaling-stroke;
}
.sec-eyebrow{
  font-family:'JetBrains Mono',monospace; font-size:12.5px; color:var(--accent); letter-spacing:0.12em;
  text-transform:uppercase; margin-bottom:14px; display:flex; align-items:center; gap:12px;
}
/* Height tracks the text's cap height, width follows the art's 1.32 ratio. */
.sec-eyebrow::before{
  content:""; width:0.965em; height:0.73em; flex-shrink:0;
  background:var(--row-icon) no-repeat center/contain;
}
/* The eyebrow is a flex row (icon + text), and text-align has no effect on flex items —
   so inside a centred block it still hugged the left edge while the heading below it was
   centred. Centring has to come from justify-content instead. */
.sec-head-center, .reviews-head{text-align:center;}
.sec-head-center{margin-left:auto; margin-right:auto;}
.sec-head-center .sec-eyebrow, .reviews-head .sec-eyebrow{justify-content:center;}
.page-header h1{font-size:clamp(30px,4.6vw,46px); line-height:1.05; margin-bottom:16px; max-width:760px;}
/* Carries the polisher mark on a heading itself, for spots where the small eyebrow above it
   would only repeat the same words. Sized in em so it tracks the heading, and set inline
   rather than flex so a long title still wraps normally.
   The icon art is 300x227 (landscape), so the box has to carry that same 1.32 ratio —
   a square box would fit the art to the width and leave it short of the cap height. */
.has-mark::before{
  content:""; display:inline-block; vertical-align:-0.04em;
  width:0.965em; height:0.73em; margin-right:0.32em;
  background:url("images/icon-polisher.png") no-repeat center/contain;
}
.page-header .lede{color:var(--steel); font-size:16px; max-width:640px; margin-bottom:32px;}
/* No bottom margin: it only existed to separate the buttons from the hero stats
   block, which is gone — the header's own padding-bottom closes the section now. */
.page-header .hero-cta{display:flex; gap:16px; flex-wrap:wrap;}

/* ---------- SECTION HEADERS ---------- */
.section{padding:80px 0;}
.section-alt{background:var(--graphite);}
.section-tight{padding:56px 0;}
.sec-head{max-width:680px; margin-bottom:44px;}
.sec-head h2{font-size:clamp(26px,3.6vw,36px); line-height:1.08; margin-bottom:14px;}
.sec-head p{color:var(--steel); font-size:15.5px;}

/* ---------- PRICING TICKET CARDS ---------- */
.ticket-grid{display:grid; grid-template-columns:repeat(2,1fr); gap:28px;}
.ticket-grid.cols-3{grid-template-columns:repeat(3,1fr);}
@media (max-width:860px){ .ticket-grid, .ticket-grid.cols-3{grid-template-columns:1fr;} }
.ticket{
  background:var(--graphite-2); border:1px solid var(--line); position:relative;
  display:flex; flex-direction:column; transition:transform .2s ease, border-color .2s ease;
}
.ticket:hover{transform:translateY(-4px); border-color:var(--accent);}
/* Premium reads as the step-up through its own colouring — a tinted head and an accent top
   edge — rather than by borrowing the accent border, which is also the hover state. Sharing
   that border made the card look permanently hovered next to one that wasn't. Both cards
   now sit at rest the same way and hover identically. */
.ticket.is-featured{
  background:linear-gradient(180deg, rgba(70,130,180,0.13), var(--graphite-2) 230px);
  box-shadow:inset 0 3px 0 0 var(--accent);
}
.ticket-top{padding:26px 26px 22px; border-bottom:1px dashed var(--line); position:relative;}
.ticket-badge{
  position:absolute; top:-12px; right:22px; background:var(--accent); color:var(--black);
  font-family:'JetBrains Mono',monospace; font-size:10.5px; font-weight:600;
  letter-spacing:0.06em; text-transform:uppercase; padding:5px 10px;
}
.ticket-no{font-family:'JetBrains Mono',monospace; font-size:12px; color:var(--steel); margin-bottom:14px; letter-spacing:0.04em;}
.ticket-top h3{font-size:21px; margin-bottom:10px;}
.ticket-top p{color:var(--steel); font-size:13.5px; line-height:1.6;}
.ticket-body{padding:22px 26px 26px; flex:1; display:flex; flex-direction:column;}
.ticket-body ul{list-style:none; margin-bottom:22px; flex:1;}
.ticket-body li{
  font-size:13.5px; color:var(--ivory); padding:8px 0 8px 20px; position:relative;
  border-bottom:1px solid rgba(255,255,255,0.05);
}
.ticket-body li.no{color:var(--steel); opacity:0.65;}
.ticket-body li::before{content:"✓"; position:absolute; left:0; color:var(--accent-bright); font-weight:700;}
.ticket-body li.no::before{content:"✗"; color:var(--cta-pink);}
/* The full "what's included" checklist now lives inside the tier card, so the card and the
   checklist are one thing to read instead of two sections repeating each other. */
.ticket-incl{flex:1; margin-bottom:4px;}
.ticket-body .ticket-checklist{list-style:none; margin-bottom:0; flex:none;}
.ticket-incl .check-subhead{margin-top:16px; padding-top:14px; border-top:1px dashed var(--line);}
.ticket-incl .check-subhead:first-child{margin-top:0; padding-top:0; border-top:none;}
.ticket-price{display:flex; align-items:baseline; justify-content:space-between; padding-top:16px; margin-bottom:18px;}
.ticket-price .amt{font-family:'Oswald',sans-serif; font-size:28px; color:var(--accent);}
/* Small "Starts at" sitting above the figure, so the number stays the thing you read. */
.ticket-price .amt-prefix{
  display:block; margin-bottom:3px;
  font-family:'JetBrains Mono',monospace; font-size:10.5px; color:var(--steel);
  text-transform:uppercase; letter-spacing:0.07em;
}
.ticket .btn{width:100%;}

/* ---------- PRICE TABLE ---------- */
.price-table-wrap{overflow-x:auto; border:1px solid var(--line); background:var(--graphite-2);}
table.price-table{width:100%; border-collapse:collapse; min-width:480px;}
.price-table caption{
  text-align:left; padding:16px 20px; font-family:'Oswald',sans-serif; font-size:15px;
  text-transform:uppercase; letter-spacing:0.02em; border-bottom:1px solid var(--line); color:var(--ivory);
}
.price-table th, .price-table td{padding:13px 20px; text-align:left; font-size:13.5px; border-bottom:1px solid var(--line);}
.price-table thead th{
  font-family:'JetBrains Mono',monospace; font-size:11px; text-transform:uppercase; letter-spacing:0.05em;
  color:var(--steel); border-bottom:1px solid var(--accent);
}
.price-table tbody tr:last-child td{border-bottom:none;}
.price-table tbody tr:hover{background:rgba(70,130,180,0.06);}
.price-table td.veh{color:var(--ivory); font-weight:500;}
.price-table td.veh .meta{display:block; color:var(--steel); font-size:11px; font-family:'JetBrains Mono',monospace; margin-top:2px;}
.price-table td.price{font-family:'JetBrains Mono',monospace; color:var(--accent-bright); font-size:14.5px;}
.price-table-note{padding:14px 20px; font-size:11.5px; color:var(--steel); border-top:1px dashed var(--line); line-height:1.6;}

/* ---------- CHECKLIST SUBHEADINGS (inside the tier cards) ---------- */
.check-subhead{font-family:'JetBrains Mono',monospace; font-size:10.5px; color:var(--accent-bright); text-transform:uppercase; letter-spacing:0.06em; margin-top:14px; padding-top:12px; border-top:1px dashed var(--line);}
.check-subhead:first-child{margin-top:0; padding-top:0; border-top:none;}

/* ---------- PHOTO FRAMES ---------- */
/* Photos take their character from a corner cut on the diagonal — the same geometry as the
   honeycomb tiles and the header divider — plus the hexagon accent graphic riding one edge,
   instead of sitting in a plain 1px box. Crop, which corners get cut, and where the accent
   sits are separate modifiers, so the treatment never repeats identically down a page. */
.pframe{position:relative; display:block;}
/* Top and bottom edges are slanted parallel to the blue line that closes every page header —
   low on the left, rising to the right — so a photo reads as part of the same system rather
   than a rectangle with its corners chopped off. */
.pframe-media{
  position:relative; display:block; overflow:hidden;
  background:var(--graphite-2);
  clip-path:polygon(0 24px, 100% 0, 100% calc(100% - 24px), 0 100%);
}
@media (max-width:520px){
  /* Shallower on a phone so the slant stays a similar angle on a narrower frame. */
  .pframe-media{clip-path:polygon(0 16px, 100% 0, 100% calc(100% - 16px), 0 100%);}
}
/* TO NUDGE A CROP: add object-position to the <img> itself, e.g.
     <img src="..." style="object-position: 50% 30%">
   First number pans left/right (0%=left edge, 100%=right), second pans up/down
   (0%=top, 100%=bottom). Default is 50% 50%. An inline style beats this rule, so
   nothing here needs editing. Size and scale stay handled by the frame. */
.pframe-media img{width:100%; height:100%; object-fit:cover; display:block;}

/* Crops — deliberately varied per placement. */
.pframe--wide   .pframe-media{aspect-ratio:16/10;}
.pframe--land   .pframe-media{aspect-ratio:4/3;}
.pframe--square .pframe-media{aspect-ratio:1/1;}
.pframe--port   .pframe-media{aspect-ratio:3/4;}
.pframe--tall   .pframe-media{aspect-ratio:2/3;}

/* Accent graphic. Horizontal and vertical are separate pre-rotated files rather than CSS
   transforms, so placement stays predictable at any frame size. */
.pframe::after{
  content:""; position:absolute; pointer-events:none; z-index:2;
  background:no-repeat center/contain;
}
.pframe--accent-bl::after{
  left:-12px; bottom:-16px; width:min(72%, 300px); height:38px;
  background-image:url("images/accent-hex-lines.png");
}
.pframe--accent-tr::after{
  right:-12px; top:-16px; width:min(72%, 300px); height:38px;
  background-image:url("images/accent-hex-lines.png"); transform:scaleX(-1);
}
.pframe--accent-l::after{
  left:-16px; top:8%; width:38px; height:min(62%, 260px);
  background-image:url("images/accent-hex-lines-v.png");
}
.pframe--accent-r::after{
  right:-16px; bottom:8%; width:38px; height:min(62%, 260px);
  background-image:url("images/accent-hex-lines-v.png"); transform:scaleY(-1);
}
@media (max-width:520px){
  /* Pull the accents in on a phone so nothing reaches past the page gutter. */
  .pframe--accent-bl::after, .pframe--accent-tr::after{height:28px;}
  .pframe--accent-bl::after{left:-6px; bottom:-10px;}
  .pframe--accent-tr::after{right:-6px; top:-10px;}
  .pframe--accent-l::after{left:-8px; width:28px;}
  .pframe--accent-r::after{right:-8px; width:28px;}
}

/* ---------- PHOTO SECTION BREAK ---------- */
/* Full-bleed photo band separating a page's main service from the "other services" block.
   The fade is done here rather than baked into the file so the direction and depth stay
   adjustable, and so the same crop can be reused facing either way. */
.photo-break{
  position:relative; overflow:hidden; height:190px;
  background:var(--black);
  border-top:1px solid var(--line); border-bottom:1px solid var(--line);
}
.photo-break img{
  width:100%; height:100%; object-fit:cover; display:block;
  /* Very slow drift, so the band has life on scroll without becoming a distraction. */
  animation:photo-break-drift 34s ease-in-out infinite alternate;
}
@keyframes photo-break-drift{
  from{transform:scale(1.06) translateX(-1.2%);}
  to{transform:scale(1.06) translateX(1.2%);}
}
@media (prefers-reduced-motion: reduce){ .photo-break img{animation:none; transform:none;} }
.photo-break::after{
  content:""; position:absolute; inset:0; pointer-events:none;
}
/* Photo 1 keeps its subject left and dissolves off to the right. */
.photo-break--fade-right::after{
  background:linear-gradient(90deg,
    rgba(23,26,31,0.25) 0%, rgba(23,26,31,0.10) 26%,
    rgba(23,26,31,0.72) 68%, var(--black) 100%);
}
/* Photo 2 keeps its subject right and dissolves off to the left. */
.photo-break--fade-left::after{
  background:linear-gradient(270deg,
    rgba(23,26,31,0.25) 0%, rgba(23,26,31,0.10) 26%,
    rgba(23,26,31,0.72) 68%, var(--black) 100%);
}
@media (max-width:520px){ .photo-break{height:132px;} }

/* ---------- ANIMATED SECTION BREAK ---------- */
/* Full-bleed band that separates a page's main service from the "other services" block, so
   the two don't read as one continuous list. The hexagon accent drifts slowly across it —
   enough movement to catch the eye on scroll without pulling attention off the content. */
.svc-break{
  position:relative; overflow:hidden; height:104px;
  background:var(--black);
  border-top:1px solid var(--line); border-bottom:1px solid var(--line);
}
.svc-break::before{
  content:""; position:absolute; inset:0;
  background:url("images/accent-hex-lines.png") repeat-x left center;
  background-size:350px 56px;
  opacity:0.45;
  animation:svc-break-drift 26s linear infinite;
}
/* Fades the band out at both ends so the repeat never shows a hard seam at the screen edge. */
.svc-break::after{
  content:""; position:absolute; inset:0; pointer-events:none;
  background:linear-gradient(90deg, var(--black), transparent 18%, transparent 82%, var(--black));
}
@keyframes svc-break-drift{
  from{background-position-x:0;}
  to{background-position-x:-350px;}
}
@media (prefers-reduced-motion: reduce){ .svc-break::before{animation:none;} }
@media (max-width:520px){
  .svc-break{height:76px;}
  .svc-break::before{background-size:240px 38px;}
  @keyframes svc-break-drift{ from{background-position-x:0;} to{background-position-x:-240px;} }
}

/* ---------- SERVICE EXPLAINER (what the service actually is) ---------- */
.svc-explain{display:grid; grid-template-columns:1.15fr 1fr; gap:56px; align-items:start;}
@media (max-width:860px){ .svc-explain{grid-template-columns:1fr; gap:32px;} }
.svc-explain-copy p{color:var(--steel); font-size:15.5px; line-height:1.75; margin-bottom:16px;}
.svc-explain-copy p:last-child{margin-bottom:0;}
.svc-explain-copy strong{color:var(--ivory); font-weight:600;}
.fix-card{background:var(--graphite-2); border:1px solid var(--line); padding:24px 26px;}
.fix-card h3{font-size:15px; margin-bottom:14px;}
.fix-card + .fix-card{margin-top:20px;}
.fix-card ul{list-style:none;}
.fix-card li{
  font-size:14px; color:var(--ivory); padding:9px 0 9px 26px;
  position:relative; line-height:1.45;
  border-bottom:1px solid rgba(255,255,255,0.05);
}
.fix-card li:last-child{border-bottom:none;}
.fix-card li::before{
  content:"✓"; position:absolute; left:0; top:9px;
  color:var(--accent-bright); font-weight:700;
}
.fix-card li.no{color:var(--steel); opacity:0.72;}
.fix-card li.no::before{content:"✗"; color:var(--cta-pink);}

/* ---------- MEDIA BESIDE COPY (before/after feature, and any photo + text split) ---------- */
.ba-feature, .media-feature{display:grid; grid-template-columns:1.2fr 1fr; gap:48px; align-items:center;}
@media (max-width:900px){ .ba-feature, .media-feature{grid-template-columns:1fr; gap:30px;} }
.ba-feature-copy h2, .media-feature-copy h2{font-size:clamp(26px,3.6vw,36px); line-height:1.08; margin-bottom:14px;}
.ba-feature-copy p, .media-feature-copy p{color:var(--steel); font-size:15.5px; line-height:1.7; margin-bottom:18px;}

/* ---------- TIER META STRIP (correction level, time on site) ---------- */
.ticket-meta{
  display:flex; gap:14px; flex-wrap:wrap;
  padding:15px 26px; border-bottom:1px dashed var(--line);
  background:rgba(0,0,0,0.18);
}
/* Narrow basis so the two figures stay side by side on a phone rather than stacking. */
.ticket-meta-item{flex:1 1 96px; min-width:0;}
.ticket-meta-label{
  display:block; margin-bottom:5px;
  font-family:'JetBrains Mono',monospace; font-size:10px; color:var(--steel);
  text-transform:uppercase; letter-spacing:0.07em;
}
.ticket-meta-val{
  display:block; font-family:'Oswald',sans-serif; font-size:19px;
  color:var(--accent-bright); letter-spacing:0.01em;
}
/* Unfilled real-world data — deliberately looks unfinished so it can't ship by accident. */
.ticket-meta-val.is-tbd{
  font-family:'JetBrains Mono',monospace; font-size:12.5px; color:var(--steel);
  border-bottom:1px dashed var(--steel); padding-bottom:3px;
}

/* ---------- PROCESS TIMELINE ---------- */
.process-flow{max-width:780px; position:relative;}
/* The rail is drawn behind the numbered markers and fades out toward the last step. */
.process-flow::before{
  content:""; position:absolute; left:20px; top:18px; bottom:26px; width:2px;
  background:linear-gradient(180deg, var(--accent), rgba(70,130,180,0.12));
}
.process-step{position:relative; padding:0 0 30px 64px;}
.process-step:last-child{padding-bottom:0;}
.process-num{
  position:absolute; left:0; top:0;
  width:42px; height:42px; border-radius:50%;
  background:var(--graphite-2); border:2px solid var(--accent);
  display:flex; align-items:center; justify-content:center;
  font-family:'Oswald',sans-serif; font-size:16px; font-weight:600; color:var(--accent-bright);
  transition:background .25s ease, border-color .25s ease, color .25s ease, transform .25s ease;
}
.process-step:hover .process-num{
  background:var(--accent); color:var(--black);
  border-color:var(--accent-bright); transform:scale(1.08);
}
.process-step h3{font-size:17px; margin-bottom:8px; padding-top:10px; line-height:1.25;}
.process-step p{color:var(--steel); font-size:14.5px; line-height:1.7;}
.process-step .step-tag{
  display:inline-block; margin-left:10px; vertical-align:middle;
  font-family:'JetBrains Mono',monospace; font-size:9.5px; letter-spacing:0.06em;
  text-transform:uppercase; color:var(--accent-bright);
  border:1px solid var(--accent); padding:3px 7px; border-radius:2px;
}

/* ---------- SERVICE FAQ + PHOTO (all service pages) ---------- */
/* Photo one side, content the other. Shared by the service-page FAQs and the ceramic
   packages section — same behaviour, so the same rules rather than a second copy. */
.faq-layout, .split-media{display:grid; grid-template-columns:1fr 1fr; gap:48px; align-items:start;}
@media (min-width:861px){
  /* Photo matches the questions column top and bottom instead of overhanging it — the crop
     gives way rather than the layout. The well is taken out of flow so the image's own
     proportions can't set the row height; otherwise the column stretches to the photo
     instead of the other way round. Stays matched as answers open and the column grows. */
  .faq-layout{align-items:stretch;}
  .faq-layout .pframe{position:relative; min-height:100%;}
  .faq-layout .pframe-media{position:absolute; inset:0; aspect-ratio:auto;}
}
@media (max-width:860px){
  .faq-layout, .split-media{grid-template-columns:1fr; gap:32px;}
  /* Stacked above the questions, a portrait crop eats most of a phone screen before the
     first question is even visible. Cap it, but leave the crops varied. */
  .faq-layout .pframe-media, .split-media .pframe-media{max-height:300px;}
  /* MOBILE AUDIT: a capped max-height fights a portrait aspect-ratio - the box
     satisfies the ratio by shrinking its WIDTH, so a tall crop rendered 200px
     wide inside a 311px column. Drop the ratio for the tall crops and let the
     photo fill the column and crop vertically instead. Landscape crops are
     already shorter than the cap, so they keep their varied framing. */
  .faq-layout .pframe--port .pframe-media,
  .faq-layout .pframe--tall .pframe-media,
  .faq-layout .pframe--square .pframe-media{aspect-ratio:auto; height:300px;}
}
/* "Photo coming soon" placeholder — fills and centres itself inside a .pframe-media well. */
.faq-photo-inner{
  width:100%; height:100%;
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:14px;
  padding:28px; text-align:center; color:var(--steel);
  background:linear-gradient(150deg, var(--graphite-2), var(--black));
}
.faq-photo-inner svg{width:54px; height:54px; opacity:0.4;}
.faq-photo-label{
  font-family:'JetBrains Mono',monospace; font-size:12px;
  letter-spacing:0.03em; line-height:1.5; max-width:220px;
}
.faq-col h2{font-size:clamp(26px,3.6vw,36px); line-height:1.08; margin-bottom:20px;}
.faq-item{border-bottom:1px solid var(--line);}
.faq-item:first-child{border-top:1px solid var(--line);}
.faq-item summary{
  list-style:none; cursor:pointer; position:relative;
  padding:17px 36px 17px 0;
  font-family:'Oswald',sans-serif; font-size:16px; font-weight:500;
  text-transform:uppercase; letter-spacing:0.02em; color:var(--ivory);
  transition:color .2s ease;
}
.faq-item summary::-webkit-details-marker{display:none;}
.faq-item summary:hover{color:var(--accent-bright);}
/* Chevron, rotated to point up when the answer is open. */
.faq-item summary::after{
  content:""; position:absolute; right:8px; top:50%;
  width:9px; height:9px; flex-shrink:0;
  border-right:2px solid var(--accent); border-bottom:2px solid var(--accent);
  transform:translateY(-70%) rotate(45deg);
  transition:transform .2s ease, border-color .2s ease;
}
.faq-item[open] summary::after{transform:translateY(-25%) rotate(225deg);}
.faq-item summary:hover::after{border-color:var(--accent-bright);}
.faq-answer{padding:0 8px 20px 0; color:var(--steel); font-size:14.5px; line-height:1.7;}

/* ---------- ADD-ON CARDS ---------- */
.addon-grid{display:grid; grid-template-columns:repeat(3,1fr); gap:20px;}
@media (max-width:900px){ .addon-grid{grid-template-columns:repeat(2,1fr);} }
@media (max-width:600px){ .addon-grid{grid-template-columns:1fr;} }
.addon-card{background:var(--graphite-2); border:1px solid var(--line); padding:22px; transition:border-color .2s ease, transform .2s ease;}
.addon-card:hover{border-color:var(--accent); transform:translateY(-3px);}
.addon-card-top{display:flex; align-items:baseline; justify-content:space-between; gap:10px; margin-bottom:10px;}
.addon-card h3{font-size:15.5px;}
.addon-card .price{font-family:'JetBrains Mono',monospace; color:var(--accent-bright); font-size:14px; flex-shrink:0;}
.addon-card p{font-size:13px; color:var(--steel); line-height:1.55;}

/* ---------- NOTE / CALLOUT ---------- */
.note{
  background:rgba(70,130,180,0.1); border:1px solid rgba(70,130,180,0.4);
  padding:18px 22px; font-size:13.5px; color:var(--ivory); line-height:1.6; margin-top:24px;
}
.note strong{color:var(--accent-bright);}

/* ---------- CTA BANNER ---------- */
.cta-banner{
  background:linear-gradient(120deg, var(--accent), var(--accent-bright));
  color:var(--black); padding:60px 0;
}
.cta-banner .wrap{display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap; gap:24px;}
.cta-banner h2{font-size:clamp(24px,3.2vw,34px); color:var(--black); max-width:520px;}
.cta-banner .btn-ghost{border-color:var(--black); color:var(--black);}
.cta-banner .btn-ghost:hover{background:var(--black); color:var(--accent);}
.cta-actions{display:flex; gap:14px; flex-wrap:wrap;}

/* ---------- TRUST BADGES ---------- */
.trust-section{padding:60px 0 70px;}
/* The badge cards ride up over the blue CTA band so they straddle the edge.
   Scoped to the adjacent-sibling case on purpose: on /apply/ the badges follow
   a dark section instead, where riding up would just look cramped. */
.cta-banner + .trust-section{padding-top:0; margin-top:-46px; position:relative; z-index:2;}
.trust-grid{display:grid; grid-template-columns:repeat(4,1fr); gap:28px;}
@media (max-width:800px){ .trust-grid{grid-template-columns:repeat(2,1fr);} }
@media (max-width:460px){ .trust-grid{grid-template-columns:1fr;} }
.trust-box{
  display:flex; flex-direction:column; align-items:center; text-align:center; gap:16px;
  padding:30px 20px; background:var(--graphite-2); border:1px solid var(--line);
  transition:border-color .2s ease, transform .2s ease;
}
.trust-box:hover{border-color:var(--accent); transform:translateY(-3px);}
.trust-box svg{width:38px; height:38px; color:var(--accent-bright);}
.trust-box h3{font-size:15px; letter-spacing:0.02em; color:var(--ivory);}

/* ---------- FORM FIELDS (shared by quote.html + apply.html) ---------- */
.form-fields{display:grid; grid-template-columns:1fr 1fr; gap:12px;}
@media (max-width:520px){ .form-fields{grid-template-columns:1fr;} }
.form-field{display:flex; flex-direction:column; gap:6px;}
.form-field.full{grid-column:1 / -1;}
.form-field label{font-size:11.5px; color:var(--steel); text-transform:uppercase; letter-spacing:0.04em;}
.form-field .req{color:var(--cta-pink-bright);}
.form-field input, .form-field textarea, .form-field select{
  background:var(--graphite-2); border:1px solid var(--line); color:var(--ivory);
  padding:10px 12px; font-family:'Inter',sans-serif; font-size:13.5px; border-radius:var(--radius);
}
.form-field select{
  appearance:none; -webkit-appearance:none;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='%236FA3D0'%3E%3Cpath d='M5.5 7.5l4.5 5 4.5-5z'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:right 12px center; background-size:16px;
  padding-right:34px; cursor:pointer;
}
.form-field select:hover{border-color:var(--accent);}
.form-field textarea{resize:vertical; min-height:72px;}
.form-field input::placeholder, .form-field textarea::placeholder{color:#5A6270;}
.form-field input:invalid:not(:placeholder-shown){border-color:var(--cta-pink);}

/* ---------- SOCIAL LINKS (footer) ---------- */
/* Wraps because the icons are fixed-width and don't shrink — six of them are wider than
   the footer column on a phone, and without this they spill into the Contact column. */
.social-row{display:flex; flex-wrap:wrap; gap:12px; margin-top:16px;}
.social-row a{
  width:34px; height:34px; flex-shrink:0; border-radius:50%; border:1px solid var(--line);
  display:flex; align-items:center; justify-content:center; color:var(--steel);
  transition:border-color .2s ease, color .2s ease;
}
.social-row a:hover{border-color:var(--accent); color:var(--accent-bright);}
.social-row svg{width:16px; height:16px;}

/* ---------- FOOTER ---------- */
footer{padding:70px 0 40px; border-top:1px solid var(--line);}
.foot-grid{display:grid; grid-template-columns:2fr 1fr 1fr 1fr; gap:40px; margin-bottom:60px;}
@media (max-width:800px){
  /* minmax(0,1fr) lets the tracks shrink below their content's min-width. Without it
     the unbreakable email address pins its column at its own 139px, the two tracks
     eat the full row, and the 40px gap pushes the Contact column off-screen. */
  .foot-grid{grid-template-columns:repeat(2,minmax(0,1fr)); gap:32px 24px;}
  .foot-grid a, .foot-grid p{overflow-wrap:anywhere;}
}
.foot-grid h4{font-size:12px; text-transform:uppercase; letter-spacing:0.08em; color:var(--steel); margin-bottom:16px;}
.foot-grid a, .foot-grid p{font-size:14px; color:var(--ivory); display:block; margin-bottom:10px;}
.foot-grid a:hover{color:var(--accent);}
.foot-bottom{
  border-top:1px solid var(--line); padding-top:24px;
  display:flex; justify-content:space-between; flex-wrap:wrap; gap:12px;
  font-size:12.5px; color:var(--steel); font-family:'JetBrains Mono',monospace;
}
.foot-legal{display:flex; gap:20px;}
.foot-legal a{color:var(--steel);}
.foot-legal a:hover{color:var(--accent);}

/* ---------- REVEAL ON SCROLL ---------- */
.reveal{opacity:0; transform:translateY(18px); transition:opacity .6s ease, transform .6s ease;}
.reveal.in{opacity:1; transform:translateY(0);}
/* Staggered variant for grid children — set once via JS (--stagger-i) so cards in a
   row settle in sequence instead of all popping at once. Falls back to 0 (no delay)
   if JS hasn't run, so it degrades gracefully. */
.reveal-stagger{transition-delay:calc(var(--stagger-i, 0) * 70ms);}

/* ---------- BEFORE/AFTER GALLERY (homepage teaser + gallery.html) ---------- */
.gallery-grid{display:grid; grid-template-columns:repeat(2,1fr); gap:20px;}
@media (max-width:760px){ .gallery-grid{grid-template-columns:1fr;} }

.ba-panel{
  aspect-ratio:1/1; position:relative; overflow:hidden;
  background:linear-gradient(135deg, var(--graphite-2), var(--black));
  display:flex; align-items:center; justify-content:center;
  border:1px solid var(--line);
}
.ba-panel .tag{
  position:absolute; top:14px; left:14px;
  font-family:'JetBrains Mono',monospace; font-size:10px; letter-spacing:0.08em;
  text-transform:uppercase; color:var(--steel); border:1px solid var(--line);
  padding:4px 9px;
}
.ba-panel svg{opacity:0.25; width:56px; height:56px;}
.gallery-note{
  text-align:center; color:var(--steel); font-size:13.5px; margin-top:24px;
  font-family:'JetBrains Mono',monospace;
}
.gallery-cta{text-align:center; margin-top:56px;}

.ba-waterfall{display:flex; flex-direction:column; gap:76px;}
.ba-row{display:flex; align-items:center; gap:56px;}
.ba-row.ba-row-reverse{flex-direction:row-reverse;}
@media (max-width:760px){
  .ba-row, .ba-row.ba-row-reverse{flex-direction:column; align-items:stretch; gap:24px;}
}
.ba-row-media{flex:1 1 50%; min-width:0;}
.ba-row-copy{flex:1 1 50%; min-width:0;}
.ba-row-eyebrow{
  font-family:'Oswald',sans-serif; font-size:24px; font-weight:600; color:var(--accent);
  letter-spacing:0.02em; text-transform:uppercase; margin-bottom:14px;
  display:flex; align-items:center; gap:12px;
}
.ba-row-eyebrow::before{
  content:""; width:0.965em; height:0.73em; flex-shrink:0;
  background:url("images/icon-polisher.png") no-repeat center/contain;
}
.ba-row-desc{color:var(--steel); font-size:15px; line-height:1.7; max-width:440px;}

.ba-slider{display:flex; flex-direction:column; gap:12px;}
.ba-slider-title{
  font-family:'JetBrains Mono',monospace; font-size:12px; color:var(--steel);
  text-transform:uppercase; letter-spacing:0.06em;
}
.ba-slider-frame{
  position:relative; width:100%; aspect-ratio:700/927;
  overflow:hidden; border:1px solid var(--line); cursor:ew-resize;
  touch-action:pan-y; user-select:none;
  --pos:50%;
}
.ba-slider-frame img{
  position:absolute; inset:0; width:100%; height:100%; object-fit:cover;
  display:block; pointer-events:none; -webkit-user-drag:none;
}
.ba-after-wrap{
  position:absolute; inset:0;
  clip-path:inset(0 calc(100% - var(--pos)) 0 0);
}
.ba-slider-frame.is-hinting .ba-after-wrap{transition:clip-path .05s linear;}
.ba-slider-frame.is-dragging .ba-after-wrap{transition:none;}

.ba-divider{
  position:absolute; top:0; bottom:0; left:var(--pos);
  width:2px; margin-left:-1px; background:var(--ivory);
  box-shadow:0 0 6px rgba(0,0,0,0.5); pointer-events:none;
}
.ba-slider-frame.is-hinting .ba-divider{transition:left .05s linear;}
.ba-slider-frame.is-dragging .ba-divider{transition:none;}

.ba-handle{
  position:absolute; top:50%; left:var(--pos);
  width:38px; height:38px; margin:-19px 0 0 -19px;
  background:var(--ivory); border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  box-shadow:0 4px 14px rgba(0,0,0,0.45); pointer-events:none;
}
.ba-slider-frame.is-hinting .ba-handle{transition:left .05s linear;}
.ba-slider-frame.is-dragging .ba-handle{transition:none;}
.ba-handle svg{width:18px; height:18px; color:var(--black);}
.ba-slider-frame.is-hint-active .ba-handle{
  animation:ba-handle-pulse 1.6s ease-in-out;
}
@keyframes ba-handle-pulse{
  0%, 100%{box-shadow:0 4px 14px rgba(0,0,0,0.45);}
  50%{box-shadow:0 4px 14px rgba(0,0,0,0.45), 0 0 0 8px rgba(111,163,208,0.35);}
}

.ba-tag{
  position:absolute; top:14px;
  font-family:'JetBrains Mono',monospace; font-size:10px; letter-spacing:0.08em;
  text-transform:uppercase; color:var(--ivory);
  background:rgba(23,26,31,0.65); border:1px solid rgba(255,255,255,0.25);
  padding:4px 9px; pointer-events:none;
}
.ba-tag-before{left:14px;}
.ba-tag-after{right:14px;}

/* ---------- SERVICE HONEYCOMB (homepage + city pages) ---------- */
.svc-honeycomb{max-width:920px; margin:0 auto;}
.svc-hex-row{display:flex; justify-content:center; gap:24px;}
.svc-hex-row + .svc-hex-row{margin-top:-51px;}
.svc-hex-btn{
  display:block; position:relative;
  width:270px; cursor:pointer;
  transition:transform .35s cubic-bezier(.2,.8,.2,1);
}
.svc-hex-btn:hover{transform:scale(1.22); z-index:5;}
.svc-hex-shape{
  display:block; position:relative; width:270px; height:311.8px;
  clip-path:polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
  overflow:hidden; background:var(--graphite-2);
}
.svc-hex-border{
  position:absolute; inset:0; width:100%; height:100%; pointer-events:none; z-index:3;
}
.svc-hex-border polygon{
  fill:none; stroke:var(--accent); stroke-width:3; vector-effect:non-scaling-stroke;
  transition:stroke .25s ease;
}
.svc-hex-btn:hover .svc-hex-border polygon{stroke:var(--accent-bright);}
.svc-hex-media{position:absolute; inset:0;}
.svc-hex-media img{
  position:absolute; inset:0; width:100%; height:100%; object-fit:cover;
  filter:saturate(0.85) brightness(0.62);
  transition:filter .35s ease, transform .35s cubic-bezier(.2,.8,.2,1);
}
.svc-hex-btn:hover .svc-hex-media img{filter:saturate(1.1) brightness(1.05); transform:scale(1.18);}
.svc-hex-icon-fallback{
  position:absolute; inset:0;
  background:radial-gradient(circle at 40% 32%, rgba(70,130,180,0.4), var(--graphite) 75%);
  display:flex; align-items:center; justify-content:center;
  color:var(--accent-bright);
  transition:transform .35s cubic-bezier(.2,.8,.2,1);
}
.svc-hex-icon-fallback svg{width:50px; height:50px; opacity:0.85;}
.svc-hex-btn:hover .svc-hex-icon-fallback{transform:scale(1.12);}
.svc-hex-scrim{
  position:absolute; inset:0; z-index:1;
  background:radial-gradient(circle at 50% 50%, rgba(23,26,31,0.65), transparent 68%);
  transition:opacity .3s ease;
}
.svc-hex-label{
  position:absolute; inset:0; z-index:2;
  display:flex; align-items:center; justify-content:center; text-align:center;
  padding:0 28px;
  transition:opacity .3s ease, transform .3s ease;
}
.svc-hex-btn:hover .svc-hex-scrim{opacity:0.3;}
.svc-hex-btn:hover .svc-hex-label{opacity:0.5; transform:translateY(16px) scale(0.9);}
.svc-hex-label h3{
  font-size:18px; color:var(--ivory); letter-spacing:0.01em;
  text-shadow:0 2px 10px rgba(0,0,0,0.65);
}
@media (max-width:760px){
  /* Below desktop the honeycomb goes fluid: each tile is sized off the row width
     rather than a fixed px value, so three-across always fits the screen and the
     hexagons keep their true 1:1.1547 proportion. (The old fixed 190px tiles
     needed 602px of row on a 496px container, which clipped the outer two hexes
     against the page edges anywhere from 521px to 760px.) */
  .svc-honeycomb{
    max-width:640px;
    --hex-gap:16px;
    --hex-w:calc((100% - var(--hex-gap) * 2) / 3);
  }
  .svc-hex-row{gap:var(--hex-gap);}
  .svc-hex-row + .svc-hex-row{
    /* A hexagon nests into the row above at 3/4 of its height, so the pull-up is
       0.25h (h = 1.1547w → 0.2887w); the gap term keeps the diagonal spacing even.
       Same geometry as the desktop -51px, just expressed fluidly. */
    margin-top:calc(var(--hex-gap) * 1.13 - var(--hex-w) * 0.2887);
  }
  .svc-hex-btn{width:var(--hex-w);}
  .svc-hex-shape{width:100%; height:auto; aspect-ratio:1 / 1.1547;}
  .svc-hex-label h3{font-size:15px;}
  .svc-hex-icon-fallback svg{width:38px; height:38px;}
}
@media (max-width:520px){
  /* Phones keep the real honeycomb — same fluid 3-over-2 hexagons as above, just
     tuned tighter so three still read clearly across a 360px screen. */
  .svc-honeycomb{
    max-width:none;
    /* Run slightly wider than the 32px page gutter, otherwise three hexes across
       get squeezed too small to read on a narrow phone. */
    margin-inline:-18px;
    --hex-gap:6px;
  }
  .svc-hex-border polygon{stroke-width:2;}
  .svc-hex-label{padding:0 7px;}
  .svc-hex-label h3{font-size:11px; line-height:1.15;}
  .svc-hex-icon-fallback svg{width:26px; height:26px;}
  /* On mobile there's no hover, so the label needs to stay put and legible by default —
     the shrink/shift/fade above is a desktop-only flourish. */
  .svc-hex-btn:hover{transform:none;}
  .svc-hex-btn:hover .svc-hex-label{opacity:1; transform:none;}
  .svc-hex-btn:hover .svc-hex-scrim{opacity:1;}
  .svc-hex-btn:hover .svc-hex-media img{filter:saturate(0.85) brightness(0.62); transform:none;}
}

/* ---------- MAP EMBED (city pages) ---------- */
.map-embed{
  aspect-ratio:16/7; width:100%; max-height:420px;
  border:1px solid var(--line); overflow:hidden; background:var(--graphite-2);
}
.map-embed iframe{width:100%; height:100%; display:block; border:0;}

/* ---------- SERVICE AREA LIST (city pages + hub) ---------- */
.area-grid{display:grid; grid-template-columns:repeat(3,1fr); gap:20px;}
@media (max-width:760px){ .area-grid{grid-template-columns:repeat(2,1fr);} }
@media (max-width:480px){ .area-grid{grid-template-columns:1fr;} }
.area-card{
  background:var(--graphite-2); border:1px solid var(--line); padding:22px 20px;
  transition:border-color .2s ease, transform .2s ease;
}
.area-card:hover{border-color:var(--accent); transform:translateY(-3px);}
.area-card h3{font-size:16px; margin-bottom:6px;}
.area-card p{font-size:12.5px; color:var(--steel); line-height:1.5;}
.area-card .go{
  display:inline-block; margin-top:10px; font-family:'JetBrains Mono',monospace;
  font-size:11.5px; color:var(--accent-bright); letter-spacing:0.04em;
}

/* Photo variant — used once a city has a real labeled photo. Fixed aspect-ratio +
   object-fit:cover keeps every card the same shape regardless of the source image's
   original size, per the "buttons stay uniform" requirement. Cards without a photo
   keep the plain style above untouched. */
.area-card.has-photo{
  position:relative; aspect-ratio:16/10; padding:0; overflow:hidden;
  display:flex; align-items:flex-end;
  /* Soft corners only. These sit many-to-a-grid at matching sizes, where an angled cut reads
     as damage rather than design — the slanted treatment is reserved for the standalone
     page photos. */
  border-radius:12px;
}
.area-card-media{position:absolute; inset:0; z-index:0;}
.area-card-media img{
  width:100%; height:100%; object-fit:cover; display:block;
  filter:saturate(0.85) brightness(0.65);
  transition:filter .35s ease, transform .35s cubic-bezier(.2,.8,.2,1);
}
.area-card.has-photo::before{
  content:""; position:absolute; inset:0; z-index:1;
  background:linear-gradient(to top, rgba(23,26,31,0.92) 0%, rgba(23,26,31,0.4) 55%, rgba(23,26,31,0.05) 85%);
  transition:opacity .3s ease;
}
.area-card.has-photo:hover::before{opacity:0.6;}
.area-card.has-photo:hover .area-card-media img{filter:saturate(1.1) brightness(1.05); transform:scale(1.08);}
.area-card.has-photo .area-card-body{
  position:relative; z-index:2; padding:16px 18px;
  transform-origin:left bottom;
  transition:opacity .3s ease, transform .3s ease;
}
.area-card.has-photo:hover .area-card-body{opacity:0.6; transform:translateX(10px) scale(0.92);}
.area-card.has-photo h3{text-shadow:0 2px 10px rgba(0,0,0,0.5);}
.area-card.has-photo p{color:#D7DBE0;}

/* ---------- CERAMIC PACKAGE ROWS ----------
   The photo runs a little taller than the card beside it, top and bottom, so the
   pair reads as a card set against a photo rather than two blocks of equal
   weight. Done with a negative margin against a stretched row instead of a fixed
   aspect ratio, so the overhang stays the same whatever the card ends up
   measuring — card text can change without the photo needing a new number.
   The card is trimmed slightly at the same time, which is what makes room for
   the overhang without the row growing. */
/* The photos overhang their cards by 22px top and bottom, which eats into the
   waterfall's standard 76px gap and leaves the two packages looking joined.
   Widening it by twice the overhang restores 76px of clear space between the
   photos themselves. */
.pkg-waterfall{gap:120px;}
@media (max-width:760px){ .pkg-waterfall{gap:76px;} }
@media (min-width:761px){
  .pkg-waterfall .ba-row{align-items:stretch;}
  /* The frame comes out of flow, the same trick .faq-layout uses: otherwise the
     photo's own proportions set the row height and the card just follows it,
     which is backwards here. Out of flow, the card sets the height and the photo
     fills whatever that turns out to be, plus the overhang. */
  .pkg-waterfall .ba-row-media{position:relative; margin-block:-22px;}
  .pkg-waterfall .ba-row-media .pframe{position:absolute; inset:0;}
  .pkg-waterfall .ba-row-media .pframe-media{height:100%; aspect-ratio:auto;}
}
.pkg-waterfall .ticket-top{padding:22px 24px 18px;}
.pkg-waterfall .ticket-meta{padding:12px 24px;}
.pkg-waterfall .ticket-body{padding:18px 24px 22px;}
.pkg-waterfall .ticket-body li{padding:7px 0 7px 20px;}
.pkg-waterfall .ticket-price{padding-top:12px; margin-bottom:14px;}

/* ---------- BEFORE / AFTER PAIR (add-ons rows) ----------
   Two stills side by side rather than the drag-slider used elsewhere. The
   add-on shots weren't taken from a locked-off position — the "after" is often
   framed wider than the "before" — so a slider would jump between viewpoints
   instead of revealing the same spot. Presented as two labelled photos, that
   mismatch reads as normal.
   Every half is cropped to 2:3 on disk, so the two sit level without CSS having
   to force it. */
.ba-pair{display:grid; grid-template-columns:1fr 1fr; gap:10px;}
.ba-pair figure{
  position:relative; margin:0; overflow:hidden; aspect-ratio:2/3;
  background:var(--graphite-2);
  /* Same angled cut as .pframe-media, scaled down for the narrower well, so the
     pairs read as part of the site rather than as bare photos dropped in. */
  clip-path:polygon(0 16px, 100% 0, 100% calc(100% - 16px), 0 100%);
}
.ba-pair img{width:100%; height:100%; object-fit:cover; display:block;}
.ba-pair .ba-tag{top:10px;}
.ba-pair .ba-tag-before{left:10px;}
.ba-pair .ba-tag-after{right:10px;}

/* A single still in an alternating row. */
.ba-row-media > img, .ba-row-media > .ba-single img{width:100%; height:auto; display:block;}
.ba-row-media .pframe-media{aspect-ratio:4/3;}

/* Per-row eyebrow icon — defaults to the polisher the before/after rows use,
   but an add-on row can point at its own icon instead. */
.ba-row-eyebrow{--row-icon:url("images/icon-polisher.png");}

/* The add-on rows carry a price beside the name. */
.ba-row-price{
  font-family:'Oswald',sans-serif; font-size:26px; color:var(--accent); margin-bottom:12px;
}
.ba-row-price .amt-prefix{
  display:block; margin-bottom:3px;
  font-family:'JetBrains Mono',monospace; font-size:10.5px; color:var(--steel);
  text-transform:uppercase; letter-spacing:0.07em;
}

/* A product shot rather than a scene: cropping it to the row's landscape frame
   would cut the can off top and bottom, so it sits whole inside the frame
   instead. Row heights stay uniform because the frame is unchanged — only what
   happens inside it differs. The frame's background is near enough to the
   photo's own that the space either side reads as part of the shot. */
.pframe-media.is-contain img{object-fit:contain;}

/* ---------- BLOG INDEX ----------
   Three across on desktop, two on tablet, one on a phone. Cards are equal
   height so a short summary next to a long one doesn't leave a ragged row. */
.blog-grid{display:grid; grid-template-columns:repeat(3,1fr); gap:26px;}
@media (max-width:900px){ .blog-grid{grid-template-columns:repeat(2,1fr);} }
@media (max-width:620px){ .blog-grid{grid-template-columns:1fr;} }

.blog-card{
  background:var(--graphite-2); border:1px solid var(--line);
  display:flex; flex-direction:column;
  transition:transform .2s ease, border-color .2s ease;
}
.blog-card:hover{transform:translateY(-4px); border-color:var(--accent);}
.blog-card-media{
  aspect-ratio:16/10; display:flex; align-items:center; justify-content:center;
  background:var(--graphite); border-bottom:1px solid var(--line);
  color:var(--steel);
  clip-path:polygon(0 0, 100% 0, 100% calc(100% - 14px), 0 100%);
}
.blog-card-media svg{width:34px; height:34px; opacity:0.5;}
.blog-card-media img{width:100%; height:100%; object-fit:cover; display:block;}
.blog-card-body{padding:20px 22px 24px; display:flex; flex-direction:column; flex:1;}
.blog-card-meta{
  font-family:'JetBrains Mono',monospace; font-size:10.5px; color:var(--steel);
  text-transform:uppercase; letter-spacing:0.07em; margin-bottom:10px;
}
.blog-card h2{font-size:18px; line-height:1.25; margin-bottom:10px;}
.blog-card p{color:var(--steel); font-size:13.5px; line-height:1.65; flex:1;}
.blog-card-cta{
  display:inline-block; margin-top:16px;
  font-family:'JetBrains Mono',monospace; font-size:11px; letter-spacing:0.05em;
  text-transform:uppercase; color:var(--accent-bright);
}


/* ---------- INSTANT QUOTE CTA — PULSE RING + HOVER GLOW ----------
   Applies to every link that sends the user to the instant quote page.
   The static build links to quote.html; the WordPress build links to /quote/,
   so both are matched. Nothing here changes the button's colour, size or
   corner radius — the glow colour is inherited from the variant class, and
   the ring's radius is derived from --radius so it stays concentric.
   The global prefers-reduced-motion rule near the top of this file already
   neutralises the pulse for users who ask for less motion. */

a.btn[href$="quote.html"],
a.btn[href$="/quote/"], a.btn[href$="/quote"]{
  position:relative;
  --cta-glow:var(--accent-bright);
  --cta-pulse:rgba(111,163,208,0.5);
  animation:cta-pulse 2.4s ease-out infinite;
}
a.btn-pink[href$="quote.html"],
a.btn-pink[href$="/quote/"], a.btn-pink[href$="/quote"]{
  --cta-glow:var(--cta-pink-bright);
  --cta-pulse:rgba(242,113,134,0.5);
}
a.btn-ghost[href$="quote.html"],
a.btn-ghost[href$="/quote/"], a.btn-ghost[href$="/quote"]{
  --cta-glow:var(--accent);
  --cta-pulse:rgba(70,130,180,0.45);
}

/* The expanding ring. Drawn as an outer box-shadow so it never paints over
   the label and never has to fight a section background for z-index. */
@keyframes cta-pulse{
  0%   {box-shadow:0 0 0 0 var(--cta-pulse);}
  70%  {box-shadow:0 0 0 14px rgba(0,0,0,0);}
  100% {box-shadow:0 0 0 0 rgba(0,0,0,0);}
}

/* The outlined halo that appears on hover/focus. */
a.btn[href$="quote.html"]::before,
a.btn[href$="/quote/"]::before, a.btn[href$="/quote"]::before{
  content:'';
  position:absolute;
  inset:-7px;
  border:2px solid var(--cta-glow);
  border-radius:calc(var(--radius) + 7px);
  box-shadow:0 0 22px -2px var(--cta-glow);
  opacity:0;
  pointer-events:none;
  transition:opacity .3s ease-in-out;
}

/* On hover the pulse stops and the halo takes over, same as the original. */
a.btn[href$="quote.html"]:hover,
a.btn[href$="/quote/"]:hover, a.btn[href$="/quote"]:hover,
a.btn[href$="quote.html"]:focus-visible,
a.btn[href$="/quote/"]:focus-visible, a.btn[href$="/quote"]:focus-visible{
  animation:none;
  transform:translateY(-4px);
}
a.btn[href$="quote.html"]:hover::before,
a.btn[href$="/quote/"]:hover, a.btn[href$="/quote"]:hover::before,
a.btn[href$="quote.html"]:focus-visible::before,
a.btn[href$="/quote/"]:focus-visible, a.btn[href$="/quote"]:focus-visible::before{
  opacity:1;
}


/* ---------- BLOG POST BODY ----------
   Single posts render through index.php's is_singular('post') branch. */
.post-section{padding-top:24px;}
.post-body{max-width:760px;}
.post-body h2{font-size:22px; margin:38px 0 12px;}
.post-body h3{font-size:17px; margin:28px 0 10px;}
.post-body p{color:var(--steel); margin-bottom:14px; line-height:1.7;}
.post-body ul, .post-body ol{color:var(--steel); margin:0 0 16px 20px; line-height:1.7;}
.post-body li{margin-bottom:6px;}
.post-body strong{color:var(--ivory);}
.post-body a{color:var(--accent-bright); text-decoration:underline;}
.post-body img{margin:20px 0;}


/* ---------- BOOKING PAGE: SERVICE CHECKBOXES ----------
   Replaces the old single-select so people can pick more than one service. */
.field-hint{color:var(--steel); font-weight:400; text-transform:none; letter-spacing:0;}
.service-choices{display:grid; grid-template-columns:repeat(auto-fit,minmax(190px,1fr)); gap:10px 14px;}
.service-choice{
  display:flex; align-items:center; gap:10px;
  padding:11px 13px; border:1px solid var(--line); background:var(--graphite-2);
  font-size:14px; color:var(--ivory); cursor:pointer;
  transition:border-color .15s ease, background .15s ease;
}
.service-choice:hover{border-color:var(--accent);}
.service-choice input{accent-color:var(--cta-pink); width:16px; height:16px; flex-shrink:0; cursor:pointer;}
.service-choice:has(input:checked){border-color:var(--cta-pink); background:rgba(232,85,110,0.08);}


/* Pink outline button. Used for the quote CTA on the booking page so it reads
   as the same call to action as the pink button on the homepage. */
.btn-ghost-pink{border-color:var(--cta-pink); color:var(--cta-pink-bright);}
.btn-ghost-pink:hover{border-color:var(--cta-pink-bright); color:var(--cta-pink-bright);}
a.btn-ghost-pink[href$="quote.html"],
a.btn-ghost-pink[href$="/quote/"], a.btn-ghost-pink[href$="/quote"]{--cta-glow:var(--cta-pink-bright); --cta-pulse:rgba(242,113,134,0.5);}


/* Small leading icon inside a button, e.g. the phone glyph on Call Now. */
.btn-icon{width:15px; height:15px; flex-shrink:0; margin-right:8px;}


/* ---------- FLUENT FORMS ----------
   The plugin ships light-theme defaults that look wrong on this dark site.
   These mirror the hand-built .form-field styles above so an embedded form
   is indistinguishable from the static markup it replaces. Scoped to
   .frm-fluent-form so nothing leaks. */
.frm-fluent-form .ff-el-group{margin-bottom:14px;}
.frm-fluent-form .ff-el-input--label label{
  font-size:11.5px; color:var(--steel); text-transform:uppercase; letter-spacing:0.04em;
  font-weight:400; margin-bottom:6px;
}
.frm-fluent-form .ff-el-input--label.ff-el-is-required label:after{color:var(--cta-pink-bright);}
.frm-fluent-form .ff-el-form-control{
  background:var(--graphite-2); border:1px solid var(--line); color:var(--ivory);
  padding:10px 12px; font-family:'Inter',sans-serif; font-size:13.5px;
  border-radius:var(--radius); box-shadow:none; width:100%;
}
.frm-fluent-form .ff-el-form-control:focus{border-color:var(--accent); outline:none; box-shadow:none;}
.frm-fluent-form .ff-el-form-control::placeholder{color:#5A6270;}
.frm-fluent-form textarea.ff-el-form-control{resize:vertical; min-height:72px;}
.frm-fluent-form select.ff-el-form-control{
  appearance:none; -webkit-appearance:none;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='%236FA3D0'%3E%3Cpath d='M5.5 7.5l4.5 5 4.5-5z'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:right 12px center; background-size:16px;
  padding-right:34px; cursor:pointer;
}
.frm-fluent-form select.ff-el-form-control:hover{border-color:var(--accent);}
.frm-fluent-form .ff-el-input--content{margin:0;}

/* Checkboxes, matched to the booking page's service picker. */
.frm-fluent-form .ff-el-group.ff_list_inline .ff-el-form-check{display:block;}
.frm-fluent-form .ff-el-form-check{
  display:flex; align-items:center; gap:10px; margin-bottom:8px;
  padding:11px 13px; border:1px solid var(--line); background:var(--graphite-2);
  transition:border-color .15s ease, background .15s ease;
}
.frm-fluent-form .ff-el-form-check:hover{border-color:var(--accent);}
.frm-fluent-form .ff-el-form-check:has(input:checked){border-color:var(--cta-pink); background:rgba(232,85,110,0.08);}
.frm-fluent-form .ff-el-form-check input{accent-color:var(--cta-pink); width:16px; height:16px; margin:0; flex-shrink:0;}
.frm-fluent-form .ff-el-form-check label{font-size:14px; color:var(--ivory); margin:0; cursor:pointer;}

/* Submit button, matched to .btn.btn-pink. */
.frm-fluent-form .ff-btn-submit{
  display:inline-flex; align-items:center; justify-content:center;
  padding:13px 26px; font-size:13px; font-weight:600; text-transform:uppercase;
  letter-spacing:0.06em; border-radius:var(--radius); border:1px solid transparent;
  background:var(--cta-pink); color:#fff; cursor:pointer; width:100%;
  transition:transform .15s ease, box-shadow .15s ease, background .15s ease;
}
.frm-fluent-form .ff-btn-submit:hover{
  background:var(--cta-pink-bright); transform:translateY(-1px);
  box-shadow:0 6px 20px -6px rgba(232,85,110,0.6);
}

/* Validation + success, in the site's colours rather than the plugin's. */
.frm-fluent-form .error-text, .frm-fluent-form .ff-el-is-error .text-danger{color:var(--cta-pink-bright); font-size:12px;}
.frm-fluent-form .ff-el-form-control.ff-el-is-error{border-color:var(--cta-pink);}
.ff-message-success{
  border:1px solid var(--line); border-left:3px solid var(--accent);
  background:var(--graphite-2); color:var(--ivory);
  padding:18px 20px; font-size:14px; line-height:1.6;
}


/* ff-override: Fluent Forms injects per-form appearance CSS at a higher
   specificity than a plain class selector, so the properties it sets have to
   be forced. Only the ones it actually overrides are marked. */
.frm-fluent-form .ff-el-form-control{
  border-color:var(--line) !important;
  color:var(--ivory) !important;
  background-color:var(--graphite-2) !important;
}
.frm-fluent-form .ff-el-form-control:focus{border-color:var(--accent) !important;}
.frm-fluent-form .ff-el-form-control.ff-el-is-error{border-color:var(--cta-pink) !important;}
.frm-fluent-form .ff-btn-submit{
  background-color:var(--cta-pink) !important;
  color:#fff !important;
  border-color:transparent !important;
}
.frm-fluent-form .ff-btn-submit:hover{background-color:var(--cta-pink-bright) !important;}
.frm-fluent-form .ff-el-input--label label{color:var(--steel) !important;}
