/* ---------------------------------------------------------------- tokens */
:root {
  --bg:        #0A0C0A;
  --panel:     #101310;
  --panel-alt: #171B17;
  --ink:       #F1F4EF;
  --ink-dim:   #7C857A;
  --accent:    #1FDD85;
  --on-accent: #04140C;
  --accent-2:  #8A9687;
  --warn:      #FF6F61;
  --border:    rgba(241,244,239,0.09);
  --font-display: "Archivo", sans-serif;
  --font-mono: "Martian Mono", monospace;

  --glass-blur: blur(22px) saturate(160%);

  /* Where the key light sits relative to a panel, from -1 (off to the panel's
     left) through 0 (straight overhead) to 1 (off to its right). Every panel
     sets its own further down, and the glass recipe reads it. At -1 the recipe
     produces exactly the fixed upper-left lighting the panels used to have, so
     this generalises the material rather than replacing it. */
  --lit: -1;
}

/* ---------------------------------------------------------------- ground */
* { box-sizing: border-box; }

html {
  color-scheme: dark;
  scroll-behavior: smooth;
  scroll-padding-top: 90px;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 400 15px/1.55 var(--font-display);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* The key light. It sits above the page and a little left of centre, and that
   position is the whole lighting model: every panel further down places its
   specular hotspot facing back at this and throws its shadow the other way. */
body::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 760px;
  background: radial-gradient(ellipse 1000px 470px at 50% -12%, rgba(31,221,133,0.15), transparent 66%);
  pointer-events: none;
  z-index: -1;
}

/* Ambient field: three soft pools and a deep vignette, no texture at all, fixed
   to the viewport. The upper left pool is the strongest of the three, which is
   what pulls the effective light left of centre. Taller than the viewport so the
   scroll drift below never exposes an edge. */
body::after {
  content: "";
  position: fixed;
  top: 0; left: 0; right: 0;
  height: calc(100vh + 240px);
  background:
    radial-gradient(ellipse 130% 110% at 50% 46%, transparent 38%, rgba(0,0,0,0.6)),
    radial-gradient(ellipse 900px 640px at 6% 16%, rgba(31,221,133,0.10), transparent 62%),
    radial-gradient(ellipse 780px 580px at 98% 44%, rgba(31,221,133,0.08), transparent 60%),
    radial-gradient(ellipse 1040px 540px at 44% 106%, rgba(31,221,133,0.095), transparent 64%);
  pointer-events: none;
  z-index: -1;
}

/* the field drifts up slowly while scrolling; browsers without
   scroll-driven animations keep the static version */
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: scroll()) {
    body::after {
      animation: bg-drift linear both;
      animation-timeline: scroll(root);
    }
  }
}

@keyframes bg-drift {
  to { transform: translateY(-240px); }
}

body.no-scroll { overflow: hidden; }

.container {
  max-width: 1080px;
  margin: 0 auto;
  padding: 0 28px;
}

h1, h2, h3 { color: var(--ink); }

h1 {
  font-size: clamp(2.7rem, 6.4vw, 4.5rem);
  font-weight: 700;
  letter-spacing: -0.033em;
  line-height: 1.02;
  max-width: 15ch;
  text-wrap: balance;
  margin: 0 0 22px;
}

h2 {
  font-size: clamp(1.7rem, 3.2vw, 2.25rem);
  font-weight: 700;
  letter-spacing: -0.028em;
  line-height: 1.1;
  margin: 12px 0 10px;
}

h3 {
  font-weight: 700;
  letter-spacing: -0.02em;
}

a { color: inherit; }

a:focus-visible,
button:focus-visible,
video:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

/* ---------------------------------------------------------------- type utils */
.eyebrow {
  font: 500 10px/1 var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--accent);
  margin: 0;
}

.section-sub {
  color: var(--ink-dim);
  font-size: 15px;
  max-width: 54ch;
  margin: 0;
}

/* ---------------------------------------------------------------- buttons */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border-radius: 999px;
  border: 1px solid transparent;
  font: 600 14px/1 var(--font-display);
  padding: 13px 24px;
  text-decoration: none;
  cursor: pointer;
  transition: filter 0.18s ease, background 0.18s ease, transform 0.18s ease, box-shadow 0.18s ease;
}

@media (hover: hover) {
  .btn:hover { transform: translateY(-2px); }
}

.btn-solid {
  background: var(--accent);
  color: var(--on-accent);
}

@media (hover: hover) {
  .btn-solid:hover { filter: brightness(1.08); }
}

.btn-hero { box-shadow: 0 8px 26px rgba(31,221,133,0.2); }

.btn-ghost {
  background: var(--panel);
  border-color: var(--border);
  color: var(--ink);
}

@media (hover: hover) {
  .btn-ghost:hover { background: var(--panel-alt); }
}

/* ---------------------------------------------------------------- nav */
.nav-shell {
  position: sticky;
  top: 16px;
  z-index: 60;
  padding: 0 16px;
}

.nav {
  position: relative;
  max-width: 660px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 7px 7px 7px 22px;
  border-radius: 999px;
  background:
    linear-gradient(168deg, rgba(255,255,255,0.055), rgba(255,255,255,0.014)),
    rgba(16,19,16,0.52);
  -webkit-backdrop-filter: blur(26px) saturate(165%);
  backdrop-filter: blur(26px) saturate(165%);
  border: 1px solid rgba(241,244,239,0.12);
  box-shadow: 0 12px 34px rgba(0,0,0,0.42);
}

