/* ============================================================
   Plainly — window cleaning

   One building, thirteen storeys, fixed behind the page. A rope-
   access cleaner hangs at a fixed point on screen and the building
   scrolls up past him. Above his line the glass is clean, below it
   is not. Scrolling is the cleaning.
   ============================================================ */

@property --ss{ syntax:"<number>"; inherits:false; initial-value:0.4; }

:root{
  --ink:        #0d1420;
  --paper:      #f6fafe;
  --paper-dim:  #d3e0ec;
  --paper-mute: #93a8bc;

  --line:       rgba(255,255,255,.22);
  --line-soft:  rgba(255,255,255,.13);

  --sun:        #ffd08a;
  --glass-tint: #bfe0f5;

  --sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --serif: "Instrument Serif", Georgia, "Times New Roman", serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  --gut: clamp(22px, 5vw, 82px);
  --ease: cubic-bezier(.22,.61,.36,1);

  /* the rig — where he works. --cx, --cy and --dirt are written by app.js.
     The three cutouts are 580x1200: him on a suspended deck, the two
     cables running from the deck's ends out of the top. Helmet at row
     350, harness belt at row 690, underside of the deck at row 1163. */
  --cx:   64vw;              /* his centre line across the screen */
  --ch:   34svh;             /* helmet to the underside of the deck */
  --ci:   calc(var(--ch) * 1.476);   /* the cutout's height */
  --cw:   calc(var(--ci) * .4833);   /* the cutout's width */
  --cy:   47svh;             /* his waist — the clean/dirty line */
  --dirt: 47svh;             /* top of the dirty layer, latched */
  --hero: 0;                 /* kept for the fade hooks; there is no separate establishing shot any more */
  --wet:  0;                 /* 1 while scrolling, decays to 0 when still — written by app.js */
  --split: 50%;              /* the before/after line on the compare floor */
  --night: 0;                /* 0 dusk, 1 night — written by app.js */
}

*,*::before,*::after{ box-sizing:border-box; }
html{ scroll-behavior:smooth; -webkit-text-size-adjust:100%; }

body{
  margin:0;
  background:var(--ink);
  color:var(--paper);
  font-family:var(--sans);
  font-weight:300;
  font-size:clamp(15px,1.05vw,17px);
  line-height:1.6;
  overflow-x:hidden;
  -webkit-font-smoothing:antialiased;
}

a{ color:inherit; }

/* ============================================================
   THE LOADING SCREEN
   ============================================================ */
