/* ============================================================
   MERIDIAN — landing page
   ------------------------------------------------------------
   Dark only. The page is ONE surface: a single continuous
   background runs from the top of the hero to the last line of
   the footer. No section paints its own fill, no section draws a
   rule across the page, so nothing reads as a seam.

   Depth comes from three fixed layers stacked behind the content:

     .aura    a slow gradient wash that drifts with scroll
     #grain   a static film grain, kills gradient banding
     #field   the logo swirl as a live 3D point cloud

   Motion lives in the [data-anim] system at the bottom of this
   file: every card, bubble, row and message flies into place in
   3D, and replays each time it comes back into view.
   ============================================================ */

/* ---------------- tokens ---------------- */
:root{
  --bg:        oklch(13% 0.014 258);
  --bg-2:      oklch(16.5% 0.016 258);
  --bg-3:      oklch(21% 0.018 258);
  --rule:      oklch(28% 0.018 258);
  --rule-soft: oklch(22% 0.016 258);
  --ink:       oklch(96% 0.005 258);
  --ink-2:     oklch(80% 0.010 258);
  --muted:     oklch(66% 0.014 258);

  /* action colour — clickable things only */
  --accent:     oklch(78% 0.175 152);
  --accent-dim: oklch(62% 0.150 152);
  --accent-ink: oklch(20% 0.060 152);

  /* the swirl blue */
  --field:      oklch(66% 0.170 258);
  --field-hi:   oklch(86% 0.105 248);
  --field-lo:   oklch(44% 0.150 264);

  --t-display: clamp(2.6rem, 6.6vw, 5.6rem);
  --t-2xl:     clamp(2rem, 4.4vw, 3.4rem);
  --t-xl:      clamp(1.4rem, 2.3vw, 1.9rem);
  --t-lg:      1.25rem;
  --t-md:      1.0625rem;
  --t-sm:      0.9375rem;
  --t-xs:      0.8125rem;

  --serif: "Outfit", ui-sans-serif, system-ui, -apple-system, sans-serif;
  --sans:  "Outfit", ui-sans-serif, system-ui, -apple-system, sans-serif;
  --mono:  "JetBrains Mono", ui-monospace, SFMono-Regular, monospace;

  --s-1:.25rem; --s-2:.5rem; --s-3:.75rem; --s-4:1rem;
  --s-5:1.5rem; --s-6:2rem;  --s-7:3rem;   --s-8:4.5rem; --s-9:7rem;

  --r-sm:6px; --r:14px; --r-bubble:20px; --r-pill:999px;
  --shadow: 0 24px 60px oklch(4% 0.01 258 / .55);

  --ease: cubic-bezier(.16,1,.3,1);
  --ease-back: cubic-bezier(.22,1.15,.36,1);
  --d-in: 760ms;
  --d-3d: 850ms;
  --d-ui: 160ms;

  --pad: clamp(1.25rem, 5vw, 5rem);
  --wrap: 1240px;
  --nav-h: 62px;          /* the bar itself */
  --nav-gap: 0px;         /* the bar meets the top edge */

  /* written each frame by landing.js */
  --scrollp:0;               /* 0 at the top of the page, 1 at the bottom */
  --field-a:1;               /* the swirl dims once the hero is behind you */
}

*,*::before,*::after{box-sizing:border-box}
html{overflow-x:clip;-webkit-text-size-adjust:100%}
body{
  overflow-x:clip;margin:0;color:var(--ink);
  font-family:var(--sans);font-size:var(--t-md);line-height:1.6;
  font-synthesis-weight:none;-webkit-font-smoothing:antialiased;
  /* the one background of the whole page */
  background:var(--bg);
}
img{display:block;max-width:100%}
a{color:inherit;text-decoration:none}
p{margin:0 0 1em}
::selection{background:var(--accent);color:var(--accent-ink)}
:where(a,button,summary,[tabindex]):focus-visible{
  outline:2px solid var(--accent);outline-offset:3px;border-radius:var(--r-sm)}
.skip{position:absolute;left:-9999px;top:8px;background:var(--ink);color:var(--bg);
  padding:var(--s-2) var(--s-4);border-radius:var(--r-sm);z-index:120}
.skip:focus{left:8px}
.wrap{width:min(var(--wrap),100% - var(--pad)*2);margin-inline:auto}

h1,h2,h3{font-family:var(--serif);font-weight:500;font-style:normal;margin:0;
  line-height:1.02;overflow-wrap:anywhere;min-width:0}