.wordmark {
  font: 700 15.5px/1 var(--font-display);
  letter-spacing: -0.01em;
  text-decoration: none;
  white-space: nowrap;
}

.nav-links {
  display: flex;
  gap: 20px;
  list-style: none;
  margin: 0 0 0 auto;
  padding: 0;
}

.nav-links a {
  font-size: 13.5px;
  font-weight: 500;
  color: var(--ink-dim);
  text-decoration: none;
  white-space: nowrap;
  transition: color 0.15s ease;
}

@media (hover: hover) {
  .nav-links a:hover { color: var(--ink); }
}

.nav-end {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
}

.nav-links + .nav-end { margin-left: 0; }

.btn-nav {
  font-size: 12.5px;
  padding: 10px 18px;
}

.menu-btn {
  display: none;
  width: 36px;
  height: 36px;
  border-radius: 999px;
  background: var(--panel-alt);
  border: 1px solid var(--border);
  color: var(--ink);
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: transform 0.18s ease;
}

@media (hover: hover) {
  .menu-btn:hover { transform: translateY(-2px); }
}

@media (max-width: 639.98px) {
  .menu-btn { display: inline-flex; }

  /* The links drop out of the flow here to become the menu panel, so the
     auto margin they were carrying stops pushing anything and the rule that
     cancels this one has nothing left to sit against. Without this the pair
     bunched up against the wordmark and left the right of the pill empty. */
  .nav-links + .nav-end { margin-left: auto; }

  .nav-links {
    display: none;
    position: absolute;
    top: calc(100% + 10px);
    left: 0;
    right: 0;
    flex-direction: column;
    gap: 2px;
    margin: 0;
    padding: 10px;
    /* solid on purpose: this panel sits inside .nav, whose own backdrop-filter
       makes it a backdrop root, so a blur here has nothing behind it to
       sample. Even 4% transmission was enough for the hero headline to ghost
       through the links, so the colour is opaque and the sheen comes from the
       gradient layered over it. */
    background:
      linear-gradient(168deg, rgba(255,255,255,0.05), rgba(255,255,255,0.014)),
      var(--panel);
    border: 1px solid rgba(241,244,239,0.12);
    border-radius: 20px;
    box-shadow: 0 18px 44px rgba(0,0,0,0.55);
  }

  .nav.menu-open .nav-links { display: flex; }

  .nav-links a {
    display: block;
    padding: 11px 14px;
    border-radius: 12px;
    font-size: 14px;
  }

  .nav-links a:active { background: var(--panel-alt); }

  @media (hover: hover) {
    .nav-links a:hover { background: var(--panel-alt); }
  }
}

/* ---------------------------------------------------------------- hero */
.hero { padding-top: 108px; padding-bottom: 40px; }

/* The hero reads as a title card inside the crop marks, so it is centred at
   every width rather than only on phones. The headline and the paragraph both
   carry a max-width, and a max-width alone leaves a block flush left, so they
   need auto side margins to follow the text-align. */
.hero-frame {
  position: relative;
  text-align: center;
}

.hero-frame h1 {
  margin-left: auto;
  margin-right: auto;
}

.crop {
  position: absolute;
  width: 18px;
  height: 18px;
}

.crop-tl { top: -30px; left: -30px;  border-top: 1px solid rgba(241,244,239,0.26); border-left: 1px solid rgba(241,244,239,0.26); }
.crop-tr { top: -30px; right: -30px; border-top: 1px solid rgba(241,244,239,0.26); border-right: 1px solid rgba(241,244,239,0.26); }
.crop-bl { bottom: -30px; left: -30px;  border-bottom: 1px solid rgba(241,244,239,0.26); border-left: 1px solid rgba(241,244,239,0.26); }
.crop-br { bottom: -30px; right: -30px; border-bottom: 1px solid rgba(241,244,239,0.26); border-right: 1px solid rgba(241,244,239,0.26); }

@media (max-width: 1179.98px) {
  .crop { display: none; }
}

.status-chip {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 8px 14px;
  border-radius: 999px;
  background: var(--panel);
  border: 1px solid var(--border);
  font: 500 10px/1 var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--ink);
  margin: 0 0 28px;
}

.dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 3px rgba(31,221,133,0.16);
  animation: pulse 2.4s ease-in-out infinite;
}

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.3; }
}

/* the auto sides belong in this shorthand rather than a rule above it, or the
   shorthand would reset them straight back to zero */
.hero-sub {
  font-size: 17px;
  line-height: 1.6;
  color: var(--ink-dim);
  max-width: 54ch;
  margin: 0 auto 30px;
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px;
  margin: 0 0 36px;
}

.cap-line {
  font: 500 10px/1.8 var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--accent-2);
  margin: 0;
}

/* ---------------------------------------------------------------- sections */
.section { padding-top: 130px; }

/* ---------------------------------------------------------------- glass */
/* Every panel is cut from the same material. Only the radius and the padding
   change from one to the next, so they are set on each panel below and the
   material itself lives here. The contact card and the featured plan override
   the rim and the tint on top of this; they are the two surfaces meant to pull
   the eye, and they do it with more green rather than a different material.

   The three light-dependent parts are declared HERE rather than in :root, and
   that is load-bearing. A custom property declared on :root has its own var()
   references substituted against :root, so a --glass built up there would bake
   in the root's --lit and every panel would inherit the same frozen angles no
   matter what it set. Declared on the panels, each one resolves against its own.

   Read the three together and they are one light: the hotspot slides toward the
   light, the tint sweeps away from it, and the shadow falls opposite it. */
