/* The marketing site's stylesheet.
   Lifted out of public/homeface.html so the blog pages can use it too. It was
   inline, which meant a Next page could not reach it — and the alternative was
   restating the palette, the nav and the footer in a second file, where they
   would drift. One sheet, two consumers: homeface.html links it, and so does
   every page under /blog.

   Edit it here. Nothing generates this file. */
  /* The same muted sage the app runs on (lib/theme.ts). Green is spent on
     accents and on the deep panels; cards stay white, hairlines and shadows
     stay near-neutral, and the page wash is a green-grey rather than a mint —
     a green over every surface stops reading as a colour and starts reading
     as a filter. --on-dark* are the tones used inside the dark panels. */
  :root{
    --bg:#F1F6F3;
    --bg-soft:#E7F0EB;
    --card:#FFFFFF;
    --ink:#2B4A40;
    --ink-strong:#0D3021;
    --muted:#4F7062;
    --faint:#8AACA0;
    --accent:#406250;
    --accent-dark:#2F5443;
    --accent-soft:#DCEBE4;
    --indigo:#0D3021;
    --line:#DBE7E1;
    --on-dark:#DCEBE4;
    --on-dark-soft:#8AACA0;
    --on-dark-bright:#BEDBD3;
    --grad-btn:linear-gradient(135deg,#4B7260,#2F5443);
    --grad-ink:linear-gradient(150deg,#1B3E31,#0D3021 70%);
    --shadow-card:0 4px 10px rgba(13,48,33,.06),0 18px 46px rgba(13,48,33,.14);
    --shadow-card-hover:0 8px 18px rgba(13,48,33,.1),0 30px 70px rgba(13,48,33,.24);
    --shadow-btn:0 10px 26px rgba(13,48,33,.4);
  }
  *,*:before,*:after{box-sizing:border-box;margin:0;padding:0}
  html{scroll-behavior:smooth;scrollbar-width:none;-ms-overflow-style:none}
  html::-webkit-scrollbar,body::-webkit-scrollbar{width:0;height:0;display:none}
  body{font-family:"Hanken Grotesk",system-ui,sans-serif;background:var(--bg);color:var(--ink);line-height:1.6;overflow-x:hidden}
  img{display:block;max-width:100%}
  a{color:inherit;text-decoration:none}
  .serif{font-family:"Fraunces",Georgia,serif;font-weight:600;letter-spacing:-.01em;font-optical-sizing:auto}
  .serif em{font-style:italic;font-weight:500;color:var(--accent-dark)}
  .wrap{margin:0 auto;padding:0 3%}
  .eyebrow{display:inline-flex;align-items:center;gap:10px;font-size:12.5px;font-weight:700;letter-spacing:.16em;
    text-transform:uppercase;color:var(--accent)}
  .eyebrow:before{content:"";width:26px;height:2px;border-radius:2px;background:linear-gradient(90deg,#4B7260,#2F5443)}
  .sec{position:relative;padding:48px 0}
  .sec h2{font-size:clamp(28px,3.4vw,40px);color:var(--ink-strong);margin-top:12px;line-height:1.15}
  .sec .sub{margin-top:14px;font-size:15.5px;color:var(--muted);max-width:580px}

  /* ===== motion ===== */
  .rv{opacity:0;transform:translateY(26px);transition:opacity .8s cubic-bezier(.2,.6,.2,1),transform .8s cubic-bezier(.2,.6,.2,1);transition-delay:var(--d,0s)}
  .rv.in{opacity:1;transform:none}
  @keyframes fadeUp{from{opacity:0;transform:translateY(24px)}to{opacity:1;transform:none}}
  @keyframes kenburns{from{transform:scale(1)}to{transform:scale(1.09)}}
  @keyframes pulse{0%{transform:scale(.9);opacity:.7}70%{transform:scale(1.25);opacity:0}100%{opacity:0}}
  @keyframes spinbg{to{transform:rotate(1turn)}}
  @keyframes floaty{0%,100%{transform:translateY(0)}50%{transform:translateY(-10px)}}
  @media (prefers-reduced-motion: reduce){
    *,*:before,*:after{animation:none!important;transition:none!important}
    .rv{opacity:1;transform:none}
  }

  /* ===== buttons ===== */
  .btn{position:relative;overflow:hidden;display:inline-flex;align-items:center;gap:8px;border-radius:999px;
    background:var(--grad-btn);color:#fff;font-weight:600;font-size:15px;padding:13px 30px;
    box-shadow:var(--shadow-btn);transition:transform .18s ease,filter .18s ease}
  .btn:hover{filter:brightness(1.06);transform:translateY(-2px)}
  .btn .ar{transition:transform .18s ease}
  .btn:hover .ar{transform:translateX(4px)}
  .btn-outline{display:inline-flex;align-items:center;gap:8px;border-radius:999px;border:1.5px solid var(--accent);
    color:var(--accent);font-weight:600;font-size:14.5px;padding:11px 26px;background:var(--card);
    transition:background .18s ease,color .18s ease,transform .18s ease}
  .btn-outline:hover{background:var(--accent);color:#fff;transform:translateY(-2px)}
  .btn-ghost{display:inline-flex;align-items:center;border-radius:999px;border:1.5px solid rgba(255,255,255,.35);
    color:#fff;font-weight:600;font-size:15px;padding:12px 28px;transition:background .18s ease}
  .btn-ghost:hover{background:rgba(255,255,255,.12)}

  /* ===== nav (transparent over hero → frosted on scroll) ===== */
  /* ---- the promotion bar, inside the nav ------------------------------
     Height lives in a variable because the hero pads for it and the dismiss
     button zeroes it. The ink gradient rather than the page tint: at the top of
     a video hero a translucent bar reads as part of the footage. */
  :root{--promo-h:50px}
  .promo{position:relative;height:var(--promo-h);display:flex;align-items:center;
    justify-content:center;gap:20px;background:var(--grad-ink);color:#fff;
    font-size:13px;overflow:hidden;transition:height .25s ease}
  /* A hairline of the mint accent along the top, brightest in the middle. One
     pixel, and it is most of the difference between a painted slab and
     something that looks made. */
  .promo:before{content:"";position:absolute;top:0;left:0;right:0;height:1px;
    background:linear-gradient(90deg,transparent,rgba(190,219,211,.5),transparent)}
  .promo:after{content:"";position:absolute;bottom:0;left:0;right:0;height:1px;
    background:rgba(0,0,0,.25)}
  .promo a{color:inherit;text-decoration:none;line-height:1.25;letter-spacing:.005em}
  .promo b{font-weight:700;color:#fff}
  /* The code reads as a coupon: dashed edge, wide letter-spacing, mint rather
     than white so the eye lands on it before the sentence around it. */
  .promo .code{display:inline-block;margin:0 2px;padding:3px 9px;border-radius:7px;
    border:1px dashed rgba(190,219,211,.55);background:rgba(190,219,211,.12);
    color:var(--on-dark-bright);font-weight:700;letter-spacing:.12em;
    font-size:12px;transition:background .2s ease,border-color .2s ease}
  .promo a:hover .code{background:rgba(190,219,211,.22);
    border-color:rgba(190,219,211,.85)}
  .promo-rule{width:1px;height:22px;flex-shrink:0;
    background:linear-gradient(180deg,transparent,rgba(255,255,255,.22),transparent)}
  /* The countdown, as four units rather than one run of text. Each keeps its own
     width so nothing shuffles sideways as the seconds turn over, and the labels
     are what stop "05 14 09" needing to be worked out. */
  .promo-timer{display:flex;align-items:center;gap:5px;flex-shrink:0}
  .promo-timer .unit{display:flex;flex-direction:column;align-items:center;
    min-width:33px;padding:3px 5px 2px;border-radius:8px;
    background:rgba(255,255,255,.09);border:1px solid rgba(255,255,255,.13)}
  .promo-timer b{font-size:13px;font-weight:700;line-height:1;color:#fff;
    font-variant-numeric:tabular-nums;font-feature-settings:"tnum" 1}
  .promo-timer i{font-style:normal;font-size:7.5px;line-height:1;margin-top:3px;
    letter-spacing:.14em;text-transform:uppercase;color:rgba(255,255,255,.55)}
  .promo button{position:absolute;right:12px;top:50%;transform:translateY(-50%);
    width:26px;height:26px;border:0;border-radius:8px;background:none;
    color:rgba(255,255,255,.55);font-size:18px;line-height:1;cursor:pointer;
    transition:background .2s ease,color .2s ease}
  .promo button:hover{background:rgba(255,255,255,.12);color:#fff}
  /* On a phone the sentence already wraps to two lines. A ticking clock beside
     it would make three and push the nav down the screen, so the date in the
     words carries the deadline there instead. */
  @media(max-width:560px){
    :root{--promo-h:56px}
    .promo{font-size:12px}
    .promo a{padding:0 38px 0 12px;text-align:left}
    .promo-timer{display:none}
  }

  nav{position:fixed;top:0;left:0;right:0;z-index:40;background:transparent;
    border-bottom:1px solid transparent;
    transition:background .6s ease,border-color .6s ease,box-shadow .6s ease}
  /* Frosted, not painted: the fill stays translucent and saturated so the
     page tint and whatever scrolls under it still read through. At .92 white
     the blur did nothing and the bar landed as a flat slab. */
  nav.scrolled{background:rgba(244,249,246,.72);
    -webkit-backdrop-filter:blur(20px) saturate(1.6);
    backdrop-filter:blur(20px) saturate(1.6);
    border-color:rgba(13,48,33,.09);box-shadow:0 6px 24px rgba(13,48,33,.07)}
  .nav-in{margin:0 auto;padding:14px 3%;display:flex;align-items:center;justify-content:space-between;gap:16px;
    transition:padding .35s ease}
  /* the bar tightens as you scroll, so it feels attached to the scrolling */
  nav.scrolled .nav-in{padding:9px 3%}
  .brand{display:flex;align-items:center;gap:10px}
  .brand img{height:38px;width:auto;filter:drop-shadow(0 2px 8px rgba(8,32,22,.35));
    transition:filter .35s ease,height .35s ease}
  nav.scrolled .brand img{filter:none;height:33px}
  .brand-name{font-family:"Jost",sans-serif;font-size:21px;font-weight:600;letter-spacing:.02em;
    color:#fff;transition:color .35s ease}
  .brand-name b{color:var(--on-dark-bright);font-weight:600;transition:color .35s ease}
  .brand-tag{font-size:10.5px;color:rgba(255,255,255,.65);letter-spacing:.02em;margin-top:-3px;
    display:block;transition:color .35s ease}
  nav.scrolled .brand-name{color:var(--ink-strong)}
  nav.scrolled .brand-name b{color:var(--accent)}
  /* the strapline is scene-setting for the hero; once the bar is a working
     toolbar it is just noise, so it folds away */
  nav.scrolled .brand-tag{opacity:0;max-height:0;overflow:hidden}
  .brand-tag{transition:color .35s ease,opacity .3s ease,max-height .3s ease;max-height:16px}
  .nav-links{display:flex;align-items:center;gap:8px;font-size:14.5px;font-weight:500;
    color:rgba(255,255,255,.85)}
  .nav-links a{position:relative;padding:7px 13px;border-radius:999px;
    transition:color .2s ease,background .2s ease}
  .nav-links a:after{content:"";position:absolute;left:13px;right:13px;bottom:3px;height:2px;border-radius:2px;
    background:currentColor;transform:scaleX(0);transform-origin:left;opacity:.55;
    transition:transform .24s cubic-bezier(.2,.6,.2,1)}
  .nav-links a:hover{color:#fff}
  .nav-links a:hover:after{transform:scaleX(1)}
  /* on the frosted bar the links carry the page's ink, not the muted tone —
     a toolbar people are meant to use should look usable */
  nav.scrolled .nav-links{color:var(--ink)}
  nav.scrolled .nav-links a:hover{color:var(--accent-dark);background:rgba(64,98,80,.07)}
  nav.scrolled .nav-links a:after{opacity:1}
  /* the section you are actually in */
  nav.scrolled .nav-links a.on{color:var(--accent-dark);font-weight:600}
  nav.scrolled .nav-links a.on:after{transform:scaleX(1)}
  .nav-cta{display:flex;align-items:center;gap:18px}
  .nav-tel{display:flex;align-items:center;gap:7px;font-size:14.5px;font-weight:600;
    color:rgba(255,255,255,.9);transition:color .35s ease;white-space:nowrap}
  .nav-tel:hover{color:#fff}
  .nav-tel svg{opacity:.75}
  nav.scrolled .nav-tel{color:var(--ink-strong)}
  nav.scrolled .nav-tel:hover{color:var(--accent-dark)}
  .nav-cta .signin{font-size:14.5px;font-weight:500;color:rgba(255,255,255,.85);transition:color .35s ease}
  .nav-cta .signin:hover{color:#fff}
  nav.scrolled .nav-cta .signin{color:var(--ink);font-weight:600}
  nav.scrolled .nav-cta .signin:hover{color:var(--accent-dark)}
  .nav-book{background:#fff!important;color:#0D3021!important;font-weight:700;
    box-shadow:0 12px 30px rgba(8,32,22,.35);transition:background .35s ease,color .35s ease,
    box-shadow .35s ease,transform .18s ease,filter .18s ease}
  nav.scrolled .nav-book{background:var(--grad-btn)!important;color:#fff!important;
    box-shadow:var(--shadow-btn)}
  @media(max-width:980px){.nav-links{display:none}}
  /* Seven nav links and a written-out international number do not fit one line
     below this, and the nav silently grows to three rows. The tap target stays —
     the digits are in the hero, the CTA band and the footer, so all that is lost
     here is reading them. */
  @media(max-width:1400px){
    .nav-tel .d{display:none}
    .nav-tel{padding:8px;border-radius:10px;background:rgba(255,255,255,.14)}
    nav.scrolled .nav-tel{background:var(--bg-soft)}
  }

  /* ===== contact dialog =====
     A dialog rather than a page: somebody reading the pricing who wants to ask
     about it should not lose the pricing to do it. The form posts to
     /api/contact on this origin, which hands it to the API — so this static file
     never needs to know where the API lives. */
  .cx-veil{position:fixed;inset:0;z-index:200;display:none;padding:20px;
    background:rgba(8,32,22,.55);backdrop-filter:blur(4px);overflow-y:auto}
  .cx-veil.open{display:grid;place-items:start center;align-content:center}
  .cx{width:100%;max-width:520px;background:var(--card);border-radius:22px;
    box-shadow:0 40px 90px rgba(8,32,22,.4);position:relative;
    animation:cxIn .28s cubic-bezier(.16,1,.3,1) both;
    /* the form is taller than a laptop viewport with the keyboard up, so the
       body scrolls inside the card and the header stays put */
    max-height:calc(100vh - 40px);display:flex;flex-direction:column}
  @keyframes cxIn{from{opacity:0;transform:translateY(14px) scale(.98)}
                  to{opacity:1;transform:none}}
  .cx-hd{padding:22px 24px 16px;border-bottom:1px solid var(--line);flex-shrink:0}
  .cx-hd h3{font-family:"Fraunces",serif;font-size:21px;font-weight:600;color:var(--ink-strong)}
  .cx-hd p{margin-top:5px;font-size:13px;color:var(--muted);line-height:1.6}
  .cx-hd p a{color:var(--accent);font-weight:700}
  .cx-x{position:absolute;top:14px;right:14px;width:34px;height:34px;border:0;border-radius:50%;
    background:var(--bg-soft);color:var(--muted);font-size:17px;line-height:1;cursor:pointer;
    display:grid;place-items:center;transition:all .15s ease}
  .cx-x:hover{background:var(--accent);color:#fff}
  .cx-bd{padding:18px 24px 22px;overflow-y:auto;display:grid;gap:13px}
  .cx-lbl{display:block;font-size:12px;font-weight:700;letter-spacing:.04em;color:var(--ink);margin-bottom:5px}
  .cx-lbl em{font-style:normal;font-weight:500;color:var(--faint)}
  .cx-in{width:100%;border:1.5px solid #CBDDD5;border-radius:11px;padding:10px 12px;
    font-family:inherit;font-size:14px;color:var(--ink-strong);background:var(--bg);
    transition:border-color .15s ease,background .15s ease}
  .cx-in:focus{outline:0;border-color:var(--accent);background:#fff}
  .cx-in::placeholder{color:var(--faint)}
  textarea.cx-in{resize:vertical;min-height:84px;line-height:1.6}
  .cx-two{display:grid;grid-template-columns:1fr 1fr;gap:11px}
  .cx-chips{display:flex;flex-wrap:wrap;gap:6px}
  .cx-chips button{border:1.5px solid #CBDDD5;background:var(--bg);border-radius:999px;
    padding:7px 13px;font-family:inherit;font-size:12px;font-weight:600;color:var(--muted);
    cursor:pointer;transition:all .15s ease}
  .cx-chips button:hover{border-color:var(--accent);color:var(--accent)}
  .cx-chips button.on{background:var(--grad-btn);color:#fff;border-color:transparent}
  .cx-send{width:100%;border:0;border-radius:999px;padding:13px;font-family:inherit;font-size:15px;
    font-weight:700;color:#fff;background:var(--grad-btn);cursor:pointer;box-shadow:var(--shadow-btn);
    transition:transform .15s ease,opacity .15s ease}
  .cx-send:hover:not(:disabled){transform:translateY(-1px)}
  .cx-send:disabled{opacity:.65;cursor:default}
  .cx-fine{font-size:11px;color:var(--faint);text-align:center;line-height:1.6}
  /* "Ring me instead". A checkbox rather than another topic, because it changes
     what the studio does with the message, not what it is about. */
  .cx-call{display:flex;align-items:flex-start;gap:10px;border:1.5px solid #CBDDD5;
    border-radius:12px;padding:11px 13px;cursor:pointer;background:var(--bg);
    transition:border-color .15s ease,background .15s ease}
  .cx-call:hover{border-color:var(--accent)}
  .cx-call.on{border-color:var(--accent);background:var(--accent-soft)}
  .cx-call input{width:17px;height:17px;margin-top:1px;accent-color:var(--accent);flex-shrink:0}
  .cx-call b{display:block;font-size:13px;font-weight:700;color:var(--ink-strong)}
  .cx-call span{display:block;margin-top:2px;font-size:11.5px;color:var(--muted);line-height:1.5}
  /* when they have asked for a call, the number stops being optional */
  .cx-phone.need .cx-lbl em{color:var(--accent);font-weight:700}
  .cx-phone.need .cx-in{border-color:var(--accent)}
  .cx-err{font-size:12.5px;font-weight:600;color:#B4402F;background:#FDECE8;border-radius:10px;padding:9px 12px}
  /* the honeypot: off-screen rather than display:none, because some form-fillers
     skip hidden inputs and none of them read a label */
  .cx-trap{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
  .cx-done{padding:34px 26px 30px;text-align:center}
  .cx-done .tick{width:50px;height:50px;margin:0 auto 14px;border-radius:50%;display:grid;place-items:center;
    color:#fff;background:var(--grad-btn)}
  .cx-done h3{font-family:"Fraunces",serif;font-size:22px;font-weight:600;color:var(--ink-strong)}
  .cx-done p{margin-top:9px;font-size:13.5px;color:var(--muted);line-height:1.65}
  .cx-done .call{display:inline-block;margin-top:18px;font-size:15px;font-weight:700;color:var(--accent)}
  @media(max-width:560px){
    .cx-veil{padding:0}
    .cx{max-width:none;border-radius:20px 20px 0 0;max-height:100vh;margin-top:auto}
    .cx-veil.open{place-items:end center}
    .cx-two{grid-template-columns:1fr}
  }

  .deco{position:absolute;pointer-events:none;opacity:.55}

  /* ===== hero (full-bleed) ===== */
  /* `align-items:center` was centring the hero copy, and a centred flex item that
     is taller than its container overflows *both* ends equally — so on a short
     window the badge and the headline went up behind the fixed nav and were
     clipped by the overflow:hidden above, leaving the paragraph sitting on top of
     the logo. Auto margins centre the same way when there is room and collapse to
     nothing when there is not, so the copy can only ever grow downward. */
  .hero{position:relative;overflow:hidden;min-height:100vh;
    display:flex;align-items:flex-start;padding:calc(130px + var(--promo-h)) 0 64px}
  .hero-bg{position:absolute;inset:0;background-size:cover;background-position:center;
    background-image:url('/homeface/media/aerial-suburb-poster.webp');
    animation:kenburns 22s ease-in-out infinite alternate}
  /* The hero is drone footage of an English suburb — the work, not a mood shot.
     The poster frame is also the .hero-bg behind it, so a phone on a bad
     connection, a reduced-motion setting or a browser that refuses autoplay all
     land on the same picture rather than on a black box. Loaded lazily and only
     on wide screens: nobody should pay 3 MB to read a headline on 4G. */
  .hero-vid{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
    animation:fadeIn 1.2s .2s both}
  @keyframes fadeIn{from{opacity:0}to{opacity:1}}
  @media(max-width:900px),(prefers-reduced-motion:reduce){.hero-vid{display:none}}
  /* A second aerial, alternating with the clip. It is a photograph, so it pans
     rather than plays: a slow push toward the house reads as footage at a
     fraction of the weight, and it is the only motion a phone gets — the clip is
     never attached there, so this is what stops the hero being a still.
     transform-origin sits on the house, not the centre, or the zoom drifts into
     the river. Sits above the video and below .hero-ovl by DOM order, never by
     z-index: lifting a layer over the scrim is what bleached the headline last
     time. */
  .hero-still{position:absolute;inset:0;background-size:cover;
    background-position:50% 30%;background-repeat:no-repeat;
    transform-origin:50% 30%;will-change:transform,opacity;
    transition:opacity 1.8s ease;
    /* 11s to match the 11s the layer is on screen (SHOWING in the script
       below), so each appearance is exactly one complete push rather than a
       third of a slower one — which is what made it read as a still. */
    animation:heroPush 11s ease-in-out infinite alternate}
  .hero-still.hide{opacity:0}
  @keyframes heroPush{from{transform:scale(1.02)}to{transform:scale(1.20)}}
  /* the small file is 236 kB against 650 kB, and a media query means a phone
     never fetches the one it cannot use */
  .hero-still{background-image:url('/homeface/media/aerial-river-villa-sm.webp')}
  @media(min-width:901px){
    .hero-still{background-image:url('/homeface/media/aerial-river-villa.webp')}
  }
  /* Below this there is no clip, so the aerial never fades away and the poster
     behind it is never seen — 328 kB fetched to be covered. Dropping it costs a
     phone nothing: if the aerial fails, the scrim over the dark hero is still a
     readable background. */
  @media(max-width:900px){.hero-bg{background-image:none}}
  .hero-ovl{position:absolute;inset:0;
    background:linear-gradient(92deg,rgba(8,32,22,.92) 0%,rgba(8,32,22,.78) 38%,rgba(8,32,22,.46) 70%,rgba(8,32,22,.62) 100%)}
  .hero-fade{position:absolute;inset:auto 0 0 0;height:180px;
    background:linear-gradient(180deg,transparent,rgba(8,32,22,.6))}
  .hero-in{position:relative;z-index:2;width:100%;margin-top:auto;margin-bottom:auto}
  .hero-badge{display:inline-flex;align-items:center;gap:8px;border:1px solid rgba(255,255,255,.3);
    background:rgba(255,255,255,.14);backdrop-filter:blur(8px);border-radius:999px;padding:7px 16px 7px 10px;
    font-size:13px;font-weight:600;color:#fff;animation:fadeUp .7s .05s both}
  .hero-badge .dot{width:7px;height:7px;border-radius:99px;background:var(--on-dark-soft);box-shadow:0 0 0 4px rgba(138,172,160,.25)}
  .hero h1{font-size:clamp(42px,5vw,68px);line-height:1.06;color:#fff;font-weight:600;margin-top:24px;
    animation:fadeUp .7s .15s both;text-shadow:0 2px 30px rgba(8,32,22,.4)}
  .hero h1 em{color:var(--on-dark-bright)}
  .hero p.lead{margin-top:24px;max-width:500px;font-size:17px;font-weight:300;color:rgba(255,255,255,.85);
    line-height:1.75;animation:fadeUp .7s .25s both}
  .hero p.lead b{color:#fff;font-weight:600}
  .hero p.lead .gold{color:var(--on-dark-bright);font-weight:600}
  /* The end-to-end promise, drawn as the journey itself: shoot → edit → live on
     the portals. A sentence claiming "end to end" is a claim; three connected
     steps are a demonstration, and it costs one line of hero. The portals are
     named underneath because that is the part agents do not expect a photography
     company to do. */
  /* Three equal columns with the arrows sized to their glyph. Equal, not elastic:
     when the last step was the only column that could grow it also carried a fill
     and the portal names, so it dwarfed the other two and the strip read as one
     lit panel with two small captions beside it. The portals now sit on their own
     full-width line under the three steps — same claim, still next to step 3,
     without making step 3 a different kind of object. */
  .hero-flow{margin-top:26px;display:grid;
    grid-template-columns:repeat(5,auto);justify-content:center;column-gap:6px;
    align-items:center;
    border:1px solid rgba(255,255,255,.18);background:rgba(255,255,255,.07);
    backdrop-filter:blur(10px);border-radius:16px;padding:4px;max-width:700px;
    animation:fadeUp .7s .3s both}
  /* The columns are sized to their labels, not to equal thirds. Equal thirds
     centre each label in its own column, which centres nothing you can see:
     "We shoot" is a third the width of "Delivered, ready to publish", so the ink
     piles up on the right and the whole rail reads as hung off-centre. Sized to
     content and centred as one group, it is symmetrical to the eye. */
  .hero-flow .step{display:flex;align-items:center;justify-content:center;gap:9px;
    padding:12px 8px;font-size:13px;font-weight:600;color:rgba(255,255,255,.86);
    border-radius:12px;white-space:nowrap}
  .hero-flow .step i{display:grid;place-items:center;width:19px;height:19px;flex-shrink:0;
    border-radius:50%;border:1px solid rgba(255,255,255,.35);font-style:normal;
    font-size:10.5px;font-weight:700;color:rgba(255,255,255,.75)}
  .hero-flow .arw{display:grid;place-items:center;color:rgba(255,255,255,.35);font-size:12px}
  /* the payoff, on its own rule-separated line rather than inside step 3 */
  .hero-flow .portals{grid-column:1/-1;margin:0 8px;padding:9px 4px 7px;
    border-top:1px solid rgba(255,255,255,.15);text-align:center;font-size:11px;
    font-weight:500;letter-spacing:.05em;color:var(--on-dark-bright)}
  .hero-ctas{margin-top:30px;display:flex;align-items:center;gap:16px;flex-wrap:wrap;animation:fadeUp .7s .4s both}
  .hero-note{margin-top:20px;font-size:13px;color:rgba(255,255,255,.55);animation:fadeUp .7s .48s both}
  .hero-trust{margin-top:52px;display:flex;flex-wrap:wrap;border-top:1px solid rgba(255,255,255,.22);
    padding-top:22px;max-width:780px;animation:fadeUp .7s .55s both}
  .hero-trust div{padding:0 28px;font-size:13px;color:rgba(255,255,255,.72)}
  .hero-trust div:first-child{padding-left:0}
  .hero-trust div + div{border-left:1px solid rgba(255,255,255,.22)}
  .hero-trust b{display:block;font-family:"Fraunces",serif;font-size:19px;font-weight:600;color:#fff}
  @media(max-width:900px){
    /* Clear of the nav, which is 72px here and fixed. The old 44px put the
       badge under the brand, and the two collided on every phone whenever the
       promotion bar was down -- with the bar up, --promo-h happened to make up
       the difference, which is why it only showed sometimes. */
    .hero{min-height:calc(100vh - 60px);padding:calc(92px + var(--promo-h)) 0 44px}
    .hero-trust{display:grid;grid-template-columns:1fr 1fr;gap:16px 12px}
    .hero-trust div{padding:0}
    .hero-trust div + div{border-left:0}
    /* the flow becomes a vertical rail: three steps side by side on a phone
       would either wrap into nonsense or shrink past reading size */
    .hero-flow{grid-template-columns:1fr;justify-content:stretch;column-gap:0;
      align-items:stretch;padding:6px;max-width:none;margin-top:22px}
    /* left-aligned on the rail, so the three numbers stack in one line down the
       left edge instead of drifting with each label's length */
    .hero-flow .step{white-space:normal;padding:9px 12px;justify-content:flex-start}
    .hero-flow .portals{margin:2px 6px 0;letter-spacing:.03em}
    /* a rail, not a rotated arrow: "→" turned on its side reads as a glyph
       nobody recognises, and a 1px line says "next" without being read at all */
    .hero-flow .arw{position:relative;height:13px;font-size:0;margin-left:22px}
    .hero-flow .arw:before{content:"";position:absolute;top:0;bottom:0;left:0;
      border-left:1px solid rgba(255,255,255,.3)}
  }

  /* ===== feature strip ===== */
  .strip-card{background:var(--card);border-radius:24px;box-shadow:var(--shadow-card);border:1px solid rgba(255,255,255,.9);
    display:grid;grid-template-columns:repeat(4,1fr);padding:28px 12px;position:relative;overflow:hidden}
  .strip-card:before{content:"";position:absolute;inset:0 0 auto 0;height:3px;
    background:linear-gradient(90deg,transparent,rgba(64,98,80,.6),transparent)}
  .strip-item{display:flex;align-items:center;gap:16px;padding:8px 28px;transition:transform .2s ease}
  .strip-item:hover{transform:translateY(-3px)}
  .strip-item + .strip-item{border-left:1px solid var(--line)}
  .strip-ico{flex-shrink:0;width:50px;height:50px;border-radius:16px;background:var(--grad-btn);
    display:grid;place-items:center;color:#fff;box-shadow:0 10px 22px rgba(13,48,33,.35)}
  .strip-item h3{font-size:15.5px;font-weight:700;color:var(--ink-strong)}
  /* The same pill the coming-soon section uses, sized for a 15.5px card heading
     rather than the section headline it was drawn against. */
  .strip-item h3 .soon-pill{margin-left:8px;padding:2px 8px;font-size:9.5px}
  .strip-item p{font-size:12.5px;color:var(--muted);margin-top:2px}
  /* four across needs the full width; two-up before it gets cramped, one-up on
     a phone */
  @media(max-width:1120px){
    .strip-card{grid-template-columns:1fr 1fr}
    .strip-item:nth-child(3){border-left:0}
    .strip-item:nth-child(n+3){border-top:1px solid var(--line);padding-top:20px;margin-top:12px}
  }
  @media(max-width:860px){
    .strip-card{grid-template-columns:1fr}
    .strip-item + .strip-item{border-left:0;border-top:1px solid var(--line)}
    .strip-item{padding:16px 18px}
    .strip-item:nth-child(n+3){margin-top:0;padding-top:16px}
  }

  /* ===== end to end ===== */
  /* The pipeline as a numbered rail. Five steps is too many for the hero, which
     is why the hero carries three and this section carries the whole job —
     including the two steps agents assume they still have to do themselves. */
  .e2e{border-radius:28px;background:var(--grad-ink);color:var(--on-dark);padding:46px 46px 40px;
    box-shadow:var(--shadow-card);position:relative;overflow:hidden}
  .e2e:before{content:"";position:absolute;width:420px;height:420px;right:-140px;top:-180px;
    border-radius:50%;background:radial-gradient(circle,rgba(190,219,211,.16),transparent 70%)}
  .e2e-head{position:relative;max-width:640px}
  .e2e h2{font-size:clamp(28px,3.4vw,40px);line-height:1.14;color:#fff;font-weight:600;margin-top:12px}
  .e2e h2 em{color:var(--on-dark-bright)}
  .e2e .sub{margin-top:14px;font-size:15.5px;line-height:1.75;color:rgba(220,235,228,.78)}
  .e2e-steps{position:relative;margin-top:38px;display:grid;grid-template-columns:repeat(5,1fr);gap:0}
  .e2e-step{position:relative;padding:0 20px 0 0}
  .e2e-step:before{content:"";position:absolute;left:0;top:15px;right:0;height:1px;
    background:rgba(255,255,255,.2)}
  .e2e-step:last-child:before{background:linear-gradient(90deg,rgba(190,219,211,.55),transparent)}
  .e2e-num{position:relative;z-index:1;width:31px;height:31px;border-radius:50%;display:grid;
    place-items:center;font-size:12.5px;font-weight:700;color:var(--on-dark);
    background:rgba(255,255,255,.1);border:1px solid rgba(255,255,255,.3);
    backdrop-filter:blur(4px)}
  .e2e-step.ours .e2e-num{background:var(--on-dark-bright);border-color:transparent;color:var(--ink-strong)}
  .e2e-step h3{margin-top:16px;font-size:15px;font-weight:700;color:#fff}
  .e2e-step p{margin-top:5px;font-size:12.5px;line-height:1.6;color:rgba(220,235,228,.62);
    padding-right:12px}
  .e2e-step .tag{display:inline-block;margin-top:9px;font-size:10px;font-weight:700;
    letter-spacing:.1em;text-transform:uppercase;border-radius:6px;padding:3px 7px;
    background:rgba(190,219,211,.18);color:var(--on-dark-bright)}
  .e2e-step .tag.you{background:rgba(255,255,255,.08);color:rgba(220,235,228,.6)}
  /* the integration half: what we plug into, next to proof of what "live" looks
     like. The claim is "we publish for you", so the section has to show a
     published listing rather than assert one. */
  .e2e-plug{position:relative;margin-top:38px;padding-top:30px;
    border-top:1px solid rgba(255,255,255,.16);display:grid;
    grid-template-columns:1fr 1fr;gap:34px;align-items:start}
  .e2e-plug h3{font-size:19px;font-weight:600;color:#fff;
    font-family:"Fraunces",Georgia,serif}
  .e2e-plug .lead{margin-top:9px;font-size:14px;line-height:1.7;
    color:rgba(220,235,228,.72)}
  .e2e-ticks{margin-top:16px;display:grid;gap:9px}
  .e2e-ticks div{display:flex;gap:10px;align-items:flex-start;font-size:13.5px;
    line-height:1.6;color:rgba(220,235,228,.82)}
  .e2e-ticks svg{flex-shrink:0;margin-top:3px;color:var(--on-dark-bright)}
  .e2e-ticks b{color:#fff;font-weight:600}
  /* the mock: a white card on the dark panel, so "it went live" is the brightest
     thing in the section */
  .e2e-live{border-radius:18px;overflow:hidden;background:#fff;
    box-shadow:0 30px 60px rgba(8,32,22,.45);color:var(--ink)}
  .e2e-live .bar{display:flex;align-items:center;gap:9px;padding:11px 14px;
    background:var(--bg-soft);border-bottom:1px solid var(--line);font-size:12px;
    font-weight:700;color:var(--ink-strong)}
  .e2e-live .bar .live{display:inline-flex;align-items:center;gap:6px;color:#2C7752;
    font-size:11px;letter-spacing:.06em;text-transform:uppercase}
  .e2e-live .bar .live i{width:7px;height:7px;border-radius:50%;background:#2C7752;
    box-shadow:0 0 0 3px rgba(44,119,82,.18);animation:pulseDot 2.2s ease-in-out infinite}
  @keyframes pulseDot{0%,100%{opacity:1}50%{opacity:.35}}
  .e2e-live .bar .sync{margin-left:auto;font-weight:500;color:var(--muted);font-size:11.5px}
  .e2e-live .shot{height:158px;background-size:cover;background-position:center}
  .e2e-live .body{padding:14px 16px 16px}
  .e2e-live .price{font-family:"Fraunces",Georgia,serif;font-size:23px;font-weight:600;
    color:var(--ink-strong)}
  .e2e-live .price span{font-family:inherit;font-size:11.5px;font-weight:500;
    color:var(--muted);margin-left:7px;font-family:"Hanken Grotesk",sans-serif}
  .e2e-live .addr{margin-top:3px;font-size:13px;color:var(--muted)}
  .e2e-live .chips{margin-top:11px;display:flex;flex-wrap:wrap;gap:6px}
  .e2e-live .chips span{font-size:11px;font-weight:600;color:#2F5443;
    background:#EAF3EE;border-radius:999px;padding:4px 10px}
  .e2e-live .also{padding:10px 16px;border-top:1px solid var(--line);font-size:11.5px;
    color:var(--muted);display:flex;flex-wrap:wrap;gap:6px;align-items:center}
  .e2e-live .also b{color:var(--ink-strong);font-weight:600}
  @media(max-width:1000px){.e2e-plug{grid-template-columns:1fr;gap:26px}}
  .e2e-foot{position:relative;margin-top:30px;padding-top:22px;
    border-top:1px solid rgba(255,255,255,.16);display:flex;flex-wrap:wrap;gap:18px;
    align-items:center;justify-content:space-between}
  .e2e-portals{display:flex;flex-wrap:wrap;gap:8px}
  .e2e-portals span{font-size:12.5px;font-weight:600;color:var(--on-dark);
    border:1px solid rgba(255,255,255,.22);background:rgba(255,255,255,.07);
    border-radius:999px;padding:6px 13px}
  .e2e-foot .note{font-size:13px;color:rgba(220,235,228,.7);max-width:520px;line-height:1.65}
  @media(max-width:1000px){
    .e2e{padding:34px 26px 30px}
    .e2e-steps{grid-template-columns:1fr 1fr;gap:26px 0}
    .e2e-step:before{display:none}
    .e2e-step{padding-right:16px}
  }
  @media(max-width:560px){.e2e-steps{grid-template-columns:1fr}}

  /* ===== AI studio ===== */
  .ai-card{border-radius:28px;background:var(--grad-ink);color:var(--on-dark);padding:52px;
    display:grid;grid-template-columns:1.05fr .95fr;gap:46px;align-items:center;
    box-shadow:0 34px 80px rgba(13,48,33,.38);position:relative;overflow:hidden}
  .ai-card:before{content:"";position:absolute;top:-180px;right:-140px;width:480px;height:480px;border-radius:50%;
    background:radial-gradient(circle,rgba(75,114,96,.35),transparent 65%)}
  .ai-card:after{content:"";position:absolute;bottom:-200px;left:-120px;width:420px;height:420px;border-radius:50%;
    background:radial-gradient(circle,rgba(255,255,255,.07),transparent 65%)}
  .ai-badge{display:inline-flex;gap:8px;border-radius:999px;padding:7px 16px;font-size:13px;font-weight:600;
    color:var(--on-dark-bright);background:rgba(255,255,255,.12);border:1px solid rgba(255,255,255,.15)}
  .ai-card h2{font-size:clamp(26px,3vw,38px);margin-top:18px;color:#fff}
  .ai-card h2 em{color:var(--on-dark-bright)}
  .ai-card .sub{color:rgba(220,235,228,.72);font-size:15px;margin-top:14px;max-width:470px}
  .ai-list{margin-top:26px;display:grid;grid-template-columns:1fr 1fr;gap:11px 26px;position:relative;z-index:1}
  .ai-row{display:flex;justify-content:space-between;align-items:center;gap:10px;border-bottom:1px solid rgba(255,255,255,.14);
    padding-bottom:9px;font-size:14px;transition:border-color .2s ease}
  .ai-row:hover{border-color:rgba(255,255,255,.4)}
  .ai-row .inc{font-size:10.5px;font-weight:700;letter-spacing:.06em;color:var(--on-dark);
    background:rgba(75,114,96,.28);border-radius:999px;padding:3px 10px;white-space:nowrap}
  .ai-fine{margin-top:18px;font-size:12px;color:rgba(220,235,228,.5)}
  /* Both halves are real files. The left is the licensed frame as it was shot;
     the right is that frame after our own grade. There is deliberately no CSS
     filter here: dulling the "before" in the browser would be inventing a
     photograph nobody took, and the transformation being sold would be a lie
     told with one image. */
  .ba{position:relative;border-radius:20px;overflow:hidden;aspect-ratio:16/11;user-select:none;
    box-shadow:0 20px 50px rgba(8,32,22,.45);border:1px solid rgba(255,255,255,.16)}
  .ba .layer{position:absolute;inset:0;background-size:cover;background-position:center}
  .ba .after{clip-path:inset(0 0 0 50%)}
  .ba .tagb,.ba .taga{position:absolute;bottom:12px;font-size:11px;padding:4px 10px;border-radius:8px;color:#fff}
  .ba .tagb{left:12px;background:rgba(0,0,0,.5);backdrop-filter:blur(4px)}
  .ba .taga{right:12px;background:linear-gradient(135deg,#4B7260,#2F5443)}
  .ba .line{position:absolute;top:0;bottom:0;width:2px;background:#fff;left:50%;transform:translateX(-1px);pointer-events:none}
  .ba .knob{position:absolute;top:50%;left:50%;width:40px;height:40px;border-radius:99px;background:#fff;color:var(--indigo);
    display:grid;place-items:center;transform:translate(-50%,-50%);box-shadow:0 4px 14px rgba(0,0,0,.35);pointer-events:none;font-size:15px}
  .ba input{position:absolute;inset:0;width:100%;height:100%;opacity:0;cursor:ew-resize;margin:0}
  /* One slider showed one edit while the panel beside it lists five. The tabs
     are what make the list checkable — each names an edit and shows it. */
  .ba-tabs{margin-top:12px;display:flex;gap:7px;flex-wrap:wrap;justify-content:center}
  .ba-tab{border:1px solid rgba(255,255,255,.2);background:rgba(255,255,255,.07);border-radius:999px;
    padding:7px 15px;font-family:inherit;font-size:12px;font-weight:600;letter-spacing:.02em;
    color:rgba(255,255,255,.72);cursor:pointer;transition:all .18s ease}
  .ba-tab:hover{border-color:rgba(190,219,211,.5);color:#fff}
  .ba-tab.on{background:rgba(190,219,211,.18);border-color:rgba(190,219,211,.55);color:#fff}
  .ba-hint{margin-top:12px;text-align:center;font-size:11.5px;line-height:1.6;color:rgba(220,235,228,.5)}
  @media(max-width:980px){.ai-card{grid-template-columns:1fr;padding:34px}}

  /* ===== services ===== */
  .svc-grid{margin-top:36px;display:grid;grid-template-columns:repeat(3,1fr);gap:24px}
  .svc{position:relative;background:var(--card);border-radius:22px;box-shadow:var(--shadow-card);overflow:hidden;
    border:1px solid rgba(255,255,255,.9);transition:transform .25s ease,box-shadow .25s ease}
  .svc:hover{transform:translateY(-6px);box-shadow:var(--shadow-card-hover)}
  .svc .ph{height:215px;overflow:hidden;position:relative}
  .svc .ph>div{position:absolute;inset:0;background-size:cover;background-position:center;transition:transform .6s cubic-bezier(.2,.6,.2,1)}
  .svc:hover .ph>div{transform:scale(1.07)}
  /* the wash exists so the floating icon and the heading sit on something light
     — it only needs the bottom third, not half the frame */
  .svc .ph:after{content:"";position:absolute;inset:0;
    background:linear-gradient(180deg,transparent 62%,rgba(255,255,255,.9) 100%)}
  .svc-body{padding:20px 24px 24px;position:relative}
  .svc .fl-ico{position:absolute;top:-26px;right:20px;width:52px;height:52px;border-radius:16px;background:var(--grad-btn);
    display:grid;place-items:center;color:#fff;box-shadow:0 12px 26px rgba(13,48,33,.4);z-index:2}
  .svc h3{font-size:17px;font-weight:700;color:var(--ink-strong)}
  .svc p{font-size:13.5px;color:var(--muted);margin-top:7px}
  .svc .price{display:inline-block;margin-top:14px;font-size:12px;font-weight:700;color:var(--accent);
    background:var(--accent-soft);border-radius:999px;padding:5px 13px}
  @media(max-width:640px){.svc .ph{height:190px}}
  @media(max-width:980px){.svc-grid{grid-template-columns:1fr 1fr}}
  @media(max-width:640px){.svc-grid{grid-template-columns:1fr}}

  /* ===== portfolio ===== */
  .pf-head{display:flex;justify-content:space-between;align-items:flex-end;gap:18px;flex-wrap:wrap}
  .pf-tags{display:flex;gap:8px;flex-wrap:wrap}
  .pf-tag{border:1px solid var(--line);background:var(--card);border-radius:999px;padding:8px 18px;font-size:13px;
    font-weight:600;cursor:pointer;color:var(--muted);transition:all .2s ease}
  .pf-tag:hover{border-color:var(--accent);color:var(--accent)}
  .pf-tag.on{background:var(--grad-btn);color:#fff;border-color:transparent;box-shadow:0 8px 20px rgba(13,48,33,.35)}
  .mosaic{margin-top:32px;display:grid;grid-template-columns:repeat(4,1fr);grid-auto-rows:175px;gap:16px}
  .tile{position:relative;border-radius:18px;overflow:hidden;box-shadow:0 10px 30px rgba(13,48,33,.14)}
  /* The tint is what a tile looks like before its frame has been fetched: the
     mosaic paints late, and an empty tile on the page's own paper reads as a
     hole rather than as something arriving. */
  .tile>div{position:absolute;inset:0;background-color:var(--bg-soft);
    background-size:cover;background-position:center;
    transition:transform .7s cubic-bezier(.2,.6,.2,1)}
  .tile:hover>div{transform:scale(1.08)}
  .tile:after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,transparent 50%,rgba(13,48,33,.55));
    opacity:.5;transition:opacity .3s ease}
  .tile:hover:after{opacity:1}
  .tile.tall{grid-row:span 2}
  .tile span{position:absolute;left:14px;bottom:12px;z-index:2;background:rgba(11,42,29,.6);color:#fff;
    font-size:11px;font-weight:500;padding:5px 11px;border-radius:9px;backdrop-filter:blur(4px);
    transform:translateY(4px);opacity:.85;transition:all .3s ease}
  .tile:hover span{transform:none;opacity:1}
  .tile.hide{display:none}
  .pf-fine{margin-top:16px;font-size:11.5px;color:var(--faint)}
  /* ===== the offer, and what it does to a price ===== */

  /* A package card carrying a discount. The old figure stays on screen, struck
     through: a number nobody can compare against is not a saving, it is just a
     price. */
  .pr .was{margin-right:9px;font-size:20px;font-weight:500;text-decoration:line-through;
    text-decoration-thickness:1.5px;color:var(--faint);opacity:.85}
  .plan.feat .pr .was{color:rgba(255,255,255,.55)}
  /* What the discount actually covers, under the price. Without it "50% off"
     beside a monthly figure reads as the new monthly price, which it is not. */
  .pr-off{flex-basis:100%;margin-top:6px;font-size:11.5px;font-weight:600;
    letter-spacing:.02em;line-height:1.5;color:var(--accent)}
  .plan.feat .pr-off{color:var(--on-dark-bright)}
  .pr-code{align-self:flex-start;display:inline-flex;align-items:center;gap:6px;
    margin-top:8px;
    padding:4px 10px;border-radius:999px;border:1px dashed var(--accent);
    font-size:11px;letter-spacing:.08em;font-weight:700;color:var(--accent);
    font-family:ui-monospace,SFMono-Regular,Menlo,monospace}
  .plan.feat .pr-code{border-color:rgba(255,255,255,.45);color:#fff}

  /* A price in prose with an offer on it. The struck figure is the one that was
     there a moment ago, so it is dimmed rather than removed: two numbers where
     one used to be is only a saving if both are legible. */
  .lead s,.cta-panel s{opacity:.5;text-decoration-thickness:1.5px;font-weight:500}
  /* Inside the <b> that carries the price, so it inherits the sentence it
     belongs to rather than floating under the paragraph. */
  .prose-off{display:block;margin-top:5px;font-size:12px;font-weight:600;
    letter-spacing:.01em;color:var(--on-dark-bright)}
  .cta-panel .prose-off{color:var(--on-dark-bright)}

  /* The popup.
   *
   * Light, over a veil you can see the page through. The first version was a
   * dark panel on a near-opaque black veil, which read as an error dialog rather
   * than an offer: the page vanished behind it, and what was left had the weight
   * of something that had gone wrong. This sits on the page rather than
   * replacing it.
   *
   * No close control at all, by choice. A cross in the corner of a panel this
   * small is the first thing the eye lands on, so the first thing the offer says
   * becomes "you can get rid of me", and a "no thanks" under it is a second
   * thing to read before the offer itself. The ways out are the ones people
   * already reach for: the page behind it, Escape, and the button.
   */
  .of-veil{position:fixed;inset:0;z-index:220;display:none;padding:22px;
    background:rgba(13,48,33,.34);
    backdrop-filter:blur(9px) saturate(1.15);
    -webkit-backdrop-filter:blur(9px) saturate(1.15);
    animation:ofIn .3s ease both}
  .of-veil.open{display:grid;place-items:center}
  @keyframes ofIn{from{opacity:0}to{opacity:1}}
  .of{position:relative;width:min(408px,100%);padding:34px 38px 26px;
    text-align:center;border-radius:24px;background:var(--card);
    border:1px solid var(--line);
    box-shadow:0 2px 6px rgba(13,48,33,.05),0 30px 70px rgba(13,48,33,.26);
    animation:ofRise .5s cubic-bezier(.2,.7,.3,1) both}
  @keyframes ofRise{from{opacity:0;transform:translateY(14px) scale(.98)}
                    to{opacity:1;transform:none}}
  .of-mark{display:block;margin:0 auto 16px;opacity:.9}
  /* A badge, not a caption. "For the first 10 customers" is the reason to act
     now, and as faint grey small-caps it read as a label on the panel rather
     than as part of the offer. */
  .of-eyebrow{display:inline-flex;align-items:center;gap:7px;
    padding:6px 13px 6px 11px;border-radius:999px;
    background:var(--accent-soft);color:var(--accent-dark);
    font-size:10px;font-weight:700;letter-spacing:.14em;text-transform:uppercase}
  .of-eyebrow:before{content:"";width:6px;height:6px;border-radius:50%;
    background:var(--accent);flex-shrink:0;
    animation:ofPulse 2.4s ease-in-out infinite}
  @keyframes ofPulse{0%,100%{opacity:1}50%{opacity:.35}}
  /* One weight, one colour. The gradient fill this had looked like a effect
     rather than a number, and a price is not the place for one. */
  .of-big{margin-top:12px;line-height:1}
  .of-big b{font-family:"Fraunces",serif;font-size:50px;font-weight:600;
    letter-spacing:-.035em;color:var(--ink-strong)}
  .of-h{margin-top:2px;font-family:"Fraunces",serif;font-size:20px;
    font-weight:500;font-style:italic;color:var(--accent);line-height:1.35}
  .of-sub{margin:14px auto 0;max-width:36ch;font-size:12.5px;line-height:1.7;
    color:var(--muted)}
  /* A ticket, not a form field: a hairline rule above it, the label small and
     spaced, the code large and monospaced. Nothing to fill in. */
  .of-code{margin-top:20px;padding:15px 14px 16px;border-radius:14px;
    background:var(--bg-soft);border:1px solid var(--line)}
  .of-code span{display:block;font-size:9.5px;letter-spacing:.2em;
    text-transform:uppercase;color:var(--faint)}
  .of-code b{display:block;margin-top:6px;
    font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:22px;
    font-weight:600;letter-spacing:.14em;color:var(--ink-strong)}
  .of-go{display:block;margin-top:14px;padding:14px;border-radius:999px;
    background:var(--grad-btn);color:#fff;font-size:14.5px;font-weight:600;
    box-shadow:0 10px 24px rgba(13,48,33,.28);transition:transform .25s ease}
  .of-go:hover{transform:translateY(-1px)}
  .of-fine{margin:13px auto 0;max-width:34ch;font-size:10.5px;line-height:1.65;
    color:var(--faint)}
  @media(max-width:640px){
    .of{padding:30px 24px 22px;border-radius:20px}
    .of-big b{font-size:44px}
  }

  /* A tile that opens a tour. The badge is real markup rather than a pseudo
     element, because it is the only thing on the tile that says the picture is
     a door: a hover-only affordance is no affordance at all on a phone. */
  .is360{cursor:pointer}
  .is360:focus-visible{outline:3px solid var(--accent);outline-offset:3px}
  .p360{position:absolute;top:11px;right:11px;z-index:3;display:flex;align-items:center;gap:5px;
    background:rgba(11,42,29,.72);color:#fff;border-radius:999px;padding:5px 11px 5px 8px;
    font-size:10.5px;font-weight:700;letter-spacing:.05em;backdrop-filter:blur(4px);
    transition:background .3s ease}
  .tile.is360:hover .p360{background:var(--accent)}
  /* The viewer. Above the contact dialog's 200 only so that the two can never
     argue about which is in front; they are never open at the same time. */
  .pv-veil{position:fixed;inset:0;z-index:210;display:none;padding:24px;
    background:rgba(4,17,11,.86);backdrop-filter:blur(6px)}
  .pv-veil.open{display:grid;place-items:center}
  .pv{position:relative;width:min(1120px,100%);display:flex;flex-direction:column;
    background:#071B12;border:1px solid rgba(190,219,211,.14);border-radius:24px;overflow:hidden;
    box-shadow:0 50px 120px rgba(2,12,7,.7),0 0 0 1px rgba(0,0,0,.4)}
  .pv-stage{position:relative;width:100%;aspect-ratio:16/10;max-height:64vh;background:#04110B}
  .pv-canvas{position:absolute;inset:0}
  /* A photograph is contained, never cropped: the mosaic already showed a crop,
     and the reason somebody pressed it is to see the frame the photographer
     actually took. */
  .pv-shot{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;
    background:#04110B}
  /* One shell, two things inside it. Whichever is not on show is out of the
     layout entirely, so neither can catch a drag meant for the other. */
  .pv:not(.photo) .pv-shot{display:none}
  .pv.photo .pv-canvas,.pv.photo .pv-drag,.pv.photo .pv-rooms{display:none}
  .pv:not(.photo) .pv-nav{display:none}
  /* The room name sits on the photograph rather than in a bar above it. A white
     header strip turns the picture into the card's contents; this leaves the
     picture as the whole card. */
  .pv-scrim{position:absolute;left:0;right:0;top:0;height:170px;pointer-events:none;z-index:2;
    background:linear-gradient(180deg,rgba(4,17,11,.82),rgba(4,17,11,.42) 45%,transparent)}
  .pv-cap{position:absolute;top:21px;left:26px;z-index:3;pointer-events:none}
  .pv-eyebrow{display:block;font-size:9.5px;font-weight:700;letter-spacing:.22em;
    text-transform:uppercase;color:rgba(190,219,211,.7)}
  .pv-cap h3{margin-top:5px;font-family:"Fraunces",serif;font-size:25px;font-weight:600;
    color:#fff;letter-spacing:-.01em;text-shadow:0 2px 18px rgba(4,17,11,.6)}
  .pv-tools{position:absolute;top:18px;right:18px;z-index:4;display:flex;gap:8px}
  .pv-btn{display:grid;place-items:center;width:38px;height:38px;border-radius:50%;
    border:1px solid rgba(220,235,228,.24);background:rgba(7,27,18,.5);color:#DCEBE4;
    cursor:pointer;backdrop-filter:blur(10px);transition:all .25s ease}
  .pv-btn:hover{background:var(--accent);border-color:transparent;color:#fff}
  /* The one instruction the viewer needs, said once and then out of the way: it
     fades on the first drag and does not come back. */
  .pv-drag{position:absolute;left:50%;bottom:18px;transform:translateX(-50%);z-index:3;
    display:flex;align-items:center;gap:7px;padding:7px 15px;border-radius:999px;
    background:rgba(7,27,18,.55);border:1px solid rgba(220,235,228,.18);backdrop-filter:blur(10px);
    color:rgba(255,255,255,.9);font-size:11.5px;letter-spacing:.02em;pointer-events:none;
    transition:opacity .5s ease}
  .pv-drag.gone{opacity:0}
  .pv-load{position:absolute;inset:0;z-index:5;display:flex;align-items:center;justify-content:center;
    gap:11px;background:#04110B;color:rgba(220,235,228,.75);font-size:12.5px;letter-spacing:.02em;
    text-align:center;padding:24px}
  .pv-ring{width:17px;height:17px;border-radius:50%;flex-shrink:0;
    border:2px solid rgba(220,235,228,.22);border-top-color:var(--faint);
    animation:pvspin .8s linear infinite}
  @keyframes pvspin{to{transform:rotate(360deg)}}
  .pv-bar{padding:15px 22px 17px;background:linear-gradient(180deg,#0B2418,#071B12);
    border-top:1px solid rgba(190,219,211,.1)}
  .pv-rooms{display:flex;gap:7px;overflow-x:auto;scrollbar-width:none}
  .pv-rooms::-webkit-scrollbar{display:none}
  .pv-rooms button{flex-shrink:0;border:1px solid rgba(220,235,228,.18);background:rgba(220,235,228,.06);
    border-radius:999px;padding:8px 16px;font-family:inherit;font-size:12.5px;
    color:rgba(220,235,228,.82);cursor:pointer;transition:all .25s ease;white-space:nowrap}
  .pv-rooms button:hover{border-color:var(--faint);color:#fff;background:rgba(220,235,228,.12)}
  .pv-rooms button.on{background:var(--on-dark);border-color:transparent;color:#0D3021;font-weight:600}
  .pv-nav{display:flex;align-items:center;justify-content:center;gap:16px}
  .pv-arrow{display:grid;place-items:center;width:36px;height:36px;border-radius:50%;
    border:1px solid rgba(220,235,228,.18);background:rgba(220,235,228,.06);color:#DCEBE4;
    cursor:pointer;transition:all .25s ease}
  .pv-arrow:hover{background:var(--on-dark);border-color:transparent;color:#0D3021}
  .pv-count{min-width:74px;text-align:center;font-size:11px;letter-spacing:.14em;
    text-transform:uppercase;color:rgba(190,219,211,.72)}
  .pv-fine{margin-top:11px;text-align:center;font-size:10.5px;line-height:1.6;
    color:rgba(190,219,211,.48)}
  /* Full screen is the viewer's own button, not pannellum's: its control is a bare
     icon in the corner of the photograph and it looks like a debug affordance. */
  .pv:fullscreen{width:100%;height:100%;border:0;border-radius:0}
  .pv:fullscreen .pv-stage{flex:1;aspect-ratio:auto;max-height:none}
  @media(max-width:640px){
    .pv-veil{padding:12px}
    .pv{border-radius:18px}
    .pv-stage{aspect-ratio:4/3;max-height:56vh}
    .pv-cap{top:16px;left:18px}
    .pv-cap h3{font-size:20px}
    .pv-tools{top:14px;right:14px;gap:6px}
    .pv-btn{width:34px;height:34px}
    .pv-bar{padding:13px 16px 15px}
    .pv-drag{bottom:14px;font-size:11px}
  }
  @media(max-width:860px){.mosaic{grid-template-columns:1fr 1fr;grid-auto-rows:150px}}

  /* ===== equipment ===== */
  .eq-card{background:var(--card);border-radius:28px;box-shadow:var(--shadow-card);padding:48px;
    border:1px solid rgba(255,255,255,.9);display:grid;grid-template-columns:1fr 1.15fr;gap:46px;align-items:center}
  .eq-vis{position:relative}
  /* 16/9 to match the frame in it. This box was 4/3.4, which is nearly square, and
     `cover` threw away a third of the width of a landscape photograph: the tripod
     at the left edge of kit-photographer.webp disappeared entirely. Keep this ratio
     close to whatever frame the equipment section is using. */
  .eq-main{border-radius:22px;overflow:hidden;aspect-ratio:16/9;background-size:cover;background-position:center;
    box-shadow:0 24px 55px rgba(13,48,33,.25)}
  /* The drone in flight, floating over the bottom-right corner of `.eq-main`.
     44% of the width is the figure from when `.eq-main` was 4/3.4 and nearly
     square: it covered 39% of the frame's height. On the 16/9 frame the same
     width covers 59% of the height, so if it stops reading as an accent, cut
     the width rather than moving it. `floaty` has no other user. */
  .eq-small{position:absolute;right:-22px;bottom:-26px;width:44%;aspect-ratio:4/3;border-radius:16px;
    background-size:cover;background-position:center;border:5px solid #fff;box-shadow:0 18px 40px rgba(13,48,33,.3);
    animation:floaty 6.5s ease-in-out infinite}
  .kit{display:grid;grid-template-columns:1fr 1fr;gap:14px}
  .kit-item{display:flex;gap:12px;background:var(--bg);border-radius:15px;padding:16px;border:1px solid var(--line);
    transition:transform .2s ease,border-color .2s ease,background .2s ease}
  .kit-item:hover{transform:translateX(4px);border-color:rgba(64,98,80,.4);background:#fff}
  .kit-item .em{flex-shrink:0;width:34px;height:34px;border-radius:10px;background:var(--accent-soft);
    display:grid;place-items:center;color:var(--accent)}
  .kit-item b{display:block;font-size:14px;color:var(--ink-strong)}
  .kit-item span{font-size:12.5px;color:var(--muted)}
  .pills{margin-top:18px;display:flex;gap:8px;flex-wrap:wrap}
  .pill{border:1px solid var(--line);background:var(--bg);border-radius:999px;padding:7px 14px;font-size:12.5px;font-weight:500}
  @media(max-width:980px){.eq-card{grid-template-columns:1fr;padding:32px}.kit{grid-template-columns:1fr}}

  /* ===== pricing ===== */
  .plan-banner{margin:28px auto 0;max-width:720px;display:flex;justify-content:center;align-items:center;gap:8px;
    border:1px solid rgba(64,98,80,.3);background:rgba(255,255,255,.7);backdrop-filter:blur(6px);border-radius:999px;
    padding:12px 24px;font-size:14px;font-weight:600;color:var(--accent);text-align:center;
    box-shadow:0 10px 30px rgba(13,48,33,.12)}
  /* auto-fit, not repeat(3,1fr): the cards are rendered from the packages the
     studio is selling, and there have not always been three. A fourth used to
     land alone on a second row and two used to leave a third of the row empty. */
  .plans{margin-top:34px;display:grid;
    grid-template-columns:repeat(auto-fit,minmax(262px,1fr));gap:24px;
    align-items:stretch;justify-content:center}
  .plan{display:flex;flex-direction:column;background:var(--card);border-radius:24px;padding:32px;
    box-shadow:var(--shadow-card);border:1px solid rgba(255,255,255,.9);
    transition:transform .25s ease,box-shadow .25s ease}
  .plan:hover{transform:translateY(-6px);box-shadow:var(--shadow-card-hover)}
  .plan .nm{font-size:20px;font-weight:600;color:var(--ink-strong);font-family:"Fraunces",serif}
  .plan .who{font-size:13px;color:var(--muted);margin-top:2px}
  /* Wraps, because a discount adds two more things to this row: what the
     offer covers, and the code. Both belong under the figure rather than
     squeezed alongside it. */
  .plan .pr{margin-top:20px;display:flex;align-items:baseline;gap:6px;
    flex-wrap:wrap}
  .plan .pr b{font-family:"Fraunces",serif;font-size:44px;font-weight:600;color:var(--ink-strong);letter-spacing:-.02em}
  .plan .pr span{font-size:14px;color:var(--muted)}
  .plan .per{font-size:12.5px;color:var(--faint);margin-top:3px}
  .plan hr{border:0;height:1px;background:var(--line);margin:20px 0}
  /* align-content:start is load-bearing: `flex:1` makes this grid as tall as the
     tallest card in the row, and without it the rows share out all that height
     — four ticks spread down a card that had space for thirteen. */
  .plan ul{list-style:none;display:grid;gap:10px;font-size:14px;flex:1;
    align-content:start}
  .plan li{display:flex;gap:9px}
  .plan li:before{content:"✓";font-weight:700;color:var(--accent)}
  .plan .btn,.plan .btn-outline{justify-content:center;text-align:center;margin-top:24px;display:flex}
  .plan.feat{position:relative;background:var(--grad-ink);color:var(--on-dark);border:0;overflow:hidden;
    box-shadow:0 30px 70px rgba(13,48,33,.45)}
  .plan.feat:before{content:"";position:absolute;top:-160px;right:-120px;width:380px;height:380px;border-radius:50%;
    background:radial-gradient(circle,rgba(75,114,96,.4),transparent 65%)}
  .plan.feat .nm,.plan.feat .pr b{color:#fff}
  .plan.feat .who,.plan.feat .pr span,.plan.feat .per{color:rgba(220,235,228,.6)}
  .plan.feat hr{background:rgba(255,255,255,.15)}
  .plan.feat li:before{color:var(--on-dark-soft)}
  /* A forest button on a forest card has no call left in it — the featured
     plan's CTA inverts, the way the sign-in screens do. */
  .plan.feat .btn{background:#fff;color:var(--ink-strong);
    box-shadow:0 10px 26px rgba(8,32,22,.35)}
  .plan.feat .btn:hover{background:var(--on-dark-bright)}
  /* Shown only when the list was cut. A package can promise thirteen things and
     the card next to it four, and stretching every card to the longest one is how
     the whole row became mostly whitespace. */
  .plan .more{margin-top:12px;align-self:start;border:0;background:none;padding:0;
    font-family:inherit;font-size:13px;font-weight:700;color:var(--accent);
    cursor:pointer;border-bottom:1.5px solid transparent;transition:border-color .15s ease}
  .plan .more:hover{border-bottom-color:var(--accent)}
  .plan.feat .more{color:var(--on-dark-bright)}
  .plan.feat .more:hover{border-bottom-color:var(--on-dark-bright)}

  /* Everything a package promises, in full. A <dialog> rather than a div: the
     backdrop, Escape, the focus trap and returning focus to the button are all
     the browser's, and none of them are worth reimplementing. */
  /* margin:auto is what centres a modal <dialog> — the browser sets it, and the
     `*{margin:0}` reset at the top of this sheet takes it away again, which pins
     the dialog to the top-left corner of the viewport. Restated here, and not
     removable: without it this opens in the corner. */
  #plan-all{border:0;padding:0;background:none;margin:auto;
    max-width:520px;width:calc(100% - 32px)}
  #plan-all::backdrop{background:rgba(8,32,22,.55);backdrop-filter:blur(3px)}
  #plan-all .sheet{background:var(--card);border-radius:24px;padding:30px;
    box-shadow:0 40px 90px rgba(8,32,22,.4);max-height:82vh;overflow-y:auto;
    text-align:left}
  #plan-all .x{position:absolute;top:18px;right:18px;width:32px;height:32px;border:0;
    border-radius:50%;background:var(--bg-soft);color:var(--muted);font-size:19px;
    line-height:1;cursor:pointer;display:grid;place-items:center;
    transition:background .15s ease,color .15s ease}
  #plan-all .x:hover{background:var(--accent);color:#fff}
  #plan-all .nm{font-family:"Fraunces",serif;font-size:24px;font-weight:600;
    color:var(--ink-strong);padding-right:38px}
  #plan-all .who{font-size:13.5px;color:var(--muted);margin-top:3px}
  #plan-all .pr{margin-top:16px;display:flex;align-items:baseline;gap:6px}
  #plan-all .pr b{font-family:"Fraunces",serif;font-size:36px;font-weight:600;
    color:var(--ink-strong);letter-spacing:-.02em}
  #plan-all .pr span{font-size:14px;color:var(--muted)}
  #plan-all .per{font-size:12.5px;color:var(--faint);margin-top:3px}
  #plan-all h4{margin-top:22px;font-size:11.5px;font-weight:700;letter-spacing:.08em;
    text-transform:uppercase;color:var(--faint)}
  #plan-all ul{list-style:none;display:grid;gap:10px;margin-top:12px;font-size:14px}
  #plan-all li{display:flex;gap:9px}
  #plan-all li:before{content:"✓";font-weight:700;color:var(--accent)}
  #plan-all .fine{margin-top:18px;font-size:12.5px;color:var(--muted);line-height:1.6}
  #plan-all .btn{margin-top:22px;display:flex;justify-content:center;text-align:center}
  .plan .tagpop{position:absolute;top:20px;right:20px;background:var(--on-dark-bright);
    color:var(--ink-strong);font-size:11.5px;font-weight:700;border-radius:999px;padding:6px 14px;
    box-shadow:0 8px 20px rgba(8,32,22,.35)}
  .addons{margin-top:24px;background:var(--card);border-radius:24px;box-shadow:var(--shadow-card);
    border:1px solid rgba(255,255,255,.9);padding:30px}
  .addons h3{font-size:17px;font-weight:700;color:var(--ink-strong)}
  .addons .note{font-size:12px;color:var(--faint)}
  .addon-grid{margin-top:18px;display:grid;grid-template-columns:1fr 1fr;gap:11px 36px}
  .addon{display:flex;justify-content:space-between;align-items:baseline;border-bottom:1px solid var(--line);
    padding-bottom:9px;font-size:14px;transition:border-color .2s ease}
  .addon:hover{border-color:rgba(64,98,80,.5)}
  .addon b{font-family:"Fraunces",serif;font-weight:600;color:var(--ink-strong)}
  /* "Coming soon", said the same way in both places it is needed. A section that
     describes next month's work in the present tense is the page promising
     something a customer would then pay for — see LISTING_MANAGEMENT_LIVE. */
  .soon-pill{display:inline-block;margin-left:10px;vertical-align:middle;
    border:1px solid var(--accent-soft);border-radius:999px;background:var(--accent-wash);
    padding:3px 11px;font-size:11px;font-weight:700;letter-spacing:.04em;
    color:var(--accent-deep);white-space:nowrap}
  .e2e-step .tag.soon{background:var(--accent-wash);color:var(--accent-deep);
    border:1px solid var(--accent-soft)}
  /* ---- notes: the blog, as cards. One <a> per card, so the whole card is the
     link and there is no "read more" to miss on a phone. ---- */
  .nt-head{display:flex;align-items:flex-end;justify-content:space-between;gap:20px;
    flex-wrap:wrap}
  .nt-all{font-size:13.5px;font-weight:700;color:var(--accent);text-decoration:none;
    white-space:nowrap}
  .nt-all:hover{text-decoration:underline}
  .nt-grid{margin-top:30px;display:grid;
    grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:24px}
  .nt-card{display:flex;flex-direction:column;background:var(--card);
    border-radius:20px;overflow:hidden;box-shadow:var(--shadow-card);
    border:1px solid rgba(255,255,255,.9);text-decoration:none;color:inherit;
    transition:transform .25s ease,box-shadow .25s ease}
  .nt-card:hover{transform:translateY(-6px);box-shadow:var(--shadow-card-hover)}
  .nt-card .shot{aspect-ratio:16/10;background:var(--bg-soft);overflow:hidden}
  .nt-card .shot img{width:100%;height:100%;object-fit:cover;display:block;
    transition:transform .5s ease}
  .nt-card:hover .shot img{transform:scale(1.04)}
  .nt-card .in{padding:20px 21px 22px;display:flex;flex-direction:column;flex:1}
  .nt-card .meta{font-size:11px;font-weight:600;letter-spacing:.06em;
    text-transform:uppercase;color:var(--faint)}
  .nt-card h3{margin-top:8px;font-family:"Fraunces",serif;font-weight:600;
    font-size:19px;line-height:1.25;color:var(--ink-strong);letter-spacing:-.01em}
  .nt-card p{margin-top:8px;font-size:13px;line-height:1.6;color:var(--muted);flex:1}
  .nt-card .more{margin-top:14px;font-size:12.5px;font-weight:700;color:var(--accent)}
  /* Reserved height, so the section does not jump when the posts land. */
  .nt-skel{border-radius:20px;background:var(--bg-soft);min-height:330px}
  @media(max-width:640px){.nt-grid{margin-top:22px;gap:18px}}
  .price-fine{margin-top:18px;text-align:center;font-size:13px;color:var(--muted)}
  @media(max-width:980px){.plans{grid-template-columns:1fr}.addon-grid{grid-template-columns:1fr}}

  /* ===== duo sections ===== */
  .duo{background:var(--card);border-radius:28px;box-shadow:var(--shadow-card);padding:48px;
    border:1px solid rgba(64,98,80,.18);display:grid;grid-template-columns:1.1fr .9fr;gap:44px;align-items:center;
    position:relative;overflow:hidden}
  .duo .checks{margin-top:18px;display:grid;gap:10px;font-size:14.5px}
  .duo .checks div{display:flex;gap:9px}
  .duo .checks div:before{content:"✓";font-weight:700;color:var(--accent)}
  .steps{counter-reset:st;margin-top:18px;display:grid;gap:12px}
  .steps div{display:flex;gap:12px;font-size:14.5px;align-items:baseline}
  .steps div:before{counter-increment:st;content:counter(st);flex-shrink:0;width:24px;height:24px;border-radius:99px;
    background:var(--accent-soft);color:var(--accent);font-weight:700;font-size:12.5px;display:grid;place-items:center}
  .warn{margin-top:18px;border:1px solid #E4D9B6;background:#FBF6E4;color:#7F682A;border-radius:12px;
    padding:12px 16px;font-size:13px}
  @media(max-width:980px){.duo{grid-template-columns:1fr;padding:32px}}

  /* airbnb photo card */
  .bnb-card{position:relative;border-radius:22px;overflow:hidden;max-width:360px;margin:0 auto;width:100%;
    box-shadow:0 28px 60px rgba(13,48,33,.4)}
  .bnb-card .bgimg{position:absolute;inset:0;background-size:cover;background-position:center}
  .bnb-card .ovl{position:absolute;inset:0;background:linear-gradient(165deg,rgba(13,48,33,.82),rgba(13,48,33,.96))}
  .bnb-in{position:relative;z-index:2;padding:30px;color:var(--on-dark)}
  .bnb-in .nm{font-size:18px;font-weight:600;font-family:"Fraunces",serif;color:#fff}
  .bnb-in .who{font-size:12.5px;color:rgba(220,235,228,.65);margin-top:2px}
  .bnb-in .pr{margin-top:16px;display:flex;align-items:baseline;gap:6px}
  .bnb-in .pr b{font-family:"Fraunces",serif;font-size:42px;color:#fff}
  .bnb-in .pr span{font-size:13.5px;color:rgba(220,235,228,.65)}
  .bnb-in hr{border:0;height:1px;background:rgba(255,255,255,.18);margin:16px 0}
  .bnb-in ul{list-style:none;display:grid;gap:8px;font-size:13.5px}
  .bnb-in li{display:flex;gap:8px}
  .bnb-in li:before{content:"✓";font-weight:700;color:var(--on-dark-soft)}
  .bnb-in .xtra{margin-top:14px;display:grid;gap:5px;font-size:12.5px;color:rgba(220,235,228,.65)}
  .bnb-in .xtra div{display:flex;justify-content:space-between}
  .bnb-in .btn{display:flex;justify-content:center;margin-top:20px}

  /* referral credit card */
  .credit{position:relative;border-radius:22px;overflow:hidden;max-width:360px;margin:0 auto;width:100%;
    background:var(--grad-ink);color:var(--on-dark);padding:30px;box-shadow:0 28px 60px rgba(13,48,33,.4);
    border:1px solid rgba(255,255,255,.14)}
  .credit:before{content:"";position:absolute;top:-120px;right:-90px;width:300px;height:300px;border-radius:50%;
    background:radial-gradient(circle,rgba(75,114,96,.3),transparent 65%)}
  .credit .chiprow{display:flex;justify-content:space-between;align-items:center}
  .credit .cchip{width:40px;height:40px;border-radius:12px;display:grid;place-items:center;
    background:rgba(255,255,255,.12);border:1px solid rgba(255,255,255,.22)}
  .credit .lbl{font-size:11.5px;font-weight:700;letter-spacing:.16em;text-transform:uppercase;color:var(--on-dark-soft)}
  .credit .pr{margin-top:18px;display:flex;align-items:baseline;gap:6px}
  .credit .pr b{font-family:"Fraunces",serif;font-size:44px;color:#fff}
  .credit .pr span{font-size:13.5px;color:rgba(220,235,228,.65)}
  .credit hr{border:0;height:1px;background:rgba(255,255,255,.16);margin:16px 0}
  .credit ul{list-style:none;display:grid;gap:8px;font-size:13.5px}
  .credit li{display:flex;gap:8px}
  .credit li:before{content:"✓";font-weight:700;color:var(--on-dark-soft)}
  .credit .fine{margin-top:16px;font-size:12px;color:rgba(220,235,228,.5)}

  /* ===== coverage rings ===== */
  .rings{position:relative;width:290px;height:290px;margin:0 auto;display:grid;place-items:center}
  .rings:before{content:"";position:absolute;inset:0;border-radius:50%;
    background:radial-gradient(circle,rgba(64,98,80,.18),transparent 70%)}
  .ring1{position:absolute;width:250px;height:250px;border-radius:50%;border:1.5px dashed rgba(64,98,80,.5);
    animation:spinbg 40s linear infinite}
  .ring2{position:absolute;width:165px;height:165px;border-radius:50%;border:1.5px solid rgba(64,98,80,.45)}
  .ringp{position:absolute;width:165px;height:165px;border-radius:50%;border:2px solid rgba(64,98,80,.5);
    animation:pulse 3s ease-out infinite}
  .pin{position:relative;z-index:2;width:66px;height:66px;border-radius:50%;display:grid;place-items:center;color:#fff;
    background:var(--grad-btn);box-shadow:0 14px 32px rgba(13,48,33,.45)}
  .miles{position:absolute;bottom:40%;right:12%;font-size:11.5px;font-weight:600;color:var(--accent)}
  .ring-cap{margin-top:12px;text-align:center;font-size:11.5px;color:var(--faint)}
  /* Where we operate. Three named places beat a radius nobody can measure from
     a listing page — an agent in Solihull wants to read "Solihull", not do
     arithmetic about a studio they cannot see. */
  .areas{margin-top:22px;display:grid;grid-template-columns:repeat(3,1fr);gap:12px}
  .area{border:1px solid var(--line);background:var(--card);border-radius:16px;
    padding:16px 18px;box-shadow:var(--shadow-card);position:relative;overflow:hidden}
  .area:before{content:"";position:absolute;inset:0 auto 0 0;width:3px;
    background:var(--grad-btn)}
  .area .nm{font-family:"Fraunces",Georgia,serif;font-size:19px;font-weight:600;
    color:var(--ink-strong)}
  .area .det{margin-top:4px;font-size:12.5px;color:var(--muted);line-height:1.55}
  .area .tag{display:inline-block;margin-top:9px;font-size:10.5px;font-weight:700;
    letter-spacing:.09em;text-transform:uppercase;color:var(--accent);
    background:#EAF3EE;border-radius:999px;padding:3px 9px}
  @media(max-width:760px){.areas{grid-template-columns:1fr}}

  /* ===== homevox band ===== */
  .hv{position:relative;overflow:hidden;background:var(--grad-ink);color:var(--on-dark);border-radius:22px;padding:32px 38px;
    display:flex;justify-content:space-between;align-items:center;gap:20px;flex-wrap:wrap;
    box-shadow:0 24px 60px rgba(13,48,33,.35)}
  .hv:before{content:"";position:absolute;top:-140px;right:16%;width:320px;height:320px;border-radius:50%;
    background:radial-gradient(circle,rgba(75,114,96,.35),transparent 65%)}
  .hv h3{font-size:20px;font-weight:600;color:#fff;font-family:"Fraunces",serif}
  .hv p{font-size:14px;color:rgba(220,235,228,.68);margin-top:5px;max-width:560px}

  /* ===== CTA band ===== */
  .cta{position:relative;padding:24px 0 88px}
  .cta-panel{position:relative;overflow:hidden;border-radius:34px;background:var(--grad-ink);color:var(--on-dark);
    padding:64px;display:grid;grid-template-columns:1.05fr .95fr;gap:52px;align-items:center;
    box-shadow:0 40px 90px rgba(13,48,33,.45)}
  .cta-panel:before{content:"";position:absolute;top:-200px;right:-140px;width:520px;height:520px;border-radius:50%;
    background:radial-gradient(circle,rgba(75,114,96,.4),transparent 65%)}
  .cta-panel:after{content:"";position:absolute;bottom:-220px;left:-140px;width:460px;height:460px;border-radius:50%;
    background:radial-gradient(circle,rgba(255,255,255,.08),transparent 65%)}
  .cta-left{position:relative;z-index:2}
  .cta .eyebrow{color:var(--on-dark-soft)}
  .cta .eyebrow:before{background:var(--on-dark-soft)}
  .cta h2{font-size:clamp(32px,3.8vw,48px);color:#fff;margin-top:14px;line-height:1.12}
  .cta h2 em{color:var(--on-dark-bright)}
  .cta p{margin-top:18px;font-size:15.5px;color:rgba(220,235,228,.72);max-width:460px}
  .cta-btns{margin-top:30px;display:flex;gap:14px;flex-wrap:wrap}
  .cta-or{margin-top:14px;font-size:12.5px;color:rgba(220,235,228,.6)}
  .cta-or a{color:var(--on-dark-bright);font-weight:600}
  .btn-white{display:inline-flex;align-items:center;gap:8px;border-radius:999px;background:#fff;color:var(--indigo);
    font-weight:700;font-size:15px;padding:13px 30px;box-shadow:0 14px 34px rgba(8,32,22,.4);
    transition:transform .18s ease,box-shadow .18s ease}
  .btn-white:hover{transform:translateY(-2px);box-shadow:0 20px 44px rgba(8,32,22,.5)}
  .btn-white .ar{transition:transform .18s ease}
  .btn-white:hover .ar{transform:translateX(4px)}
  .cta-trust{margin-top:34px;display:flex;gap:0;flex-wrap:wrap;border-top:1px solid rgba(255,255,255,.16);padding-top:20px}
  .cta-trust div{font-size:13px;color:rgba(220,235,228,.72);padding:0 22px}
  .cta-trust div:first-child{padding-left:0}
  .cta-trust div + div{border-left:1px solid rgba(255,255,255,.16)}
  .cta-trust b{display:block;font-family:"Fraunces",serif;font-size:17px;color:#fff;font-weight:600}
  .cta-vis{position:relative;z-index:2}
  .cta-img{border-radius:24px;overflow:hidden;aspect-ratio:16/12;background-size:cover;background-position:center;
    box-shadow:0 28px 60px rgba(8,32,22,.5);border:1px solid rgba(255,255,255,.18)}
  .cta-mini{position:absolute;left:-26px;bottom:-26px;width:42%;aspect-ratio:4/3;border-radius:18px;
    background-size:cover;background-position:center;border:5px solid rgba(255,255,255,.95);
    box-shadow:0 22px 45px rgba(8,32,22,.55)}
  @media(max-width:900px){.cta-panel{grid-template-columns:1fr;padding:36px}.cta-mini{left:8px}}

  /* ===== footer ===== */
  footer{position:relative;overflow:hidden;background:linear-gradient(160deg,#0D3021,#0B2A1D 75%);
    color:var(--on-dark);padding:64px 0 34px;border-radius:38px 38px 0 0}
  footer:before{content:"";position:absolute;top:-180px;right:-120px;width:480px;height:480px;border-radius:50%;
    background:radial-gradient(circle,rgba(75,114,96,.28),transparent 65%)}
  .foot-wm{position:absolute;right:2%;bottom:-58px;font-family:"Fraunces",serif;font-style:italic;font-weight:600;
    font-size:200px;line-height:1;color:rgba(255,255,255,.035);pointer-events:none;user-select:none;white-space:nowrap}
  .foot-grid{position:relative;z-index:2;display:grid;grid-template-columns:1.4fr 1fr 1fr 1.1fr;gap:40px}
  footer .brand-name{color:#fff}
  footer .brand-name b{color:var(--on-dark-soft)}
  footer .brand-tag{color:rgba(220,235,228,.55)}
  .foot-blurb{margin-top:16px;font-size:13.5px;color:rgba(220,235,228,.62);max-width:290px;line-height:1.75}
  /* Set at heading size: this is the fallback for a visitor who has read the
     whole page and still wants a person. */
  .foot-tel{margin-top:18px}
  .foot-tel a{display:block;font-family:"Fraunces",serif;font-size:22px;font-weight:600;color:#fff}
  .foot-tel span{display:block;margin-top:3px;font-size:12px;color:rgba(220,235,228,.55)}
  .foot-h{font-size:12px;font-weight:700;letter-spacing:.16em;text-transform:uppercase;color:var(--on-dark-soft)}
  .foot-col a{display:block;font-size:14px;color:rgba(220,235,228,.68);margin-top:13px;
    transition:color .15s ease,transform .15s ease}
  .foot-col a:hover{color:#fff;transform:translateX(3px)}
  .foot-social{display:flex;gap:12px;align-items:center;margin-top:22px}
  .foot-social a{width:38px;height:38px;border-radius:999px;background:rgba(255,255,255,.1);
    border:1px solid rgba(255,255,255,.18);display:grid;place-items:center;color:#fff;
    transition:transform .18s ease,background .18s ease}
  .foot-social a:hover{transform:translateY(-3px);background:rgba(255,255,255,.2)}
  .foot-cta{margin-top:22px;display:inline-flex;align-items:center;gap:8px;border-radius:999px;background:#fff;
    color:var(--indigo);font-weight:700;font-size:13.5px;padding:10px 22px;
    box-shadow:0 12px 30px rgba(8,32,22,.4);transition:transform .18s ease}
  .foot-cta:hover{transform:translateY(-2px)}
  .foot-bottom{position:relative;z-index:2;margin-top:44px;padding-top:18px;border-top:1px solid rgba(255,255,255,.14);
    display:flex;justify-content:space-between;gap:10px;flex-wrap:wrap;font-size:12.5px;color:rgba(220,235,228,.45)}
  @media(max-width:860px){.foot-grid{grid-template-columns:1fr 1fr}.foot-wm{font-size:120px}}

  /* small screens */
  @media(max-width:560px){
    .foot-grid{grid-template-columns:1fr;gap:28px}
    .cta-panel{padding:26px;border-radius:26px}
    .cta-trust div{padding:0 12px}
    .ai-card{padding:24px;border-radius:22px}
    .ai-list{grid-template-columns:1fr}
    .mosaic{grid-auto-rows:130px;gap:10px}
    .duo{padding:22px;border-radius:22px}
    .eq-card{padding:22px;border-radius:22px}
    .eq-small{display:none}
    .plan{padding:24px}
    .sec{padding:32px 0}
    .hero-img{max-height:none}
    footer{border-radius:24px 24px 0 0;padding:44px 0 26px}
    .brand-tag{display:none}
    .nav-cta .signin{display:none}
    .brand img{height:32px}
  }

  /* The narrow end of the range: a 320px phone is still a phone somebody is
     holding, and the bar has to hold three things on one row there.
     Brand plus the number plus the button came to 323px inside 320, so the bar
     wrapped onto two rows, grew to 151px tall, and the hero's first line landed
     underneath it. The wordmark was squeezed and clipped as well: it is the one
     thing in the bar that must not shrink.

     The number goes rather than the button. It is on the page four more times
     -- under the hero, in the coverage band, in the contact dialog, in the
     footer -- and the button is the reason the bar is there. */
  @media(max-width:380px){
    .brand{flex-shrink:0}
    .brand img{height:28px}
    .brand-name{font-size:19px}
    .nav-tel{display:none}
    .nav-cta{gap:10px}
    .nav-cta .btn{padding:9px 16px;font-size:13.5px}
    .nav-in{padding:12px 4%}
  }
