
/* ===== HERO COPY =====
   The hero grew from four elements to seven (see build.render step 2d), so the
   three new lines get their styling here. Appended after the base page's own
   media queries, which is the only reason the mobile overrides below can win:
   at equal specificity it is source order that decides, and the base page
   restates .hero-sub inside two of its own breakpoints. */

/* The eyebrow is typed in sentence case and uppercased here, so a screen
   reader reads a phrase rather than spelling out capitals. It is a long line
   for a pill, so it is allowed to wrap and centres itself when it does —
   .hero-pill is an inline-flex, which does not centre its own text. */
.hero-pill{text-transform:uppercase;letter-spacing:.11em;font-size:.875rem;
  font-weight:600;text-align:center;max-width:min(100%,40rem);
  line-height:1.5;white-space:normal}

/* The base page sizes the hero h1 at clamp(3rem,8.5vw,8.5rem) with an 18ch
   cap, which was tuned for three short lines. "Less hassle running the
   business." is 32 characters on one line, so at 1440px it rendered 1,370px
   wide — wider than the container, touching both edges. Sized down so the long
   line sits inside the column with air around it.

   SCOPED to min-width:769px on purpose. The base page restates .hero h1 inside
   its own 768px and 480px breakpoints, and this stylesheet is appended after
   all of them, so a bare .hero h1 here would beat those rules at equal
   specificity and take the phone sizing with it. Mobile already wraps to three
   lines and is left alone. */
@media (min-width:769px){
  .hero h1{font-size:clamp(2.9rem,6.2vw,5.8rem);max-width:34ch;
    margin-bottom:1.75rem}
}

/* Two sentences, two lines, as the copy is written. A block span rather than a
   <br>: a <br> would still break at that point when the line is wide enough to
   hold both, and would leave a short orphan second line on a phone. */
.hero-h1-l2{display:block}

/* The sub carries the long explanatory sentence now, so it loses the serif
   display treatment it had when it was one short line, and it widens — 42ch of
   Fraunces at 1.5rem was built for nine words, and this is forty. */
.hero-sub{font-family:var(--body),system-ui,sans-serif;
  font-size:clamp(1.1875rem,1.45vw,1.3125rem);line-height:1.55;
  max-width:62ch;color:var(--ink-muted);margin-bottom:1.5rem}

/* The package and the price: the one line in the hero that has to be read, so
   it is the only one at full ink weight under the headline. */
.hero-offer{font-family:'Fraunces','Times New Roman',serif;
  font-size:clamp(1.1875rem,1.6vw,1.4375rem);line-height:1.45;font-weight:650;
  color:var(--ink);max-width:46ch;margin:0 auto .5rem;
  text-shadow:0 1px 14px rgba(242,240,238,.75)}

/* The risk reversal. Quieter than the price but still ink, not muted — it is
   the sentence that answers "what does it cost me to find out". */
.hero-terms{font-family:var(--body),system-ui,sans-serif;font-size:1.0625rem;
  line-height:1.5;color:var(--ink-muted);max-width:52ch;
  margin:0 auto 2.25rem}

/* UNDER the buttons on purpose: it qualifies the offer, not the click, and
   above them it would be the last thing read before the CTA. */
.hero-foot{font-family:var(--body),system-ui,sans-serif;font-size:.9375rem;
  line-height:1.5;color:var(--ink-faint);margin:1.25rem auto 0;
  position:relative;z-index:2}

/* The base page z-indexes each hero element by name against the A behind it.
   The three new ones are not in that list, so they would sit under the canvas
   and be unclickable-through rather than invisible. */
.hero-offer,.hero-terms,.hero-foot{position:relative;z-index:2}

@media (max-width:768px){
  .hero-pill{font-size:.75rem;letter-spacing:.07em;max-width:min(100%,26rem)}
  .hero-sub{font-size:1.0625rem;max-width:40ch;margin-bottom:1.25rem}
  .hero-offer{font-size:1.1875rem;max-width:32ch}
  .hero-terms{font-size:.9375rem;max-width:36ch;margin-bottom:1.75rem}
  .hero-foot{font-size:.8125rem}
}
@media (max-width:420px){
  .hero-pill{font-size:.6875rem;letter-spacing:.06em;max-width:min(100%,21rem);padding:.5rem .9rem}
  .hero-sub{font-size:1rem;max-width:34ch}
  .hero-offer{font-size:1.125rem;max-width:28ch}
}

/* ===== VIDEO ===== */
.vsl{padding:var(--section-y) 0;background:var(--bg);position:relative}
.vsl-intro{max-width:54rem;margin:0 auto clamp(2.5rem,5vw,3.75rem);
  text-align:center}
.vsl-title{font-family:'Fraunces','Times New Roman',serif;font-weight:700;
  font-size:clamp(2.1rem,6.2vw,4.5rem);line-height:1.02;letter-spacing:-.025em;
  margin:0;color:var(--ink)}
/* The duration is its own line, always. It is the half being underlined, and
   a drawn underline is absolutely positioned under ONE line of text - let the
   phrase wrap and the stroke sits under the first half of it with the second
   half hanging below. Its own line also means the two halves can be sized
   independently, which is what keeps "1 minute 59 seconds" on one line at
   390px without shrinking "What we offer in" to match. */
.vsl-l1{display:block}
/* inline-block, not block: the underline is absolutely positioned inside this
   span, so the span has to be exactly as wide as the words. A block span is as
   wide as the 54rem heading and the stroke then runs from the left edge of the
   column to nowhere in particular. The line break is .vsl-l1 above. */
.vsl-mark{display:inline-block;position:relative;margin-top:.12em}
/* width:100%, not left+right. An <svg> is a replaced element: `width:auto` on
   one resolves to its 300px intrinsic width rather than stretching between the
   two offsets, so left/right alone drew a 300px stroke under a 560px phrase. */
.vsl-ul{position:absolute;left:0;top:100%;width:100%;margin-top:-.08em;
  height:.34em;overflow:visible;fill:none;pointer-events:none}
.vsl-ul path{stroke-linecap:round;vector-effect:non-scaling-stroke;
  stroke-dasharray:340;stroke-dashoffset:340;
  transition:stroke-dashoffset 1.05s cubic-bezier(.33,0,.2,1) .2s}
.vsl-ul-a{stroke:var(--ink);stroke-width:2.6}
/* The second, lower stroke is the overshoot of somebody underlining by hand:
   warm, offset, and drawn a beat later so the two do not move as one line. */
.vsl-ul-b{stroke:var(--c-clay);stroke-width:2;opacity:.85;
  transition-delay:.42s}
.vsl-intro.in .vsl-ul path{stroke-dashoffset:0}

/* ===== THE DRAWN UNDERLINE, anywhere on the page =====
   Same two strokes as the video heading, off its own classes so a heading can
   carry one without being inside .vsl-intro. It draws when the block it lives
   in is revealed: `.in` is the base page's reveal class, `.in-view` is the one
   the contact band uses instead, and `[data-shown]` is the permanent mark the
   failsafe writes - so a stroke that has drawn itself once stays drawn even
   if the observer lets its section go on the way back up. */
.ul-mark{display:inline-block;position:relative}
.ul-draw{position:absolute;left:0;top:100%;width:100%;margin-top:-.08em;
  height:.34em;overflow:visible;fill:none;pointer-events:none}
.ul-draw path{stroke-linecap:round;vector-effect:non-scaling-stroke;
  stroke-dasharray:340;stroke-dashoffset:340;
  transition:stroke-dashoffset 1.05s cubic-bezier(.33,0,.2,1) .2s}