.card,
.process-grid,
.plan,
.rate-card,
.rate-includes,
.contact-card {
  --glass:
    radial-gradient(ellipse 90% 60% at calc(50% + var(--lit) * 30%) -8%, rgba(255,255,255,0.09), transparent 62%),
    linear-gradient(calc(180deg + var(--lit) * 12deg), rgba(255,255,255,0.06), rgba(255,255,255,0.016) 50%, rgba(31,221,133,0.045));
  --glass-rim: linear-gradient(calc(180deg + var(--lit) * 28deg), rgba(255,255,255,0.38), rgba(255,255,255,0.06) 34%, rgba(255,255,255,0.03) 64%, rgba(31,221,133,0.26));
  --glass-shadow:
    calc(var(--lit) * -10px) 22px 48px rgba(0,0,0,0.46),
    calc(var(--lit) * -2px) 4px 12px rgba(0,0,0,0.26),
    inset 0 -1px 0 rgba(255,255,255,0.04);

  position: relative;
  isolation: isolate;
  background: var(--glass);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  box-shadow: var(--glass-shadow);
}

/* Which way each panel faces. The container is centred and the light is at
   roughly 42% of the viewport, so in a three-across row the left card catches it
   on its right cheek, the middle card is almost square on, and the right card is
   furthest from it and tilts hardest. Panels that span the whole container sit
   under the light rather than beside it, so they barely tilt at all. */
.work-grid > *:nth-child(3n + 1),
.plans-grid > *:nth-child(3n + 1),
.rate-grid > *:nth-child(3n + 1) { --lit: 0.55; }

.work-grid > *:nth-child(3n + 2),
.plans-grid > *:nth-child(3n + 2),
.rate-grid > *:nth-child(3n + 2) { --lit: -0.25; }

.work-grid > *:nth-child(3n),
.plans-grid > *:nth-child(3n),
.rate-grid > *:nth-child(3n) { --lit: -1; }

.process-grid,
.rate-includes,
.rate-solo .rate-card,
.contact-card { --lit: -0.25; }

.card::before,
.process-grid::before,
.plan::before,
.rate-card::before,
.rate-includes::before,
.contact-card::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1px;
  background: var(--glass-rim);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
  pointer-events: none;
}

/* ---------------------------------------------------------------- work */
.work-grid {
  --grid-gap: 20px;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--grid-gap);
  margin-top: 44px;
}

.card {
  border-radius: 14px;
  padding: 13px 13px 22px;
  transition: transform 0.22s ease, box-shadow 0.22s ease, opacity 0.25s ease;
}

@media (hover: hover) {
  /* the rim is a gradient behind a mask, so hover swaps the gradient rather
     than a border colour, and the glow lands on top of the panel's own shadow */
  .card:hover {
    --glass-rim: linear-gradient(calc(180deg + var(--lit) * 28deg), rgba(31,221,133,0.55), rgba(31,221,133,0.18) 36%, rgba(255,255,255,0.05) 66%, rgba(31,221,133,0.34));
    transform: translateY(-4px);
    box-shadow: var(--glass-shadow), calc(var(--lit) * -6px) 14px 44px rgba(31,221,133,0.14);
  }

  /* while one card is hovered, the other two step back */
  .work-grid:has(.card:hover) .card:not(:hover) {
    opacity: 0.55;
  }
}

.thumb {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 9 / 16;
  border: 0;
  padding: 0;
  border-radius: 9px;
  overflow: hidden;
  background: var(--panel-alt);
  cursor: pointer;
}

.thumb video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.playhead {
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--px, 34%);
  width: 1.5px;
  background: var(--accent);
  box-shadow: 0 0 11px rgba(31,221,133,0.65);
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.18s ease;
}

@media (hover: hover) {
  .thumb:hover .playhead { opacity: 1; }
}

.timecode {
  position: absolute;
  right: 9px;
  bottom: 9px;
  font: 500 9px/1 var(--font-mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
  color: var(--ink);
  background: rgba(6,10,6,0.74);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  padding: 4px 7px;
  border-radius: 5px;
  pointer-events: none;
}

/* Work is filtered by type rather than stacked, because the three services are
   priced and scheduled differently and a visitor is usually shopping for one.
   Tab semantics, so the arrow keys move between types the way they would in
   any other tab strip. */
.work-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px 28px;
  flex-wrap: wrap;
}

/* the h2's own bottom margin moves to the row, so the toggle stays centred
   against the heading instead of being pushed off its baseline */
.work-head { margin-bottom: 10px; }
.work-head h2 { margin: 12px 0 0; }

.seg {
  display: inline-flex;
  gap: 2px;
  padding: 3px;
  border-radius: 999px;
  background: rgba(255,255,255,0.03);
  border: 1px solid var(--border);
}

.seg-btn {
  border: 0;
  background: transparent;
  color: var(--ink-dim);
  font: 500 10px/1 var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: 10px 15px;
  border-radius: 999px;
  cursor: pointer;
  white-space: nowrap;
  transition: color 0.18s ease, background 0.18s ease;
}

@media (hover: hover) {
  .seg-btn:hover { color: var(--ink); }
}

.seg-btn[aria-selected="true"] {
  background: var(--accent);
  color: var(--on-accent);
}