body.is-loading{ overflow:hidden; }
.loader{
  position:fixed; inset:0; z-index:900;
  background:var(--ink);
  display:grid; place-items:center;
}
.loader__inner{ display:flex; flex-direction:column; align-items:center; gap:22px; color:#fff; }
.loader .mark{ font-size:15px; }
.loader__line{
  margin:0; width:160px; height:1px; background:rgba(255,255,255,.14); position:relative; overflow:hidden;
}
.loader__line i{
  position:absolute; left:0; top:0; bottom:0; width:0;
  background:var(--sun);
  transition:width .35s var(--ease);
}
.loader__txt{
  margin:0; font-size:10px; letter-spacing:.3em; text-transform:uppercase;
  color:rgba(255,255,255,.5);
}
/* the squeegee pass: the screen is clipped away from the left, with a
   bright wet edge running just ahead of the clip */
.loader__edge{
  position:absolute; top:0; bottom:0; left:0; width:3px;
  background:#fff; box-shadow:0 0 18px rgba(255,255,255,.8), 0 0 50px rgba(190,220,255,.5);
  opacity:0;
}
.loader.is-done{ animation:squeegee .95s cubic-bezier(.6,0,.3,1) forwards; }
.loader.is-done .loader__inner{ transition:opacity .25s var(--ease); opacity:0; }
.loader.is-done .loader__edge{ opacity:1; animation:squeegee-edge .95s cubic-bezier(.6,0,.3,1) forwards; }
@keyframes squeegee{ from{ clip-path:inset(0 0 0 0); } to{ clip-path:inset(0 0 0 100%); } }
@keyframes squeegee-edge{ from{ transform:translateX(0); } to{ transform:translateX(100vw); } }
.loader.is-gone{ display:none; }
@media (prefers-reduced-motion:reduce){
  .loader.is-done{ animation:none; opacity:0; transition:opacity .3s; }
  .loader.is-done .loader__edge{ animation:none; opacity:0; }
}

.skip{ position:absolute; left:-9999px; top:0; z-index:1000; background:var(--sun); color:var(--ink); padding:12px 18px; font-size:13px; }
.skip:focus{ left:12px; top:12px; }
:focus-visible{ outline:2px solid var(--sun); outline-offset:3px; }

/* ============================================================
   THE BUILDING
   Geometry is owned by app.js — it writes --tw and --ty so each
   storey of the photograph is centred in its own section.
   ============================================================ */

.tower{
  position:fixed; inset:0;
  background-image:url("img/tower.webp?v=2026-09-03");
  background-repeat:no-repeat;
  background-size:var(--tw, 165vh) auto;
  background-position:50% var(--ty, 0px);
  background-color:var(--ink);
}
.tower--clean{ z-index:0; }
.tower--dirty{
  z-index:1;
  background-image:url("img/tower-dirty.webp?v=2026-09-03");
  clip-path:inset(var(--dirt) 0 0 0);
  transition:opacity .5s var(--ease);
}
body.is-clean .tower--dirty{ opacity:0; }
/* on the wipe floor the canvas draws the dirty layer instead, so the
   pointer can erase it */
body.is-wiping .tower--dirty{ opacity:0; }
/* on the compare floor the split is a vertical line you drag, whatever
   he has done so far */
body.is-comparing .tower--dirty{
  opacity:1;
  clip-path:inset(0 calc(100% - var(--split)) 0 0);
}
body.is-comparing .edge, body.is-comparing .drips{ opacity:0; }

/* ============================================================
   THE EVENING — a multiply tint over the building. Sky and concrete go
   to night; the lit rooms stay lit because they are bright underneath.
   ============================================================ */
.night{
  position:fixed; inset:0; z-index:2;
  background:linear-gradient(180deg, #16204a, #2a3560 55%, #3a3550);
  mix-blend-mode:multiply;
  opacity:calc(var(--night) * .82);
  pointer-events:none;
}
.rig{ filter:brightness(calc(1 - .42 * var(--night))); }
/* his helmet lamp, only at night */
.man::after{
  content:""; position:absolute; left:14%; top:14%; width:72%; height:30%;
  background:radial-gradient(ellipse at 50% 42%, rgba(255,226,160,.6), rgba(255,226,160,0) 62%);
  mix-blend-mode:screen; opacity:var(--night); pointer-events:none;
}

/* the wet edge — a bright line where he has just been, a sheen above it */
.edge{
  position:fixed; z-index:3; left:0; right:0;
  top:var(--dirt); height:0;
  opacity:calc(1 - var(--hero));
  pointer-events:none;
  transition:opacity .5s var(--ease);
}
.edge::before{
  content:""; position:absolute; left:0; right:0; top:-1px; height:3px;
  background:linear-gradient(90deg, rgba(255,255,255,.55), rgba(255,255,255,.95) 40%, rgba(255,255,255,.95) 60%, rgba(255,255,255,.55));
  box-shadow:0 0 18px rgba(255,255,255,.7), 0 0 44px rgba(190,220,255,.45);
  opacity:calc(.7 + .3 * var(--wet));
}
/* the sheen above the line is the glass still wet from the blade — it
   brightens while you scroll (he is working) and settles when you stop */
.edge::after{
  content:""; position:absolute; left:0; right:0; bottom:1px; height:min(11vh,110px);
  background:linear-gradient(0deg, rgba(255,255,255,.26), rgba(255,255,255,0));
  opacity:calc(.4 + .6 * var(--wet));
}
body.is-clean .edge{ opacity:0; }

/* ============================================================
   THE CLEANER
   ============================================================ */

.rig{
  position:fixed; z-index:5; top:0; bottom:0;
  left:var(--cx); width:0;
  opacity:calc(1 - var(--hero));
  pointer-events:none;
  transition:opacity .5s var(--ease);
}
/* the two suspension cables in the photograph run from the deck to the
   top of the cutout; these carry them on to the top of the window, meeting
   the photographed cable where it leaves the frame. Nothing hangs below
   the deck. */
.rope{ position:absolute; left:0; top:0; bottom:0; width:0; }
.rope::before{
  content:""; position:absolute; width:2px;
  top:0; height:calc(var(--cy) - .575 * var(--ci) + 1px);
  background:rgba(214,220,228,.7);
  box-shadow:1px 0 0 rgba(0,0,0,.3);
}
.rope--a::before{ left:calc(-.4026 * var(--cw)); }
.rope--b::before{ left:calc( .3957 * var(--cw)); }
/* he does not move; the world around him does. The whole rig swings a
   degree either way from the top of the ropes, his shadow drifts on the
   glass, water runs down from the line and the blade glistens. */
.swing{
  position:absolute; inset:0;
  transform-origin:50% 0;
  animation:sway 7.5s cubic-bezier(.45,0,.55,1) infinite alternate;
}
@keyframes sway{
  0%  { transform:rotate(-1.05deg) translateY(0); }
  50% { transform:rotate(0deg)     translateY(4px); }
  100%{ transform:rotate(1.05deg)  translateY(0); }
}
.man{
  position:absolute; left:0; top:var(--cy);
  width:var(--cw); height:var(--ci);
  transform:translate(-50%, -57.5%);
  will-change:top;
}
.man .cleaner, .man .shadow{ position:absolute; inset:0; width:100%; height:100%; }
/* three strokes of the same man; app.js picks one per half-storey and
   the swap is a quick cut, not a dissolve, so arms never double up */
.man .cleaner{ opacity:0; transition:opacity .18s var(--ease); }
.man.pose-0 .cleaner--0, .man.pose-1 .cleaner--1, .man.pose-2 .cleaner--2, .man.pose-3 .cleaner--3{ opacity:1; }

/* ============================================================
   THE TALLY
   ============================================================ */
.tally{
  position:fixed; z-index:400; left:var(--gut); bottom:clamp(18px,3vh,30px);
  margin:0; display:flex; align-items:center; gap:10px;
  font-family:var(--mono); font-size:10.5px; letter-spacing:.18em; text-transform:uppercase;
  color:rgba(255,255,255,.72); text-shadow:0 1px 10px rgba(0,0,0,.9);
  pointer-events:none;
}
.tally b{ font-weight:400; color:var(--sun); font-variant-numeric:tabular-nums; }
.tally i{ width:18px; height:1px; background:currentColor; opacity:.5; }
.storey--ground ~ .tally, body.is-clean .tally{ color:rgba(255,255,255,.9); }
@media (max-width:760px){ .tally{ display:none; } }
.again{ margin:22px 0 0; }
.man .shadow{
  filter:brightness(0) blur(9px);
  opacity:.5;
  animation:shadowdrift 7.5s cubic-bezier(.45,0,.55,1) infinite alternate;
}
@keyframes shadowdrift{
  0%  { transform:translate(8px, 18px); }
  100%{ transform:translate(20px, 26px); }
}
.drips{
  position:fixed; z-index:3;
  left:calc(var(--cx) - 14vw); width:28vw;
  top:var(--dirt); height:32vh; overflow:hidden;
  pointer-events:none;
  opacity:calc((1 - var(--hero)) * (.55 + .45 * var(--wet)));
  transition:opacity .4s var(--ease);
}
body.is-clean .drips{ opacity:0; }
.drips i{
  position:absolute; top:-140px; left:var(--x);
  width:2px; height:140px; border-radius:2px;
  background:linear-gradient(180deg, rgba(255,255,255,0), rgba(255,255,255,.5) 70%, rgba(255,255,255,.95));
  box-shadow:0 0 6px rgba(255,255,255,.35);
  animation:drip var(--d) linear infinite;
  animation-delay:var(--dl);
}
@keyframes drip{
  0%  { transform:translateY(0); opacity:0; }
  12% { opacity:.85; }
  100%{ transform:translateY(calc(32vh + 160px)); opacity:0; }
}
.drips i:nth-child(1){ --x:22%; --d:4.6s; --dl:-1.2s; }
.drips i:nth-child(2){ --x:36%; --d:6.8s; --dl:-4s;   height:90px; }
.drips i:nth-child(3){ --x:45%; --d:3.9s; --dl:-2.6s; }
.drips i:nth-child(4){ --x:52%; --d:5.7s; --dl:-.4s;  height:200px; }
.drips i:nth-child(5){ --x:60%; --d:4.3s; --dl:-3.3s; }
.drips i:nth-child(6){ --x:69%; --d:7.4s; --dl:-5.1s; height:80px; }
.drips i:nth-child(7){ --x:80%; --d:5.1s; --dl:-1.9s; }
.drips i:nth-child(8){ --x:10%; --d:8.2s; --dl:-6s;   height:60px; }

/* ============================================================
   THE WIPE — a canvas of grime, live on one floor only
   ============================================================ */

.glass{
  position:fixed; inset:0; z-index:3;
  width:100%; height:100%;
  opacity:0; pointer-events:none;
  transition:opacity .6s var(--ease);
  touch-action:pan-y;
}
body.is-wiping .glass{ opacity:1; pointer-events:auto; cursor:none; }
@media (hover:none){ body.is-wiping .glass{ cursor:auto; } }

.squeegee{
  position:fixed; z-index:8; left:0; top:0;
  width:132px; height:15px; margin:-7px 0 0 -66px;
  --sx:0px; --sy:0px; --ss:.4;
  transform:translate(var(--sx), var(--sy)) rotate(-5deg) scale(var(--ss));
  opacity:0; pointer-events:none;
  transition:opacity .3s var(--ease), --ss .3s var(--ease);
}
.squeegee i{
  position:absolute; inset:0; border-radius:3px;
  background:linear-gradient(180deg, rgba(255,252,244,.95), rgba(206,222,238,.85) 42%, rgba(64,80,102,.92));
  box-shadow:0 6px 22px rgba(0,0,0,.45), inset 0 1px 0 rgba(255,255,255,.95);
}
.squeegee i::after{
  content:""; position:absolute; left:5px; right:5px; bottom:-6px; height:6px;
  border-radius:0 0 3px 3px;
  background:linear-gradient(180deg, rgba(26,36,50,.95), rgba(26,36,50,.5));
}
.squeegee::before{
  content:""; position:absolute; left:50%; bottom:100%; width:16px; height:32px;
  margin-left:-8px; border-radius:4px 4px 2px 2px;
  background:linear-gradient(180deg, var(--sun), rgba(168,124,52,.9));
  box-shadow:0 3px 12px rgba(0,0,0,.4);
}
.squeegee.is-on{ opacity:1; --ss:1; }
@media (hover:none){ .squeegee{ display:none; } }

/* ============================================================
   THE COMPARE LINE — live on the living-room floor only
   ============================================================ */

.compare{
  position:fixed; inset:0; z-index:4;
  opacity:0; pointer-events:none;
  transition:opacity .55s var(--ease);
}
body.is-comparing .compare{ opacity:1; }
body.is-comparing .compare__handle{ pointer-events:auto; }
.compare__handle{
  position:absolute; top:0; bottom:0; left:var(--split);
  width:2px; margin-left:-1px;
  background:rgba(255,252,244,.95);
  box-shadow:0 0 34px rgba(255,220,160,.5);
  cursor:ew-resize;
  touch-action:none;
}
.compare__grip{
  position:absolute; top:50%; left:50%;
  width:60px; height:60px; margin:-30px 0 0 -30px;
  border-radius:50%;
  background:rgba(255,255,255,.14);
  border:1px solid rgba(255,255,255,.55);
  backdrop-filter:blur(10px); -webkit-backdrop-filter:blur(10px);
  display:grid; place-items:center;
}
.compare__grip::before{ content:"‹ ›"; font-size:17px; letter-spacing:.16em; color:#fff; }
.compare__tag{
  position:absolute; bottom:32px;
  font-size:10px; letter-spacing:.26em; text-transform:uppercase;
  color:rgba(255,255,255,.92); text-shadow:0 2px 14px rgba(0,0,0,.85);
}
.compare__tag--l{ left:var(--gut); }
.compare__tag--r{ right:var(--gut); }

/* ============================================================
   TOP BAR — ink on the sky, paper on the building
   ============================================================ */

.top{
  position:fixed; z-index:500; left:0; right:0; top:0;
  display:flex; align-items:center; justify-content:space-between; gap:24px;
  padding:clamp(14px,2.2vh,24px) var(--gut);
  color:#171a21;
  transition:color .5s var(--ease);
}
body.past-hero .top{ color:#fff; }
.top ul{ display:flex; align-items:center; gap:clamp(14px,2.2vw,34px); list-style:none; margin:0; padding:0; }
.top a{
  text-decoration:none; font-size:12px; letter-spacing:.18em; text-transform:uppercase;
  color:inherit; transition:color .3s var(--ease), opacity .3s var(--ease);
}
.top a:hover{ opacity:.6; }
.top__cta{
  border:1px solid currentColor; padding:8px 16px; border-radius:2px;
}
.top__cta:hover{ opacity:1 !important; background:var(--sun); border-color:var(--sun); color:#1e1608 !important; }
body.past-hero .top a{ text-shadow:0 1px 14px rgba(10,20,40,.6); }

.mark{
  display:inline-flex; text-decoration:none;
  border:1px solid currentColor;
  font-size:13px; line-height:1; letter-spacing:.02em; font-weight:400;
  color:inherit;
}
.mark span{ padding:6px 7px 7px; border-right:1px solid currentColor; }
.mark span:last-child{ border-right:0; }
.mark--sm{ font-size:11px; }
/* the mark sits over the dark side of the establishing shot, so it is
   always paper, whatever the links are doing */
.top .mark{ color:#fff; text-shadow:0 1px 12px rgba(10,20,40,.7); }

@media (max-width:760px){
  .top ul li:not(:last-child){ display:none; }
}

/* ============================================================
   THE LIFT
   ============================================================ */

.lift{
  position:fixed; z-index:400;
  right:clamp(10px,1.5vw,22px); top:50%; transform:translateY(-50%);
  display:flex; flex-direction:column; gap:clamp(6px,.9vh,12px);
  align-items:flex-end; pointer-events:none;
  opacity:calc(1 - var(--hero));
  transition:opacity .5s var(--ease);
}
.lift a{
  pointer-events:auto; display:flex; align-items:center; gap:8px;
  text-decoration:none;
  font-family:var(--mono); font-size:10px; letter-spacing:.12em;
  color:rgba(255,255,255,.4);
  text-shadow:0 1px 10px rgba(0,0,0,.9);
  transition:color .4s var(--ease);
}
.lift a i{ display:block; width:12px; height:1px; background:currentColor; opacity:.7;
  transition:width .4s var(--ease); }
.lift a span{ min-width:1.4em; text-align:right; }
.lift a:hover{ color:rgba(255,255,255,.85); }
.lift a.is-on{ color:var(--sun); }
.lift a.is-on i{ width:28px; opacity:1; }
@media (max-height:520px){ .lift{ display:none; } }

/* ============================================================
   THE ROOF — the first screen. The name sits in the sky above the
   building's own parapet; he is rigged on it at the right.
   ============================================================ */

.storey.storey--roof{
  flex-direction:column; align-items:flex-start; justify-content:space-between;
  padding-top:clamp(84px,13vh,150px);
  padding-bottom:clamp(22px,4vh,40px);
}
.roof__name{ color:#fff; }
.hero__name{
  margin:0;
  font-family:var(--serif); font-style:italic; font-weight:400;
  font-size:clamp(64px, 9.5vw, 150px); line-height:.9;
  letter-spacing:-.01em;
  text-shadow:0 4px 40px rgba(10,20,40,.6), 0 1px 6px rgba(10,20,40,.45);
}
.hero__tag{
  margin:18px 0 0 .12em;
  font-size:clamp(11px,.85vw,13px); letter-spacing:.34em; text-transform:uppercase;
  color:rgba(255,255,255,.9);
  text-shadow:0 1px 14px rgba(10,20,40,.8);
}
.storey--roof .pane{ margin:clamp(20px,4vh,40px) 0; }
.hero__cue{
  margin:0; display:flex; align-items:center; gap:12px; color:#fff;
  font-size:10.5px; letter-spacing:.26em; text-transform:uppercase;
  text-shadow:0 1px 14px rgba(0,0,0,.6);
}
.hero__cue i{
  display:block; width:1px; height:44px; background:currentColor; opacity:.8;
  animation:drop 2.4s var(--ease) infinite;
  transform-origin:top;
}
@keyframes drop{ 0%{ transform:scaleY(0); opacity:0 } 30%{ opacity:.9 } 100%{ transform:scaleY(1); opacity:0 } }

@media (max-width:760px){
  .storey.storey--roof{ align-items:flex-start; padding-top:clamp(70px,11vh,110px); }
  .hero__name{ font-size:clamp(44px,13vw,64px); }
  .hero__cue{ display:none; }
}

/* ============================================================
   STOREYS — text sits left; he hangs right
   ============================================================ */

.storey{
  position:relative; z-index:7;
  min-height:100svh;
  display:flex; align-items:center;
  padding:clamp(70px,9vh,120px) var(--gut);
}
/* he zig-zags down the facade; the text always takes the side he is not on */
.storey--r{ justify-content:flex-end; }
/* two floors carry no text at all: the before/after line and the wipe */
.storey--bare{ pointer-events:none; }

.floor-cue{
  position:fixed; z-index:6; left:50%; bottom:clamp(26px,5vh,48px);
  transform:translateX(-50%);
  margin:0; display:flex; align-items:center; gap:12px; white-space:nowrap;
  font-size:10.5px; letter-spacing:.26em; text-transform:uppercase;
  color:var(--sun); text-shadow:0 1px 14px rgba(0,0,0,.85);
  opacity:0; pointer-events:none;
  transition:opacity .5s var(--ease);
}
.floor-cue i{ width:16px; height:16px; border-radius:50%; border:1px solid currentColor; }
body.is-wiping .floor-cue--wipe{ opacity:1; }
body.is-wiping .floor-cue--wipe.is-done{ opacity:.35; }
/* the whole window is his to clean on that floor: no line, no water */
body.is-wiping .edge, body.is-wiping .drips{ opacity:0; }

/* the reveal — appears once most of the glass is clean, on that floor only */
.reveal-line{
  position:fixed; z-index:6; left:50%; top:50%;
  transform:translate(-50%, -46%);
  width:min(92vw, 640px); text-align:center;
  opacity:0; pointer-events:none;
  transition:opacity 1.1s var(--ease), transform 1.1s var(--ease);
}
.reveal-line__text{
  margin:0 0 22px;
  font-size:clamp(28px, 4.2vw, 56px); line-height:1.05;
  font-weight:500; letter-spacing:-.03em; color:#fff;
  text-shadow:0 4px 40px rgba(10,20,40,.8), 0 1px 6px rgba(10,20,40,.6);
}
/* white and bright, over a very dark cave */
.reveal-line__text em{ font-family:var(--serif); font-style:italic; font-weight:400; color:#fff; }
.reveal-line__text{ text-shadow:0 0 30px rgba(255,255,255,.35), 0 4px 40px rgba(0,0,0,.9), 0 1px 6px rgba(0,0,0,.8); }
/* the words never catch the pointer — the glass under them stays cleanable;
   only the button does */
body.is-wiping.is-revealed .reveal-line{ opacity:1; transform:translate(-50%, -50%); }
body.is-wiping.is-revealed .reveal-line .btn{ pointer-events:auto; }
/* neighbouring storeys overlap the window at its edges; on this floor
   they must not sit between the pointer and the glass */
body.is-wiping .storey{ pointer-events:none; }
body.is-wiping .storey .pane{ pointer-events:auto; }
body.is-wiping.is-revealed .floor-cue--wipe{ opacity:0; }
body.is-wiping.is-revealed .squeegee{ opacity:0; }

.pane{
  position:relative;
  width:100%; max-width:min(500px, 46vw);
  padding:clamp(24px,2.8vw,40px);
  border-radius:2px;
  background:linear-gradient(140deg, rgba(255,255,255,.16) 0%, rgba(255,255,255,.07) 55%, rgba(255,255,255,.10) 100%);
  backdrop-filter:blur(22px) saturate(1.35);
  -webkit-backdrop-filter:blur(22px) saturate(1.35);
  border:1px solid var(--line);
  box-shadow:
    0 28px 70px rgba(0,0,0,.4),
    inset 0 1px 0 rgba(255,255,255,.45),
    inset 0 0 60px rgba(255,255,255,.05);
}
.pane--wide{ max-width:min(640px, 50vw); }
@supports not ((backdrop-filter:blur(2px)) or (-webkit-backdrop-filter:blur(2px))){
  .pane{ background:rgba(20,32,48,.9); }
}

.pane__no{
  margin:0 0 16px;
  font-family:var(--mono); font-size:10.5px; letter-spacing:.2em; text-transform:uppercase;
  color:var(--sun);
  display:flex; align-items:baseline; gap:10px;
}
.pane__no span{ font-family:var(--sans); letter-spacing:.24em; color:rgba(255,255,255,.62); }
.pane__no::after{ content:""; flex:1; height:1px; background:var(--line-soft); }

.pane h2{
  margin:0 0 16px;
  font-size:clamp(25px,3.1vw,40px); line-height:1.08;
  font-weight:500; letter-spacing:-.03em;
}
.pane h2 em{ font-family:var(--serif); font-style:italic; font-weight:400; letter-spacing:-.005em; color:var(--glass-tint); }
.pane__lede{ margin:0 0 16px; color:var(--paper-dim); font-size:clamp(14px,1.05vw,16px); }
.pane__lede:last-child{ margin-bottom:0; }

.pane__cue{
  margin:18px 0 0;
  font-size:10px; letter-spacing:.26em; text-transform:uppercase;
  color:var(--sun); display:flex; align-items:center; gap:10px;
  transition:opacity .6s var(--ease);
}
.pane__cue::before{
  content:""; width:16px; height:16px; border-radius:50%;
  border:1px solid currentColor;
}
.pane__cue.is-done{ opacity:.35; }

.spec{ margin:18px 0 0; display:flex; gap:26px; flex-wrap:wrap; padding-top:16px; border-top:1px solid var(--line-soft); }
.spec div{ display:flex; flex-direction:column; gap:3px; }
.spec dt{ font-size:9.5px; letter-spacing:.2em; text-transform:uppercase; color:var(--paper-mute); }
.spec dd{ margin:0; font-family:var(--mono); font-size:13px; color:var(--paper); }

.ticks{ margin:18px 0 0; padding:16px 0 0; list-style:none; border-top:1px solid var(--line-soft); }
.ticks li{ position:relative; padding-left:22px; margin-bottom:8px; color:var(--paper-dim); font-size:14.5px; }
.ticks li::before{ content:"—"; position:absolute; left:0; color:var(--sun); }
.ticks li:last-child{ margin-bottom:0; }

/* ============================================================
   BUTTONS
   ============================================================ */

.btn{
  display:inline-flex; align-items:center; justify-content:center;
  text-decoration:none; cursor:pointer; font-family:inherit;
  font-size:12px; letter-spacing:.15em; text-transform:uppercase; font-weight:500;
  padding:13px 24px; border-radius:2px;
  border:1px solid var(--line);
  background:rgba(255,255,255,.12);
  backdrop-filter:blur(10px); -webkit-backdrop-filter:blur(10px);
  color:var(--paper);
  transition:background .3s var(--ease), color .3s var(--ease), border-color .3s var(--ease), transform .3s var(--ease);
}
.btn:hover{ background:rgba(255,255,255,.22); transform:translateY(-1px); }
.btn--lg{ padding:16px 30px; }
.btn--solid{ background:var(--sun); border-color:var(--sun); color:#1e1608; }
.btn--solid:hover{ background:#fff0d2; border-color:#fff0d2; }

/* ============================================================
   PRICES
   ============================================================ */

.freq{ display:flex; flex-wrap:wrap; gap:7px; margin:4px 0 22px; }
.freq__btn{
  appearance:none; cursor:pointer; font-family:inherit;
  font-size:11px; letter-spacing:.16em; text-transform:uppercase;
  padding:11px 16px; border-radius:2px;
  border:1px solid var(--line-soft);
  background:rgba(255,255,255,.07);
  color:var(--paper-dim);
  transition:background .3s var(--ease), color .3s var(--ease), border-color .3s var(--ease);
}
.freq__btn em{ font-style:normal; font-family:var(--mono); letter-spacing:0; opacity:.7; margin-left:5px; }
.freq__btn:hover{ color:var(--paper); border-color:var(--line); }
.freq__btn.is-on{ background:rgba(255,255,255,.9); color:#152130; border-color:rgba(255,255,255,.9); }

.price{ list-style:none; margin:0; padding:0; border-top:1px solid var(--line-soft); }
.price li{ display:flex; align-items:baseline; gap:12px; padding:14px 0 12px; border-bottom:1px solid var(--line-soft); }
.price__name{ display:flex; flex-direction:column; gap:2px; font-size:clamp(15px,1.25vw,17px); }
.price__name em{ font-style:normal; font-size:12px; color:var(--paper-mute); }
.price__dots{ flex:1; border-bottom:1px dotted var(--line-soft); transform:translateY(-4px); min-width:16px; }
.price__fig{ font-family:var(--mono); font-size:clamp(15px,1.35vw,18px); color:var(--sun);
  font-variant-numeric:tabular-nums; white-space:nowrap; transition:opacity .2s var(--ease); }
.price__fig.is-swapping{ opacity:0; }
.price__note{ margin:16px 0 0; font-size:11.5px; letter-spacing:.12em; text-transform:uppercase; color:var(--glass-tint); }
@media (max-width:520px){ .price li{ flex-wrap:wrap; } .price__dots{ display:none; } .price__fig{ margin-left:auto; } }

/* ============================================================
   AREAS
   ============================================================ */

.checker{ margin:20px 0 20px; }
.checker__label{ display:block; margin-bottom:10px; font-size:10px; letter-spacing:.24em; text-transform:uppercase; color:var(--paper-mute); }
.checker__row{ display:flex; gap:8px; flex-wrap:wrap; }
.checker__in{
  flex:1 1 200px; border-radius:2px;
  border:1px solid var(--line-soft); background:rgba(255,255,255,.08);
  color:var(--paper); font-family:inherit; font-size:15px; padding:13px 15px;
}
.checker__in::placeholder{ color:var(--paper-mute); }
.checker__in:focus{ outline:0; border-color:var(--sun); }
.checker__out{ margin:12px 0 0; font-size:14px; min-height:1.4em; color:var(--paper-dim); }
.checker__out.is-yes{ color:var(--sun); }

.chips{ list-style:none; margin:0; padding:0; display:flex; flex-wrap:wrap; gap:7px; }
.chips li{
  border:1px solid var(--line-soft); border-radius:2px;
  background:rgba(255,255,255,.06);
  padding:7px 13px; font-size:12px; color:var(--paper-dim);
  transition:background .35s var(--ease), color .35s var(--ease), border-color .35s var(--ease);
}
.chips li.is-hit{ background:var(--sun); color:#1e1608; border-color:var(--sun); }

/* ============================================================
   BOOKING
   ============================================================ */

.form{ display:grid; gap:16px 20px; grid-template-columns:repeat(auto-fit,minmax(200px,1fr)); margin-top:6px; }
.field{ display:flex; flex-direction:column; gap:7px; }
.field--wide{ grid-column:1/-1; }
.field label{ font-size:9.5px; letter-spacing:.22em; text-transform:uppercase; color:var(--paper-mute); }
.field input, .field select, .field textarea{
  border:0; border-bottom:1px solid var(--line-soft); border-radius:0;
  background:rgba(255,255,255,.06);
  color:var(--paper); font-family:inherit; font-size:15px; font-weight:300;
  padding:10px 10px; resize:vertical;
}
.field select{ appearance:none; cursor:pointer; }
.field select option{ background:#16232f; color:var(--paper); }
.field input::placeholder, .field textarea::placeholder{ color:rgba(147,168,188,.75); }
.field input:focus, .field select:focus, .field textarea:focus{ outline:0; border-bottom-color:var(--sun); }
.field.is-bad input{ border-bottom-color:#ff9b8a; }

.form__est{ grid-column:1/-1; margin:2px 0 0; font-size:13px; color:var(--paper-dim); min-height:1.4em; }
.form__est b{ font-family:var(--mono); font-weight:400; font-size:16px; color:var(--sun); margin-right:7px; }
.form__est em{ font-style:normal; color:var(--paper-mute); }
.form__actions{ grid-column:1/-1; display:flex; flex-wrap:wrap; gap:10px; margin-top:4px; }
.form__out{ grid-column:1/-1; margin:0; font-size:13.5px; color:var(--glass-tint); min-height:1.4em; }

/* ============================================================
   FOOTER — inside the entrance panel
   ============================================================ */

.foot{
  display:grid; gap:22px;
  grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
  margin-top:34px; padding-top:26px;
  border-top:1px solid var(--line-soft);
}
.foot h4{ margin:0 0 8px; font-size:9.5px; letter-spacing:.22em; text-transform:uppercase; color:var(--paper-mute); font-weight:400; }
.foot p{ margin:0; font-size:13.5px; color:var(--paper-dim); }
.foot a{ text-decoration:none; transition:color .3s var(--ease); }
.foot a:hover{ color:var(--sun); }
.foot > div:first-child p{ margin-top:14px; }
.foot__base{
  margin:22px 0 0; padding-top:16px;
  border-top:1px solid var(--line-soft);
  font-size:10.5px; letter-spacing:.12em; text-transform:uppercase; color:var(--paper-mute);
}

/* ============================================================
   REVEALS
   ============================================================ */

.reveal{ opacity:0; transform:translateY(26px); transition:opacity 1s var(--ease), transform 1s var(--ease); }
.reveal.is-in{ opacity:1; transform:none; }
.no-obs .reveal{ opacity:1; transform:none; transition:none; }

/* ============================================================
   PHONES — he moves to the right edge and higher; text takes
   the bottom half
   ============================================================ */

@media (max-width:760px){
  :root{ --cx:76vw; --ch:27svh; }
  .storey{ align-items:flex-end; padding-bottom:clamp(40px,8vh,80px); }
  .pane, .pane--wide{ max-width:none; }
  /* the lift sits under his squeegee arm on a phone, and over the form */
  .lift{ display:none; }
}

@media (prefers-reduced-motion:reduce){
  html{ scroll-behavior:auto; }
  *,*::before,*::after{ animation-duration:.001ms !important; transition-duration:.001ms !important; }
  .reveal{ opacity:1; transform:none; }
  .hero__cue i{ animation:none; }
  .swing, .man .shadow{ animation:none; }
  .drips{ display:none; }
}

/* the two bare floors carry only their own labels */
body.is-comparing .tally, body.is-wiping .tally{ opacity:0; transition:opacity .4s var(--ease); }