h1{font-size:var(--t-display);letter-spacing:-.035em}
h2{font-size:var(--t-2xl);letter-spacing:-.028em;line-height:1.04}
h3{font-size:var(--t-xl);letter-spacing:-.02em;line-height:1.1}
.lede{font-size:var(--t-lg);line-height:1.5;color:var(--ink-2);max-width:34ch;margin:0}
.body{max-width:66ch}
.muted{color:var(--muted)}

.mark{position:relative;white-space:nowrap}
.mark::after{content:"";position:absolute;left:0;right:0;bottom:-.06em;
  height:clamp(2px,.045em,5px);background:var(--accent);border-radius:2px}

/* ============================================================
   THE CONTINUOUS BACKGROUND
   Three fixed layers. Because they are fixed they cannot seam:
   there is no edge to line up as the content scrolls over them.
   The wash moves with --scrollp instead, so the page still travels
   through a changing light rather than sitting on a flat wall.
   ============================================================ */
.aura{position:fixed;inset:0;z-index:0;pointer-events:none;
  background:
    radial-gradient(120% 80% at 78% calc(6% + var(--scrollp) * 30%),
      oklch(30% 0.075 262 / .75) 0%, transparent 62%),
    radial-gradient(95% 70% at calc(10% + var(--scrollp) * 26%) calc(82% - var(--scrollp) * 46%),
      oklch(26% 0.070 178 / .42) 0%, transparent 58%),
    radial-gradient(140% 110% at 50% calc(120% - var(--scrollp) * 58%),
      oklch(22% 0.055 292 / .55) 0%, transparent 70%),
    linear-gradient(180deg,
      oklch(15% 0.020 258) 0%,
      oklch(12.5% 0.016 258) 46%,
      oklch(14% 0.022 264) 100%);
}
/* Grain is the difference between a gradient and a surface. */
#grain{position:fixed;inset:0;z-index:0;pointer-events:none;opacity:.16;
  mix-blend-mode:overlay}

#field{position:fixed;inset:0;z-index:0;pointer-events:none;
  opacity:0;transition:opacity 900ms var(--ease)}
#field.ready{opacity:var(--field-a)}

/* Everything the reader reads sits above all three. */
#smooth,.nav,.foot{position:relative;z-index:1}

/* ---------------- buttons ---------------- */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--s-2);
  font-family:var(--sans);font-size:var(--t-sm);font-weight:600;
  padding:var(--s-3) var(--s-5);min-height:48px;border-radius:var(--r-pill);
  border:1px solid transparent;cursor:pointer;white-space:nowrap;
  transition:background var(--d-ui) var(--ease),color var(--d-ui) var(--ease),
    border-color var(--d-ui) var(--ease),transform var(--d-ui) var(--ease),
    box-shadow var(--d-ui) var(--ease)}
.btn svg{width:18px;height:18px;fill:currentColor;flex:none}
.btn-go{background:var(--accent);color:var(--accent-ink)}
.btn-go:hover{background:var(--accent-dim);transform:translateY(-1px);
  box-shadow:0 10px 30px oklch(78% 0.175 152 / .22)}
.btn-go:active{transform:translateY(0)}
.btn-line{border-color:var(--rule);color:var(--ink);
  background:oklch(20% 0.016 258 / .35);backdrop-filter:blur(6px)}
.btn-line:hover{border-color:var(--ink);transform:translateY(-1px)}
.btn-line:active{transform:translateY(0)}
.btn[disabled]{opacity:.45;pointer-events:none}
.link{color:var(--accent);position:relative;padding-bottom:2px;font-weight:500;font-size:var(--t-sm)}
.link::after{content:"";position:absolute;left:0;bottom:0;height:1px;width:100%;
  background:currentColor;transform:scaleX(0);transform-origin:left;
  transition:transform var(--d-ui) var(--ease)}
.link:hover::after,.link:focus-visible::after{transform:scaleX(1)}

/* ---------------- nav ---------------- */
/* A floating bar rather than a band across the top: it sits centred on
   the same measure as the page content, clear of the top edge, with its
   own rounded shell. The full-width <header> keeps the bar fixed but is
   itself transparent and click-through, so only the bar catches clicks
   and the hero stays reachable underneath it. */
.nav{position:fixed;top:0;left:0;right:0;z-index:100;
  padding:var(--nav-gap) var(--pad) 0;pointer-events:none}