@media (hover: hover) {
  .seg-btn[aria-selected="true"]:hover { color: var(--on-accent); }
}

.work-panel .card { padding-bottom: 14px; }

/* the toggle already names the service, so a card only needs an index to be
   pointed at in conversation. Mono because it reads as a label. */
.card h4 {
  font: 500 11px/1 var(--font-mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.06em;
  color: var(--ink-dim);
  margin: 14px 0 0;
}

/* A landscape piece among vertical ones. Cropping it to 9:16 would quietly
   throw away the sides of someone's edit, and letterboxing it inside a tall
   frame left the picture floating in dead space. So the frame takes the shape
   of the video and the card just ends up shorter than its neighbours, which
   reads as deliberate rather than broken. */
.card.is-wide .thumb {
  aspect-ratio: 16 / 9;
}

/* cards size to their own content now that they are not all one shape */
.work-grid { align-items: start; }

/* Two pieces of different shape sitting side by side. Left to the three-across
   grid, a 9:16 next to a 16:9 comes out at wildly different heights, and where
   the pair is the whole panel it also leaves a hole in the third column, so the
   row reads as one that lost a card rather than as a pair.

   81:256 is the one column ratio where 9/16 and 16/9 resolve to the same height.
   It is the ratio of the two ratios, and it puts both thumbnails on a shared top
   and bottom line with nothing cropped and nothing letterboxed. The 26px is the
   card's own side padding: it sits inside the column and has to come out of the
   width before the ratio is applied, or the two shapes miss each other by about
   30px. 337 is 81 + 256, and --pair-lead is the share belonging to whichever
   shape is on the left. */
.work-grid.is-pair,
.pair-row {
  --pair-lead: 81; /* the tall piece leads */
  grid-template-columns:
    calc(26px + (100% - var(--grid-gap) - 52px) * var(--pair-lead) / 337)
    1fr;
}

.pair-row.leads-wide { --pair-lead: 256; }

/* A pair that is one row of a longer grid rather than the whole of it. It takes
   the full row, so its split has the same width to divide as the three-across
   rows above it, and it carries the grid's own gap so the columns stay in step
   with them. */
.pair-row {
  grid-column: 1 / -1;
  display: grid;
  gap: var(--grid-gap);
  align-items: start;
}

/* Lighting read off the pair's own two columns rather than the three-across rule
   above, and not as an even split, because these columns are not halves. With
   the tall piece leading it is a narrow strip against the left edge and the wide
   one is centred near 63%. With the wide piece leading that flips: it covers
   most of the row and the tall one is pushed out to the far right, which is the
   hardest tilt on the page. */
.work-grid.is-pair > *:nth-child(1) { --lit: 0.75; }
.work-grid.is-pair > *:nth-child(2) { --lit: -0.6; }
.pair-row.leads-wide > *:nth-child(1) { --lit: 0.1; }
.pair-row.leads-wide > *:nth-child(2) { --lit: -1; }

/* Every piece lives in one grid, and a collapsed panel shows exactly one row of
   it. The cut-off tracks the column count at each width below, so narrowing the
   window moves a card under "More" instead of stranding it alone on a half-empty
   second row. Scoped to .is-collapsible, a class the script adds only where there
   is genuinely more than one row, so without JS every card stays on the page. */
.work-panel.is-collapsible:not(.is-open) .card:nth-child(n + 4) { display: none; }

/* A pair-row is one child holding two cards, so the counts above step over it
   instead of reaching the cards inside. It is always past the first row anyway,
   which makes one rule right at every width. */
.work-panel.is-collapsible:not(.is-open) .pair-row { display: none; }

/* Centred in the section, which on a three-column grid puts it under the
   middle video. A block-level button with auto side margins rather than a
   text-align, so the arrow stays glued to the label. */
.more-btn {
  display: flex;
  align-items: center;
  gap: 7px;
  margin: 26px auto 0;
  padding: 9px 12px;
  border: 0;
  background: transparent;
  color: var(--accent);
  font: 500 10px/1 var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  cursor: pointer;
}

/* The script hides this with the hidden attribute when a panel has nothing more
   to show. An author display beats the UA sheet's [hidden] rule, so without this
   the motion pair sits under a MORE that does nothing when clicked. */
.more-btn[hidden] { display: none; }

.more-arrow {
  stroke: var(--accent);
  transition: transform 0.2s ease;
}

.more-btn[aria-expanded="true"] .more-arrow { transform: rotate(180deg); }

@media (hover: hover) {
  .more-btn:hover { filter: brightness(1.15); }
}

/* ---------------------------------------------------------------- process */
/* one pane of glass split by hairlines, rather than three opaque cells
   sitting in a 1px gap */
.process-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  border-radius: 20px;
  overflow: hidden;
  margin-top: 44px;
}

.process-cell {
  padding: 28px 26px 34px;
}

.process-cell + .process-cell {
  border-left: 1px solid rgba(241,244,239,0.08);
}

.step-num {
  font: 500 9.5px/1 var(--font-mono);
  letter-spacing: 0.06em;
  color: var(--accent);
  margin: 0 0 16px;
}

.process-cell h3 {
  font-size: 17px;
  margin: 0 0 8px;
}

.process-cell p:last-child {
  font-size: 14px;
  color: var(--ink-dim);
  margin: 0;
}

/* ---------------------------------------------------------------- plans */
.plans-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 18px;
  align-items: start;
  margin-top: 44px;
}