.ul-a{stroke:var(--ink);stroke-width:2.6}
.ul-b{stroke:var(--c-clay);stroke-width:2;opacity:.85;transition-delay:.42s}
/* On the dark bands the ink stroke is invisible and the clay goes muddy. */
.ul-low .ul-draw{margin-top:.13em}
/* the two-colour version: blue under, red overshooting it */
.ul-pop .ul-a{stroke:#2563eb;stroke-width:3}
.ul-pop .ul-b{stroke:#e23b3b;stroke-width:2.4;opacity:.95}
.ul-light .ul-a{stroke:#fff}
.ul-light .ul-b{stroke:#e8a492;opacity:.9}
.in .ul-draw path,.in-view .ul-draw path,[data-shown] .ul-draw path,
.ul-mark.in .ul-draw path{stroke-dashoffset:0}
/*  The hero is not a .reveal — it has its own load stagger (.hero-load) and
    nothing ever adds .in to it, so a mark in the hero would have sat at full
    dash-offset forever: invisible, with no error anywhere to say why. It
    draws on load instead, after the line it belongs to has arrived. */
.hero-load .ul-draw path{stroke-dashoffset:0;transition-delay:.9s}
.hero-load .ul-draw .ul-b{transition-delay:1.15s}
/* Somebody who has asked for less motion gets the mark, not the drawing. */
@media (prefers-reduced-motion:reduce){
  .ul-draw path,.vsl-ul path{transition:none;stroke-dashoffset:0}
}
.vsl-frame{position:relative;max-width:980px;margin:0 auto;border-radius:20px;
  overflow:hidden;background:#0a0a0a;box-shadow:0 2px 4px rgba(10,10,10,.04),
  0 24px 70px -28px rgba(10,10,10,.45);border:1px solid var(--line)}
.vsl-video{display:block;width:100%;height:auto;aspect-ratio:16/9;
  background:#0a0a0a}
/* The play button covers the whole frame so the hit area is the video, not a
   56px circle. It removes itself on first play and never comes back — once the
   native controls are in use a second overlay on top of them is a trap. */
.vsl-play{position:absolute;inset:0;width:100%;height:100%;border:0;padding:0;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:1rem;background:rgba(10,10,10,.18);cursor:pointer;
  transition:background .3s ease,opacity .3s ease}
.vsl-play:hover{background:rgba(10,10,10,.08)}
.vsl-play[hidden]{display:none}
.vsl-play-dot{width:84px;height:84px;border-radius:999px;display:grid;
  place-items:center;background:rgba(255,255,255,.94);color:#0a0a0a;
  box-shadow:0 10px 36px -8px rgba(10,10,10,.55);
  transition:transform .35s cubic-bezier(.4,0,.2,1)}
.vsl-play:hover .vsl-play-dot{transform:scale(1.06)}
.vsl-play-dot svg{width:34px;height:34px;margin-left:4px}
.vsl-play-label{font-family:var(--mono);font-size:.6875rem;letter-spacing:.22em;
  text-transform:uppercase;color:#fff;text-shadow:0 1px 10px rgba(0,0,0,.5);
  display:inline-flex;align-items:center;gap:.6rem}
.vsl-dur{opacity:.72}
.vsl-dur::before{content:"·";margin-right:.6rem}

/* ===== ONE PACKAGE =====
   Dark, because every other band around it is cream and this is the one a
   reader is meant to stop on. Nothing in here inherits a usable colour from
   the base stylesheet - .eyebrow, .display and every paragraph are ink, which
   is invisible on #171614 - so each one is restated. */
.pkg{padding:var(--section-y) 0;background:#171614;color:#fff;
  position:relative;overflow:hidden}
.pkg::before{content:"";position:absolute;left:-10%;right:-10%;top:-25%;
  height:75%;pointer-events:none;
  background:radial-gradient(55% 55% at 50% 0,rgba(181,217,232,.17),
    rgba(181,217,232,0) 72%)}
.pkg > .container{position:relative;z-index:1}
.pk-head{max-width:46rem;margin:0 auto 3.25rem;text-align:center}
.pk-head .eyebrow{margin-bottom:1.25rem;color:var(--c-blue)}
.pk-head h2.display{font-family:'Fraunces','Times New Roman',serif;
  font-size:clamp(2.25rem,5.5vw,4rem);margin:0 0 1.25rem;font-weight:700;
  color:#fff}
.pk-head p{color:rgba(255,255,255,.64);font-size:clamp(1rem,1.4vw,1.125rem);
  line-height:1.65;margin:0}

.pk-card{max-width:680px;margin:0 auto;text-align:center;
  background:rgba(255,255,255,.055);border:1px solid rgba(255,255,255,.15);
  border-radius:24px;
  padding:clamp(2.25rem,4vw,3.25rem) clamp(1.5rem,4vw,3rem);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.1),
    0 40px 90px -50px rgba(0,0,0,.95)}
/* [hidden] is only `display:none` in the UA sheet, so any display rule of our
   own on .pk-form would outrank it and show the form on a cold load. */
.pk-face[hidden],.pk-form[hidden]{display:none !important}
.pk-price{display:flex;align-items:flex-start;justify-content:center;
  gap:.25rem;line-height:1;color:#fff}
.pk-cur{font-family:'Fraunces','Times New Roman',serif;font-weight:700;
  font-size:clamp(1.75rem,3.5vw,2.5rem);margin-top:.45em}
.pk-num{font-family:'Fraunces','Times New Roman',serif;font-weight:700;
  font-size:clamp(4.5rem,11vw,7.5rem);letter-spacing:-.04em}
.pk-per{align-self:flex-end;font-family:var(--mono);font-size:.75rem;
  letter-spacing:.2em;text-transform:uppercase;color:rgba(255,255,255,.5);
  margin-bottom:1.1em;margin-left:.5rem}
.pk-terms{margin:1.25rem auto 0;max-width:28rem;color:rgba(255,255,255,.72);
  font-size:1rem;line-height:1.6}
.pk-ctas{display:flex;flex-wrap:wrap;gap:.75rem;justify-content:center;
  margin-top:2rem}
.pk-note{margin:1.5rem auto 0;max-width:32rem;font-size:.8125rem;
  color:rgba(255,255,255,.44);line-height:1.6}

/* Two buttons, and they are deliberately not equals: one is the page's only
   white button, the other is an outline. Both are <button>/<a> on a dark
   ground, so neither can lean on .btn-ghost - that is a white glass pill
   built for the cream hero. */
.pkg .btn{border:1px solid transparent;cursor:pointer;font-family:var(--body);
  text-decoration:none}
.pkg .pk-btn-main{background:#fff;color:#0a0a0a;border-color:#fff}
.pkg .pk-btn-main:hover{background:var(--c-blue);border-color:var(--c-blue);
  color:#0a0a0a;transform:translateY(-1px)}
.pkg .pk-btn-alt{background:rgba(255,255,255,.04);color:#fff;
  border-color:rgba(255,255,255,.34)}
.pkg .pk-btn-alt:hover{background:rgba(255,255,255,.12);border-color:#fff;
  transform:translateY(-1px)}
.pkg .btn:focus-visible{outline:2px solid var(--c-blue);outline-offset:3px}

/* --- the card as the booking form -------------------------------------- */
.pk-form{text-align:center}
.pk-form-head h3{font-family:'Fraunces','Times New Roman',serif;font-weight:700;
  font-size:clamp(1.625rem,3.5vw,2.25rem);margin:0 0 .65rem;color:#fff;
  letter-spacing:-.02em}
.pk-form-head p{margin:0 auto 1.9rem;max-width:30rem;
  color:rgba(255,255,255,.64);font-size:.9375rem;line-height:1.6}
.pk-grid{display:grid;gap:1rem;text-align:left;
  grid-template-columns:repeat(auto-fit,minmax(min(100%,220px),1fr))}
.pk-field-wide{grid-column:1/-1}
.pk-field label{display:block;font-family:var(--mono);font-size:.625rem;
  letter-spacing:.2em;text-transform:uppercase;color:rgba(255,255,255,.5);
  margin:0 0 .5rem}
.pk-field input{width:100%;box-sizing:border-box;font-family:var(--body);
  font-size:1rem;color:#fff;background:rgba(255,255,255,.06);
  border:1px solid rgba(255,255,255,.18);border-radius:12px;padding:.9rem 1rem;
  transition:border-color .3s,background .3s}
.pk-field input::placeholder{color:rgba(255,255,255,.3)}
.pk-field input:focus{outline:0;border-color:var(--c-blue);
  background:rgba(255,255,255,.1)}
.pk-botcheck{display:none}
.pk-submit{margin-top:1.75rem}
.pk-submit[disabled]{cursor:default}
.pk-form-foot{margin:1.1rem auto 0;max-width:30rem;font-size:.8125rem;
  color:rgba(255,255,255,.42);line-height:1.55}
.pk-back{display:inline-block;margin-top:1.25rem;background:0;border:0;
  padding:.45rem;color:rgba(255,255,255,.55);font-family:var(--mono);
  font-size:.6875rem;letter-spacing:.18em;text-transform:uppercase;
  cursor:pointer;text-decoration:underline;text-underline-offset:4px}
.pk-back:hover{color:#fff}
.pk-sent h3{font-family:'Fraunces','Times New Roman',serif;font-weight:700;
  font-size:clamp(1.625rem,3.5vw,2.25rem);margin:0 0 .75rem;color:#fff}
.pk-sent p{margin:0 auto;max-width:30rem;color:rgba(255,255,255,.7);
  font-size:1rem;line-height:1.65}

.pk-list{list-style:none;margin:clamp(2.5rem,5vw,4rem) auto 0;padding:0;
  max-width:1040px;display:grid;gap:clamp(1.25rem,2.5vw,2rem);
  grid-template-columns:repeat(auto-fit,minmax(min(100%,270px),1fr))}
.pk-item{display:flex;gap:.9rem;align-items:flex-start}
.pk-tick{width:20px;height:20px;flex:0 0 20px;margin-top:.3rem;
  color:var(--c-blue)}
.pk-item h3{font-family:var(--display);font-size:1.0625rem;font-weight:600;
  letter-spacing:-.01em;margin:0 0 .4rem;color:#fff;line-height:1.3}
.pk-item p{margin:0;color:rgba(255,255,255,.6);font-size:.9375rem;
  line-height:1.6}

/* ===== INTEGRATIONS — inherited mobile bug =====
   The band stacks to `grid-template-columns:1fr` below 900px, and a bare `1fr`
   is minmax(AUTO,1fr): its minimum is the widest thing in the column, which is
   a marquee of 32 logos that never wraps. The column therefore measured 2496px
   at a 390px viewport, the heading stretched to match, and `.intg{overflow:
   hidden}` sliced it off mid-word — "Connects to the tools you a". minmax(0,1fr)
   lets the column shrink to the viewport instead.

   The desktop two-column rule has to be restated here because this stylesheet
   is appended after the base one: at equal specificity the later rule wins, so
   a bare .intg-inner here would beat the base page's own @media(min-width:900px)
   and flatten the desktop layout to one column. */
.intg-inner{grid-template-columns:minmax(0,1fr)}
.intg-left,.intg-right{min-width:0}
.intg-right .ilmq{overflow:hidden}
@media(min-width:900px){
  .intg-inner{grid-template-columns:.82fr minmax(0,1.18fr);
    gap:clamp(2.5rem,5vw,5rem)}
}

@media (max-width:760px){
  .vsl-frame{border-radius:14px}
  .vsl-play-dot{width:66px;height:66px}
  .vsl-play-dot svg{width:26px;height:26px}
  .vsl-mark{font-size:.74em}
  .pk-card{border-radius:18px}
  .pk-ctas{flex-direction:column;align-items:stretch}
  .pkg .btn{width:100%;max-width:none;justify-content:center;
    padding-left:1.1rem;padding-right:1.1rem;white-space:normal;
    text-align:center}
  .pk-list{grid-template-columns:1fr}
}

/* ===== THE CHROME A, ON A PHONE =====
   The base page's mobile block builds the A down twice - the GLB is fitted to
   a smaller world size in the hero script AND the stage is scaled to 0.7 and
   faded to 0.55 here - which between them left it a ghost about a third of the
   hero high. The owner could not see it on his phone.

   The fade is what has to go: the model fit is handled in build.py, where the
   camera frustum can be reasoned about, and there is no point growing the
   model while the thing it is drawn on is at 55% opacity. The headline sits
   OVER the A, so it gets a cream halo rather than the A getting dimmed - a
   text-shadow costs the text nothing and keeps the chrome at full strength
   behind it. Matches the base page's own 768px breakpoint exactly: at 760 or
   769 one of the two blocks would apply without the other. */
@media (max-width:768px){
  .hero-stage{display:flex !important;opacity:.92 !important;
    transform:translateY(-3%) scale(1.04) !important;
    transform-origin:center 42% !important}
  #heroCanvas{display:block !important}
  .hero .hero-content{position:relative;z-index:2}
  .hero h1.display,.hero .hero-sub{
    text-shadow:0 1px 16px rgba(242,240,238,.9),0 1px 3px rgba(242,240,238,.9)}
  .hero .hero-pill{backdrop-filter:blur(6px)}
}

/* ====================================================================
   THE STRAPLINE
   The line under the headline. Sized between the headline and the
   paragraph so it reads as a statement rather than a second heading,
   and kept off the chrome A's busiest band by the same halo the
   headline already uses.
   ==================================================================== */
.hero-strap{font-family:var(--body);font-weight:800;
  font-size:clamp(1.0625rem,1.6vw,1.375rem);line-height:1.25;
  letter-spacing:-.01em;color:var(--ink);max-width:24ch;
  margin:0 auto .9rem}

/* ====================================================================
   THE STORE BADGES
   One row, two targets, each one comfortably over the 44px Apple asks
   for. They wrap rather than shrink: a badge squeezed to fit is a
   badge nobody can read the small line on.
   ==================================================================== */
.pk-apps{margin:2.75rem auto 0;text-align:center;max-width:46rem}
.pk-apps-line{font-family:var(--body);font-size:.9375rem;line-height:1.5;
  color:rgba(255,255,255,.62);margin:0 0 1.25rem}
.store-badges{display:flex;flex-wrap:wrap;gap:.875rem;justify-content:center}
.store-badge{display:inline-flex;align-items:center;gap:.7rem;
  min-height:56px;padding:.7rem 1.35rem;border-radius:12px;
  border:1px solid rgba(255,255,255,.28);background:rgba(255,255,255,.04);
  color:#fff;text-decoration:none;transition:background .25s,border-color .25s}
.store-badge:hover{background:rgba(255,255,255,.1);
  border-color:rgba(255,255,255,.5)}
.store-badge .sb-mark{width:26px;height:26px;flex:0 0 auto}
.sb-txt{display:flex;flex-direction:column;align-items:flex-start;
  line-height:1.1;text-align:left}
.sb-small{font-family:var(--body);font-size:.625rem;font-weight:600;
  letter-spacing:.1em;text-transform:uppercase;
  color:rgba(255,255,255,.66)}
.sb-big{font-family:var(--body);font-size:1.0625rem;font-weight:800;
  letter-spacing:-.01em}

/* ====================================================================
   MOBILE: what was actually wrong on a 390px screen
   ==================================================================== */
@media (max-width:768px){
  /* 1. THE HERO COPY ON THE CHROME A
     The A runs at .92 opacity behind the text on purpose - the owner
     could not see it when it was faded, and he was right. But its
     reflections are near-black slabs, and grey body copy laid over one
     of them fails on contrast. The halo text-shadow was not enough on
     a paragraph: it haloes glyphs, and the gaps between them stay
     dark. A soft cream scrim behind the text COLUMN gives the copy a
     ground to sit on while the A still reads either side of it. */
  .hero .hero-content{position:relative;z-index:2}
  /*  The base page already draws a scrim here, but it tops out at .94 in the
      very centre and is down to .5 by 56% - tuned for a wide desktop hero
      where the copy is a band across the middle and the A has room either
      side. On a 390px phone the copy IS the hero, top to bottom, and the A's
      brightest edge runs straight down the middle of it. So on phones the
      scrim goes near-solid across the whole text column and only lets go at
      the very edges, where the A still reads. */
  /*  This went too far the other way on 2026-10-02: a .97 scrim over the
      whole content box made the copy perfectly readable and rubbed the A out
      altogether, which is the complaint the .55 version got in the first
      place. The scrim now tops out at .72 and is gone by 86%, so the chrome
      reads as chrome through it, and the legibility is carried by the TEXT
      instead — a cream halo on the glyphs and near-black ink, which costs the
      A nothing because it only paints where the letters are. */
  .hero .hero-content::before{content:"";position:absolute;
    left:50%;top:50%;transform:translate(-50%,-50%);
    width:124%;height:100%;z-index:-1;pointer-events:none;
    background:radial-gradient(ellipse at center,
      rgba(242,240,238,.72) 0%,rgba(242,240,238,.6) 46%,
      rgba(242,240,238,.34) 66%,rgba(242,240,238,0) 86%) !important}
  /*  The halo does the work the scrim used to. Two shadows: a wide soft one
      to lift the glyph off whatever is behind it, and a tight one so the
      counters of the letters do not fill in. */
  .hero h1.display,.hero .hero-strap,.hero .hero-sub,
  .hero .hero-offer,.hero .hero-terms{
    text-shadow:0 0 18px rgba(242,240,238,.95),
      0 0 7px rgba(242,240,238,.95),0 1px 2px rgba(242,240,238,.9)}
  /*  And the A itself comes off full strength. .92 was set because .55 at
      scale .7 was a ghost the owner could not see on his phone - but that was
      a SMALL faded A. This one is still at scale 1.04, so it is big, and .8
      is plenty to read it through a scrim that now has to carry the copy. */
  /*  Back up where it can be seen. It is behind a scrim now, not a wall. */
  .hero-stage{opacity:.95 !important}
  /* the sub paragraph was the worst-hit: give it the ink it needs */
  .hero .hero-sub{color:rgba(10,10,10,.92)}

  /* 2. THE HERO IS NOT 406px WIDE
     .hero-stage is absolutely positioned on .hero, which has its own
     overflow:hidden - but the canvas is sized in device pixels by
     three.js and rounds up past the viewport. It never scrolled the
     body, it just pushed the A 8px off-centre. */
  .hero-stage{left:0;right:0;width:100%;max-width:100%}
  #heroCanvas{max-width:100%}

  /* 3. THE STRAPLINE, TIGHTER
     It is a new line in a hero that was already long on a phone, so
     the beats either side of it come in to pay for it. */
  .hero-strap{font-size:1.0625rem;max-width:22ch;margin-bottom:.75rem}
  .hero h1.display{margin-bottom:.85rem !important}
  .hero-strap{text-shadow:0 1px 16px rgba(242,240,238,.9),
    0 1px 3px rgba(242,240,238,.9)}

  /* 4. THE STICKY HEADER WAS SEE-THROUGH
     .nav.scrolled is rgba(255,255,255,.18) over a blur. backdrop-filter
     is the whole plan, and iOS drops it on a compositing layer it does
     not like - which leaves an 18%-white bar with the page running
     underneath it, legibly. The cream ground goes to 92% so the bar is
     a bar whether or not the blur lands. */
  .nav.scrolled{background:rgba(242,240,238,.94) !important;
    box-shadow:0 1px 0 rgba(10,10,10,.07),0 6px 18px rgba(10,10,10,.05)
      !important}

  /* 5. TAP TARGETS
     The footer column links and the social icons were 17px and 36px
     tall. Apple's minimum is 44, and these are the links somebody
     reaches for one-handed at the bottom of a long page. */
  .footer-right a,.footer-left a,.footer-meta a{display:inline-block;
    min-height:44px;line-height:44px}
  .footer-socials a{min-width:44px;min-height:44px;
    display:inline-flex;align-items:center;justify-content:center}

  /* 6. THE BADGES at 390px: two full-width rows beat two cramped ones */
  .pk-apps{margin-top:2.25rem}
  .store-badges{flex-direction:column;align-items:stretch}
  .store-badge{justify-content:center}
}

/*  The smallest phones still sold. "See pricing options" is 19 tracked-out
    characters in a button with 1.5rem of padding each side and an arrow after
    it - at 320px the S goes under the arrow. The label is the thing that has
    to give, not the tap target: the button keeps its 52px height. */
@media (max-width:360px){
  .hero-ctas .btn{font-size:.6875rem;letter-spacing:.06em;
    padding-left:1rem;padding-right:1rem;gap:.5rem}
  .hero-strap{font-size:1rem;max-width:20ch}
}

/* ====================================================================
   THE REVEAL, ONCE IT IS IN
   The base page's observer REMOVES .in when a section leaves the
   viewport, which is why a fast flick down a phone meets cream: the
   observer fires a frame or two behind the scroll, and anything it has
   already let go of starts from opacity 0 again on the way back.
   [data-shown] is written once, by the sweep in JS, and never removed.
   It beats .reveal on specificity, so the fade still plays the first
   time and nothing can ever un-play it.
   ==================================================================== */
.reveal[data-shown]{opacity:1 !important;transform:none !important}

/* ===== THE CLIENT BELT =====
   Shared: Our Work and the package page both run it. */
/* ---- the belts ---- */
.wk-belts{padding:0 0 var(--section-y);position:relative;overflow:hidden}
.wk-belt{overflow:hidden;position:relative;padding:.6rem 0}
/*  NO `gap` ON THE TRACK.
    The loop works by writing the tiles twice and translating the track by
    exactly -50%, so -50% has to be exactly one copy wide. With `gap`, the
    track is 2N tiles plus 2N-1 gaps, so half the track is N tiles plus N-0.5
    gaps — half a gap short. The belt therefore crept by half a gap on every
    wrap, which is the visible tick. The spacing is a margin on each tile
    instead: 2N x (tile + margin), and half of that is exactly N of them. */
.wk-track{display:flex;width:max-content;
  animation:wkRun 54s linear infinite;will-change:transform}
.wk-belt.rev .wk-track{animation-direction:reverse;animation-duration:66s}
@keyframes wkRun{from{transform:translate3d(0,0,0)}
  to{transform:translate3d(-50%,0,0)}}
/* Hovering to read a tile should not mean chasing it across the screen. */
.wk-belts:hover .wk-track{animation-play-state:paused}
@media (prefers-reduced-motion:reduce){
  .wk-track{animation:none}
  .wk-belt{overflow-x:auto;-webkit-overflow-scrolling:touch}
}
/* The edges fade, or a tile sliced by the viewport reads as a layout fault
   rather than as a belt going past. */
.wk-belts::before,.wk-belts::after{content:"";position:absolute;top:0;
  bottom:0;width:70px;z-index:4;pointer-events:none}
.wk-belts::before{left:0;background:linear-gradient(90deg,
  var(--bg) 20%,rgba(242,240,238,0))}
.wk-belts::after{right:0;background:linear-gradient(270deg,
  var(--bg) 20%,rgba(242,240,238,0))}

.wk-tile{flex:0 0 auto;width:330px;margin-right:1.1rem;
  text-decoration:none;display:block;transition:transform .3s ease}
.wk-tile:hover{transform:translateY(-5px)}
/* ---- the browser window ---- */
.wk-win{display:block;border-radius:14px;overflow:hidden;
  border:1px solid rgba(10,10,10,.14);background:#fff;
  box-shadow:0 1px 2px rgba(10,10,10,.05),
    0 22px 44px -28px rgba(10,10,10,.55);
  transition:box-shadow .3s ease,border-color .3s ease}
.wk-tile:hover .wk-win{border-color:rgba(10,10,10,.3);
  box-shadow:0 1px 2px rgba(10,10,10,.06),
    0 30px 60px -26px rgba(10,10,10,.6)}
.wk-bar{display:flex;align-items:center;gap:.55rem;
  padding:.5rem .7rem;background:#EDEAE6;
  border-bottom:1px solid rgba(10,10,10,.1)}
.wk-dots{display:flex;gap:4px;flex:0 0 auto}
.wk-dots i{width:8px;height:8px;border-radius:50%;display:block;
  background:rgba(10,10,10,.17)}
.wk-url{flex:1 1 auto;min-width:0;background:#fff;border-radius:999px;
  padding:.2rem .6rem;font-family:var(--mono),ui-monospace,monospace;
  font-size:.625rem;letter-spacing:.01em;color:rgba(16,16,16,.55);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  border:1px solid rgba(10,10,10,.07)}
.wk-shot{display:block;background:#eceae7;aspect-ratio:16/10}
.wk-shot img{width:100%;height:100%;object-fit:cover;object-position:top center;
  display:block}
.wk-meta{display:block;padding:.8rem .25rem 0}
.wk-name{display:block;font-family:var(--body);font-weight:800;
  font-size:.9375rem;letter-spacing:-.01em;color:var(--ink);line-height:1.25}
.wk-trade{display:block;font-family:var(--body);font-size:.8125rem;
  color:rgba(16,16,16,.6);margin-top:.2rem}
.wk-tap{text-align:center;margin:1.6rem auto 0;font-family:var(--body);
  font-size:.8125rem;letter-spacing:.1em;text-transform:uppercase;
  color:rgba(16,16,16,.45)}

/* ===== THE SHARED ICON BUBBLE =====
   The homepage's capabilities badge, available to any page. Same glass, same
   float, same six tones — it is the one bit of colour the site has and the
   service pages had none of it. */
.aa-bub{width:52px;height:52px;border-radius:50%;display:grid;
  place-items:center;flex:0 0 auto;color:var(--ink);
  background:radial-gradient(circle at 32% 26%,rgba(255,255,255,.95),
    rgba(255,255,255,0) 58%),linear-gradient(150deg,var(--b1),var(--b2));
  box-shadow:inset 0 1px 0 rgba(255,255,255,.9),
    0 12px 22px -10px var(--glow),0 2px 6px rgba(10,10,10,.1);
  animation:aaBubFloat 6s ease-in-out infinite;
  animation-delay:var(--fd,0s)}
.aa-bub svg{width:24px;height:24px}
@keyframes aaBubFloat{0%,100%{transform:translateY(0)}
  50%{transform:translateY(-5px)}}
@media (prefers-reduced-motion:reduce){.aa-bub{animation:none}}

/* ===== THE TAB YOU ARE ON =====
   A drawn bar under the active tab rather than a colour change: the nav is
   already all one ink, so colour would have had to be invented for this and a
   rule reads as "you are here" on its own. The .nav-flip span is positioned,
   so the bar hangs off the <a> and sits under both halves of the flip. */
.nav-links a.is-active{position:relative}
.nav-links a.is-active::after{content:"";position:absolute;
  left:0;right:0;bottom:-7px;height:2px;border-radius:2px;
  background:var(--ink)}
.mobile-menu-links a.is-active{position:relative}
.mobile-menu-links a.is-active::after{content:"";position:absolute;
  left:0;width:100%;bottom:-6px;height:2px;border-radius:2px;
  background:currentColor;opacity:.9}

/* ===== THE HEADER'S SECOND BUTTON =====
   It takes the Log in pill's old shape so the header keeps the two-button
   balance it was drawn with, and stays the quieter of the two: the solid
   Get started is what should be read last. */
.nav-demo{padding:.85rem 1.4rem;border-radius:999px;
  border:1px solid rgba(10,10,10,.22);color:var(--ink);
  font-family:var(--body);font-size:.75rem;font-weight:700;
  letter-spacing:.12em;text-transform:uppercase;
  display:inline-flex;align-items:center;background:transparent;
  transition:all .3s;white-space:nowrap;text-decoration:none}
.nav-demo:hover{border-color:var(--ink);background:var(--ink);color:#fff}
.mobile-menu-demo{display:inline-flex;align-items:center;
  justify-content:center;min-height:52px;padding:.9rem 1.4rem;
  border-radius:999px;border:1px solid rgba(255,255,255,.35);
  color:#fff;font-family:var(--body);font-size:.8125rem;font-weight:700;
  letter-spacing:.1em;text-transform:uppercase;text-decoration:none;
  margin-bottom:.75rem}
@media (max-width:1240px){
  /* the desktop nav links are hidden below this width and the header is
     logo + buttons + burger; two pills plus a burger is too much at 390px,
     so the demo button steps out and the drawer carries it instead. */
  .nav-demo{display:none}
}

/* ====================================================================
   THE LIGHT BUTTONS
   .btn-ghost is rgba(255,255,255,.88) on a #F2F0EE page: a button
   BRIGHTER than the surface it sits on, with a white border, which on
   a bright screen is a glare with words in it rather than an object.
   It goes the other way instead — a half-tone BELOW the page, a real
   ink border and an inner highlight, so it reads as a raised key
   without going dark.
   ==================================================================== */
.btn-ghost{background:#E9E5E1 !important;
  border:1px solid rgba(10,10,10,.2) !important;
  color:var(--ink) !important;
  backdrop-filter:none !important;-webkit-backdrop-filter:none !important;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.75),
    0 1px 2px rgba(10,10,10,.05),
    0 10px 22px -16px rgba(10,10,10,.45) !important}
.btn-ghost:hover{background:#E1DCD6 !important;
  border-color:rgba(10,10,10,.34) !important}
/* on the dark bands a light button is right as it is */
.pkg .btn-ghost,.cta .btn-ghost,.intg .btn-ghost{
  background:rgba(255,255,255,.95) !important;
  border-color:rgba(255,255,255,.95) !important}

/* ====================================================================
   PHONES: CONTRAST, COLOUR AND SOMETHING TO HOLD ON TO
   ====================================================================
   The page was one cream wall. Every section was the same cream, every
   heading was centred black, every paragraph was the same grey at the
   same size, both hero buttons were white-on-cream, and the cards were
   near-white on near-cream so their edges barely existed. On a desktop
   there is width enough for that restraint to read as calm. On a 390px
   screen it reads as a wall of text with nothing to look at and
   nothing to press.

   Nothing here changes the layout or the words. It gives the page
   edges, weight and three points of colour.
   ==================================================================== */
@media (max-width:900px){

  /* ---- 1. ONE BUTTON LEADS. ----------------------------------------
     Both hero buttons were .btn-ghost: white on cream, the same weight
     as each other, so there was no first thing to press. The first one
     goes solid ink. */
  .hero-ctas .btn:first-child{
    background:var(--ink) !important;color:#fff !important;
    border-color:var(--ink) !important;
    box-shadow:0 10px 26px -10px rgba(10,10,10,.55) !important}
  .hero-ctas .btn:first-child .arrow{color:#fff}
  /*  The second button used to be given a white fill here. It is the one
      that read as a glare on a bright screen, so it now takes the same
      half-tone-below-the-page surface as every other light button and this
      rule only has to stop fighting it. */
  .hero-ctas .btn+.btn{border:1px solid rgba(10,10,10,.2) !important;
    background:#E9E5E1 !important}

  /* ---- 2. THE PRICE IS A THING, NOT A LINE OF TEXT ------------------
     "Your website, local SEO and business app. £197 a month." was bold
     text in a column of other bold text. It is the offer, so it gets a
     box of its own to sit in. */
  .hero-offer{display:block;margin-left:auto;margin-right:auto;
    max-width:21rem;padding:.9rem 1.15rem;
    background:rgba(255,255,255,.82);
    border:1px solid rgba(10,10,10,.14);border-radius:16px;
    box-shadow:0 1px 2px rgba(10,10,10,.04),
      0 14px 30px -22px rgba(10,10,10,.5)}

  /* ---- 3. READABLE GREY ---------------------------------------------
     The body greys were set for a wide column on a bright desktop. */
  .hero-sub{color:rgba(10,10,10,.92) !important}
  /* .hero-terms lands on the brightest band of the chrome, so it needs more
     ink than the disclaimer below it, which sits on plain cream. */
  .hero-terms{color:rgba(10,10,10,.8)}
  .hero-foot{color:rgba(16,16,16,.6)}
  .cap-head p{color:rgba(16,16,16,.74)}
  /* NOT .intg-left p and NOT .pk-head p: both of those sit on the dark
     bands, where darkening the grey is the opposite of contrast. They
     go the other way. */
  .intg-left p,.pk-head p{color:rgba(255,255,255,.76)}
  .cap-mod p{color:rgba(16,16,16,.72)}

  /* ---- 4. EYEBROWS BECOME BADGES ------------------------------------
     "CAPABILITIES", "PRICING", "INTEGRATIONS" were floating grey
     letter-spaced words with nothing round them. A small bubble gives
     each section a visible start. */
  .eyebrow{display:inline-block;padding:.45rem .9rem;border-radius:999px;
    background:rgba(10,10,10,.06);border:1px solid rgba(10,10,10,.09);
    font-size:.6875rem;letter-spacing:.16em}
  .pkg .eyebrow,.intg .eyebrow{background:rgba(255,255,255,.1);
    border-color:rgba(255,255,255,.16);color:#fff}

  /* ---- 5. CARDS WITH EDGES ------------------------------------------
     .cap-mod was white-ish on cream with a white border, so on a phone
     the card and the page were the same colour and the only thing that
     said "card" was a very soft shadow. */
  .cap-mod{border-color:rgba(10,10,10,.1) !important;
    background:#fdfdfc !important;
    box-shadow:0 1px 2px rgba(10,10,10,.05),
      0 20px 40px -28px rgba(10,10,10,.45) !important;
    padding-top:2.4rem !important}

  /* ---- 6. SECTIONS STOP AND START ----------------------------------
     Three cream sections ran into each other with no seam. A hairline
     and a half-tone step is enough to say "new thing". */
  .cap{background:linear-gradient(180deg,
    rgba(255,255,255,.5) 0%,rgba(255,255,255,0) 38%)}
  .ringcar{border-bottom:1px solid rgba(10,10,10,.08)}
  .vsl{border-bottom:1px solid rgba(10,10,10,.08)}
  .aa-book{border-bottom:1px solid rgba(10,10,10,.08)}

  /* ---- 7. THE TRADE MARQUEE IS SCROLLING, NOT BROKEN ----------------
     Cards are sliced in half at both edges, which on a still screen
     reads as a layout fault rather than a belt of cards going past. A
     fade at each edge is what makes it read as motion.

     The fades hang off the SECTION, not .ring-viewport. The viewport is
     overflow:visible and its track is transformed, so a pseudo-element
     inside it loses the stacking argument with the cards it is meant to
     cover. On .ringcar they are above the whole belt and can be wide
     enough to actually swallow a card edge. */
  .ringcar{position:relative;overflow:hidden}
  .ringcar::before,.ringcar::after{content:"";position:absolute;
    top:0;bottom:0;width:56px;z-index:30;pointer-events:none}
  .ringcar::before{left:0;background:linear-gradient(90deg,
    var(--bg) 18%,rgba(242,240,238,0))}
  .ringcar::after{right:0;background:linear-gradient(270deg,
    var(--bg) 18%,rgba(242,240,238,0))}

  /* ---- 8. THE SECTION LABEL IS A BADGE TOO --------------------------
     "AN APP FOR ANY BUSINESS" is the same job as .eyebrow but a
     different class, so it was the one label left floating. */
  .ringcar-label{display:inline-block;padding:.45rem .9rem;
    border-radius:999px;background:rgba(10,10,10,.06);
    border:1px solid rgba(10,10,10,.09);color:rgba(16,16,16,.66);
    font-size:.6875rem;letter-spacing:.16em;margin:.75rem auto 1.3rem}
  .ringcar .container:has(>.ringcar-label),
  .ringcar-label-wrap{text-align:center}

  /* ---- 9. THE HEADER IS A HEADER -----------------------------------
     94% cream still let the line of hero text underneath read through
     it as the page scrolled past. On a phone the bar is small and the
     thing behind it is six lines of centred copy, so the last 6% is
     the difference between a header and a smear. */
  .nav.scrolled{background:#F2F0EE !important}
}

/* ===== THE TRIAL SWITCH =====
   Both states are in the markup and CSS decides which is on screen, so the
   page is correct before a byte of JavaScript runs and correct again if the
   fetch never comes back. OFF is the default: a visitor is never shown an
   offer we cannot honour. */
[data-trial-only]{display:none!important}
html.trial-live [data-trial-off]{display:none!important}
/* `revert` rather than a guessed value: these elements are paragraphs, spans,
   divs and a bar, and hard-coding `display:block` would turn an inline span
   into a line of its own. */
html.trial-live [data-trial-only]{display:revert!important}

.aa-trial-note{font-family:var(--body);font-size:.8125rem;line-height:1.5;
  color:rgba(16,16,16,.55);margin:.9rem 0 0}
.aa-trial-note.on-dark{color:rgba(255,255,255,.62)}

.aa-applink{font-family:var(--body);font-size:.875rem;line-height:1.5;
  color:rgba(16,16,16,.62);margin:.85rem 0 0}
.aa-applink a{color:var(--ink);font-weight:700;
  text-decoration:underline;text-underline-offset:3px;
  text-decoration-thickness:1px;
  text-decoration-color:rgba(10,10,10,.3)}
.aa-applink a:hover{text-decoration-color:var(--ink)}
.aa-applink.on-dark{color:rgba(255,255,255,.7)}
.aa-applink.on-dark a{color:#fff;text-decoration-color:rgba(255,255,255,.45)}

/* ===== THE ANNOUNCEMENT BAR =====
   Fixed, not in the flow: `.nav` is `position:fixed;top:0`, so a bar in the
   flow would be sat on by the header. The page is only padded, and the header
   only pushed down, once the bar is actually shown — a page with the trial
   off keeps exactly the geometry it has today. */
:root{--aa-ann-h:38px}
.aa-ann{position:fixed;top:0;left:0;right:0;z-index:120;
  min-height:var(--aa-ann-h);display:flex;align-items:center;
  background:var(--ink,#101010);color:#fff;
  padding:0 2.75rem 0 1rem}
.aa-ann[hidden]{display:none}
.aa-ann-link{display:flex;align-items:center;gap:.6rem;margin:0 auto;
  padding:.5rem 0;color:#fff;font-family:var(--body);font-size:.8125rem;
  line-height:1.3;text-align:center;flex-wrap:wrap;
  justify-content:center}
.aa-ann-tag{font-size:.625rem;font-weight:800;letter-spacing:.12em;
  text-transform:uppercase;background:#fff;color:var(--ink,#101010);
  border-radius:999px;padding:.2rem .5rem;flex:0 0 auto}
.aa-ann-txt{font-weight:600}
.aa-ann-go{font-weight:700;opacity:.8}
.aa-ann-link:hover .aa-ann-go{opacity:1}
.aa-ann-x{position:absolute;right:.35rem;top:50%;transform:translateY(-50%);
  width:34px;height:34px;display:flex;align-items:center;
  justify-content:center;background:none;border:0;color:#fff;opacity:.6;
  font-size:1.35rem;line-height:1;cursor:pointer;border-radius:50%}
.aa-ann-x:hover{opacity:1;background:rgba(255,255,255,.12)}
/* --aa-adapt-top is 0 everywhere except on a page unify_shell converted
   from a <header> that used to sit IN THE FLOW. The canonical nav is
   `position:fixed`, so swapping one for the other takes 86px of space out
   from under the page's first line and the header lands on top of it. The
   two rules compose through the variable rather than fighting over
   padding-top. */
body{padding-top:var(--aa-adapt-top,0px)}
body.aa-ann-on{padding-top:calc(var(--aa-ann-h) + var(--aa-adapt-top,0px))}
body.aa-ann-on .nav{top:var(--aa-ann-h)}
@media (max-width:600px){
  :root{--aa-ann-h:44px}
  .aa-ann{padding-right:2.5rem}
  .aa-ann-link{font-size:.75rem;gap:.45rem}
}

/* ===== ANDROID, IN WORDS ===== */
/* Shaped like the badge beside it so the pair still reads as a pair, but
   carrying none of Google's trade dress: no triangle, no "Get it on". */
.store-android{display:inline-flex;flex-direction:column;justify-content:center;
  padding:.55rem 1rem;border-radius:10px;border:1px solid rgba(10,10,10,.28);
  color:var(--ink);line-height:1.15;text-align:left}
.store-android:hover{background:var(--ink);color:#fff;border-color:var(--ink)}
.store-badges:not(.sb-on-light) .store-android{border-color:rgba(255,255,255,.4);
  color:#fff}
.store-badges:not(.sb-on-light) .store-android:hover{background:#fff;
  color:var(--ink)}
.store-android .sb-small{font-size:.625rem;letter-spacing:.06em;opacity:.7}
.store-android .sb-big{font-size:.9375rem;font-weight:700}

/* ===== THE APP STORE BADGE ON ITS OWN ===== */
.store-badges.sb-solo{justify-content:flex-start}
.store-badges.sb-small .store-badge{padding:.5rem .8rem}
.store-badges.sb-small .sb-big{font-size:.9375rem}
/* On the DARK footer. Written ink-on-cream first and it was invisible:
   nothing inside that band inherits a usable colour, which is the same trap
   the package band's eyebrow and headings hit. */
.footer-apptag{font-family:var(--body);font-size:.6875rem;font-weight:700;
  letter-spacing:.14em;text-transform:uppercase;color:rgba(255,255,255,.5);
  margin:0 0 .7rem}
.footer-left .store-badges{justify-content:flex-start;margin:0}
@media(max-width:900px){.footer-left .store-badges{justify-content:flex-start}}

/* ===== THE HOMEPAGE'S BUSINESS APP BAND ===== */
.aa-apphome{padding:clamp(3.5rem,7vw,6rem) 0 clamp(2rem,4vw,3rem)}
.aa-apphome-in{display:grid;gap:clamp(2rem,5vw,4rem);align-items:center;
  max-width:72rem;margin:0 auto;grid-template-columns:minmax(0,1fr)}
@media(min-width:920px){
  .aa-apphome-in{grid-template-columns:minmax(0,1fr) minmax(0,22rem)}
}
.aa-apphome h2.display{font-size:clamp(1.9rem,4.4vw,2.9rem);line-height:1.04;
  letter-spacing:-.025em;margin:.5rem 0 1rem}
.aa-apphome-sub{font-family:var(--body);font-size:1rem;line-height:1.6;
  color:rgba(16,16,16,.74);margin:0 0 1.5rem;max-width:40ch}
.aa-applist{list-style:none;margin:0 0 1.75rem;padding:0;display:grid;
  gap:.7rem}
.aa-applist li{display:flex;gap:.7rem;align-items:flex-start;
  font-family:var(--body);font-size:.9375rem;line-height:1.45;
  color:rgba(16,16,16,.82)}
.aa-applist svg{flex:0 0 auto;margin-top:.15rem}
.aa-appcta{display:flex;flex-wrap:wrap;gap:.75rem;align-items:center}
.aa-appcta .btn{background:var(--ink);color:#fff;border:1px solid var(--ink)}
.aa-appcta .btn:hover{background:#000}
.aa-appcta .btn-ghost{background:transparent;color:var(--ink);
  border:1px solid rgba(10,10,10,.26)}
.aa-appcta .btn-ghost:hover{background:var(--ink);color:#fff}

/* ===== THE PHONE FRAME =====
   A real screenshot in a drawn bezel. `aspect-ratio` on the frame rather than
   a height, so the frame can never be a different shape from the image inside
   it — a mismatch there reads as a stretched screenshot, which is exactly the
   thing that makes a product page look fake. */
.aa-phone{position:relative;width:100%;max-width:19rem;margin:0 auto;
  aspect-ratio:390/844;border-radius:2.4rem;padding:.55rem;
  background:linear-gradient(160deg,#2a2a2c,#111113 58%,#2a2a2c);
  box-shadow:0 1px 2px rgba(10,10,10,.3),
    0 40px 70px -34px rgba(10,10,10,.65)}
.aa-phone::after{content:"";position:absolute;left:50%;top:.9rem;
  transform:translateX(-50%);width:28%;height:.45rem;border-radius:999px;
  background:#000;opacity:.85}
.aa-phone img{display:block;width:100%;height:100%;object-fit:cover;
  object-position:top center;border-radius:1.95rem;background:#faf9f6}
.aa-phone-sm{max-width:15rem}

/* ===== /uk/app ===== */
.ap-hero{padding:9rem 0 clamp(2rem,4vw,3.5rem)}
body.aa-ann-on .ap-hero{padding-top:calc(9rem + var(--aa-ann-h))}
.ap-hero-in{display:grid;gap:clamp(2rem,5vw,4rem);align-items:center;
  grid-template-columns:minmax(0,1fr)}
@media(min-width:920px){
  .ap-hero-in{grid-template-columns:minmax(0,1fr) minmax(0,21rem)}
}
.ap-hero h1.display{font-size:clamp(2.2rem,6vw,4rem);line-height:1.02;
  letter-spacing:-.03em;margin:.6rem 0 1.1rem;max-width:15ch}
.ap-hero-sub{font-family:var(--body);font-size:clamp(1rem,1.4vw,1.1875rem);
  line-height:1.55;color:rgba(16,16,16,.76);max-width:44ch;margin:0 0 1.75rem}
.ap-ctas{display:flex;flex-wrap:wrap;gap:.75rem;align-items:center}
.ap-ctas .btn{background:var(--ink);color:#fff;border:1px solid var(--ink)}
.ap-ctas .btn:hover{background:#000}
.ap-ctas .btn-ghost{background:transparent;color:var(--ink);
  border:1px solid rgba(10,10,10,.26)}
.ap-ctas .btn-ghost:hover{background:var(--ink);color:#fff}
.ap-ctas .store-badges{margin:0}

/* The alternating feature rows.
   No bottom padding: `.ap-how` directly under it has its own `--section-y`
   on top, and two of them stacked left a 500px hole between the last feature
   and "Three steps, and you are running." */
.ap-feats{padding:clamp(1rem,3vw,2rem) 0 0}
.ap-row{display:grid;gap:clamp(1.75rem,5vw,4rem);align-items:center;
  grid-template-columns:minmax(0,1fr);padding:clamp(2rem,5vw,3.5rem) 0;
  border-top:1px solid rgba(10,10,10,.1)}
.ap-row:first-child{border-top:0}
@media(min-width:900px){
  .ap-row{grid-template-columns:minmax(0,1fr) minmax(0,20rem)}
  .ap-row.flip .ap-row-txt{order:2}
  .ap-row.flip .ap-row-shot{order:1}
}
.ap-row h2{font-family:var(--body);font-weight:800;
  font-size:clamp(1.25rem,2.4vw,1.625rem);letter-spacing:-.015em;
  margin:.65rem 0 .75rem;color:var(--ink)}
.ap-row p{font-family:var(--body);font-size:1rem;line-height:1.6;
  color:rgba(16,16,16,.74);margin:0;max-width:44ch}
.ap-row-shot .aa-phone{max-width:17rem}

/* How it works: three steps. */
.ap-how{background:#f3f1ec;padding:var(--section-y) 0}
.ap-how h2.display{font-size:clamp(1.8rem,4.2vw,2.6rem);line-height:1.05;
  letter-spacing:-.025em;margin:.5rem 0 2rem}
.ap-steps{display:grid;gap:1.25rem;grid-template-columns:minmax(0,1fr)}
@media(min-width:820px){.ap-steps{grid-template-columns:repeat(3,minmax(0,1fr))}}
.ap-step{background:#fdfdfc;border:1px solid rgba(10,10,10,.1);
  border-radius:18px;padding:1.5rem 1.4rem}
.ap-step-n{font-family:'Fraunces','Times New Roman',serif;font-weight:700;
  font-size:1.75rem;line-height:1;color:var(--ink);margin:0 0 .6rem}
.ap-step h3{font-family:var(--body);font-weight:800;font-size:1.0625rem;
  margin:0 0 .5rem;color:var(--ink)}
.ap-step p{font-family:var(--body);font-size:.9375rem;line-height:1.55;
  color:rgba(16,16,16,.74);margin:0}

/* Pricing: two cards, equal height. */
.ap-price{padding:var(--section-y) 0}
.ap-price h2.display{font-size:clamp(1.8rem,4.2vw,2.6rem);line-height:1.05;
  letter-spacing:-.025em;margin:.5rem 0 2rem;text-align:center}
.ap-plans{display:grid;gap:1.25rem;max-width:56rem;margin:0 auto;
  grid-template-columns:minmax(0,1fr)}
@media(min-width:820px){.ap-plans{grid-template-columns:repeat(2,minmax(0,1fr))}}
.ap-plan{background:#fdfdfc;border:1px solid rgba(10,10,10,.12);
  border-radius:22px;padding:1.9rem 1.6rem 1.7rem;display:flex;
  flex-direction:column;
  box-shadow:0 1px 2px rgba(10,10,10,.04),
    0 22px 46px -30px rgba(10,10,10,.5)}
.ap-plan.feature{border-color:rgba(10,10,10,.28)}
.ap-plan h3{font-family:var(--body);font-weight:800;font-size:1.1875rem;
  margin:0 0 .75rem;color:var(--ink)}
.ap-plan-price{display:flex;align-items:baseline;gap:.5rem;margin:0 0 1rem}
.ap-plan-price strong{font-family:'Fraunces','Times New Roman',serif;
  font-weight:700;font-size:2.4rem;letter-spacing:-.03em;line-height:1;
  color:var(--ink)}
.ap-plan-price span{font-family:var(--body);font-size:.6875rem;font-weight:700;
  letter-spacing:.12em;text-transform:uppercase;color:rgba(16,16,16,.5)}
.ap-plan ul{list-style:none;margin:0 0 1.6rem;padding:0;display:grid;
  gap:.65rem}
.ap-plan li{display:flex;gap:.7rem;align-items:flex-start;
  font-family:var(--body);font-size:.9375rem;line-height:1.45;
  color:rgba(16,16,16,.82)}
.ap-plan li svg{flex:0 0 auto;margin-top:.15rem}
.ap-plan .btn{margin-top:auto;width:100%;justify-content:center;
  background:var(--ink);color:#fff;border:1px solid var(--ink)}
.ap-plan:not(.feature) .btn{background:transparent;color:var(--ink);
  border-color:rgba(10,10,10,.26)}
.ap-plan:not(.feature) .btn:hover{background:var(--ink);color:#fff}

/* FAQ. <details> rather than a script: it opens with JS off and it is
   keyboard-operable without anything being wired up. */
.ap-faq{padding:0 0 var(--section-y)}
.ap-faq h2.display{font-size:clamp(1.8rem,4.2vw,2.6rem);line-height:1.05;
  letter-spacing:-.025em;margin:.5rem 0 1.75rem;text-align:center}
.ap-faq-list{max-width:46rem;margin:0 auto;border-top:1px solid rgba(10,10,10,.12)}
.ap-q{border-bottom:1px solid rgba(10,10,10,.12)}
.ap-q summary{list-style:none;cursor:pointer;padding:1.15rem 2.5rem 1.15rem 0;
  position:relative;font-family:var(--body);font-weight:700;font-size:1rem;
  line-height:1.4;color:var(--ink)}
.ap-q summary::-webkit-details-marker{display:none}
.ap-q summary::after{content:"+";position:absolute;right:.25rem;top:1rem;
  font-size:1.25rem;font-weight:400;color:rgba(16,16,16,.5)}
.ap-q[open] summary::after{content:"\2212"}
.ap-q p{font-family:var(--body);font-size:.9375rem;line-height:1.65;
  color:rgba(16,16,16,.74);margin:0 0 1.2rem;max-width:58ch}

/* The closing band. */
.ap-end{background:#171614;color:#fff;padding:var(--section-y) 0}
.ap-end-in{max-width:40rem;margin:0 auto;text-align:center}
.ap-end h2.display{font-size:clamp(1.8rem,4.2vw,2.6rem);line-height:1.05;
  letter-spacing:-.025em;margin:.5rem 0 .9rem;color:#fff}
.ap-end p{font-family:var(--body);font-size:1rem;line-height:1.6;
  color:rgba(255,255,255,.72);margin:0 0 1.75rem}
.ap-end .ap-ctas{justify-content:center}
.ap-end .ap-ctas .btn{background:#fff;color:var(--ink);border-color:#fff}
.ap-end .ap-ctas .btn:hover{background:#f0efe9}
.ap-end .ap-ctas .btn-ghost{background:transparent;color:#fff;
  border-color:rgba(255,255,255,.4)}
.ap-end .ap-ctas .btn-ghost:hover{background:#fff;color:var(--ink)}
.ap-end .eyebrow{color:rgba(255,255,255,.6)}
@media (max-width:600px){
  .ap-hero{padding-top:6.5rem}
  body.aa-ann-on .ap-hero{padding-top:calc(6.5rem + var(--aa-ann-h))}
  .ap-ctas .btn,.ap-ctas .btn-ghost{width:100%;justify-content:center}
  .ap-ctas .store-badges{width:100%}
  .ap-ctas .store-badge{width:100%;justify-content:center}
}

/* ===== "ONE JOB, START TO FINISH" — the scroll-driven explainer =====
   A sticky phone whose screen changes as the reader scrolls through the
   steps beside it. It is the product working, which is the one thing a
   feature list cannot show, and it is built from the SAME real screenshots
   as the rest of the page rather than from a video: it paints with the page,
   costs nothing on a phone over 4G, stays sharp at any density, and is
   correct again the moment the screenshots are re-shot.

   It degrades in three directions, all of which have to be right:
     * NO JAVASCRIPT — every step is visible and every screen is stacked
       under its own step. `.jb-live` is added by the script, and only then
       does the sticky/cross-fade layout switch on.
     * REDUCED MOTION — the cross-fade is removed, not the content.
     * NARROW — the phone sticks to the top of the viewport instead of
       beside the text, so a phone still gets the sequence. */
.jb{padding:clamp(2.5rem,6vw,4.5rem) 0 clamp(1rem,3vw,2rem)}
.jb-head{max-width:46rem;margin:0 0 clamp(1.75rem,4vw,2.75rem)}
.jb-head h2.display{font-size:clamp(1.8rem,4.4vw,2.9rem);line-height:1.04;
  letter-spacing:-.025em;margin:.5rem 0 .9rem}
.jb-head p{font-family:var(--body);font-size:1.0625rem;line-height:1.6;
  color:rgba(16,16,16,.74);margin:0;max-width:52ch}

.jb-grid{display:grid;gap:clamp(1.5rem,4vw,3.5rem);
  grid-template-columns:minmax(0,1fr)}
@media(min-width:900px){
  .jb-grid{grid-template-columns:minmax(0,1fr) minmax(0,19rem);
    align-items:start}
}

/* The steps. Numbered, because this IS a sequence: it is one job moving
   through the app in the order it really happens. */
.jb-steps{list-style:none;margin:0;padding:0;counter-reset:jb}
.jb-step{position:relative;padding:0 0 0 3.25rem;margin:0 0 2.25rem}
.jb-step:last-child{margin-bottom:0}
.jb-step::before{counter-increment:jb;content:counter(jb,decimal-leading-zero);
  position:absolute;left:0;top:.1rem;width:2.25rem;height:2.25rem;
  display:flex;align-items:center;justify-content:center;border-radius:50%;
  border:1px solid rgba(10,10,10,.2);background:#fdfdfc;
  font-family:var(--body);font-size:.75rem;font-weight:700;
  letter-spacing:.04em;color:rgba(16,16,16,.5);
  transition:background .35s,color .35s,border-color .35s}
.jb-step h3{font-family:var(--body);font-weight:800;
  font-size:clamp(1.0625rem,2vw,1.3125rem);letter-spacing:-.012em;
  color:var(--ink);margin:0 0 .5rem}
.jb-step p{font-family:var(--body);font-size:1rem;line-height:1.6;
  color:rgba(16,16,16,.74);margin:0;max-width:46ch}
/* The rail. Drawn between the markers, so it reads as one thread through
   the job rather than six unrelated paragraphs. */
.jb-step::after{content:"";position:absolute;left:1.125rem;top:2.6rem;
  bottom:-2.25rem;width:1px;background:rgba(10,10,10,.14)}
.jb-step:last-child::after{display:none}
.jb-live .jb-step.is-on::before{background:var(--ink);color:#fff;
  border-color:var(--ink)}

/* The phone. Sticky, and only once the script says the cross-fade is on. */
.jb-phone-wrap{position:relative}
.jb-live .jb-phone-wrap{position:sticky;top:calc(6.5rem + var(--aa-ann-h,0px))}
@media(min-width:900px){
  .jb-live .jb-phone-wrap{top:calc(7.5rem + var(--aa-ann-h,0px))}
}
.jb-phone{position:relative;width:100%;max-width:17rem;margin:0 auto;
  aspect-ratio:390/844;border-radius:2.2rem;padding:.5rem;
  background:linear-gradient(160deg,#2a2a2c,#111113 58%,#2a2a2c);
  box-shadow:0 1px 2px rgba(10,10,10,.3),
    0 40px 70px -34px rgba(10,10,10,.65)}
.jb-phone::after{content:"";position:absolute;left:50%;top:.85rem;
  transform:translateX(-50%);width:28%;height:.4rem;border-radius:999px;
  background:#000;opacity:.85;z-index:3}
.jb-screen{position:relative;width:100%;height:100%;border-radius:1.8rem;
  overflow:hidden;background:#faf9f6}
/* WITHOUT the script every shot is simply in the flow, stacked under its
   own step. With it they are layered and cross-faded. */
.jb-screen img{display:block;width:100%;height:auto;margin:0 0 .5rem}
.jb-live .jb-screen img{position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;object-position:top center;margin:0;opacity:0;
  transition:opacity .45s ease}
.jb-live .jb-screen img.is-on{opacity:1}
.jb-cap{font-family:var(--body);font-size:.8125rem;line-height:1.5;
  color:rgba(16,16,16,.52);text-align:center;margin:.9rem 0 0;min-height:2.4em}

@media (prefers-reduced-motion:reduce){
  .jb-live .jb-screen img{transition:none}
}
/* The phone above the steps on a narrow screen, so the sequence still
   works on the device most of this page is read on. */
@media(max-width:899px){
  .jb-grid{grid-template-columns:minmax(0,1fr)}
  .jb-phone-wrap{order:-1}
  .jb-phone{max-width:13.5rem}
  .jb-live .jb-phone-wrap{padding:.75rem 0;
    background:linear-gradient(180deg,var(--cream,#f2f0ee) 70%,transparent)}
}

/* ===== WHAT YOU GET — the index, so the scope is readable without
   scrolling ten sections to find it. ===== */
.ap-index{padding:clamp(1.5rem,4vw,2.5rem) 0 0}
.ap-index-grid{display:grid;gap:.6rem;
  grid-template-columns:repeat(auto-fit,minmax(15rem,1fr));
  max-width:72rem}
.ap-index-grid a{display:flex;gap:.65rem;align-items:flex-start;
  border:1px solid rgba(10,10,10,.12);border-radius:12px;background:#fdfdfc;
  padding:.85rem 1rem;font-family:var(--body);font-size:.9375rem;
  line-height:1.4;color:var(--ink);transition:border-color .25s,transform .25s}
.ap-index-grid a:hover{border-color:rgba(10,10,10,.34);transform:translateY(-1px)}
.ap-index-grid svg{flex:0 0 auto;margin-top:.1rem}

/* ===== A CALL TO ACTION BETWEEN THE RUNS ===== */
.ap-band{padding:clamp(2rem,5vw,3rem) 0}
.ap-band-in{border:1px solid rgba(10,10,10,.14);border-radius:20px;
  background:#fdfdfc;padding:clamp(1.5rem,4vw,2.5rem);text-align:center;
  box-shadow:0 1px 2px rgba(10,10,10,.04),
    0 22px 46px -32px rgba(10,10,10,.5)}
.ap-band h2{font-family:'Fraunces','Times New Roman',serif;font-weight:700;
  font-size:clamp(1.4rem,3vw,2rem);line-height:1.1;letter-spacing:-.02em;
  margin:0 0 .6rem;color:var(--ink)}
.ap-band p{font-family:var(--body);font-size:1rem;line-height:1.6;
  color:rgba(16,16,16,.72);margin:0 auto 1.5rem;max-width:44ch}
.ap-band .ap-ctas{justify-content:center}

/* ===== THE STICKY BAR ON A PHONE =====
   The page is 13,000px tall on a 390px screen. Without this the only way to
   act on it is to scroll back to the top or all the way to the bottom. */
.ap-sticky{position:fixed;left:0;right:0;bottom:0;z-index:90;display:none;
  gap:.5rem;padding:.6rem .75rem calc(.6rem + env(safe-area-inset-bottom));
  background:rgba(253,253,252,.94);backdrop-filter:blur(12px);
  -webkit-backdrop-filter:blur(12px);
  border-top:1px solid rgba(10,10,10,.12)}
@media(max-width:899px){
  .ap-sticky{display:flex}
  /* Room for it, so the last line of the footer is not under the bar. */
  body.ap-page{padding-bottom:calc(4.5rem + env(safe-area-inset-bottom))}
}
.ap-sticky a{flex:1 1 auto;display:inline-flex;align-items:center;
  justify-content:center;gap:.5rem;height:46px;border-radius:999px;
  font-family:var(--body);font-size:.75rem;font-weight:700;
  letter-spacing:.1em;text-transform:uppercase;
  background:var(--ink);color:#fff;border:1px solid var(--ink)}
.ap-sticky a.alt{flex:0 0 auto;padding:0 1rem;background:transparent;
  color:var(--ink);border-color:rgba(10,10,10,.26)}
.ap-sticky .arrow{width:14px;height:14px}

/* ===== BOOKING CARD — scoped tokens for adlp/interactive.CSS ===== */
.aa-book{
  --aa-blue:#246BFD; --aa-blue-mist:#CFE5FF; --aa-blue-soft:#EAF2FF;
  --aa-border:rgba(14,29,48,.08); --aa-border-strong:rgba(14,29,48,.13);
  --aa-copy:#68758A; --aa-copy-light:#8D97A5;
  --aa-green:#18A768; --aa-green-soft:#E6F7EF;
  --aa-ink:#0B1728; --aa-ink-soft:#142136;
  --display:Inter,Geist,ui-sans-serif,system-ui,-apple-system,
    BlinkMacSystemFont,"Segoe UI",sans-serif;
  --sans:Inter,Geist,ui-sans-serif,system-ui,-apple-system,
    BlinkMacSystemFont,"Segoe UI",sans-serif;
  --display-track:-.02em;
  padding:0 0 var(--section-y);background:var(--bg);
}
.aa-book .wrap{max-width:720px;margin:0 auto;
  padding:0 var(--gutter)}
/* The funnel page is a full-bleed ad destination; this is a band inside a
   page that already has a rhythm, so the card sits in the page's gutter. */
.aa-book-intro{max-width:46rem;margin:0 auto clamp(1.5rem,3vw,2.25rem);
  text-align:center;padding:0 var(--gutter)}
.aa-book-intro h2{font-family:var(--display-face,'Fraunces','Times New Roman',serif);
  font-weight:700;font-size:clamp(1.75rem,4.6vw,2.75rem);line-height:1.05;
  letter-spacing:-.025em;margin:0 0 .6rem;color:var(--ink)}
.aa-book-intro p{font-family:var(--body);font-size:1rem;line-height:1.55;
  color:rgba(20,20,20,.68);margin:0}
/* The funnel's sticky "book now" bar is an ad-page device and is not rendered
   here. If its class ever gets set without the bar existing, the only thing it
   does is pad the bottom of the page, so it is pinned back to nothing. */
html.cbar-on body{padding-bottom:0 !important}

/* The white panel itself. interactive.CSS styles every element the script
   draws INSIDE the card, but the card is `.booking-card` and that lives in
   adlp/css.py - the ad page's whole stylesheet, which cannot come along: it
   carries a hero, a video player and a footer that would fight this page for
   the same class names. So the two rules the panel actually needs are copied
   here, narrowed to 640px to match the content the qualifier draws. */
.aa-book .booking-card{max-width:640px;margin:0 auto;
  padding:34px 30px 38px;border-radius:22px;
  background:rgba(255,255,255,.94);
  border:1px solid rgba(15,29,48,.08);
  box-shadow:0 18px 60px rgba(15,29,48,.07)}
@media (max-width:600px){
  .aa-book .booking-card{padding:26px 20px 30px;border-radius:18px}
}

/* Same story for the Continue button: interactive.CSS sizes `.qual-go` but
   the button's LOOK is `.btn-primary`, which is in adlp/css.py. Without it the
   step ends in the word "Continue" set as body text, which reads as a page
   that has not finished loading. The page's own `.btn` cannot stand in - it is
   a cream ghost pill, invisible on a white card. */
.aa-book .btn-primary{display:inline-flex;align-items:center;gap:9px;
  justify-content:center;background:#0E1A2B;color:#fff;border:0;
  border-radius:999px;font-family:var(--sans);font-size:15px;font-weight:600;
  letter-spacing:.005em;cursor:pointer;
  transition:transform 160ms ease,box-shadow 160ms ease}
.aa-book .btn-primary:hover{transform:translateY(-1px);
  box-shadow:0 10px 22px rgba(14,26,43,.16)}
.aa-book .btn-primary:disabled{opacity:.55;cursor:default;transform:none;
  box-shadow:none}

/* The second way in, under the card. Somebody who does not want a call should
   not have to scroll back up to the price band to find that out. */
.aa-book-or{display:flex;align-items:center;gap:1rem;
  max-width:640px;margin:1.9rem auto 1.25rem;padding:0 var(--gutter)}
.aa-book-or::before,.aa-book-or::after{content:"";flex:1;height:1px;
  background:rgba(10,10,10,.14)}
.aa-book-or span{font-family:var(--body);font-size:.6875rem;font-weight:700;
  letter-spacing:.14em;text-transform:uppercase;color:rgba(16,16,16,.5)}
/*  The price, where the decision is. It was stated in the hero and again in
    the package band, and nowhere in between -- so the one place somebody is
    actually choosing between ringing us and paying had no number on it. */
.aa-book-price{max-width:640px;margin:0 auto;background:#fdfdfc;
  border:1px solid rgba(10,10,10,.14);border-radius:22px;
  padding:1.6rem 1.4rem 1.5rem;text-align:center;
  box-shadow:0 1px 2px rgba(10,10,10,.04),
    0 22px 46px -30px rgba(10,10,10,.5)}
.aa-book-price-top{display:flex;align-items:baseline;gap:.5rem;
  justify-content:center;margin-bottom:.65rem}
.aa-book-price-top strong{font-family:'Fraunces','Times New Roman',serif;
  font-weight:700;font-size:clamp(2.6rem,8vw,3.4rem);letter-spacing:-.03em;
  line-height:1;color:var(--ink)}
.aa-book-price-top span{font-family:var(--body);font-size:.75rem;
  font-weight:700;letter-spacing:.12em;text-transform:uppercase;
  color:rgba(16,16,16,.5)}
.aa-book-price-what{font-family:var(--body);font-size:.9375rem;line-height:1.55;
  color:rgba(16,16,16,.74);margin:0 auto 1.4rem;max-width:36ch}
/*  The ads upsell. It was one grey sentence trailing off the bottom of the
    band, which is where a reader stops reading. It is a card with its own
    label now: the question is the thing, and it is asked rather than
    mentioned. */
.aa-book-more{max-width:640px;margin:1.5rem auto 0;text-align:center;
  background:#fdfdfc;border:1px solid rgba(10,10,10,.14);border-radius:20px;
  padding:1.4rem 1.3rem 1.3rem;
  box-shadow:0 1px 2px rgba(10,10,10,.04),
    0 18px 38px -30px rgba(10,10,10,.5)}
.aa-book-more-tag{display:inline-block;font-family:var(--body);
  font-size:.75rem;font-weight:800;letter-spacing:.1em;text-transform:uppercase;
  color:var(--ink);background:#E9E5E1;border:1px solid rgba(10,10,10,.12);
  border-radius:999px;padding:.45rem .95rem;margin-bottom:.9rem}
.aa-book-more p{font-family:var(--body);font-size:.9375rem;line-height:1.6;
  color:rgba(16,16,16,.72);margin:0 auto 1.25rem;max-width:36ch}
.aa-book-more-btn{background:transparent;color:var(--ink);
  border:1px solid rgba(10,10,10,.26);cursor:pointer;
  justify-content:center;width:100%;max-width:22rem}
.aa-book-more-btn:hover{background:var(--ink);color:#fff;
  border-color:var(--ink)}
@media (max-width:600px){
  .aa-book-more{margin-left:var(--gutter);margin-right:var(--gutter)}
}

/* ===== THE APP BAND: pill, badges, belt ===== */
.ringcar-head{text-align:center;margin:0 auto;
  padding:0 var(--gutter) clamp(1.5rem,3.5vw,2.25rem)}
.ringcar-head .ringcar-label{margin:0 auto .85rem}
.ringcar-one{font-family:var(--body);font-weight:700;
  font-size:clamp(1.0625rem,2.4vw,1.375rem);line-height:1.3;
  letter-spacing:-.01em;color:var(--ink);margin:0 auto 1.15rem;max-width:22ch}
.ringcar-one em{font-family:'Fraunces','Times New Roman',serif;
  font-style:italic;font-weight:500}
/* The badges sit on cream here, not on the dark package band, so the white
   border and white type they wear down there are invisible. */
.sb-on-light .store-badge{border-color:rgba(10,10,10,.18);
  background:rgba(255,255,255,.72);color:var(--ink)}
.sb-on-light .store-badge:hover{background:#fff;
  border-color:rgba(10,10,10,.4)}
.sb-on-light .sb-small{color:rgba(16,16,16,.55)}
@media (max-width:600px){
  /* side by side at 390px, because two full-width badges where a heading used
     to be is the same wall of furniture in a different shape. */
  .ringcar-head .store-badges{flex-direction:row;gap:.6rem}
  .ringcar-head .store-badge{flex:1 1 0;min-width:0;padding:.6rem .7rem;
    gap:.5rem;justify-content:center}
  .ringcar-head .store-badge .sb-mark{width:22px;height:22px}
  /* "Download on the" is three words in a badge about 140px wide. Let it
     wrap and the Apple badge is two lines tall while the Play one is one,
     which looks like a mistake rather than a pair. */
  .ringcar-head .sb-small{font-size:.4375rem;letter-spacing:.05em;
    white-space:nowrap}
  .ringcar-head .sb-big{font-size:.8125rem;white-space:nowrap}
  .ringcar-head .sb-txt{gap:.1rem}
}
.aa-book-pay{display:flex;max-width:none;margin:0;
  justify-content:center;text-align:center;
  background:var(--ink);color:#fff;border:1px solid var(--ink);
  box-shadow:0 10px 26px -10px rgba(10,10,10,.5)}
.aa-book-pay:hover{background:#000}
.aa-book-pay-note{max-width:40rem;margin:1rem auto 0;text-align:center;
  font-family:var(--body);font-size:.875rem;line-height:1.55;
  color:rgba(16,16,16,.62);padding:0 var(--gutter)}

/* ====================================================================
   ALL PACKAGES — the sheet
   A full-height sheet rather than a centred dialog, because on a phone
   a centred dialog with two package cards in it is a box with its own
   scrollbar inside a page with another one. This one IS the screen
   while it is open: the body is locked behind it and the sheet is the
   only thing that scrolls.

   Sized off --vv-h/--vv-top where the browser gives them, never 100vh:
   on iOS 100vh is the address-bar-less height, so a 100vh sheet puts
   its close button under the toolbar. The fallback keeps it working
   where those are not set.
   ==================================================================== */
.pmod[hidden]{display:none}
.pmod{position:fixed;inset:0;z-index:300;display:flex;
  align-items:flex-end;justify-content:center}
.pmod-scrim{position:absolute;inset:0;background:rgba(10,10,10,.5);
  backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px);
  animation:pmodFade .25s ease}
.pmod-sheet{position:relative;width:100%;max-width:980px;
  max-height:calc(100dvh - 2.5rem);
  background:var(--bg);border-radius:24px 24px 0 0;
  display:flex;flex-direction:column;overflow:hidden;
  box-shadow:0 -10px 60px rgba(10,10,10,.3);
  animation:pmodUp .32s cubic-bezier(.2,.8,.2,1)}
@supports not (height:100dvh){.pmod-sheet{max-height:calc(100vh - 2.5rem)}}
@keyframes pmodFade{from{opacity:0}to{opacity:1}}
@keyframes pmodUp{from{transform:translateY(24px);opacity:0}
  to{transform:translateY(0);opacity:1}}
.pmod-head{display:flex;align-items:center;justify-content:space-between;
  gap:1rem;padding:1.25rem var(--gutter) 1rem;
  border-bottom:1px solid rgba(10,10,10,.1);flex:0 0 auto}
.pmod-head h2{font-family:'Fraunces','Times New Roman',serif;font-weight:700;
  font-size:1.5rem;letter-spacing:-.02em;margin:0;color:var(--ink)}
.pmod-x{width:44px;height:44px;border:1px solid rgba(10,10,10,.16);
  background:rgba(255,255,255,.7);border-radius:999px;font-size:1.5rem;
  line-height:1;color:var(--ink);cursor:pointer;flex:0 0 auto}
.pmod-body{flex:1 1 auto;overflow-y:auto;-webkit-overflow-scrolling:touch;
  padding:1.5rem var(--gutter) 2.5rem;display:grid;gap:1.25rem;
  overscroll-behavior:contain}
@media (min-width:900px){
  .pmod{align-items:center}
  .pmod-sheet{border-radius:24px;max-height:min(86dvh,860px);max-width:1140px}
  .pmod-body{grid-template-columns:repeat(3,1fr);gap:1.25rem;
    padding-bottom:2rem}
}
.pmod-card{background:#fdfdfc;border:1px solid rgba(10,10,10,.12);
  border-radius:20px;padding:1.6rem 1.4rem 1.5rem;display:flex;
  flex-direction:column;
  box-shadow:0 1px 2px rgba(10,10,10,.04),
    0 20px 40px -30px rgba(10,10,10,.5)}
.pmod-card.feature{border-color:rgba(10,10,10,.26);
  box-shadow:0 1px 2px rgba(10,10,10,.05),
    0 24px 50px -28px rgba(10,10,10,.55)}
.pmod-card h3{font-family:var(--body);font-weight:800;font-size:1.0625rem;
  letter-spacing:-.01em;margin:0 0 .5rem;color:var(--ink)}
.pmod-price{display:flex;align-items:baseline;gap:.45rem;margin:0 0 .75rem}
.pmod-price strong{font-family:'Fraunces','Times New Roman',serif;
  font-weight:700;font-size:2.1rem;letter-spacing:-.02em;color:var(--ink)}
.pmod-price span{font-family:var(--body);font-size:.75rem;font-weight:700;
  letter-spacing:.12em;text-transform:uppercase;color:rgba(16,16,16,.5)}
.pmod-lead{font-family:var(--body);font-size:.9375rem;line-height:1.55;
  color:rgba(16,16,16,.72);margin:0 0 1.1rem}
.pmod-list{list-style:none;margin:0 0 1.4rem;padding:0;display:grid;
  gap:.6rem}
.pmod-list li{display:flex;gap:.65rem;align-items:flex-start;
  font-family:var(--body);font-size:.9375rem;line-height:1.45;
  color:rgba(16,16,16,.8)}
.pmod-list svg{flex:0 0 auto;margin-top:.15rem}
.pmod-cta{margin-top:auto;justify-content:center;background:var(--ink);
  color:#fff;border:1px solid var(--ink);width:100%}
.pmod-cta:hover{background:#000}
.pmod-card:not(.feature) .pmod-cta{background:transparent;color:var(--ink);
  border-color:rgba(10,10,10,.26)}
.pmod-card:not(.feature) .pmod-cta:hover{background:var(--ink);color:#fff}
.pmod-note{font-family:var(--body);font-size:.8125rem;line-height:1.5;
  color:rgba(16,16,16,.55);margin:.85rem 0 0}
/* ===== THE BOOKING POP-UP =====
   Same sheet mechanics as the packages one, its own ids. The card inside is
   the funnel's, so .aa-book on the sheet is what gives it the scoped tokens
   adlp/interactive.CSS expects. */
.bkmod[hidden]{display:none}
.bkmod{position:fixed;inset:0;z-index:320;display:flex;
  align-items:flex-end;justify-content:center}
.bkmod-scrim{position:absolute;inset:0;background:rgba(10,10,10,.55);
  backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px)}
.bkmod-sheet{position:relative;width:100%;max-width:720px;
  max-height:calc(100dvh - 2rem);background:var(--bg);
  border-radius:24px 24px 0 0;display:flex;flex-direction:column;
  overflow:hidden;box-shadow:0 -10px 60px rgba(10,10,10,.3);
  animation:pmodUp .32s cubic-bezier(.2,.8,.2,1);padding:0}
@supports not (height:100dvh){.bkmod-sheet{max-height:calc(100vh - 2rem)}}
.bkmod-head{display:flex;align-items:center;justify-content:space-between;
  gap:1rem;padding:1.1rem var(--gutter) .9rem;
  border-bottom:1px solid rgba(10,10,10,.1);flex:0 0 auto}
.bkmod-head h2{font-family:'Fraunces','Times New Roman',serif;font-weight:700;
  font-size:1.35rem;letter-spacing:-.02em;margin:0;color:var(--ink)}
.bkmod-x{width:44px;height:44px;border:1px solid rgba(10,10,10,.16);
  background:rgba(255,255,255,.7);border-radius:999px;font-size:1.5rem;
  line-height:1;color:var(--ink);cursor:pointer;flex:0 0 auto}
.bkmod-body{flex:1 1 auto;overflow-y:auto;-webkit-overflow-scrolling:touch;
  padding:1.25rem var(--gutter) 2rem;overscroll-behavior:contain}
.bkmod-body .booking-card{max-width:none;margin:0;box-shadow:none;
  border:1px solid rgba(10,10,10,.1)}
@media (min-width:900px){
  .bkmod{align-items:center}
  .bkmod-sheet{border-radius:24px;max-height:min(88dvh,900px)}
}
.bk-open{cursor:pointer}
.aa-book-open{margin-top:1.5rem}
.aa-book-openbtn{background:var(--ink);color:#fff;border:1px solid var(--ink);
  box-shadow:0 10px 26px -10px rgba(10,10,10,.55)}
.aa-book-openbtn:hover{background:#000}
html.bkmod-on,html.bkmod-on body{overflow:hidden}
html.pmod-on,html.pmod-on body{overflow:hidden}
/* the button that opens it, so it matches the ghost buttons beside it */
.pkg-open{cursor:pointer}
@media (max-width:600px){
  .aa-book-price{margin-left:var(--gutter);margin-right:var(--gutter);
    padding:1.4rem 1.1rem 1.3rem}
  .aa-book-pay{padding-left:1rem;padding-right:1rem;
    font-size:.625rem;letter-spacing:.06em}
}

/* ---- cookie consent bar --------------------------------------------------
   Pinned to the TOP, and the page is pushed down by its height rather than the
   bar being floated over the page.

   The old bar was bottom-anchored with `bottom:14px`, which meant the shorter
   the viewport the higher it rode. Measured on the live page: at 390x699 it
   covered the player's play button, at 375x640 by 82px, at 375x600 by 122px.
   Only a plain 390x844 Safari window escaped it, which is why nobody caught
   this by looking. 76% of the traffic arrives in the Instagram in-app browser,
   so for three visitors in four the first thing on top of the play button was a
   cookie card. That is the whole explanation for a poster tapped 1.94 times per
   session and for 12 accepts out of 164.

   Top-pinned and in-flow it cannot cover anything, at any height, ever. */
.cbar{
  position:fixed;top:0;left:0;right:0;z-index:150;
  display:none;align-items:center;gap:12px;
  min-height:44px;padding:6px 14px;
  background:#fff;border-bottom:1px solid rgba(15,29,48,.12);
  box-shadow:0 6px 18px rgba(11,23,40,.06);
}
/* Shown by the class the <head> script sets before first paint, so a visitor
   who has already decided never sees a flash and the layout never shifts. No
   JS at all (a crawler) means no class, which means no bar. */
html.cbar-on .cbar{display:flex}
html.cbar-on body{padding-top:56px}
.cbar p{margin:0;flex:1 1 auto;min-width:0;font-size:12.5px;line-height:1.35;
  color:var(--aa-copy-light)}
.cbar-btns{display:flex;gap:8px;flex:none}
.cbar-yes,.cbar-no{
  font:inherit;font-size:12.5px;font-weight:600;cursor:pointer;
  padding:0 15px;height:32px;border-radius:999px;border:1px solid transparent;
  white-space:nowrap;
}
.cbar-yes{background:var(--aa-blue);color:#fff}
.cbar-no{background:#fff;color:var(--aa-ink-soft);border-color:rgba(15,29,48,.16)}
@media(max-width:400px){
  .cbar{gap:8px;padding:6px 10px}
  .cbar p{font-size:12px}
  .cbar-yes,.cbar-no{padding:0 12px;font-size:12px}
}

/* ---- the qualifier card --------------------------------------------------
   Centred, one question at a time, and every answer a FULL WIDTH stacked
   button. Never a horizontal chip row and never wrapping chips: a row of small
   chips is a tag picker, and this is a question with answers.
--------------------------------------------------------------------------- */
.booking-card.qual{
  max-width:640px;margin:0 auto;padding:40px;
  display:flex;flex-direction:column;
}
.qual-head{text-align:center}
.qual-h{font-family:var(--display);font-weight:800;font-size:28px;line-height:1.14;
  letter-spacing:var(--display-track);color:#0B1220;margin:0}
.qual-sub{margin:10px 0 0;font-size:15px;line-height:1.5;color:var(--aa-copy);
  font-weight:400}

/* Seven segments, full width, 6px gaps. The calendar is step 8 and fills all
   of them: it is the reward, not an eighth thing to get through. */
.qual-bar{display:flex;gap:6px;margin:26px 0 0;width:100%}
.qual-bar i{flex:1;height:5px;border-radius:3px;background:var(--aa-blue-soft);
  transition:background .25s ease}
.qual-bar i.on{background:var(--aa-blue)}

.qual-body{margin-top:30px}
/* Left aligned, not centred: it is a question being asked, and the answers
   under it are left aligned too. */
.qual-q{font-family:var(--sans);font-weight:700;font-size:20px;line-height:1.35;
  letter-spacing:-.01em;color:#0B1220;margin:0 0 6px;text-align:left}
.qual-note{margin:0 0 18px;font-size:14.5px;line-height:1.5;color:var(--aa-copy);
  text-align:left}
.qual-q + .qual-chips,.qual-q + .qual-field{margin-top:18px}
/* ---- the two-field step (name + mobile) ---------------------------------
   Stacked, not side by side: two half-width boxes on a 390 phone are two
   boxes nobody can type a name into. Each one is labelled above itself,
   because two unlabelled inputs in a column is a guess, and the label is the
   only thing that tells them apart before the keyboard is up. */
/* ---- the trade type-ahead ------------------------------------------------
   The same full-width rows the chips were, so a tap is a tap and the step
   does not suddenly behave differently from the four that follow it. Shorter
   than a chip (52 against 64) because there can be eight of them and the card
   still has to fit a phone without becoming a scroller.

   NOT a <datalist>: that renders as a native dropdown which ignores the
   card's styling completely and behaves differently in every browser. */
.qual-sugg{display:flex;flex-direction:column;gap:8px;margin-top:10px}
.qual-sugg-o{
  display:flex;align-items:center;width:100%;height:52px;padding:0 20px;
  border:1px solid #D6DEEA;border-radius:14px;background:#fff;
  font:500 16px/1 var(--sans);color:var(--aa-ink);text-align:left;
  cursor:pointer;-webkit-tap-highlight-color:transparent;
  transition:border-color .12s ease,background .12s ease,color .12s ease;
}
.qual-sugg-o:hover,.qual-sugg-o.hi{border-color:var(--aa-blue);color:var(--aa-blue)}
.qual-sugg-o.on{border-color:var(--aa-blue);background:var(--aa-blue);color:#fff}
/* "Use "sparky"" - the way out for a trade the list has never heard of. Quiet,
   because it is a fallback and not one of the answers. */
.qual-sugg-o.own{color:var(--aa-copy);font-style:normal}
.qual-sugg-o.own:hover{color:var(--aa-blue)}

/* The box "Yes" opens on the Google question. Hidden until then, so the step
   opens as a plain two-chip question and does not look like a form. */
.qual-reveal{display:none;margin-top:14px}
.qual-reveal.on{display:block}
/* The file control. The real <input type=file> is off screen and the label is
   the button, because the native control cannot be styled and renders as a
   different website inside this card. */
.qual-file-in{position:absolute;left:-9999px;width:1px;height:1px;opacity:0}
.qual-file-btn{
  display:flex;align-items:center;justify-content:center;width:100%;height:56px;
  border:1.5px dashed #C3CFDF;border-radius:14px;background:#fff;
  font:600 15px/1 var(--sans);color:var(--aa-blue);cursor:pointer;
  -webkit-tap-highlight-color:transparent;
}
.qual-file-btn:hover{border-color:var(--aa-blue);background:var(--aa-blue-soft)}
.qual-file-msg{margin:8px 0 0;font-size:13px;color:var(--aa-copy)}
.qual-file-msg.ok{color:var(--aa-blue);font-weight:600}
.qual-file-msg.bad{color:#C6283C}

/* ---- skip the call ------------------------------------------------------
   The quiet route past the booking, under the text-us line. A panel rather
   than a third button, because the call IS the default here and this must not
   compete with "Book my free preview" - it is for the people who are already
   sure, and it says where the link goes before they click it. */
.qual-skip{margin-top:18px;padding:16px;border-radius:14px;
  border:1px solid var(--aa-border);background:rgba(36,107,253,.035);
  text-align:center}
.qual-skip-h{margin:0;font:700 14px/1.35 var(--sans);color:var(--aa-ink)}
.qual-skip-p{margin:6px 0 0;font-size:12.5px;line-height:1.5;color:var(--aa-copy)}
.qual-skip-go{display:inline-block;margin-top:11px;font:600 13.5px/1 var(--sans);
  color:var(--aa-blue);text-decoration:underline;text-underline-offset:3px}

.qual-pair-f + .qual-pair-f{margin-top:14px}
.qual-lab{display:block;margin:0 0 7px;font:600 13px/1.2 var(--sans);
  color:var(--aa-copy);letter-spacing:.005em}
.qual-fine{margin:14px 0 0;font-size:12.5px;line-height:1.45;
  color:var(--aa-copy-light);text-align:left}
.qual-err{margin:12px 0 0;font-size:13.5px;color:#C6283C;text-align:left;
  display:none}
.qual-err.on{display:block}

/* ---- answers: one per line, full width, 64px tall ----------------------- */
.qual-chips{display:flex;flex-direction:column;gap:12px}
.qual-chip{
  position:relative;overflow:hidden;
  display:flex;align-items:center;
  width:100%;height:64px;padding:0 20px;
  border:1px solid #D6DEEA;border-radius:14px;background:#fff;
  color:#0B1220;font:500 17px/1.3 var(--sans);text-align:left;
  cursor:pointer;-webkit-tap-highlight-color:transparent;
  transition:border-color .18s ease,color .18s ease;
}
.qual-chip:hover,.qual-chip:focus-visible{border-color:var(--aa-blue);color:var(--aa-blue)}
.qual-chip .fill{position:absolute;inset:0;background:var(--aa-blue-soft);
  transform:scaleX(0);transform-origin:left;z-index:0}
.qual-chip.on{border-color:var(--aa-blue);color:var(--aa-blue)}
.qual-chip.on .fill{transform:scaleX(1);transition:transform .15s linear}
.qual-chip span:last-child{position:relative;z-index:1}

/* ---- text steps: one input, then Back link + Continue button ------------- */
.qual-field input{
  width:100%;height:60px;padding:0 20px;
  border:1px solid #D6DEEA;border-radius:14px;background:#fff;
  color:#0B1220;font:500 17px/1 var(--sans);
}
.qual-field input::placeholder{color:var(--aa-copy-light);font-weight:400}
.qual-field input:focus{outline:none;border-color:var(--aa-blue);
  box-shadow:0 0 0 3px var(--aa-blue-soft)}
.qual-field input[aria-invalid="true"]{border-color:#C6283C}

/* Back sits on the left as an underlined grey link and Continue fills what is
   left of the row, which is the lv-4..lv-7 arrangement. */
.qual-actions{display:flex;align-items:center;gap:18px;margin-top:20px}
/* Step 8 puts the book button inside the slot box, so this row carries
   nothing but Back: bottom left, its own row, 16px clear of the text-us
   line above it. */
#slotbox ~ .qual-actions{margin-top:16px}
.qual-back{
  flex:none;padding:0;border:0;background:none;
  color:var(--aa-copy);font:400 15px/1 var(--sans);
  text-decoration:underline;text-underline-offset:3px;cursor:pointer;
}
.qual-back[hidden]{display:none}
.qual-go{flex:1;width:100%;display:flex;height:60px;margin:0;
  border-radius:14px;white-space:nowrap}
/* On step 8 the button follows the slot grid rather than sitting in a row of
   its own, so it needs the gap the .qual-actions row would have given it. */
#bk-go{margin-top:18px}

/* The honeypot. Off screen rather than display:none, because a bot that reads
   computed style skips a hidden field and fills a visible one. */
.qz-hp{position:absolute;left:-9999px;width:1px;height:1px;opacity:0}
.btn-primary.qz-busy{opacity:.72;pointer-events:none}
/* The embedded /setup wizard. It posts its own height out and the card grows
   to it, so the wizard never scrolls inside a box of its own. */
.setup-frame{display:block;width:100%;border:0;border-radius:14px}

/* ---- step 8: the day strip and the slots -------------------------------- */
.qual-info{display:flex;justify-content:center;gap:10px;margin:0 0 18px;
  font-size:13px;color:var(--aa-copy)}
.qual-info b{color:var(--aa-ink);font-weight:600}
/* A rolling ten days, scrolled sideways, rather than a month grid whose every
   cell but two was a greyed out number. */
.daystrip{display:flex;gap:8px;overflow-x:auto;padding:2px 2px 8px;
  -webkit-overflow-scrolling:touch;scrollbar-width:none}
.daystrip::-webkit-scrollbar{display:none}
.day{flex:0 0 auto;width:62px;padding:10px 0;border:1.5px solid #DCE3EC;
  border-radius:14px;background:#fff;cursor:pointer;text-align:center;
  -webkit-tap-highlight-color:transparent}
.day u{display:block;font:600 11px/1 var(--sans);text-decoration:none;
  letter-spacing:.06em;text-transform:uppercase;color:var(--aa-copy-light)}
.day b{display:block;margin-top:5px;font:700 18px/1 var(--sans);color:var(--aa-ink)}
.day.on{border-color:var(--aa-blue);background:var(--aa-blue-soft)}
.day.on u,.day.on b{color:var(--aa-blue)}
.day[disabled]{opacity:.38;cursor:default}
/* "Available times", then the grid. Three across on desktop and two on a
   phone, and NO scrolling container: thirteen hourly slots is a tall grid and
   the card is allowed to grow to it. A box that scrolls inside a page that
   scrolls is how a visitor misses the 8pm they would have taken. */
.slots-h{margin:18px 0 10px;font:700 15px/1.3 var(--sans);color:var(--aa-ink);
  text-align:left}
.qual-slots{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-top:0}
.qual-slots .slot{height:48px;border:1.5px solid #DCE3EC;border-radius:13px;
  background:#fff;color:var(--aa-blue);font:600 15px/1 var(--sans);cursor:pointer;
  -webkit-tap-highlight-color:transparent}
.qual-slots .slot.on{border-color:var(--aa-blue);background:var(--aa-blue);color:#fff}
/* The way out for somebody who cannot make any of the free times. Grey and quiet:
   it is an escape hatch, not a second call to action. */
.qual-sms{margin:14px 0 0;font-size:12.5px;line-height:1.5;
  color:var(--aa-copy-light);text-align:center}
.qual-sms a{color:var(--aa-copy);text-decoration:underline}

@media(max-width:760px){
  .booking-card.qual{max-width:none;margin:0 16px;padding:24px}
  .qual-h{font-size:24px}
  .qual-body{margin-top:24px}
  .qual-bar{margin-top:22px}
  .qual-chip{height:64px;font-size:17px;padding:0 20px}
  .qual-slots{grid-template-columns:1fr 1fr}
  .qual-actions{gap:14px}
  .qual-go{height:56px}
  .qual-field input{height:60px}
}

/* ---- the player, unlocked from the start -------------------------------- */
.video{position:relative;border-radius:18px;overflow:hidden;cursor:pointer;
  -webkit-tap-highlight-color:transparent}
.video[data-playing="1"]{cursor:default}
.play{position:absolute;inset:0;display:flex;align-items:center;
  justify-content:center;pointer-events:none;transition:opacity .2s ease}
.video[data-playing="1"] .play{opacity:0}
.play-badge{display:flex;align-items:center;justify-content:center;
  width:74px;height:74px;border-radius:50%;background:#fff;
  box-shadow:0 8px 28px rgba(12,20,36,.28)}
.play-badge svg{width:30px;height:30px;margin-left:3px;fill:var(--aa-blue);
  stroke:none}

/* ---- sticky book bar, phones only ---------------------------------------
   Appears when the gate clears, which is the moment somebody has actually
   watched something and a call means anything. It hides itself whenever the
   player is on screen and running, so it can never sit over the controls. */
.bookbar{
  position:fixed;left:0;right:0;bottom:0;z-index:140;display:none;
  padding:10px 14px calc(10px + env(safe-area-inset-bottom,0px));
  background:rgba(255,255,255,.96);backdrop-filter:blur(8px);
  border-top:1px solid rgba(15,29,48,.10);
  box-shadow:0 -6px 22px rgba(11,23,40,.08);
  transform:translateY(110%);transition:transform 220ms ease;
}
.bookbar button{width:100%;height:50px;font-size:14px}
.bookbar.on{display:block;transform:translateY(0)}
.bookbar.hide{transform:translateY(110%)}
@media(min-width:761px){.bookbar{display:none!important}}

/* ---- booking card, live states ------------------------------------------ */
.cal td span.off{color:#D3D9E1;cursor:not-allowed}
.slots-empty{font-size:13px;color:var(--aa-copy);padding:10px 0}
.bk-form{display:grid;gap:10px;margin-top:14px}
.bk-form .qz-field{margin-top:0}
.bk-row{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.bk-msg{font-size:12.5px;margin-top:9px;display:none}
.bk-msg.on{display:block}
.bk-msg.bad{color:#C2405A}
.bk-done{padding:6px 0}
.bk-done b{
  display:block;font-family:var(--serif);font-size:21px;font-weight:600;
  letter-spacing:-.015em;color:var(--aa-ink);line-height:1.15;
}
.bk-done p{font-size:13.5px;color:var(--aa-copy);margin-top:7px}
.bk-tick{
  width:34px;height:34px;border-radius:50%;background:var(--aa-green-soft);
  display:grid;place-items:center;margin-bottom:11px;
}
.bk-tick svg{width:16px;height:16px;stroke:var(--aa-green);fill:none;stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round}

/* ---- the card under the confirmation ------------------------------------
   The preview offer. Same card language as everything else on this page, one
   step down in weight so it reads as the next thing rather than a second
   headline. */
.bk-next{
  margin-top:16px;padding:16px 16px 14px;border-radius:16px;
  background:var(--aa-blue-soft);border:1px solid var(--aa-blue-mist);
}
.bk-next b{
  display:block;font-family:var(--serif);font-size:17px;font-weight:600;
  letter-spacing:-.015em;color:var(--aa-ink);line-height:1.2;
}
.bk-next p{font-size:13px;line-height:1.5;color:var(--aa-copy);margin-top:6px}
.bk-next .slots-cta{margin-top:12px;text-decoration:none;display:flex;
  align-items:center;justify-content:center}
.bk-later{
  display:block;width:100%;margin-top:9px;padding:8px 0;
  background:none;border:0;cursor:pointer;
  font:inherit;font-size:12.5px;font-weight:600;color:var(--aa-copy);
  text-decoration:underline;text-underline-offset:2px;
}
.bk-later[disabled]{opacity:.6;cursor:default;text-decoration:none}
.bk-later-msg{font-size:12px;color:var(--aa-copy);margin-top:2px;text-align:center}
.bk-sms{font-size:12.5px;color:var(--aa-copy);margin-top:10px;text-align:center}
.bk-sms a{color:var(--aa-blue);font-weight:600;text-decoration:underline;
  text-underline-offset:2px}

/* ---- intake: logo drop, colour swatches, area chips --------------------- */
.qz-drop{
  border:1.5px dashed var(--aa-blue-mist);border-radius:14px;background:var(--aa-blue-soft);
  padding:22px 16px;text-align:center;cursor:pointer;transition:border-color 140ms ease;
}
.qz-drop:hover,.qz-drop.over{border-color:var(--aa-blue)}
.qz-drop b{display:block;font-size:14px;font-weight:650;color:var(--aa-ink)}
.qz-drop span{display:block;font-size:12px;color:var(--aa-copy);margin-top:4px}
.qz-drop input{display:none}
.qz-logo{display:flex;align-items:center;gap:12px;margin-top:12px}
.qz-logo img{
  width:64px;height:64px;object-fit:contain;border-radius:10px;
  border:1px solid var(--aa-border);background:#fff;padding:5px;flex:none;
}
.qz-logo b{font-size:13px;font-weight:600;display:block}
.qz-logo span{font-size:12px;color:var(--aa-copy)}
.qz-sw{display:flex;flex-wrap:wrap;gap:9px}
.qz-sw button{
  width:44px;height:44px;border-radius:12px;border:2px solid transparent;
  position:relative;box-shadow:inset 0 0 0 1px rgba(14,29,48,.10);
}
.qz-sw button.on{border-color:var(--aa-ink);box-shadow:inset 0 0 0 1px rgba(14,29,48,.10),0 0 0 2px #fff inset}
.qz-sw button.on:after{
  content:"";position:absolute;inset:0;margin:auto;width:13px;height:7px;
  border-left:2.5px solid #fff;border-bottom:2.5px solid #fff;transform:rotate(-45deg);
  filter:drop-shadow(0 0 1px rgba(0,0,0,.45));
}
.qz-swhead{font-size:12px;font-weight:600;color:var(--aa-ink);margin:14px 0 7px}
.qz-picked{display:flex;gap:7px;align-items:center;margin-top:12px;font-size:12px;color:var(--aa-copy)}
.qz-picked i{width:20px;height:20px;border-radius:6px;display:block;box-shadow:inset 0 0 0 1px rgba(14,29,48,.12)}
.qz-area{display:flex;flex-wrap:wrap;gap:7px;margin-top:10px}
.qz-area button{
  border:1px solid var(--aa-border-strong);background:#fff;border-radius:999px;
  padding:0 13px;height:34px;font-size:12.5px;color:var(--aa-ink);
}
.qz-area button.on{background:var(--aa-blue);border-color:var(--aa-blue);color:#fff}
.qz-scroll{max-height:46vh;overflow-y:auto;margin:0 -4px;padding:0 4px}

/* Centred on a phone too. `padding:16px` on .qz is what makes the card full
   width minus 16px a side; the card keeps its 22px radius on all four corners
   and its own shadow, exactly as the booking card has. */
@media(max-width:760px){
  .qz-card{padding:20px 18px 16px}
  .qz-q{font-size:22px}
  .bk-row{grid-template-columns:1fr}
}
/* A short in-app viewport is the common case here, not the edge case: the card
   scrolls inside itself rather than pushing its own buttons off the screen. */
@media(max-height:620px){
  .qz-card{max-height:calc(100vh - 32px);overflow-y:auto}
  .qz-q{font-size:20px;margin-bottom:12px}
  .qz-chip{min-height:42px}
}
@media(prefers-reduced-motion:reduce){
  .qz-dots i{transition:none}
  .qz-chip.on:after,.qz-end .qz-tick,.qz-end .qz-tick svg{animation:none;opacity:1;
    transform:none;stroke-dashoffset:0}
}

/* The consent line under every enquiry form (2026-10-28). The form
   collects a name, an email and a phone number, so the page it sits on
   has to say where they go and link the policy that says it. */
.form-privacy-note{margin:12px 0 0;font-size:12.5px;line-height:1.5;
  opacity:.78}
.form-privacy-note a{color:inherit;text-decoration:underline;
  text-underline-offset:2px}