.nav-in{pointer-events:auto;
  display:flex;align-items:center;justify-content:space-between;gap:var(--s-5);
  height:var(--nav-h);padding:0 var(--s-2) 0 var(--s-5);
  width:min(var(--wrap),100%);margin-inline:auto;
  /* Flush with the top of the window, so nothing can pass through a gap
     above it, and rounded only where it meets the page. A full pill sat
     clear of the edge instead, which left slivers of moving content
     showing through the two top corner arcs. */
  border-radius:0 0 var(--r-pill) var(--r-pill);
  background:oklch(17% 0.016 258 / .50);
  border:1px solid oklch(100% 0 0 / .07);border-top:0;
  backdrop-filter:blur(16px) saturate(1.3);
  box-shadow:0 8px 30px oklch(4% 0.01 258 / .30);
  transition:background 320ms var(--ease),border-color 320ms var(--ease),
    box-shadow 320ms var(--ease)}
/* Once the page has moved under it, the shell firms up so the bar stays
   legible over whatever is passing beneath. */
.nav.stuck .nav-in{background:oklch(15% 0.014 258 / .82);
  border-color:oklch(100% 0 0 / .10);
  box-shadow:0 14px 44px oklch(4% 0.01 258 / .48)}
.brand{display:inline-flex;align-items:center;gap:var(--s-2);white-space:nowrap;
  font-family:var(--serif);font-size:1.2rem;line-height:1;letter-spacing:-.015em}
.brand img{width:26px;height:26px;flex:none}
.nav .btn{min-height:40px;padding:var(--s-2) var(--s-4)}
/* On a phone the studio name and a labelled button will not both fit
   inside the bar, and the name is the thing worth keeping. The button
   drops to its mark alone — a round green dot that still reads as the
   WhatsApp action, and still announces itself to a screen reader
   through the link's aria-label. */
@media (max-width:34rem){
  .nav-in{padding:0 var(--s-2) 0 var(--s-4)}
  .brand{font-size:1rem;gap:var(--s-2)}
  .brand img{width:22px;height:22px}
  .nav .btn-label{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)}
  .nav .btn{width:44px;min-width:44px;padding:0;gap:0;border-radius:50%}
  .nav .btn svg{width:20px;height:20px}
}
.nav-links{display:none;gap:var(--s-5);font-size:var(--t-sm);color:var(--muted)}
.nav-links a{transition:color var(--d-ui) var(--ease)}
.nav-links a:hover{color:var(--ink)}
@media (min-width:64rem){.nav-links{display:flex}}

/* ---------------- hero ---------------- */
.hero{position:relative;z-index:1;min-height:100svh;display:flex;flex-direction:column;
  justify-content:flex-end;
  padding:calc(var(--nav-h) + var(--nav-gap) + var(--s-7)) var(--pad) var(--s-8)}
.hero-in{width:min(var(--wrap),100%);margin-inline:auto}

/* THE HEADLINE
   A living gradient rather than one the reader has to go looking for.
   Three background layers clipped to the glyphs: two soft radial pools
   of the brand blue and a slow linear sweep beneath them. Each layer
   travels at its own speed and two of them run in opposite directions,
   so the light inside the letters never repeats the same way twice and
   there is no loop seam to spot.

   Every layer is sized so its travel equals one full tile, which is
   what keeps the motion continuous instead of snapping at the end. */
.hero-h{position:relative;display:block;max-width:15ch;margin:0 0 var(--s-5)}
.hero-h .base{display:block;color:var(--ink)}

@supports ((background-clip:text) or (-webkit-background-clip:text)){
  .hero-h .base{
    color:transparent;
    -webkit-background-clip:text;background-clip:text;
    background-image:
      radial-gradient(65% 320% at 0% 50%,  oklch(98% 0.030 230) 0%, transparent 56%),
      radial-gradient(55% 300% at 50% 50%, oklch(76% 0.155 264) 0%, transparent 58%),
      linear-gradient(90deg,
        oklch(88% 0.100 246) 0%,
        oklch(97% 0.018 240) 28%,
        oklch(75% 0.150 258) 58%,
        oklch(88% 0.100 246) 100%);
    background-size:180% 100%, 150% 100%, 200% 100%;
    background-repeat:repeat;
    animation:hero-alive 19s linear infinite;
  }
}

@keyframes hero-alive{
  from{background-position:   0% 50%,  100% 50%,   0% 50%}
  to  {background-position: 180% 50%, -150% 50%, 200% 50%}
}

.hero-lede{margin:0 0 var(--s-6);max-width:38ch;color:var(--ink-2);
  font-size:var(--t-lg);line-height:1.5}
.hero-cta{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s-4)}