.plan {
  border-radius: 22px;
  padding: 26px 24px 28px;
}

.plan-label {
  font: 500 10px/1 var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--accent-2);
  margin: 0 0 16px;
}

.plan h3 {
  font-size: 21px;
  margin: 0 0 8px;
}

.plan-note {
  font-size: 13.5px;
  color: var(--ink-dim);
  margin: 0 0 20px;
}

.plan-cta {
  width: 100%;
  background: rgba(10,12,10,0.34);
  border-color: rgba(241,244,239,0.14);
  color: var(--ink);
  font-size: 13px;
  padding: 12px 18px;
}

@media (hover: hover) {
  .plan-cta:hover {
    background: rgba(10,12,10,0.5);
    border-color: rgba(241,244,239,0.26);
  }
}

.divider {
  border: 0;
  height: 1px;
  background: var(--border);
  margin: 20px 0 16px;
}

.ticks {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 10px;
}

.ticks li {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  font-size: 13.5px;
  line-height: 1.5;
  color: rgba(241,244,239,0.8);
}

.tick {
  flex: 0 0 auto;
  margin-top: 4px;
  stroke: var(--accent);
}

.plan-guarantee {
  margin: 18px 0 0;
  font: 500 10px/1.7 var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--accent);
}

/* the middle card is the same glass with green in it, and it keeps the solid
   button so the eye still lands there first */
.plan--featured {
  --glass-rim: linear-gradient(calc(180deg + var(--lit) * 28deg), rgba(31,221,133,0.7), rgba(31,221,133,0.2) 36%, rgba(255,255,255,0.05) 66%, rgba(31,221,133,0.42));
  background:
    radial-gradient(ellipse 90% 60% at calc(50% + var(--lit) * 30%) -8%, rgba(31,221,133,0.16), transparent 62%),
    linear-gradient(calc(180deg + var(--lit) * 12deg), rgba(31,221,133,0.13), rgba(31,221,133,0.045) 52%, rgba(255,255,255,0.03));
  box-shadow:
    calc(var(--lit) * -12px) 26px 56px rgba(0,0,0,0.5),
    0 0 40px rgba(31,221,133,0.1),
    inset 0 -1px 0 rgba(255,255,255,0.05);
}

.plan--featured .plan-label { color: var(--accent); }

.plan--featured .plan-cta {
  background: var(--accent);
  border-color: transparent;
  color: var(--on-accent);
}

@media (hover: hover) {
  .plan--featured .plan-cta:hover {
    background: var(--accent);
    border-color: transparent;
    filter: brightness(1.08);
  }
}

/* ---------------------------------------------------------------- pricing */
/* the same pane of glass as the process panel, split into rate rows */
/* Three cards instead of one, because the rate now depends on which kind of
   work it is as well as how much of it there is. Identical bands in each so
   the eye can compare straight across a row. */
.rate-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
  margin-top: 44px;
}

/* A service page prices one thing. Standing the card beside the inclusions kept
   it from floating but left the inclusions two thirds empty, because three short
   lines cannot fill six hundred points of panel. So the one service spreads
   across the width instead: two panels stacked, each filled by its own content.
   Nothing is stretched to cover a row it has nothing to put in. */
.rate-solo { margin-top: 44px; }

/* The bands share a row rather than stacking. That is what lets the card go full
   width without running a band name and its figure to opposite edges of the
   container, which is the reason a stretched card was rejected the first time. */
.rate-bands {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
}

.rate-service + .rate-bands { border-top: 1px solid rgba(241,244,239,0.08); }

/* side by side, so the line between them runs down rather than across */
.rate-bands .rate-row + .rate-row {
  border-top: 0;
  border-left: 1px solid rgba(241,244,239,0.08);
}

.rate-card {
  border-radius: 20px;
  overflow: hidden;
}

/* the card is named once at the top, so a band underneath only has to say how
   many. Mono and accent-2, matching every other small label on the page. */
.rate-service {
  font: 500 10px/1 var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--accent-2);
  margin: 0;
  padding: 22px 26px 19px;
}

.rate-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 21px 26px;
}

.rate-service + .rate-row,
.rate-row + .rate-row {
  border-top: 1px solid rgba(241,244,239,0.08);
}

.rate-band-name {
  font-size: 15px;
  font-weight: 700;
  letter-spacing: -0.02em;
  margin: 0;
}

/* number and unit share a baseline so the right column reads as one figure */
.rate-figure {
  display: flex;
  align-items: baseline;
  gap: 9px;
  flex: 0 0 auto;
  margin: 0;
}

.rate-num {
  font: 700 34px/1 var(--font-display);
  letter-spacing: -0.03em;
  color: var(--accent);
}

.rate-unit {
  font: 500 10px/1 var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-dim);
}

/* a panel in its own right, so the inclusions read as part of the price rather
   than a footnote under it */
.rate-includes {
  border-radius: 20px;
  padding: 24px 26px 26px;
  margin-top: 20px;
}

.rate-includes-head {
  font: 500 10px/1 var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--accent-2);
  margin: 0 0 18px;
}

/* Three across, lining up with the three rate cards above. Two columns left the
   last tick stranded on a row of its own, and with three items there is no
   width where two columns come out even. The 720px cap is gone because the
   longest line needs the full container to stay on one row. */
.rate-ticks {
  grid-template-columns: repeat(3, 1fr);
  gap: 12px 28px;
}

.rate-foot {
  margin: 26px 0 0;
  font-size: 13.5px;
  color: var(--ink-dim);
  max-width: 54ch;
}

/* ---------------------------------------------------------------- faq */
/* The page opens centred on the hero and closes centred on the contact card, so
   the questions between them are centred too. The rows keep their own left
   alignment: a summary is a flex row with the icon pinned to the far edge, and a
   centred question would drift away from it. */
.faq { text-align: center; }

.faq-list {
  max-width: 720px;
  margin: 44px auto 0;
  border-top: 1px solid var(--border);
  text-align: left;
}

.faq-item { border-bottom: 1px solid var(--border); }

.faq-item summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  padding: 20px 2px;
  list-style: none;
  cursor: pointer;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.01em;
  transition: color 0.15s ease;
}

.faq-item summary::-webkit-details-marker { display: none; }

@media (hover: hover) {
  .faq-item summary:hover { color: var(--accent); }
}

.faq-item summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 4px;
}

.faq-icon {
  flex: 0 0 auto;
  stroke: var(--accent-2);
  transition: transform 0.2s ease, stroke 0.2s ease;
}

@media (hover: hover) {
  .faq-item summary:hover .faq-icon { stroke: var(--accent); }
}

.faq-item[open] .faq-icon {
  transform: rotate(45deg);
  stroke: var(--accent);
}

.faq-item > p {
  margin: 0;
  padding: 0 2px 22px;
  max-width: 60ch;
  font-size: 14px;
  line-height: 1.6;
  color: var(--ink-dim);
}

/* ---------------------------------------------------------------- contact */
/* One gap, not two. This footer paints no band or border of its own, so the
   130px margin and the 78px of padding above the card simply added up to a
   hole. 130px on its own is the same air that sits between any two sections. */
.contact {
  padding: 130px 0 92px;
}

.contact h2 { margin-top: 0; }

/* the same glass as everything else, turned up: the light lands here, so the
   tint carries green instead of white, the blur is deeper, and the rim is the
   brightest on the page. It is the last thing on the page and the only one
   asking for something. */
.contact-card {
  max-width: 640px;
  margin: 0 auto;
  padding: 48px 46px 44px;
  border-radius: 30px;
  --glass-rim: linear-gradient(calc(180deg + var(--lit) * 28deg), rgba(31,221,133,0.62), rgba(31,221,133,0.16) 32%, rgba(255,255,255,0.04) 62%, rgba(31,221,133,0.3));
  background:
    radial-gradient(ellipse 85% 60% at calc(50% + var(--lit) * 32%) -8%, rgba(31,221,133,0.15), transparent 62%),
    linear-gradient(calc(180deg + var(--lit) * 12deg), rgba(255,255,255,0.055), rgba(255,255,255,0.016) 48%, rgba(31,221,133,0.05));
  -webkit-backdrop-filter: blur(28px) saturate(165%);
  backdrop-filter: blur(28px) saturate(165%);
  box-shadow:
    calc(var(--lit) * -14px) 32px 70px rgba(0,0,0,0.55),
    calc(var(--lit) * -3px) 6px 18px rgba(0,0,0,0.32),
    inset 0 -1px 0 rgba(255,255,255,0.045);
}

.contact-card h2,
.contact-card .section-sub,
.contact-card .email { text-align: center; }

.contact-card .section-sub { margin-left: auto; margin-right: auto; }

.contact-form {
  margin-top: 34px;
  display: grid;
  gap: 16px;
}

.botcheck { display: none; }

.form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}

.field { display: grid; gap: 8px; }

.field label {
  font: 500 10px/1 var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--accent-2);
}

.field input,
.field textarea,
.dropdown-btn {
  width: 100%;
  background: rgba(10,12,10,0.34);
  border: 1px solid rgba(241,244,239,0.13);
  border-radius: 12px;
  color: var(--ink);
  font: 400 14px/1.5 var(--font-display);
  padding: 12px 14px;
  transition: border-color 0.15s ease, background 0.15s ease;
}

@media (hover: hover) {
  .field input:hover,
  .field textarea:hover,
  .dropdown-btn:hover {
    border-color: rgba(241,244,239,0.24);
    background: rgba(10,12,10,0.44);
  }
}

.field input:focus-visible,
.field textarea:focus-visible,
.dropdown-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.field ::placeholder { color: var(--ink-dim); opacity: 0.75; }

.field input:-webkit-autofill {
  -webkit-box-shadow: 0 0 0 1000px var(--panel) inset;
  -webkit-text-fill-color: var(--ink);
}

.field textarea { resize: vertical; min-height: 96px; }

/* our replacement for the browser's validation bubble. Sits under the field
   in the label's type, and the field itself carries the same warning colour.
   Placed after the hover rule on purpose: same specificity, so it wins. */
.field-error {
  margin: 0;
  font: 500 10.5px/1.5 var(--font-mono);
  letter-spacing: 0.03em;
  color: var(--warn);
}

.field input[aria-invalid="true"],
.field textarea[aria-invalid="true"] {
  border-color: rgba(255,111,97,0.5);
  background: rgba(255,111,97,0.05);
}

/* Custom dropdown: the native select popup can't be styled, so the list is ours */
.dropdown { position: relative; }

.dropdown-btn {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  text-align: left;
  cursor: pointer;
}

.dropdown.open .dropdown-btn { border-color: rgba(241,244,239,0.22); }