/* real facts set at the edges */
.orbit{position:absolute;inset:0;pointer-events:none;z-index:1;display:none}
.orbit span{position:absolute;font-size:var(--t-sm);color:var(--muted);
  white-space:nowrap;will-change:transform}
.orbit .o1{top:18%;right:8%}
.orbit .o2{top:62%;right:16%;font-family:var(--serif);font-size:var(--t-xl);color:var(--field-hi)}
.orbit .o3{top:12%;left:46%}
@media (min-width:64rem){.orbit{display:block}}

/* ---------------- sections ----------------
   No fill and no rule. The background behind them is the page's,
   and it never restarts. */
.sec{position:relative;z-index:1;background:none;border:0;
  padding-block:clamp(4rem,9vw,var(--s-9));
  /* the bar floats over the page, so an anchor jump has to stop short of
     it or the heading it was aimed at lands underneath */
  scroll-margin-top:calc(var(--nav-h) + var(--nav-gap) + var(--s-5))}
.sec-head{display:grid;gap:var(--s-4);margin-bottom:var(--s-8);max-width:52ch}
.sec-head h2{max-width:20ch}

/* Where a block of text crosses the swirl, it gets its own pool of
   dark rather than a slab across the whole page. */
.pane{background:
    radial-gradient(120% 140% at 0% 0%, oklch(16% 0.018 258 / .82), oklch(13% 0.014 258 / .55));
  border:1px solid var(--rule-soft);border-radius:var(--r);
  backdrop-filter:blur(10px)}

/* ---------------- work ---------------- */
.work{display:grid;gap:clamp(3rem,7vw,6rem)}
.piece{display:grid;grid-template-columns:minmax(0,6fr) minmax(0,5fr);
  gap:clamp(1.5rem,4vw,4rem);align-items:center}
.piece:nth-child(even){grid-template-columns:minmax(0,5fr) minmax(0,6fr)}
.piece:nth-child(even) .shot{order:2}
.piece:nth-child(2){margin-left:clamp(0px,6vw,5rem)}
.shot{display:block;border-radius:var(--r);overflow:hidden;background:var(--bg-2);
  border:1px solid var(--rule-soft);box-shadow:var(--shadow);
  transition:border-color var(--d-ui) var(--ease),box-shadow var(--d-ui) var(--ease)}
a.shot:hover{border-color:var(--field);box-shadow:0 30px 70px oklch(66% 0.17 258 / .18)}
/* Anchored to the top. These are full-page screenshots, so the bottom
   edge catches a sliver of whatever section follows the hero — a white
   band, usually. A frame slightly wider than the source trims that off
   the bottom while the site's own nav stays where it belongs. */
.shot img{width:100%;height:100%;object-fit:cover;object-position:top center;
  transform-origin:center;will-change:transform,opacity}
.shot-empty{display:grid;place-items:center;background:var(--bg-2);
  border-style:dashed}
.shot-pad{padding:11%;background:var(--bg-3)}
.shot-pad img{object-fit:contain}
.shot-invert img{filter:invert(1) brightness(1.06)}
.kind{font-size:var(--t-xs);letter-spacing:.08em;text-transform:uppercase;
  color:var(--muted);font-weight:600;margin-bottom:var(--s-3);display:block}
.piece h3{margin-bottom:var(--s-3)}
.piece p{color:var(--muted);font-size:var(--t-sm);max-width:52ch}
.piece ul{list-style:none;padding:0;margin:0 0 var(--s-5);display:grid;gap:var(--s-1)}
.piece li{font-size:var(--t-sm);color:var(--ink-2);padding-left:var(--s-4);position:relative}
.piece li::before{content:"";position:absolute;left:0;top:.62em;width:5px;height:5px;
  border-radius:50%;background:var(--field)}
.slot{display:inline-block;font-size:var(--t-xs);color:var(--muted);
  border:1px dashed var(--rule);border-radius:var(--r-sm);padding:var(--s-1) var(--s-2)}
@media (max-width:56rem){
  .piece,.piece:nth-child(even){grid-template-columns:minmax(0,1fr)}
  .piece:nth-child(even) .shot{order:0}
  .piece:nth-child(2){margin-left:0}
}

/* ---------------- process ---------------- */
.steps{display:grid;gap:var(--s-4);max-width:44rem;margin-left:auto}
.bubble{padding:var(--s-4) var(--s-5);border-radius:var(--r-bubble);
  font-size:var(--t-sm);line-height:1.45;box-shadow:var(--shadow)}