.dropdown-chevron {
  flex: none;
  stroke: var(--accent-2);
  transition: transform 0.18s ease;
}

.dropdown.open .dropdown-chevron { transform: rotate(180deg); }

.dropdown-list {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  z-index: 30;
  margin: 0;
  padding: 6px;
  list-style: none;
  /* Opaque rather than glass. The contact card this sits inside carries its own
     backdrop-filter, which makes it a backdrop root: a nested backdrop-filter can
     only sample what is painted within that card, so the blur here had nothing to
     work on and the textarea underneath read straight through the list. */
  background: var(--panel-alt);
  border: 1px solid rgba(241,244,239,0.14);
  border-radius: 14px;
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.5);
  opacity: 0;
  transform: translateY(-4px);
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.15s ease, transform 0.15s ease, visibility 0.15s;
}

.dropdown.open .dropdown-list {
  opacity: 1;
  transform: none;
  visibility: visible;
  pointer-events: auto;
}

.dropdown-option {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 12px;
  border-radius: 8px;
  font: 400 13.5px/1.4 var(--font-display);
  color: var(--ink);
  cursor: pointer;
}

.dropdown-option.is-active { background: rgba(241, 244, 239, 0.06); }

.dropdown-option[aria-selected="true"] { color: var(--accent); }

.dropdown-option[aria-selected="true"]::after {
  content: "";
  flex: none;
  width: 11px;
  height: 9px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='11' height='9'%3E%3Cpath d='M1 4.5l3 3L10 1' fill='none' stroke='%231FDD85' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat center / contain;
}

/* the send button carries the card's light */
.contact-form .btn-solid {
  box-shadow: 0 8px 30px rgba(31,221,133,0.34), 0 2px 10px rgba(31,221,133,0.2);
}

@media (hover: hover) {
  .contact-form .btn-solid:hover {
    box-shadow: 0 10px 40px rgba(31,221,133,0.5), 0 2px 12px rgba(31,221,133,0.28);
  }
}

/* the button stands alone and the status line drops in underneath it. The
   spacing is a margin on the status rather than a gap here, so the empty live
   region keeps taking no room while staying in the accessibility tree. */
.form-foot {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-top: 10px;
}

.form-foot .btn[disabled] {
  opacity: 0.55;
  pointer-events: none;
}

.form-status {
  font: 500 10.5px/1.5 var(--font-mono);
  letter-spacing: 0.04em;
  color: var(--ink-dim);
  text-align: center;
  margin: 0;
}

.form-status:not(:empty) { margin-top: 14px; }

.form-status.is-ok { color: var(--accent); }

.email {
  margin: 30px 0 0;
  font-size: 13px;
  color: var(--ink-dim);
}

.email a {
  font: 500 10.5px/1 var(--font-mono);
  letter-spacing: 0.05em;
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1px solid var(--border);
  padding-bottom: 3px;
  transition: color 0.15s ease;
}

@media (hover: hover) {
  .email a:hover { color: var(--accent); }
}

.copied-tag {
  font: 500 10px/1 var(--font-mono);
  letter-spacing: 0.05em;
  color: var(--accent);
  margin-left: 10px;
}

/* Service pages sell one thing and say so the whole way down, so the door back
   to the other two sits here, under the form, where it can't pull anyone off
   the pitch on the way in. */
.also-line {
  margin: 34px 0 0;
  text-align: center;
  font-size: 13.5px;
  color: var(--ink-dim);
}

.also-line a {
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1px solid var(--border);
  padding-bottom: 2px;
  transition: color 0.15s ease, border-color 0.15s ease;
}

@media (hover: hover) {
  .also-line a:hover {
    color: var(--accent);
    border-color: rgba(31,221,133,0.4);
  }
}

.footer-legal {
  margin-top: 48px;
  padding-top: 22px;
  border-top: 1px solid var(--border);
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px 18px;
  font-size: 12.5px;
  color: var(--ink-dim);
}

.footer-legal p { margin: 0; }

.footer-legal a {
  color: var(--ink-dim);
  text-decoration: none;
  border-bottom: 1px solid var(--border);
  padding-bottom: 2px;
  transition: color 0.15s ease;
}

@media (hover: hover) {
  .footer-legal a:hover { color: var(--ink); }
}

/* ---------------------------------------------------------------- legal pages */
.legal-page { padding: 84px 0 90px; }

.legal-page h1 {
  font-size: clamp(2rem, 5vw, 2.9rem);
  letter-spacing: -0.03em;
  margin: 12px 0 10px;
}

.legal-updated {
  font: 500 10px/1 var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--accent-2);
  margin: 0 0 40px;
}

.legal-page h2 {
  font-size: 17px;
  margin: 38px 0 8px;
}

.legal-page p,
.legal-page li {
  font-size: 14.5px;
  line-height: 1.65;
  color: var(--ink-dim);
  max-width: 62ch;
}

.legal-page p { margin: 0 0 12px; }

.legal-page a { color: var(--ink); }

/* ---------------------------------------------------------------- lightbox */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 28px;
  background: rgba(4,6,4,0.82);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}

.lightbox[hidden] { display: none; }

.lightbox-panel {
  position: relative;
  width: min(960px, 100%);
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 14px;
  box-shadow: 0 30px 80px rgba(0,0,0,0.6);
}

.lightbox-panel video {
  display: block;
  width: 100%;
  max-height: calc(100vh - 160px);
  max-height: calc(100dvh - 160px); /* mobile Safari: 100vh includes the browser chrome */
  object-fit: contain;
  border-radius: 9px;
  background: var(--bg);
}

.lightbox-close {
  position: absolute;
  top: -14px;
  right: -14px;
  width: 34px;
  height: 34px;
  border-radius: 999px;
  background: var(--panel-alt);
  border: 1px solid var(--border);
  color: var(--ink);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: color 0.15s ease, transform 0.15s ease;
}

@media (hover: hover) {
  .lightbox-close:hover {
    color: var(--accent);
    transform: translateY(-2px);
  }
}

/* ---------------------------------------------------------------- responsive */
@media (max-width: 859.98px) {
  .process-grid,
  .plans-grid,
  .rate-grid,
  .rate-bands,
  .rate-ticks {
    grid-template-columns: 1fr;
  }

  /* stacked again, so the line between the bands goes back across */
  .rate-bands .rate-row + .rate-row {
    border-top: 1px solid rgba(241,244,239,0.08);
    border-left: 0;
  }

  /* thumbnails go two up, and a collapsed panel follows them down to two.
     The gap is a variable because the pair layout has to subtract it before
     splitting the row, so the two cannot drift apart. */
  .work-grid {
    grid-template-columns: repeat(2, 1fr);
    --grid-gap: 14px;
  }

  .work-panel.is-collapsible:not(.is-open) .card:nth-child(n + 3) { display: none; }

  /* The rows changed shape, so the lighting has to be re-read. Plans and rates
     are one column now and sit under the light; the thumbnails are two across,
     one either side of it, with no middle card to sit square on.
     The :nth-child(n) is not decoration. It matches everything, and it is there
     to carry the same specificity as the three-across rules above, which would
     otherwise win on weight no matter how far down the file this sits. */
  .plans-grid > *:nth-child(n),
  .rate-grid > *:nth-child(n) { --lit: -0.25; }

  .work-grid > *:nth-child(2n + 1) { --lit: 0.7; }
  .work-grid > *:nth-child(2n) { --lit: -0.9; }

  /* the hairline moves to the top edge once the cells stack */
  .process-cell + .process-cell {
    border-left: 0;
    border-top: 1px solid rgba(241,244,239,0.08);
  }

  .section { padding-top: 96px; }

  .hero { padding-top: 84px; }

  .contact { padding-top: 96px; }
}

@media (max-width: 639.98px) {
  .lightbox { padding: 14px; }

  .lightbox-panel { padding: 10px; }

  .lightbox-close { top: -10px; right: -10px; }

  .contact-card {
    padding: 34px 22px 30px;
    border-radius: 24px;
  }

  /* stays down here: the base .form-row rule would win on source order */
  .form-row { grid-template-columns: 1fr; }

  /* one up. Two 9:16 boxes side by side leave each about 150px wide, which is
     small for judging an edit, and a collapsed panel only shows one of them
     anyway so the section stays short. */
  .work-grid { grid-template-columns: 1fr; }

  /* pairs stack too. Their own rules carry a class more than the one above, so
     they would otherwise hold the two-column split down to a phone and leave the
     tall card about 80px wide. */
  .work-grid.is-pair,
  .pair-row { grid-template-columns: 1fr; }

  .work-panel.is-collapsible:not(.is-open) .card:nth-child(n + 2) { display: none; }

  /* every panel is full width now, so nothing sits off to one side of the light */
  .work-grid > *:nth-child(n) { --lit: -0.25; }
  .work-grid.is-pair > *:nth-child(n) { --lit: -0.25; }
  .pair-row.leads-wide > *:nth-child(n) { --lit: -0.25; }

  /* three mono labels will not sit on one 375px line at the desktop size, so
     the strip goes full width and the buttons share it evenly */
  .seg { width: 100%; }

  .seg-btn {
    flex: 1;
    padding: 10px 4px;
    font-size: 9px;
    letter-spacing: 0.03em;
  }

  /* the band is two words now, so it stays on the figure's line even here and
     only the side padding needs to come in */
  .rate-service { padding: 20px 22px 17px; }

  .rate-row { padding: 19px 22px; }
}

/* ---------------------------------------------------------------- touch screens */
/* Bigger targets for fingers; hover styles above are already cursor-only. */
@media (pointer: coarse) {
  .btn { min-height: 44px; }

  .btn:active { filter: brightness(0.92); }

  .menu-btn { width: 44px; height: 44px; }

  .dropdown-option { min-height: 44px; }

  /* both are mono labels sized for a cursor, so they need the same padding
     out to a finger-sized target as every other control here */
  .seg-btn { min-height: 44px; }

  .more-btn { min-height: 44px; }

  .field input,
  .field textarea,
  .dropdown-btn,
  .dropdown-option {
    font-size: 16px; /* under 16px, iOS Safari zooms the page when a field gets focus */
  }

  .lightbox-close { width: 42px; height: 42px; }

  .email a { display: inline-block; padding: 10px 0 4px; }
}

/* ---------------------------------------------------------------- reduced motion */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  .dot { animation: none; }

  .faq-icon { transition: none; }

  .dropdown-chevron,
  .dropdown-list {
    transition: none;
  }

  .card,
  .card:hover {
    transform: none;
    transition: none;
  }

  .btn:hover,
  .menu-btn:hover,
  .lightbox-close:hover {
    transform: none;
  }
}