.bubble-out{background:var(--accent);color:var(--accent-ink);
  border-bottom-right-radius:var(--r-sm);justify-self:end;max-width:min(30rem,92%)}
.bubble-in{background:oklch(17% 0.018 258 / .88);color:var(--ink);
  border:1px solid var(--rule-soft);backdrop-filter:blur(10px);
  border-bottom-left-radius:var(--r-sm);justify-self:start;max-width:min(34rem,96%)}
.bubble h3{font-size:var(--t-lg);margin-bottom:var(--s-1)}
.bubble p{margin:0;font-size:var(--t-sm);line-height:1.5}

/* ---------------- packages ---------------- */
.plans{display:grid;border-top:1px solid var(--rule-soft)}
/* Every plan carries a full border, transparent on three sides so only
   the row divider shows at rest. That gives the edge something to light
   up: on hover all four sides come up in the swirl blue with a soft
   bloom behind them, the same gesture the work cards use. */
.plan{display:grid;grid-template-columns:minmax(0,4fr) minmax(0,3fr) minmax(0,5fr) auto;
  gap:var(--s-5);align-items:start;padding:var(--s-6) var(--s-5);
  border:1px solid transparent;border-bottom-color:var(--rule-soft);
  border-radius:var(--r);
  transition:background var(--d-ui) var(--ease),
    border-color var(--d-ui) var(--ease),
    box-shadow var(--d-ui) var(--ease)}
.plan:hover{background:oklch(18% 0.018 258 / .55);
  border-color:var(--field);
  box-shadow:0 0 0 1px oklch(66% 0.170 258 / .30),
             0 18px 55px oklch(66% 0.170 258 / .20)}
.plan-pick{background:oklch(18% 0.020 258 / .62);
  border:1px solid var(--rule);backdrop-filter:blur(10px)}
.plan-name{display:grid;gap:var(--s-1)}
.plan-name h3{font-size:var(--t-xl)}
.plan-tag{font-size:var(--t-xs);color:var(--muted);letter-spacing:.06em;
  text-transform:uppercase;font-weight:600}
.plan-pick .plan-tag{color:var(--field-hi)}
.price{font-size:1.75rem;font-weight:600;letter-spacing:-.02em;
  font-variant-numeric:tabular-nums;line-height:1.1}
.price span{font-size:var(--t-sm);font-weight:400;color:var(--muted);letter-spacing:0}
.per{font-size:var(--t-sm);color:var(--muted);font-variant-numeric:tabular-nums;margin-top:var(--s-1)}
.plan ul{list-style:none;padding:0;margin:0;display:grid;gap:var(--s-2)}
.plan li{font-size:var(--t-sm);color:var(--ink-2);padding-left:var(--s-5);
  position:relative;line-height:1.45}
.plan li::before{content:"";position:absolute;left:0;top:.42em;width:10px;height:6px;
  border-left:1.5px solid var(--accent);border-bottom:1.5px solid var(--accent);
  transform:rotate(-45deg)}
.plan-foot{grid-column:1/-1;font-size:var(--t-xs);color:var(--muted);margin:var(--s-3) 0 0}
@media (max-width:62rem){
  .plan{grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:var(--s-4)}
  .plan-list,.plan .btn{grid-column:1/-1}
  .plan .btn{justify-self:start}
}

/* ---------------- rates ---------------- */
/* Four groups, so two by two. auto-fit gave three across and left the
   fourth stranded alone on a second row, which is what made the section
   look unfinished. A fixed pair of columns also pairs the two four-row
   groups with the two three-row ones, so each row comes out close to
   level. */
.rates{display:grid;grid-template-columns:minmax(0,1fr);
  gap:var(--s-6) clamp(2rem,4vw,3.5rem)}
@media (min-width:60rem){
  .rates{grid-template-columns:repeat(2,minmax(0,1fr))}
}
/* Cards in a row share a height. Stretching the table to fill the
   shorter one was tried and abandoned: the rows spread out and the price
   fell out of line with its label. A little space under the last row of
   a short card reads better than a table pulled out of shape. */
.rate-g{padding:var(--s-5);border-radius:var(--r);
  background:oklch(15% 0.016 258 / .55);border:1px solid var(--rule-soft);
  backdrop-filter:blur(10px)}
.rate-g h3{font-size:var(--t-xs);letter-spacing:.08em;text-transform:uppercase;
  font-family:var(--sans);font-weight:600;color:var(--muted);
  padding-bottom:var(--s-3);border-bottom:1px solid var(--ink);margin-bottom:0}
.rate-t{width:100%;border-collapse:collapse;font-variant-numeric:tabular-nums}
.rate-t tr{border-bottom:1px solid var(--rule-soft)}
.rate-t tr:last-child{border-bottom:0}
.rate-t th{text-align:left;font-weight:400;padding:var(--s-4) var(--s-4) var(--s-4) 0}
.rate-t td{text-align:right;padding:var(--s-4) 0;vertical-align:top;white-space:nowrap}
.rate-n{display:block;font-size:var(--t-sm);color:var(--ink)}
.rate-note{display:block;font-size:var(--t-xs);color:var(--muted);margin-top:2px;line-height:1.45}
.rate-p{font-size:var(--t-sm);font-weight:600;font-family:var(--mono)}
.rate-u{display:block;font-size:var(--t-xs);color:var(--muted)}

/* ---------------- faq ---------------- */
/* Each question is a panel of its own rather than a line of text on the
   open background. Hairline dividers gave the words nothing to sit on, so
   over a moving starfield they read as floating and the eye slid past
   them. A surface, a border and a visible control fix that. */
.faq{max-width:62rem;margin-left:auto;display:grid;gap:var(--s-3)}
.faq details{border:1px solid var(--rule-soft);border-radius:var(--r);
  background:oklch(17.5% 0.018 258 / .74);backdrop-filter:blur(10px);
  transition:background var(--d-ui) var(--ease),
    border-color var(--d-ui) var(--ease),
    box-shadow var(--d-ui) var(--ease)}
.faq details:hover{border-color:var(--field);
  box-shadow:0 0 0 1px oklch(66% 0.170 258 / .30),
             0 14px 40px oklch(66% 0.170 258 / .18)}
.faq details[open]{background:oklch(20% 0.020 258 / .82);border-color:var(--rule)}

.faq summary{cursor:pointer;list-style:none;display:flex;gap:var(--s-4);
  justify-content:space-between;align-items:center;padding:var(--s-4) var(--s-5);
  font-family:var(--serif);font-size:var(--t-lg);line-height:1.25;
  transition:color var(--d-ui) var(--ease)}
.faq summary::-webkit-details-marker{display:none}
.faq summary:hover{color:var(--field-hi)}

/* The +/- was a grey glyph adrift at the far edge. It is a real control
   now: a bordered disc that fills with the action colour once open. */
.faq summary::after{content:"+";flex:none;
  display:grid;place-items:center;width:32px;height:32px;
  border:1px solid var(--rule);border-radius:50%;
  font-family:var(--sans);font-size:1.15rem;font-weight:500;line-height:1;
  color:var(--ink-2);
  transition:background var(--d-ui) var(--ease),color var(--d-ui) var(--ease),
    border-color var(--d-ui) var(--ease)}
.faq summary:hover::after{border-color:var(--field);color:var(--field-hi)}
.faq details[open] summary::after{content:"\2013";
  background:var(--accent);border-color:transparent;color:var(--accent-ink)}

.faq details p{margin:0;padding:0 var(--s-5) var(--s-5);
  color:var(--ink-2);font-size:var(--t-sm);line-height:1.6;max-width:64ch}

/* ---------------- close + footer ---------------- */
.close-grid{display:grid;grid-template-columns:minmax(0,7fr) minmax(0,5fr);
  gap:clamp(2rem,5vw,4rem);align-items:start}
.card{background:oklch(17% 0.018 258 / .78);border:1px solid var(--rule-soft);
  border-radius:var(--r);padding:var(--s-6);backdrop-filter:blur(10px);
  box-shadow:var(--shadow)}
.card h3{font-size:var(--t-lg);margin-bottom:var(--s-4)}
.card dl{margin:0;display:grid;gap:var(--s-4)}
.card dt{font-size:var(--t-xs);letter-spacing:.06em;text-transform:uppercase;
  color:var(--muted);font-weight:600}
.card dd{margin:2px 0 0;font-size:var(--t-sm)}
@media (max-width:62rem){.close-grid{grid-template-columns:minmax(0,1fr)}}

.foot{position:relative;z-index:1;background:none;
  border-top:1px solid var(--rule-soft);padding:var(--s-7) 0 var(--s-6)}
.foot-top{display:flex;flex-wrap:wrap;gap:var(--s-5);justify-content:space-between;
  align-items:baseline;padding-bottom:var(--s-5);border-bottom:1px solid var(--rule-soft)}
.foot-links{display:flex;flex-wrap:wrap;gap:var(--s-4) var(--s-5);font-size:var(--t-sm)}
.foot-links a{color:var(--muted);transition:color var(--d-ui) var(--ease)}
.foot-links a:hover{color:var(--ink)}
.foot-note{font-size:var(--t-xs);color:var(--muted);max-width:64ch;margin:var(--s-5) 0 0;line-height:1.6}
.foot-bot{display:flex;flex-wrap:wrap;gap:var(--s-4) var(--s-6);justify-content:space-between;
  font-size:var(--t-xs);color:var(--muted);margin-top:var(--s-5)}
.foot-bot p{margin:0}

/* ============================================================
   INERTIAL SCROLL
   The whole page is one surface that eases toward the real scroll
   position rather than snapping to it. The native scrollbar, keyboard
   scrolling and anchor links all still drive the real scroller.
   Off by default in the markup, so with no JS the page scrolls normally.
   ============================================================ */
#smooth{position:relative;z-index:1}
html.smooth #smooth{position:fixed;top:0;left:0;right:0;will-change:transform}
html.smooth body{overflow-x:clip}
#spacer{pointer-events:none}

/* ============================================================
   THE 3D REVEAL SYSTEM
   ------------------------------------------------------------
   Every box on the page carries a [data-anim] value naming how it
   arrives. The element starts rotated and pushed back in Z inside a
   perspective set on its parent, then flies to identity.

   Two things make it cinematic rather than a fade:

     1. real perspective — .stage gives the group a camera, so a card
        rotating about Y genuinely turns, near edge growing, far edge
        shrinking, instead of squashing flat;
     2. it replays — the observer takes the class OFF once the element
        is well clear of the viewport, so scrolling back up and down
        plays the move again every time.
   ============================================================ */
.stage{perspective:1400px;perspective-origin:50% 50%}

[data-anim]{
  opacity:0;will-change:transform,opacity;transform-style:preserve-3d;backface-visibility:hidden;
  transition:opacity var(--d-3d) var(--ease) var(--delay,0ms),
             transform var(--d-3d) var(--ease-back) var(--delay,0ms),
             filter var(--d-3d) var(--ease) var(--delay,0ms);
  filter:blur(6px)}

/* spins in from the left, hinged on its own left edge */
[data-anim="spin-left"]{transform:perspective(1400px) translate3d(-16%,8%,-340px) rotateY(-62deg) rotateZ(-4deg);
  transform-origin:left center}
/* and the mirror, for the alternating rows */
[data-anim="spin-right"]{transform:perspective(1400px) translate3d(16%,8%,-340px) rotateY(62deg) rotateZ(4deg);
  transform-origin:right center}
/* tips up off the floor, like a card being stood upright */
[data-anim="tilt-up"]{transform:perspective(1400px) translate3d(0,26%,-260px) rotateX(52deg);
  transform-origin:center bottom}
/* falls forward from the back of the scene */
[data-anim="drop-in"]{transform:perspective(1400px) translate3d(0,-18%,-420px) rotateX(-38deg);
  transform-origin:center top}
/* the camera dollies onto it */
[data-anim="dolly"]{transform:perspective(1400px) translate3d(0,6%,-520px) scale(.94)}
/* swings in on a hinge above it, the way a sign swings */
[data-anim="swing"]{transform:perspective(1400px) translate3d(0,-10%,-200px) rotateX(-58deg) rotateZ(-3deg);
  transform-origin:center -40%}
/* the plain one, for running text */
[data-anim="rise"]{transform:translate3d(0,28px,0);filter:none}

[data-anim].in{opacity:1;transform:none;filter:none}

/* no JS, no observer: everything is simply present */
html:not(.js) [data-anim]{opacity:1;transform:none;filter:none}

/* The older single-shot class is kept so any markup still using it
   behaves, now routed through the same 3D arrival. */
.up{opacity:0;transform:translate3d(0,20px,0);
  transition:opacity var(--d-in) var(--ease) var(--delay,0ms),
             transform var(--d-in) var(--ease) var(--delay,0ms)}
.up.in{opacity:1;transform:none}
html:not(.js) .up{opacity:1;transform:none}

/* Scroll-linked depth: while a group is on screen it leans a few
   degrees with the scroll, so the whole page reads as a space being
   travelled through rather than a stack of flat panels. */
.lean{transform:perspective(1600px) rotateX(calc(var(--lean,0) * 2.4deg)) translateZ(calc(var(--lean,0) * -18px));
  transition:transform 120ms linear}

/* ============================================================
   INNER PAGES
   Service pages, project pages and the location page. Same
   continuous background, same reveal system; only the furniture
   is different — a breadcrumb, a page head, and running prose.
   ============================================================ */
.page-hero{position:relative;z-index:1;
  padding:calc(var(--nav-h) + var(--nav-gap) + var(--s-8)) 0 var(--s-7)}
.page-hero h1{max-width:18ch;margin-bottom:var(--s-4)}
.page-lede{font-size:var(--t-lg);line-height:1.5;color:var(--ink-2);
  max-width:46ch;margin:0 0 var(--s-5)}
.page-price{font-size:1.75rem;font-weight:600;letter-spacing:-.02em;
  font-family:var(--mono);margin:0}
.page-price-note{font-size:var(--t-sm);color:var(--muted);margin:var(--s-1) 0 0}
.ctas{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s-4);margin-top:var(--s-6)}

.crumbs{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s-2);
  font-size:var(--t-xs);color:var(--muted);margin-bottom:var(--s-5);
  letter-spacing:.06em;text-transform:uppercase;font-weight:600}
.crumbs a{transition:color var(--d-ui) var(--ease)}
.crumbs a:hover{color:var(--ink)}
.crumbs span[aria-hidden]{opacity:.5}

.prose{max-width:68ch}
.prose-block{margin-bottom:var(--s-7)}
.prose-block h2{font-size:var(--t-xl);margin-bottom:var(--s-4)}
.prose-block p{color:var(--ink-2);font-size:var(--t-md)}
.page-intro{font-size:var(--t-lg);line-height:1.55;color:var(--ink-2);
  margin-bottom:var(--s-7);max-width:56ch}
.check{list-style:none;padding:0;margin:0;display:grid;gap:var(--s-2)}
.check li{font-size:var(--t-sm);color:var(--ink-2);padding-left:var(--s-5);
  position:relative;line-height:1.5}
.check li::before{content:"";position:absolute;left:0;top:.46em;width:10px;height:6px;
  border-left:1.5px solid var(--accent);border-bottom:1.5px solid var(--accent);
  transform:rotate(-45deg)}

.svc-grid{display:grid;gap:var(--s-5);
  grid-template-columns:repeat(auto-fit,minmax(min(20rem,100%),1fr))}
.svc-card{display:grid;align-content:start;gap:var(--s-3);
  padding:var(--s-6);border-radius:var(--r);
  background:oklch(17% 0.018 258 / .78);border:1px solid var(--rule-soft);
  backdrop-filter:blur(10px);box-shadow:var(--shadow);
  transition:border-color var(--d-ui) var(--ease),transform var(--d-ui) var(--ease),
    box-shadow var(--d-ui) var(--ease)}
.svc-card:hover{border-color:var(--field);transform:translateY(-2px);
  box-shadow:0 30px 70px oklch(66% 0.17 258 / .18)}
.svc-card h2{font-size:var(--t-xl)}
.svc-card p{color:var(--muted);font-size:var(--t-sm);margin:0}
.svc-price{font-family:var(--mono);font-size:var(--t-sm);font-weight:600;color:var(--ink)}
.svc-more{display:inline-flex;align-items:center;gap:var(--s-2);
  font-size:var(--t-sm);font-weight:600;color:var(--accent)}
.svc-more svg{fill:none;stroke:currentColor}

.related-links{display:flex;flex-wrap:wrap;gap:var(--s-3)}
.related-links a{font-size:var(--t-sm);padding:var(--s-2) var(--s-4);
  border:1px solid var(--rule);border-radius:var(--r-pill);color:var(--ink-2);
  transition:border-color var(--d-ui) var(--ease),color var(--d-ui) var(--ease)}
.related-links a:hover{border-color:var(--ink);color:var(--ink)}

/* the inner-page FAQ reuses the homepage one, just narrower */
.prose .faq{max-width:none;margin-left:0}

/* ============================================================
   REDUCED MOTION — a real path. The field renders one still frame,
   the type keeps its settled surface with no reveal, nothing moves.
   ============================================================ */
@media (prefers-reduced-motion:reduce){
  html.smooth #smooth{position:relative;transform:none!important}
  .hero-h .base{animation:none}
  [data-anim],.up{opacity:1!important;transform:none!important;filter:none!important;transition:none}
  .lean{transform:none!important}
  .shot img{transform:none!important;opacity:1!important;will-change:auto}
  .orbit span{transform:none!important}
  .aura{background:linear-gradient(180deg,oklch(15% 0.020 258),oklch(13% 0.016 258))}
  *,*::before,*::after{transition-duration:.01ms!important;animation-duration:.01ms!important}
}
