/* The fonts are in this repository, at assets/fonts/, and every page
   links them before this file. There used to be an @import here as
   well as the <link> in the markup -- a second, independent request
   to fonts.googleapis.com that the HTML audit would not have found,
   and one that fires from inside the stylesheet on every page. */

/* ═══════════════════════════════════════════════════════════════
   SOWTHZIDE
   Light, typographic, no ornament. One accent, used sparingly.
   ═══════════════════════════════════════════════════════════════ */

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
  /* ── Surface ── */
  --bg: #F8F8F7;            /* the page: off-white, neutral */
  --bg-2: #FFFFFF;          /* the lifted band: white on the off-white page */
  --surface: #FFFFFF;
  --border: rgba(10, 10, 10, 0.12);     /* ink @ 12% */
  --border-2: rgba(10, 10, 10, 0.20);   /* ink @ 20% */
  --fill: rgba(10, 10, 10, 0.06);       /* ink @ 6%: a quiet button's ground */
  --ink-ghost: rgba(10, 10, 10, 0.09);  /* a numeral as texture, never text to read */

  /* ── Ink ── */
  /* Every step clears 4.5:1 on white. The old #a1a1aa sat at 2.56:1 and was
     carrying real text (labels, meta, card links), so the scale was re-spaced
     rather than just relabelled. */
  --ink: #0a0a0a;           /* headings            19.3:1 on bg, 19.8:1 on surface */
  --ink-2: #3A3A3A;         /* body copy           10.7:1 / 11.4:1 */
  --ink-3: #555555;         /* secondary            7.0:1 /  7.5:1 */
  --ink-4: #6B6B6B;         /* labels, meta         5.0:1 /  5.3:1 */

  /* ── Accent ──
     The logo's own red, sampled from the wordmark file: the stylesheet
     carried #990000 from the start and the mark was never that colour.
     7.50:1 on the page, 7.96:1 on a white surface, so it is safe for
     text as well as fills. Still used sparingly. */
  --accent: #9E1C1F;
  --accent-hover: #841719;
  --accent-wash: #F2E9E8;      /* accent at 7% over the page */

  /* ── Status ──
     What a message MEANS gets its own colour, so the brand red no longer
     doubles as "something is wrong" (until 10 October 2026 a plain note on
     the contact page sat in the red wash and read as an error). Four roles,
     each a text colour, a wash to sit on and a line to edge it:
       info  neutral ink: notes, hints, pending, "here is how it works"
       ok    green: sent, saved, passed, good news
       warn  amber: a caution, a soft limit, "too many tries"
       bad   red: failed, invalid, blocked, destructive
     The error red is its own value, a little brighter than the brand red,
     so the two can be told apart side by side. Off the stock framework
     scales on purpose. Text on its own wash, and on the page and a white
     surface: info 9.9 / 10.7 / 11.4, ok 5.7 / 6.2 / 6.6, warn 5.9 / 6.4 /
     6.8, bad 6.3 / 6.8 / 7.2. Colour is never the only signal: every box
     carries an icon and the words say what happened. */
  --info: #3A3A3A;
  --info-wash: #EFEFED;
  --info-line: #D6D6D3;
  --ok: #1D6A40;
  --ok-wash: #E8F1EA;
  --ok-line: #B4D2BD;
  --warn: #7F5100;
  --warn-wash: #F8EEDA;
  --warn-line: #E2C483;
  --warn-mark: #9A6400;        /* icons and badges: 4.3:1 on its wash, 5.0:1 under white */
  --bad: #A8231C;
  --bad-wash: #FAECEA;
  --bad-line: #E8BDB8;
  --bad-strong: #8A1B15;       /* a danger button's hover */

  /* ── Type ── */
  --font-display: 'Inter Tight', -apple-system, BlinkMacSystemFont, sans-serif;
  --font-body: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;

  /* ── The dark band ──
     One surface change on the site, spent on the problem section.
     Verified on #0a0a0a: text 18.6, muted 9.4. The accent is the brand
     red itself: 2.2:1 on black, which is fine for the 2px rule it draws
     and would not be for text -- so it is never used for text here. */
  --dark: #0a0a0a;              /* the same black as the ink and the footer */
  --on-dark: #F8F8F7;
  --on-dark-2: #B3B3B3;
  --accent-on-dark: #9E1C1F;    /* the brand red; rules only, never text */
  --line-on-dark: rgba(248, 248, 247, 0.14);

  --track-display: -0.04em;   /* display type above ~72px */
  --track-tight: -0.032em;    /* display type 40px–72px  */
  --track-caps: 0.14em;       /* small uppercase labels  */

  /* ── Metrics ── */
  --max-w: 1760px;          /* the content runs across the width */
  --pad-x: clamp(20px, 4vw, 72px);
  --nav-h: 68px;
  --radius: 8px;
  --radius-lg: 14px;
  --radius-xl: 24px;        /* a card you can open, and the card opened */
  /* 9.4vw meets the 96px floor of the editorial band at exactly 1024px;
     9vw met it at 1067 and left a tablet in landscape 4px short. */
  --section-y: clamp(72px, 9.4vw, 128px);
  /* ── Motion ──
     One expressive curve for entrances, one snappy curve for interface
     feedback. Durations stay short: precision reads as craft, slowness
     reads as lag. */
  /* Elevation. Five steps, and the rule is that a bigger surface reads as
     thicker -- each step deepens the offset AND widens the blur together. A
     modal wearing a chip's shadow looks like paper, not like a layer.

     The first value in every step is the contact shadow: the tight dark edge
     where the surface meets what is behind it. Removing it is what makes a
     shadow look painted on rather than cast.

     Tinted with the ink colour, not pure black, so shadow sits in the same
     family as the type. */
  --elev-1: 0 1px 2px rgba(10, 10, 10, 0.04);
  --elev-2: 0 1px 2px rgba(10, 10, 10, 0.04), 0 4px 12px rgba(10, 10, 10, 0.04);
  --elev-3: 0 1px 2px rgba(10, 10, 10, 0.04), 0 12px 28px rgba(10, 10, 10, 0.07);
  --elev-4: 0 2px 6px rgba(10, 10, 10, 0.05), 0 20px 44px rgba(10, 10, 10, 0.10);
  --elev-5: 0 4px 10px rgba(10, 10, 10, 0.06), 0 32px 72px rgba(10, 10, 10, 0.20);

  /* Spacing. The stylesheet had ten different clamp() values doing the same
     job, which is how a layout drifts out of rhythm one component at a time. */
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: clamp(24px, 3vw, 34px);
  --space-7: clamp(28px, 4.5vw, 56px);
  --space-8: clamp(40px, 6vw, 72px);

  --ease: cubic-bezier(0.22, 1, 0.36, 1);        /* entrances, long travel */
  --ease-out: cubic-bezier(0.32, 0.72, 0, 1);    /* hover, press, UI */
  --dur-fast: 0.18s;
  --dur: 0.32s;
  --dur-slow: 0.72s;
}

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

body {
  background: var(--bg);
  color: var(--ink-2);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-display);
  color: var(--ink);
  font-weight: 600;
  line-height: 1.08;
  letter-spacing: -0.028em;
}

/* An author `display` beats the UA stylesheet, so any component with its own
   display value ignores the hidden attribute. .nav__signed is inline-flex,
   which is why Sign in and Sign out were both showing at once. */
[hidden] { display: none !important; }

a { color: inherit; text-decoration: none; }
img { max-width: 100%; display: block; }
button { font-family: inherit; cursor: pointer; }
ul { list-style: none; }

::selection { background: var(--accent); color: #fff; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}

.container {
  max-width: var(--max-w);
  margin: 0 auto;
  padding-left: var(--pad-x);
  padding-right: var(--pad-x);
}

.section { padding: var(--section-y) 0; }

/* ═══════════════════════════════════════════
   NAVIGATION
   ═══════════════════════════════════════════ */

.nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  height: var(--nav-h);
  background: rgba(248, 248, 247, 0.82);
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  border-bottom: 1px solid transparent;
  transition: border-color 0.3s var(--ease), opacity 0.5s var(--ease);
}

.nav.scrolled { border-bottom-color: var(--border); }

/* Three columns: the logo, the studio's pages centred on the bar,
   and Plus with the account at the right. The two outer columns share
   the leftover equally, which is what keeps the middle centred. */
.nav__inner {
  display: grid;
  grid-template-columns: minmax(max-content, 1fr) auto minmax(max-content, 1fr);
  align-items: center;
  height: var(--nav-h);
  gap: 32px;
}

.nav__logo { display: flex; align-items: center; justify-self: start; }
/* The mark is a two-line wordmark plus the goat at about 2.05:1, not the
   old square glyph, so it needs height to stay legible rather than width. */
.nav__logo img { height: 34px; width: auto; transition: height 0.3s var(--ease); }
/* main.js toggles .scrolled, not .is-scrolled. */
.nav.scrolled .nav__logo img { height: 30px; }

.nav__links,
.nav__end {
  display: flex;
  align-items: center;
  gap: 4px;
}

.nav__end { justify-self: end; }

/* No fill and no colour change on hover: the red underline below is
   the whole of the hover state. */
.nav__link {
  padding: 8px 14px;
  font-size: 14.5px;
  font-weight: 500;
  color: var(--ink-2);
  border-radius: var(--radius);
}


/* Phone reads as the nav's one call to action */
.nav__phone {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-left: 10px;
  padding: 9px 16px;
  border: 1px solid var(--border-2);
  border-radius: 100px;
  font-size: 14px;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  color: var(--ink);
  transition: border-color 0.2s var(--ease), background 0.2s var(--ease);
}

.nav__phone svg { color: var(--accent); flex-shrink: 0; }
@media (hover: hover) and (pointer: fine) {
  .nav__phone:hover { border-color: var(--ink);
  }
}


.nav__toggle {
  display: none;
  grid-column: 3;
  justify-self: end;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 40px;
  height: 40px;
  margin-left: auto;
  background: none;
  border: 0;
}

.nav__toggle span {
  display: block;
  height: 1.5px;
  width: 20px;
  margin-inline: auto;
  background: var(--ink);
  transition: transform 0.3s var(--ease), opacity 0.2s;
}

.nav__toggle.open span:nth-child(1) { transform: translateY(6.5px) rotate(45deg); }
.nav__toggle.open span:nth-child(2) { opacity: 0; }
.nav__toggle.open span:nth-child(3) { transform: translateY(-6.5px) rotate(-45deg); }

.nav__mobile {
  position: fixed;
  top: var(--nav-h);
  left: 0;
  right: 0;
  z-index: 99;
  display: flex;
  flex-direction: column;
  padding: 8px var(--pad-x) 24px;
  background: var(--bg);
  border-bottom: 1px solid var(--border);
  transform: translateY(-120%);
  transition: transform 0.38s var(--ease);
}

.nav__mobile.open { transform: translateY(0); }

.nav__mobile a {
  padding: 15px 0;
  font-family: var(--font-display);
  font-size: 19px;
  font-weight: 500;
  color: var(--ink);
  border-bottom: 1px solid var(--border);
}

.nav__mobile a:last-child { border-bottom: 0; color: var(--accent); }

/* ═══════════════════════════════════════════
   BUTTONS
   ═══════════════════════════════════════════ */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 44px;
  padding: 0 20px;
  border: 1px solid transparent;
  border-radius: var(--radius);
  font-size: 14.5px;
  font-weight: 500;
  white-space: nowrap;
  transition: background 0.2s var(--ease), border-color 0.2s var(--ease),
              color 0.2s var(--ease), transform 0.2s var(--ease);
}

.btn-lg { height: 52px; padding: 0 26px; font-size: 15.5px; }

.btn-primary { background: var(--ink); color: #fff; }
@media (hover: hover) and (pointer: fine) {
  .btn-primary:hover { background: var(--ink-2); transform: translateY(-1px);
  }
}


.btn-ghost {
  background: transparent;
  border-color: var(--border-2);
  color: var(--ink);
}
@media (hover: hover) and (pointer: fine) {
  .btn-ghost:hover { border-color: var(--ink); background: var(--bg-2);
  }
}

.hero__ctas {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px;
  margin-bottom: 52px;
}

/* ═══════════════════════════════════════════
   PAGE HERO  (inner pages)
   ═══════════════════════════════════════════ */

.page-hero {
  padding-top: calc(var(--nav-h) + clamp(56px, 8vw, 104px));
  padding-bottom: clamp(48px, 6vw, 80px);
  border-bottom: 1px solid var(--border);
}

/* Centred: left-aligned at 820px inside a 1320px container stranded ~330px
   of empty space on the right of every inner page. */
.page-hero__inner {
  max-width: 900px;
  margin-inline: auto;
  text-align: center;
}

.page-hero__title {
  font-size: clamp(34px, 5.2vw, 62px);
  font-weight: 600;
  line-height: 1.06;
  letter-spacing: -0.032em;
  margin-bottom: 24px;
}

.page-hero__sub {
  max-width: 740px;
  margin-inline: auto;
  font-size: clamp(16px, 1.4vw, 18px);
  line-height: 1.62;
  color: var(--ink-3);
  margin-bottom: 16px;
}

/* ═══════════════════════════════════════════
   SECTION HEADS
   ═══════════════════════════════════════════ */

.section-head {
  max-width: 780px;
  margin: 0 0 58px;
  text-align: left;
}

.section-title {
  font-size: clamp(28px, 3.6vw, 44px);
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: var(--track-tight);
  max-width: 22ch;
  margin-bottom: 16px;
  text-wrap: balance;
}

.section-body {
  font-size: 16.5px;
  line-height: 1.62;
  color: var(--ink-3);
  max-width: 56ch;
  margin-inline: auto;
}


.tag {
  padding: 6px 13px;
  border: 1px solid var(--border);
  border-radius: 100px;
  background: var(--bg-2);
  font-size: 12.5px;
  font-weight: 500;
  color: var(--ink-3);
}


.price-panel {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 48px;
  padding: 52px;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}

.price-panel__figure {
  font-family: var(--font-display);
  font-size: clamp(30px, 4vw, 44px);
  font-weight: 600;
  line-height: 1.08;
  letter-spacing: -0.03em;
  color: var(--ink);
  margin: 12px 0 8px;
  font-variant-numeric: tabular-nums;
}

.price-panel__note { font-size: 14.5px; color: var(--ink-3); }
.price-panel__actions { display: flex; flex-wrap: wrap; gap: 12px; }

/* ═══════════════════════════════════════════
   PORTFOLIO
   ═══════════════════════════════════════════ */

/* Four items: 4-up keeps the section compact rather than leaving an orphan
   on a second row. Drops to 2-up before the cards get too small to read. */
/* Shipped work: a short list beside one large preview.

   The previous version gave each project its own full-width row. Every
   headline was legible, which the 224px thumbnails before it were not, but
   five rows came to about 1280px of homepage for five links. This keeps the
   previews large and puts the section back inside one screen: the list is the
   index, and the stage shows whichever one you are pointing at. */
.workshow {
  display: grid;
  grid-template-columns: minmax(280px, 0.78fr) 1fr;
  gap: clamp(28px, 4vw, 56px);
  align-items: start;
}

/* ── the index ── */

.workshow__list { border-top: 1px solid var(--border); }

.workshow__item {
  position: relative;
  display: grid;
  grid-template-columns: 34px 1fr 20px;
  align-items: center;
  gap: 14px;
  padding: 17px 4px;
  border-bottom: 1px solid var(--border);
  transition: padding-left 0.3s var(--ease), background 0.25s var(--ease);
}

.workshow__item::before {
  content: '';
  position: absolute;
  left: 0; top: -1px; bottom: -1px;
  width: 2px;
  background: var(--accent);
  transform: scaleY(0);
  transition: transform 0.3s var(--ease);
}

.workshow__item.is-active::before { transform: scaleY(1); }
.workshow__item.is-active { padding-left: 16px; }

.workshow__num {
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--ink-4);
  font-variant-numeric: tabular-nums;
  transition: color 0.25s var(--ease);
}

.workshow__item.is-active .workshow__num { color: var(--accent); }

.workshow__text { display: flex; flex-direction: column; gap: 3px; min-width: 0; }

.workshow__name {
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.022em;
  color: var(--ink);
  transition: color 0.25s var(--ease);
}

.workshow__item.is-active .workshow__name { color: var(--accent); }

.workshow__sector {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-4);
}

.workshow__arrow {
  font-size: 15px;
  color: var(--ink-4);
  opacity: 0;
  transform: translateX(-4px);
  transition: opacity 0.25s var(--ease), transform 0.25s var(--ease);
}

.workshow__item.is-active .workshow__arrow {
  opacity: 1;
  transform: none;
  color: var(--accent);
}

/* ── the stage ── */

.workshow__stage {
  position: relative;
  /* Panels are stacked on top of each other, so the stage needs a height of
     its own: 16:10 for the capture plus the bar underneath it. */
  aspect-ratio: 16 / 10;
}

.workshow__panel {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.4s var(--ease), visibility 0.4s var(--ease);
}

.workshow__panel.is-active { opacity: 1; visibility: visible; }

.workshow__shot {
  display: block;
  flex: 1 1 auto;
  min-height: 0;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--bg-2);
}

.workshow__shot img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 0;
}

.workshow__bar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding-top: 14px;
}

.workshow__host { font-size: 13px; color: var(--ink-4); }

.workshow__live {
  padding: 9px 17px;
  border: 1px solid var(--border-2);
  border-radius: 999px;
  background: var(--bg);
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 500;
  color: var(--ink-3);
  white-space: nowrap;
  cursor: pointer;
  transition: border-color 0.2s var(--ease), background 0.2s var(--ease),
              color 0.2s var(--ease);
}
@media (hover: hover) and (pointer: fine) {
  .workshow__live:hover { border-color: var(--ink); background: var(--ink); color: #fff;
  }
}


/* Before the JavaScript runs, only the first panel is marked active, so the
   stage is never blank and nothing depends on a script to be readable. */

@media (max-width: 900px) {
  .workshow { grid-template-columns: 1fr; gap: 24px; }
  /* Stage first on a phone: the picture is the thing worth leading with,
     and the list reads as a caption strip underneath it. */
  .workshow__stage { order: -1; }
  .workshow__item { padding: 15px 4px; }
  .workshow__item.is-active { padding-left: 12px; }
}

.works-more {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  margin-top: 40px;
  padding-top: 28px;
  border-top: 1px solid var(--border);
  font-size: 15px;
  color: var(--ink-3);
}

.works-more__link { font-weight: 500; color: var(--accent); }
@media (hover: hover) and (pointer: fine) {
  .works-more__link:hover { text-decoration: underline;
  }
}

.story-body p, .founder-body p {
  font-size: 17px;
  line-height: 1.78;
  color: var(--ink-2);
  margin-bottom: 26px;
  max-width: 720px;
}

.story-body p:last-child, .founder-body p:last-child { margin-bottom: 0; }

.founder-sig {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: 32px;
  padding-top: 26px;
  border-top: 1px solid var(--border);
}

.founder-sig__photo {
  width: 46px;
  height: 46px;
  border-radius: 50%;
  overflow: hidden;
  border: 1px solid var(--border);
  flex-shrink: 0;
}

.founder-sig__photo img { width: 100%; height: 100%; object-fit: cover; }

.founder-sig__name {
  font-family: var(--font-display);
  font-size: 15.5px;
  font-weight: 600;
  color: var(--ink);
}

.founder-sig__role { font-size: 13.5px; color: var(--ink-4); }

/* ═══════════════════════════════════════════
   CTA BLOCK
   ═══════════════════════════════════════════ */

.cta-block { padding: var(--section-y) 0; border-top: 1px solid var(--border); }

.cta-block__text h2 {
  font-size: clamp(25px, 3.2vw, 38px);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.12;
  margin-bottom: 12px;
  max-width: 620px;
}

.cta-block__text p { font-size: 16px; color: var(--ink-3); max-width: 520px; }

/* ═══════════════════════════════════════════
   CONTACT
   ═══════════════════════════════════════════ */

.contact-grid { display: grid; grid-template-columns: 1fr 400px; gap: 96px; }

.cf-field { position: relative; margin-bottom: 36px; }

.cf-field input, .cf-field textarea {
  width: 100%;
  padding: 13px 15px;
  background: var(--surface);
  border: 1px solid var(--border-2);
  border-radius: var(--radius);
  font-family: inherit;
  font-size: 15.5px;
  color: var(--ink);
  resize: none;
  transition: border-color 0.2s var(--ease), box-shadow 0.2s var(--ease);
}


.cf-field label {
  display: block;
  margin-bottom: 8px;
  font-size: 13.5px;
  font-weight: 500;
  color: var(--ink-2);
}

.cf-field__line { display: none; }

.cf-submit {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  height: 48px;
  padding: 0 24px;
  background: var(--ink);
  color: #fff;
  border: 0;
  border-radius: var(--radius);
  font-size: 15px;
  font-weight: 500;
  transition: background 0.2s var(--ease);
}
@media (hover: hover) and (pointer: fine) {
  .cf-submit:hover:not(:disabled) { background: #262626;
  }
}

.cf-submit:disabled { opacity: 0.55; cursor: default; }

.cf-note { margin-top: 14px; font-size: 13.5px; color: var(--ink-4); }
/* The same note, sitting under its own field rather than under the
   whole form, so it needs the gap a field hint has and not the gap a
   form footer has. */
.cf-note--tight { margin-top: 7px; line-height: 1.55; }
/* The same note opening a form, as its first line: it introduces the
   fields, so the gap falls after it rather than before. */
.cf-note--lead { margin: 0 0 20px; font-size: 15px; color: var(--ink-3); }

.cf-feedback {
  margin-top: 16px;
  padding: 13px 16px;
  border-radius: var(--radius);
  font-size: 14.5px;
}

/* Its colours, by role (--success, --error, --info, --warning): see Status. */

.cf-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.ci-block { padding: 26px 0; border-bottom: 1px solid var(--border); }
.ci-block:first-child { padding-top: 0; }

.ci-label {
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-4);
  margin-bottom: 7px;
}

.ci-value { font-size: 15.5px; color: var(--ink-2); line-height: 1.6; }
@media (hover: hover) and (pointer: fine) {
  .ci-value a:hover { color: var(--accent);
  }
}


.ci-email-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.ci-email-note { font-size: 12px; color: var(--ink-4); }

.ci-socials { display: flex; flex-wrap: wrap; gap: 8px; }

.ci-social {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 13px;
  border: 1px solid var(--border);
  border-radius: 100px;
  font-size: 13px;
  color: var(--ink-2);
  transition: border-color 0.2s, color 0.2s;
}
@media (hover: hover) and (pointer: fine) {
  .ci-social:hover { border-color: var(--ink); color: var(--ink);
  }
}


/* ═══════════════════════════════════════════
   FOOTER  —  dark, for contrast
   A signature, not a sitemap: three rows. The logo and the five pages
   on one line; the studio's sentence beside its address, phone, email
   and hours as one run of small text; the registered name, the legal
   pages and the social links. Hairlines between, nothing in columns,
   nothing in a card.
   ═══════════════════════════════════════════ */

.footer {
  background: var(--ink);
  color: var(--on-dark-2);
  padding: clamp(44px, 5.5vw, 64px) 0 28px;
}

.footer__row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 18px 40px;
}

.footer__row--top { padding-bottom: clamp(22px, 2.8vw, 32px); }

.footer__logo { display: inline-block; }
.footer__logo img { height: 40px; width: auto; }

.footer__nav { display: flex; flex-wrap: wrap; gap: 6px 26px; }

.footer__nav a {
  font-size: 14.5px;
  font-weight: 500;
  color: var(--on-dark);
  transition: color 0.2s var(--ease);
}

.footer__row--where {
  align-items: baseline;
  padding: clamp(22px, 2.8vw, 32px) 0;
  border-top: 1px solid var(--line-on-dark);
  border-bottom: 1px solid var(--line-on-dark);
}

.footer__line {
  font-family: var(--font-display);
  font-size: clamp(18px, 1.8vw, 22px);
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--on-dark);
}

.footer__nap {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 22px;
  max-width: 720px;
  font-style: normal;
  font-size: 14px;
  line-height: 1.6;
  color: var(--on-dark-2);
}

.footer__nap a { color: var(--on-dark); transition: color 0.2s var(--ease); }

.footer__row--bottom { padding-top: 24px; font-size: 13.5px; }

.footer__copy { color: rgba(248, 248, 247, 0.55); font-variant-numeric: tabular-nums; }

.footer__legal { display: flex; flex-wrap: wrap; gap: 6px 18px; }

.footer__legal a,
.footer__legal .footer__choice {
  font-size: 13.5px;
  color: var(--on-dark-2);
  transition: color 0.2s var(--ease);
}

.footer__socials { display: flex; gap: 8px; }

@media (hover: hover) and (pointer: fine) {
  .footer__nav a:hover,
  .footer__nap a:hover,
  .footer__legal a:hover,
  .footer__legal .footer__choice:hover { color: var(--accent-wash); }
}

@media (max-width: 639px) {
  .footer__row { flex-direction: column; align-items: flex-start; }
  .footer__row--where { gap: 16px; }
}

.social-link {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border: 1px solid #27272a;
  border-radius: var(--radius);
  color: #a1a1aa;
  transition: border-color 0.2s, color 0.2s, background 0.2s;
}
@media (hover: hover) and (pointer: fine) {
  .social-link:hover { border-color: #3f3f46; color: #fff; background: #18181b;
  }
}


/* ═══════════════════════════════════════════
   LIVE PREVIEW MODAL
   ═══════════════════════════════════════════ */

.webmodal {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(14px, 3vw, 40px);
  opacity: 0;
  pointer-events: none;
  /* Hidden for the keyboard and the screen reader as well as the eye:
     a closed dialog at opacity 0 was still in the Tab order. The
     visibility change is delayed on the way out so the fade can run. */
  visibility: hidden;
  transition: opacity 0.28s var(--ease), visibility 0s linear 0.28s;
}

.webmodal.is-open {
  opacity: 1;
  pointer-events: auto;
  visibility: visible;
  transition: opacity 0.28s var(--ease), visibility 0s;
}
.webmodal__backdrop { position: absolute; inset: 0; background: rgba(10, 10, 10,0.55); backdrop-filter: blur(4px); }

.webmodal__panel {
  position: relative;
  display: flex;
  flex-direction: column;
  width: min(1180px, 100%);
  height: min(84vh, 820px);
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--elev-5);
  /* Arrives from 0.96 with its backdrop, as one surface. Centred, so
     no transform-origin: it is not anchored to a trigger. */
  transform: scale(0.96);
  transition: transform 0.25s var(--ease);
}

.webmodal.is-open .webmodal__panel { transform: scale(1); }

.webmodal__bar {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px 16px;
  background: var(--bg-2);
  border-bottom: 1px solid var(--border);
}

.webmodal__dots { display: inline-flex; gap: 6px; }
.webmodal__dots i { width: 8px; height: 8px; border-radius: 50%; background: var(--border-2); }

.webmodal__title {
  font-family: var(--font-display);
  font-size: 13.5px;
  font-weight: 500;
  color: var(--ink-3);
  margin-right: auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.webmodal__actions { display: flex; align-items: center; gap: 8px; }

.webmodal__open, .webmodal__close {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 32px;
  padding: 0 13px;
  border: 1px solid var(--border-2);
  border-radius: var(--radius);
  background: #fff;
  font-size: 13px;
  font-weight: 500;
  color: var(--ink-2);
  transition: border-color 0.2s, color 0.2s;
}
@media (hover: hover) and (pointer: fine) {
  .webmodal__open:hover,
  .webmodal__close:hover { border-color: var(--ink); color: var(--ink);
  }
}

.webmodal__viewport { flex: 1; background: #fff; }
.webmodal__frame { width: 100%; height: 100%; border: 0; }
.webmodal__hint { display: none; }

html.modal-open, body.modal-open { overflow: hidden; }

/* ═══════════════════════════════════════════
   MOTION SYSTEM
   ═══════════════════════════════════════════ */

/* ── Scroll reveal ──
   Children stagger off --i, set by JS, so a grid resolves in sequence
   instead of snapping in as one block. */
/* Gated on .js: without JavaScript nothing is ever hidden, so the page
   degrades to fully visible rather than blank. */
/* Same defect, eighteen pixels of it, staggered between siblings by
   reveal-delay-1..8 on the ten marketing pages. */
.js .reveal {
  opacity: 0;
  transform: translateY(20px);           /* travel 16-32px: 20 */
  transition: opacity var(--dur-slow) var(--ease),
              transform var(--dur-slow) var(--ease);
  transition-delay: calc(var(--i, 0) * 75ms);   /* siblings 60-90ms apart */
  will-change: opacity, transform;
}

.js .reveal.visible { opacity: 1; transform: none; }

/* main.js adds this on transitionend. A compositor layer per settled
   block, kept for the life of a long page, is the cost of forgetting. */
.js .reveal.is-settled { will-change: auto; }

/* Legacy per-element delay classes still used in the markup */
.reveal-delay-1 { --i: 1; } .reveal-delay-2 { --i: 2; }
.reveal-delay-3 { --i: 3; } .reveal-delay-4 { --i: 4; }
.reveal-delay-5 { --i: 5; } .reveal-delay-6 { --i: 6; }
.reveal-delay-7 { --i: 7; } .reveal-delay-8 { --i: 8; }

/* ── Page entrance ── */
/* Entrance without displacement. The rise was staggered across
   siblings, so each pair sat 14px further apart than its resting gap
   until the later one caught up -- the page previewed spacing it did
   not have, then closed it. The stagger stays; the movement goes. */
.js .animate-1, .js .animate-2, .js .animate-3,
.js .animate-4, .js .animate-5 {
  opacity: 0;
  transition: opacity 0.48s var(--ease);
}

.js.is-ready .animate-1 { opacity: 1; transform: none; transition-delay: 0.04s; }
.js.is-ready .animate-2 { opacity: 1; transform: none; transition-delay: 0.10s; }
.js.is-ready .animate-3 { opacity: 1; transform: none; transition-delay: 0.28s; }
.js.is-ready .animate-4 { opacity: 1; transform: none; transition-delay: 0.34s; }
.js.is-ready .animate-5 { opacity: 1; transform: none; transition-delay: 0.40s; }

/* ── Scroll progress ── */
.scroll-progress {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 200;
  height: 2px;
  width: 100%;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: 0 50%;
  pointer-events: none;
}

/* ── Nav underline wipe ── */
.nav__link { position: relative; }

.nav__link::after {
  content: '';
  position: absolute;
  left: 14px;
  right: 14px;
  bottom: 5px;
  height: 1.5px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform var(--dur) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .nav__link:hover::after { transform: scaleX(1);
  }
}


/* ── Buttons: press feedback and travelling arrow ── */
/* The whole control, children included, so it reads as a physical press. */
.btn:active { transform: scale(0.97); }
.btn svg { transition: transform var(--dur) var(--ease-out); }
@media (hover: hover) and (pointer: fine) {
  .btn:hover svg { transform: translateX(3px);
  }
}


/* ── Links that underline themselves ── */
.works-more__link, .price-note a {
  position: relative;
  text-decoration: none;
}

.works-more__link::after, .price-note a::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -2px;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: 100% 50%;
  transition: transform var(--dur) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .works-more__link:hover::after,
  .price-note a:hover::after {
    transform: scaleX(1);
    transform-origin: 0 50%;
  }
}

@media (hover: hover) and (pointer: fine) {
  .works-more__link:hover,
  .price-note a:hover { text-decoration: none;
  }
}


/* ── Social tiles ── */
.social-link svg { transition: transform var(--dur) var(--ease-out); }
@media (hover: hover) and (pointer: fine) {
  .social-link:hover svg { transform: scale(1.12);
  }
}


/* ── Counting figures hold their width so nothing jitters ── */
.price-panel__figure, .svc-card__price, .price-row__price {
  font-variant-numeric: tabular-nums;
}

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0,0,0,0);
  white-space: nowrap;
  border: 0;
}

/* ═══════════════════════════════════════════
   RESPONSIVE
   ═══════════════════════════════════════════ */

@media (max-width: 1024px) {
  .contact-grid { grid-template-columns: 1fr; gap: 48px; }
}

@media (max-width: 768px) {
  .nav__links,
  .nav__end { display: none; }
  .nav__toggle { display: flex; }
  .price-panel { grid-template-columns: 1fr; padding: 32px 26px; gap: 24px; }
  .price-panel__actions { width: 100%; }
  .price-panel__actions .btn { flex: 1 1 auto; }
  .footer { padding-bottom: 88px; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal, .reveal.visible,
  .animate-1, .animate-2, .animate-3, .animate-4, .animate-5 {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  .scroll-progress { display: none; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}


@keyframes rippleExpand {
  0%   { width: 0;     height: 0;     opacity: 0.55; border-width: 1.5px; }
  100% { width: 190px; height: 190px; opacity: 0;    border-width: 0.5px; }
}

/* Tilted elements need depth and a promoted layer */
.vm-card, .value-card, .founder-body, [data-tilt] {
  transform-style: preserve-3d;
  will-change: transform;
}


.cf-optional { color: var(--ink-4); font-weight: 400; }

/* The age confirmation sits between the message box and the button,
   where it is read rather than stepped over. */
.cf-age { margin: 18px 0 22px; }

/* ── Account ── */
.account { max-width: 520px; margin-inline: auto; }
.account__form { margin-top: 28px; }
.account__form .btn { width: 100%; }

/* Under the Google button in Instagram's (and similar) browsers. */
.auth-inapp { margin: 10px 0 0; line-height: 1.5; }   /* a warning box: see Status */

/* ── Email preferences ──
   Two choices, each a short heading, a line on what it means, and its
   button, ruled apart; the page reached from the foot of an email. */
.prefs__opt {
  display: grid;
  justify-items: start;
  gap: 10px;
  padding: 24px 0;
  border-top: 1px solid var(--border);
}

.prefs__opt:last-child { border-bottom: 1px solid var(--border); }

.prefs__title {
  font-family: var(--font-display);
  font-size: 19px;
  font-weight: 600;
  letter-spacing: -0.018em;
  color: var(--ink);
}

.prefs__text {
  font-size: 15.5px;
  line-height: 1.6;
  color: var(--ink-3);
  text-wrap: pretty;
}

.prefs__opt .btn { margin-top: 6px; }

/* ── Notice ── */
.notice {   /* an info box: see Status */
  padding: 18px 20px;
  border-radius: var(--radius);
  font-size: 14.5px;
  line-height: 1.62;
  margin-bottom: 32px;
}

.notice strong { display: block; margin-bottom: 4px; color: var(--ink); }


/* ═══════════════════════════════════════════
   SOWTHZIDE PLUS
   ═══════════════════════════════════════════ */

.pz-eyebrow {
  display: block;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
}

/* ── Edition chooser ── */

.pz-paths {
  display: grid;
  /* auto-fit rather than a fixed count: the shelf went from two
     editions to three, and hard-coding the number is how it breaks
     again at four. */
  grid-template-columns: repeat(auto-fit, minmax(270px, 1fr));
  gap: clamp(20px, 3vw, 32px);
}

.pz-path {
  display: flex;
  flex-direction: column;
  padding: clamp(28px, 3.4vw, 40px);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
}

.pz-path__name {
  font-family: var(--font-display);
  font-size: clamp(21px, 2.3vw, 27px);
  font-weight: 600;
  line-height: 1.16;
  letter-spacing: -0.026em;
  margin: 14px 0 20px;
  max-width: 18ch;
}

.pz-path__list { list-style: none; margin: 0 0 26px; padding: 0; }

.pz-path__list li {
  position: relative;
  padding-left: 21px;
  margin-bottom: 10px;
  font-size: 15px;
  line-height: 1.6;
  color: var(--ink-3);
}

.pz-path__list li::before {
  content: '';
  position: absolute;
  left: 0; top: 11px;
  width: 9px; height: 1.5px;
  background: var(--accent);
}

.pz-path__price {
  font-family: var(--font-display);
  font-size: 30px;
  font-weight: 600;
  letter-spacing: -0.03em;
  color: var(--ink);
  margin: auto 0 20px;
}

/* The qualifier sits under the figure rather than beside it. It used
   to be a short tail -- "once, including GST" -- that fitted on the
   same line; saying WHEN the price applies made it long enough to
   wrap, and it wrapped badly, dropping "Plus launches" onto a line of
   its own with a gap above it, reading as a separate sentence. */
.pz-path__price span {
  display: block;
  margin-top: 6px;
  font-family: var(--font-body);
  font-size: 13.5px;
  font-weight: 400;
  letter-spacing: 0;
  line-height: 1.5;
  color: var(--ink-4);
  text-wrap: pretty;
}

.pz-note {
  margin-top: clamp(28px, 4vw, 44px);
  padding-top: 22px;
  border-top: 1px solid var(--border);
  font-size: 14px;
  line-height: 1.7;
  color: var(--ink-4);
  max-width: 68ch;
}

.pz-note a { color: var(--accent); font-weight: 500; }
@media (hover: hover) and (pointer: fine) {
  .pz-note a:hover { text-decoration: underline;
  }
}


/* ── Gates ──
   Somebody who has not signed in or not bought yet is a visitor, not an
   error, so these read as an invitation rather than a refusal. */

.pz-gate {
  padding: clamp(40px, 6vw, 72px) clamp(24px, 4vw, 48px);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  text-align: center;
}

.pz-gate__lead {
  font-family: var(--font-display);
  font-size: clamp(19px, 2.2vw, 25px);
  font-weight: 600;
  letter-spacing: -0.022em;
  color: var(--ink);
  margin-bottom: 10px;
}

.pz-gate__note {
  font-size: 15px;
  line-height: 1.7;
  color: var(--ink-3);
  max-width: 44ch;
  margin: 0 auto 26px;
}

.pz-gate__who {
  margin-top: 18px;
  font-size: 13px;
  color: var(--ink-4);
}

.pz-gate__who strong { color: var(--ink-2); font-weight: 600; }

.pz-gate__uid { font-size: 12px; color: var(--ink-4); }
.pz-gate__uid code { font-size: 11.5px; color: var(--ink-3); }

.pz-linkbtn {
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  color: var(--accent);
  cursor: pointer;
  text-decoration: underline;
}

.pz-gate__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  justify-content: center;
  margin-top: 26px;
}

/* ── Continue card ── */

.pz-continue {
  margin-top: clamp(28px, 4vw, 44px);
  padding: clamp(24px, 3vw, 34px);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
}

.pz-continue__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
}

.pz-continue__meta {
  font-size: 12.5px;
  color: var(--ink-4);
  font-variant-numeric: tabular-nums;
}

.pz-continue__name {
  font-family: var(--font-display);
  font-size: clamp(20px, 2.2vw, 26px);
  font-weight: 600;
  letter-spacing: -0.024em;
  margin: 10px 0 22px;
}

/* The stage strip is the progress bar: seven named steps beat a percentage
   nobody can act on. */
.pz-stages {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  list-style: none;
  margin: 0 0 22px;
  padding: 0;
  counter-reset: none;
}

.pz-stage {
  flex: 1 1 88px;
  padding: 9px 10px 10px;
  border-top: 2px solid var(--border-2);
  font-size: 12px;
  color: var(--ink-4);
}

.pz-stage span {
  display: block;
  font-family: var(--font-display);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.08em;
  color: var(--line, var(--border-2));
  margin-bottom: 3px;
  font-variant-numeric: tabular-nums;
}

.pz-stage.is-done { border-top-color: var(--ok); color: var(--ink-3); }
.pz-stage.is-done span { color: var(--ok); }

.pz-stage.is-now {
  border-top-color: var(--ink);
  color: var(--ink);
  font-weight: 600;
}

.pz-stage.is-now span { color: var(--ink); }

.pz-continue__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
}

.pz-continue__next { font-size: 15px; color: var(--ink-3); }
.pz-continue__next strong { color: var(--ink); font-weight: 600; }

/* ── Shelves ── */

.pz-shelves { margin-top: clamp(36px, 5vw, 60px); }

.pz-shelves__head {
  padding-bottom: 14px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 26px;
}

.pz-shelf { margin-bottom: 30px; }

.pz-shelf__name {
  font-family: var(--font-display);
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -0.016em;
  color: var(--ink);
  margin-bottom: 12px;
}

.pz-shelf__list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(232px, 1fr));
  gap: 8px 24px;
  list-style: none;
  margin: 0;
  padding: 0;
}

.pz-shelf__list li {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 0;
  border-bottom: 1px solid var(--border);
  font-size: 14.5px;
  color: var(--ink-3);
}

/* Every item is a placeholder until the library is written, and the mark says
   so rather than pretending these are links. */
.pz-lock {
  flex: 0 0 auto;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--border-2);
}

.page-hero--plus { padding-bottom: clamp(20px, 3vw, 32px); }

@media (max-width: 860px) {
  .pz-paths { grid-template-columns: 1fr; }
}

@media (max-width: 560px) {
  .pz-stages { gap: 1px; }
  .pz-stage { flex-basis: 64px; font-size: 11px; }
  .pz-continue__foot { flex-direction: column; align-items: stretch; }
}

/* ── Client systems ── */

.ld__grid { min-width: 720px; }

.ld__head, .ld__row {
  display: grid;
  grid-template-columns: minmax(180px, 1.4fr) repeat(6, minmax(62px, 1fr));
  gap: 8px;
  align-items: center;
}

.ld__head {
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border-2);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-4);
}

.ld__head span:not(:first-child) { text-align: center; }

.ld__row { padding: 9px 0; border-bottom: 1px solid var(--border); }

.ld__label { font-size: 14px; color: var(--ink); min-width: 0; }


.ld__cell input { text-align: center; font-variant-numeric: tabular-nums; }


.bd__tabs {
  display: flex;
  gap: 6px;
  margin: clamp(24px, 3vw, 34px) 0 18px;
  border-bottom: 1px solid var(--border);
}

.bd__tab {
  padding: 10px 18px;
  border: 0;
  border-bottom: 2px solid transparent;
  background: none;
  font-family: var(--font-body);
  font-size: 15px;
  color: var(--ink-4);
  cursor: pointer;
}
@media (hover: hover) and (pointer: fine) {
  .bd__tab:hover { color: var(--ink-2);
  }
}

.bd__tab.is-active { color: var(--ink); border-bottom-color: var(--accent); font-weight: 500; }

.bd__table { min-width: 680px; }
.bd__table td { padding: 7px 8px 7px 0; }
.bd__table input[type="date"] { min-width: 130px; }

.apv__row {
  display: grid;
  grid-template-columns: 26px minmax(0, 1fr) 140px 140px 78px 34px;
  gap: 8px;
  align-items: center;
}

.apv__hrs { text-align: center; font-variant-numeric: tabular-nums; }

@media (max-width: 760px) {
  
  .apv__row input[type="date"], .apv__hrs { grid-column: 2; }
}

/* ── Overdue ladder ── */

.lad__summary {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 18px;
  margin-bottom: 14px;
}

.lad__big {
  padding: 22px 24px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--bg);
}

.lad__big--accent { border-color: var(--accent); }

.lad__big-label {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-4);
}

.lad__big-value {
  margin-top: 8px;
  font-family: var(--font-display);
  font-size: clamp(28px, 4vw, 40px);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.05;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.lad__big--accent .lad__big-value { color: var(--accent); }

.lad__big-sub {
  margin-top: 6px;
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--ink-3);
}

.lad__stats {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
}

.lad__stats > div { padding: 14px 16px; background: var(--bg); }
.lad__stats dt {
  font-size: 11px;
  color: var(--ink-4);
  letter-spacing: 0.04em;
}
.lad__stats dd {
  margin-top: 3px;
  font-size: 17px;
  font-weight: 600;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.lad__ratenote {
  font-size: 12.5px;
  color: var(--ink-4);
  margin-bottom: 22px;
}

.lad__gate {
  padding: 16px 18px;
  border-radius: var(--radius);
  border-left: 3px solid var(--ink-4);
  background: var(--bg-2);
  margin-bottom: 22px;
}

.lad__gate.is-stop { border-left-color: var(--bad); }
.lad__gate.is-warn { border-left-color: var(--warn-mark); }

.lad__gate-head {
  font-weight: 600;
  font-size: 15px;
  color: var(--ink);
  margin-bottom: 5px;
}

.lad__gate-why { font-size: 14px; line-height: 1.6; color: var(--ink-3); }

.lad__row {
  padding: 18px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  margin-bottom: 14px;
  background: var(--bg);
}

.lad__rowhead {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
}

.lad__rowno {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.1em;
  color: var(--ink-4);
}

.lad__del {
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  font-size: 12.5px;
  color: var(--ink-4);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}
@media (hover: hover) and (pointer: fine) {
  .lad__del:hover { color: var(--bad);
  }
}


.lad__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 180px), 1fr));
  gap: 14px;
}

.lad__verdict {
  margin-top: 13px;
  padding-top: 13px;
  border-top: 1px solid var(--border);
  font-size: 14px;
  line-height: 1.6;
  color: var(--ink-2);
}

.lad__verdict.is-quiet { color: var(--ink-4); }
.lad__verdict.is-loud { color: var(--ink); font-weight: 500; }

@media (max-width: 560px) {
  .lad__stats { grid-template-columns: 1fr; }
}

/* ── Free audit ── */

.audit { background: var(--bg-2); }

.audit__inner {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
  gap: clamp(32px, 5vw, 64px);
  align-items: center;
}

.audit__title {
  font-family: var(--font-display);
  font-size: clamp(28px, 3.6vw, 44px);
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: var(--track-tight);
  color: var(--ink);
  max-width: 22ch;
  margin-bottom: 16px;
  text-wrap: balance;
}

.audit__sub {
  margin-top: 16px;
  font-size: 16.5px;
  line-height: 1.62;
  color: var(--ink-3);
  max-width: 56ch;
}

.audit__list {
  list-style: none;
  margin: 26px 0;
  display: flex;
  flex-direction: column;
  gap: 13px;
  max-width: 58ch;
}

.audit__list li {
  position: relative;
  padding-left: 22px;
  font-size: 15.5px;
  line-height: 1.6;
  color: var(--ink-3);
}

.audit__list li::before {
  content: "";
  position: absolute;
  left: 0; top: 7px;
  width: 8px; height: 4px;
  border-left: 1.5px solid var(--accent);
  border-bottom: 1.5px solid var(--accent);
  transform: rotate(-45deg);
}

.audit__list strong { color: var(--ink); font-weight: 600; }

.audit__actions { display: flex; flex-wrap: wrap; gap: 14px; }

.audit__note {
  margin-top: 20px;
  font-size: 14px;
  line-height: 1.6;
  color: var(--ink-4);
  max-width: 52ch;
}

/* The sample findings card */

.audit__card {
  padding: clamp(22px, 2.6vw, 30px);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--bg);
  box-shadow: var(--elev-2);
}

.audit__card-head {
  display: flex;
  align-items: center;
  gap: 9px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--border);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-4);
}

.audit__dot {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--accent);
  flex: 0 0 auto;
}

.audit__rows { margin: 6px 0 16px; }

.audit__rows > div {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
  padding: 11px 0;
  border-bottom: 1px solid var(--border);
}

.audit__rows > div:last-child { border-bottom: 0; }

.audit__rows dt { font-size: 14.5px; color: var(--ink-3); }

.audit__rows dd {
  font-size: 14px;
  font-weight: 500;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.audit__rows dd.is-bad { color: var(--bad); }
.audit__rows dd.is-warn { color: var(--warn); }
.audit__rows dd.is-good { color: var(--ok); }

.audit__card-foot { font-size: 12.5px; line-height: 1.55; color: var(--ink-4); }

.cf__context {   /* an info box: see Status */
  margin-bottom: 20px;
  padding: 13px 16px;
  border-radius: var(--radius);
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--ink-2);
}

@media (max-width: 880px) {
  .audit__inner { grid-template-columns: 1fr; }
  .audit__card { order: -1; }
}

/* ── Profile ── */

.pf { max-width: 780px; }

.pf__card {
  padding: clamp(24px, 3vw, 34px);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  margin-bottom: 18px;
}

.pf__card--empty { text-align: center; }
.pf__card--empty p { font-size: 16.5px; color: var(--ink-3); margin-bottom: 20px; }
.pf__card--empty .qx__actions { justify-content: center; }

.pf__card--quiet { background: var(--bg-2); }

.pf__h3 {
  font-family: var(--font-display);
  font-size: clamp(18px, 2.2vw, 22px);
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--ink);
  margin-bottom: 14px;
}

.pf__note {
  font-size: 14.5px;
  line-height: 1.65;
  color: var(--ink-4);
  margin-bottom: 18px;
  max-width: 62ch;
}

.pf__grid { margin-top: 18px; }

.pf__uid {
  font-size: 12px !important;
  color: var(--ink-4) !important;
  word-break: break-all;
}


a.nav__account, a.mobile__account { text-decoration: none; }
@media (hover: hover) and (pointer: fine) {
  a.nav__account:hover,
  a.mobile__account:hover { color: var(--accent);
  }
}


.guide__inner { max-width: 900px; }

/* The answer, before anything else. */

.guide__answer {
  padding: clamp(22px, 2.6vw, 30px) clamp(24px, 3vw, 34px);
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius);
  background: var(--surface);
}

.guide__answer-tag {
  display: block;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 10px;
}

.guide__answer p {
  font-size: clamp(18px, 2.1vw, 21px);
  line-height: 1.55;
  color: var(--ink);
  max-width: 62ch;
}

/* The numbers somebody screenshots. */

.guide__facts {
  /* Flex rather than grid: with an odd number of facts a grid leaves empty
     cells, and because the hairlines are the parent showing through the gaps,
     those cells render as grey blocks. Flex items on the last row just grow. */
  display: flex;
  flex-wrap: wrap;
  gap: 1px;
  margin-top: 20px;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}

.guide__facts > div {
  flex: 1 1 150px;
  min-width: 0;
  padding: 16px 18px;
  background: var(--bg);
}

.guide__facts dt {
  font-size: 11.5px;
  letter-spacing: 0.04em;
  color: var(--ink-4);
  margin-bottom: 5px;
}

.guide__facts dd {
  font-family: var(--font-display);
  font-size: 19px;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.guide__section { margin-top: clamp(34px, 4vw, 50px); }

.guide__h2 {
  font-family: var(--font-display);
  font-size: clamp(21px, 2.6vw, 27px);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.25;
  color: var(--ink);
  margin-bottom: 12px;
  text-wrap: balance;
}

.guide__lead-in, .guide__section p {
  font-size: 16.5px;
  line-height: 1.7;
  color: var(--ink-2);
  margin-bottom: 14px;
  max-width: 68ch;
}

.guide__section p:last-child { margin-bottom: 0; }

.guide__list {
  list-style: none;
  margin: 16px 0;
  display: flex;
  flex-direction: column;
  gap: 9px;
  max-width: 72ch;
}

.guide__list li {
  position: relative;
  padding-left: 19px;
  font-size: 16px;
  line-height: 1.65;
  color: var(--ink-2);
}

.guide__list li::before {
  content: "";
  position: absolute;
  left: 0; top: 10px;
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--accent);
}

/* Steps */

.guide__steps {
  list-style: none;
  counter-reset: gstep;
  margin: 18px 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.guide__steps li {
  counter-increment: gstep;
  position: relative;
  padding-left: 42px;
}

.guide__steps li::before {
  content: counter(gstep);
  position: absolute;
  left: 0; top: 0;
  width: 27px; height: 27px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--bg-2);
  color: var(--ink-3);
  font-size: 13px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.guide__steps strong {
  display: block;
  font-size: 15.5px;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 3px;
}

.guide__steps span {
  display: block;
  font-size: 15.5px;
  line-height: 1.6;
  color: var(--ink-3);
  max-width: 66ch;
}

/* Tables, which are why the column got wider */

.guide__scroll { overflow-x: auto; margin: 18px 0; max-width: 100%; }

.guide__table { width: 100%; border-collapse: collapse; font-size: 15px; }

.guide__table th {
  text-align: left;
  padding: 0 16px 9px 0;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-4);
  border-bottom: 1px solid var(--border-2);
  white-space: nowrap;
}

.guide__table td {
  padding: 11px 16px 11px 0;
  border-bottom: 1px solid var(--border);
  color: var(--ink-2);
  line-height: 1.55;
  vertical-align: top;
}

.guide__table td:first-child { color: var(--ink); font-weight: 500; }
.guide__table tr:last-child td { border-bottom: 0; }

/* Do this, not this */

.guide__compare {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 14px;
  margin: 18px 0;
}

.guide__col {
  padding: 18px 20px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
}

.guide__col--do { border-left: 2px solid var(--ok); }
.guide__col--dont { border-left: 2px solid var(--bad); background: var(--bad-wash); }

.guide__col-head {
  display: block;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  margin-bottom: 11px;
}

.guide__col--do .guide__col-head { color: var(--ok); }
.guide__col--dont .guide__col-head { color: var(--bad); }

.guide__col ul { list-style: none; display: flex; flex-direction: column; gap: 8px; }

.guide__col li {
  position: relative;
  padding-left: 17px;
  font-size: 15px;
  line-height: 1.55;
  color: var(--ink-2);
}

.guide__col--do li::before {
  content: "";
  position: absolute;
  left: 0; top: 6px;
  width: 7px; height: 4px;
  border-left: 1.5px solid var(--ok);
  border-bottom: 1.5px solid var(--ok);
  transform: rotate(-45deg);
}

.guide__col--dont li::before {
  content: "\00d7";
  position: absolute;
  left: 0; top: -1px;
  color: var(--bad);
  font-size: 15px;
}

/* Pull-quote and tool link */

.guide__callout {
  margin: 20px 0 !important;
  padding: 16px 22px;
  border-left: 2px solid var(--accent);
  background: var(--accent-wash);
  font-size: 17px !important;
  line-height: 1.55 !important;
  color: var(--ink) !important;
  max-width: 64ch;
}

.guide__tool {
  margin-top: 16px !important;
  padding: 13px 18px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  font-size: 15px !important;
  color: var(--ink-4) !important;
}

.guide__tool a { color: var(--accent); font-weight: 500; }
@media (hover: hover) and (pointer: fine) {
  .guide__tool a:hover { text-decoration: underline;
  }
}


/* What goes wrong */

.guide__mistakes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(270px, 1fr));
  gap: 14px;
  margin-top: 6px;
}

.guide__mistake {
  padding: 18px 20px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
}

.guide__mistake h3 {
  font-size: 15.5px;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 6px;
  line-height: 1.35;
}

.guide__mistake p {
  font-size: 15px !important;
  line-height: 1.6 !important;
  color: var(--ink-3) !important;
  margin: 0 !important;
}

/* The takeaway */

.guide__take {
  padding: clamp(24px, 3vw, 34px);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--bg-2);
}

.guide__checklist {
  counter-reset: gcheck;
  list-style: none;
  margin: 16px 0 22px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 11px 26px;
}

.guide__checklist li {
  counter-increment: gcheck;
  position: relative;
  padding-left: 32px;
  font-size: 15.5px;
  line-height: 1.55;
  color: var(--ink);
}

.guide__checklist li::before {
  content: counter(gcheck);
  position: absolute;
  left: 0; top: 1px;
  width: 21px; height: 21px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid var(--border-2);
  color: var(--ink-4);
  font-size: 11.5px;
  font-variant-numeric: tabular-nums;
}

@media (max-width: 620px) {
  .guide__facts > div { flex-basis: 120px; padding: 13px 14px; }
  .guide__facts dd { font-size: 16px; }
}

/* ── Tools ── */

.tool {
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1fr);
  gap: clamp(28px, 4vw, 56px);
  align-items: start;
}

.tool__inputs { display: flex; flex-direction: column; gap: 22px; }

.tool__field label {
  display: block;
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 7px;
}


.tool__money { position: relative; display: flex; align-items: stretch; }

.tool__money span {
  display: flex; align-items: center;
  padding: 0 12px;
  border: 1px solid var(--border-2);
  border-right: 0;
  border-radius: var(--radius) 0 0 var(--radius);
  background: var(--sunk, var(--bg-2));
  color: var(--ink-4);
  font-size: 15px;
}

.tool__money input { border-radius: 0 var(--radius) var(--radius) 0 !important; }


.tool__out {
  padding: clamp(24px, 3vw, 34px);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
}

.tool__label {
  display: block;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 10px;
}

.tool__price {
  font-family: var(--font-display);
  font-size: clamp(38px, 5.4vw, 60px);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.04em;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.tool__range { margin-top: 10px; font-size: 14px; color: var(--ink-4); }
.tool__range strong { color: var(--ink-2); font-variant-numeric: tabular-nums; }

.tool__rows {
  margin: 26px 0;
  padding-top: 20px;
  border-top: 1px solid var(--border);
}

.tool__rows > div {
  display: flex;
  justify-content: space-between;
  gap: 18px;
  padding: 8px 0;
  font-size: 14px;
}

.tool__rows dt { color: var(--ink-3); }
.tool__rows dd { color: var(--ink); font-variant-numeric: tabular-nums; text-align: right; }

.tool__truth { padding-top: 22px; border-top: 1px solid var(--border); }
.tool__truth-note { font-size: 13.5px; color: var(--ink-4); margin-bottom: 14px; }

.tool__scroll { overflow-x: auto; }

.tool__table { width: 100%; border-collapse: collapse; font-size: 14px; }

.tool__table th {
  text-align: left;
  padding: 0 12px 8px 0;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-4);
  border-bottom: 1px solid var(--border-2);
  white-space: nowrap;
}

.tool__table td {
  padding: 9px 12px 9px 0;
  border-bottom: 1px solid var(--border);
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}

.tool__table tr.is-good td { color: var(--ok); }
.tool__table tr.is-warn td { color: var(--warn); font-weight: 500; }
.tool__table tr.is-bad td { color: var(--bad); font-weight: 500; }

/* A box whose colour says what it is (info by default; .is-ok, .is-warn
   or .is-late, .is-bad): see Status. */
.tool__floor {
  margin-top: 16px;
  padding: 13px 16px;
  border-radius: var(--radius);
  font-size: 14.5px;
  line-height: 1.6;
}

.tool__floor strong { font-weight: 600; }

.tool__note { margin-top: 18px; font-size: 12.5px; color: var(--ink-4); }

.tool__after {
  margin-top: clamp(32px, 4vw, 48px);
  padding-top: 22px;
  border-top: 1px solid var(--border);
  font-size: 14.5px;
  color: var(--ink-4);
}

.tool__after a { color: var(--accent); font-weight: 500; }
@media (hover: hover) and (pointer: fine) {
  .tool__after a:hover { text-decoration: underline;
  }
}


/* a shelf item that is actually built */
.pz-shelf__list li.is-live { color: var(--ink); }
.pz-shelf__list li.is-live a { color: var(--ink); font-weight: 500; }
@media (hover: hover) and (pointer: fine) {
  .pz-shelf__list li.is-live a:hover { color: var(--accent); text-decoration: underline;
  }
}

.pz-live { flex: 0 0 auto; width: 6px; height: 6px; border-radius: 50%; background: var(--accent); }

@media (max-width: 900px) {
  .tool { grid-template-columns: 1fr; }
}

/* ── Outsource vs build ──
   Fourteen inputs will not sit in the calculator's two-column layout, so this
   tool stacks: grouped inputs across the full width, then the answer below. */

.tool--stack { grid-template-columns: 1fr; }

/* A grid item defaults to min-width:auto, which means it refuses to shrink
   below its widest content -- so the five-column sweep table pushed the whole
   page sideways instead of scrolling inside its own container. */
.tool--stack > *, .hire__out, .tool__scroll { min-width: 0; max-width: 100%; }

.hire__form { display: flex; flex-direction: column; gap: clamp(26px, 3vw, 38px); }

.hire__group { border: 0; padding: 0; margin: 0; }

.hire__legend {
  padding: 0 0 14px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
}

.hire__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 22px 24px;
}

.tool__field--check { display: flex; flex-direction: column; justify-content: center; }

.tool__check {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
  cursor: pointer;
  margin-bottom: 7px;
}

.tool__check input { width: 17px; height: 17px; accent-color: var(--accent); }

.hire__out { margin-top: clamp(30px, 4vw, 44px); }

.hire__unit {
  display: block;
  margin-top: 6px;
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 400;
  letter-spacing: 0;
  color: var(--ink-3);
}

.tool__range s { color: var(--ink-4); text-decoration-thickness: 1px; }

/* The three ways to get the work done */

.hire__cols {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 14px;
  margin: 28px 0;
}

.hire__col {
  padding: 18px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  transition: border-color var(--dur-fast) var(--ease);
}

.hire__col.is-best { border-color: var(--ok); background: var(--ok-wash); }   /* the winner: good news */

.hire__col-name {
  display: block;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--ink-4);
  margin-bottom: 10px;
}

.hire__col.is-best .hire__col-name { color: var(--ok); }

.hire__col-per {
  font-family: var(--font-display);
  font-size: 27px;
  font-weight: 600;
  letter-spacing: -0.03em;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.hire__col-sub { font-size: 12.5px; color: var(--ink-4); margin-top: 2px; }

.hire__col-month {
  margin-top: 10px;
  font-size: 13.5px;
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}

.tool__rows-total dt { color: var(--ink) !important; font-weight: 600; }
.tool__rows-total dd { color: var(--ink) !important; font-weight: 600; }
.tool__rows-total { border-top: 1px solid var(--border-2); margin-top: 6px; padding-top: 6px; }

.hire__util {
  margin: 26px 0;
  padding-top: 22px;
  border-top: 1px solid var(--border);
}

.hire__util p { margin-top: 8px; font-size: 14.5px; line-height: 1.65; color: var(--ink-3); }
.hire__util strong { color: var(--ink); font-variant-numeric: tabular-nums; }

.hire__table tr.is-good td { color: var(--ok); }
.hire__table tr.is-bad td { color: var(--bad); }

/* Where you are now: a highlight, not a status. */
.hire__table tr.is-now td {
  background: var(--info-wash);
  color: var(--ink);
  font-weight: 500;
}

.hire__notes {
  list-style: none;
  margin-top: 22px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.hire__notes li {
  position: relative;
  padding: 13px 16px 13px 34px;
  border-radius: var(--radius);
  background: var(--bg-2);
  font-size: 14px;
  line-height: 1.6;
  color: var(--ink-2);
}

.hire__notes li::before {
  content: "!";
  position: absolute;
  left: 15px; top: 13px;
  width: 15px; height: 15px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--warn-mark);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
}

.hire__notes li.is-bad::before { background: var(--bad); }
.hire__notes li.is-ok::before { content: "\2713"; background: var(--ok); }
.hire__notes li.is-info::before { content: "i"; background: var(--ink-3); font-style: italic; font-family: Georgia, serif; }

.hire__assume { margin-top: 24px; font-size: 13.5px; color: var(--ink-4); }

.hire__assume summary {
  cursor: pointer;
  padding: 10px 0;
  color: var(--ink-3);
  border-top: 1px solid var(--border);
}
@media (hover: hover) and (pointer: fine) {
  .hire__assume summary:hover { color: var(--accent);
  }
}


.hire__assume ul {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: 6px 0 4px;
}

.hire__assume li { position: relative; padding-left: 15px; line-height: 1.6; }

.hire__assume li::before {
  content: "";
  position: absolute;
  left: 0; top: 9px;
  width: 4px; height: 4px;
  border-radius: 50%;
  background: var(--border-2);
}

/* ── Case study ── */

.cs__else { margin-top: 20px; }

.cs__boxes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 10px 20px;
  margin-top: 10px;
}

.cs__boxes .tool__check { margin-bottom: 0; font-weight: 400; }

/* ── Proposal builder ── */

.pr__steprow { grid-template-columns: 26px minmax(0, 1fr) 34px; }

.pr__num {
  display: grid;
  place-items: center;
  width: 24px; height: 24px;
  border-radius: 50%;
  background: var(--bg-2);
  color: var(--ink-4);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}

.pr__riskrow { grid-template-columns: minmax(0, 1fr) 180px 34px; }

.pr__riskrow.is-unassigned .qxl__desc { border-color: var(--warn-mark); }

@media (max-width: 620px) {
  .pr__riskrow { grid-template-columns: minmax(0, 1fr) 34px; }
  .pr__riskrow .sp__payer { grid-column: 1; }
  .pr__riskrow .qxl__del { grid-row: 1 / span 2; grid-column: 2; align-self: start; }
}

/* ── Launch checklist ── */

.qa__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 4px 16px;
  padding: 12px 14px;
  border-radius: var(--radius);
  border: 1px solid transparent;
  background: var(--bg-2);
  margin-bottom: 8px;
}

.qa__row.is-blocker { background: var(--bad-wash); border-color: var(--bad-line); }
.qa__row.is-done { background: transparent; opacity: 0.55; }
.qa__row.is-waived { background: transparent; border-color: var(--border-2);
                     border-style: dashed; }

.qa__check {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--ink);
  cursor: pointer;
  min-width: 0;
}

.qa__check input { width: 16px; height: 16px; margin-top: 2px;
                   accent-color: var(--accent); flex: 0 0 auto; }

.qa__row.is-done .qa__check span { text-decoration: line-through; }

.qa__why {
  grid-column: 1;
  padding-left: 26px;
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--ink-4);
}

.qa__waive { grid-row: 1; grid-column: 2; font-size: 12.5px; white-space: nowrap; }

@media (max-width: 560px) {
  .qa__row { grid-template-columns: 1fr; }
  .qa__waive { grid-row: auto; grid-column: 1; justify-self: start;
               padding-left: 26px; }
}

/* ── AI opportunity ── */


/* ── Monthly report ── */

.rp__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 84px auto 34px;
  gap: 9px;
  align-items: center;
}

.rp__hrs { border-left: 1px solid var(--border-2) !important;
           border-radius: var(--radius) !important; text-align: center; }

.rp__vis {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12.5px;
  color: var(--ink-4);
  white-space: nowrap;
  cursor: pointer;
}

.rp__vis input { width: 15px; height: 15px; accent-color: var(--accent); }

.rp__big {
  font-family: var(--font-display);
  font-size: 34px;
  font-weight: 600;
  letter-spacing: -0.03em;
  color: #111;
  margin-bottom: 6px;
  font-variant-numeric: tabular-nums;
}

@media (max-width: 640px) {
  
  .rp__vis { grid-column: 1 / -1; }
}

/* ── CV builder ── */

.cv__entries {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 16px;
  margin: 22px 0 14px;
}

.cv__entry {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 18px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  min-width: 0;
}

.cv__score { font-size: 12.5px; line-height: 1.5; margin-top: 5px; }
.cv__score.is-good { color: var(--ok); }
.cv__score.is-warn { color: var(--warn); }
.cv__score.is-bad { color: var(--bad); }

.cv__delentry { align-self: flex-start; }

.pf__table tr.cv__cut td {   /* where the page cuts off: a caution */
  background: var(--warn-wash);
  color: var(--warn);
  font-size: 12.5px;
  text-align: center;
  font-weight: 500;
}

/* The CV document itself */

.cvdoc { font-size: 10.5pt; line-height: 1.45; }

.cvdoc__head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 20px;
  padding-bottom: 14px;
  border-bottom: 2px solid #111;
}

.cvdoc__name {
  font-family: var(--font-display);
  font-size: 24px;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: #111;
}

.cvdoc__contact { margin-top: 4px; font-size: 12px; color: #555; }

.cvdoc__photo {
  flex: 0 0 auto;
  width: 35mm; height: 45mm;
  display: grid;
  place-items: center;
  border: 1px dashed #bbb;
  color: #999;
  font-size: 11px;
}

.cvdoc__obj { margin-top: 14px; font-size: 12px; color: #444; font-style: italic; }

.cvdoc__section {
  margin-top: 18px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #777;
  border-bottom: 1px solid #e5e5e5;
  padding-bottom: 4px;
}

.cvdoc__skills { margin-top: 8px; font-size: 12px; color: #222; }

.cvdoc__title { margin-top: 12px; font-size: 12.5px; font-weight: 600; color: #111; }

.cvdoc__bullets { list-style: none; margin-top: 5px; display: flex;
                  flex-direction: column; gap: 4px; }

.cvdoc__bullets li {
  position: relative;
  padding-left: 13px;
  font-size: 12px;
  line-height: 1.5;
  color: #333;
}

.cvdoc__bullets li::before {
  content: "";
  position: absolute;
  left: 0; top: 7px;
  width: 3px; height: 3px;
  border-radius: 50%;
  background: var(--accent);
}

.cvdoc__edu { list-style: none; margin-top: 8px; display: flex;
              flex-direction: column; gap: 5px; }

.cvdoc__edu li { font-size: 12px; color: #222; }

.cvdoc__decl { margin-top: 22px; font-size: 11px; color: #666; }

/* ── Application tracker ── */

.at__grid { margin-top: 24px; }

.at__head, .at__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 92px 92px;
  gap: 10px;
  align-items: center;
}

.at__head {
  padding: 0 0 8px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-4);
  border-bottom: 1px solid var(--border-2);
}

.at__head span:not(:first-child), .at__num { text-align: center; }

.at__row { padding: 9px 0; border-bottom: 1px solid var(--border); }

.at__label { font-size: 14.5px; color: var(--ink); min-width: 0; }

.at__p0 {
  display: block;
  font-size: 12px;
  color: var(--ink-4);
  margin-top: 2px;
}

.at__num input {
  width: 100%;
  padding: 8px 6px;
  border: 1px solid var(--border-2);
  border-radius: var(--radius);
  background: var(--bg);
  font-family: var(--font-body);
  font-size: 14.5px;
  text-align: center;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}


@media (max-width: 560px) {
  .at__head, .at__row { grid-template-columns: minmax(0, 1fr) 68px 68px; }
}

/* ── Roadmap ── */

.sp__sublabel { margin-top: 8px; }


.pf__table tr.is-good td { color: var(--ok); }

/* ── Specification builder ── */

.sp__gridwrap { margin: clamp(26px, 3vw, 38px) 0; }
.sp__gridwrap .tool__truth-note { margin-bottom: 16px; }

.sp__grid { display: flex; flex-direction: column; }

.sp__section {
  margin: 22px 0 8px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-4);
}

.sp__section:first-child { margin-top: 0; }

.sp__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 10px 18px;
  align-items: center;
  padding: 11px 13px;
  border-radius: var(--radius);
  border: 1px solid transparent;
}

.sp__row[data-state="gap"] { background: var(--warn-wash); border-color: var(--warn-line); }   /* not discussed yet */
.sp__row[data-state="in"] { background: var(--bg-2); }
.sp__row[data-state="out"] { opacity: 0.6; }

.sp__q { display: flex; align-items: baseline; gap: 10px; min-width: 0; }
.sp__qtext { font-size: 14.5px; line-height: 1.5; color: var(--ink); }
.sp__hrs {
  flex: 0 0 auto;
  font-size: 12px;
  color: var(--ink-4);
  font-variant-numeric: tabular-nums;
}

.sp__opts { display: flex; gap: 6px; flex: 0 0 auto; }

.sp__opt {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 5px 9px;
  border: 1px solid var(--border-2);
  border-radius: 99px;
  background: var(--bg);
  font-size: 12px;
  color: var(--ink-3);
  cursor: pointer;
  white-space: nowrap;
}

.sp__opt input { width: 12px; height: 12px; accent-color: var(--accent); margin: 0; }
@media (hover: hover) and (pointer: fine) {
  .sp__opt:hover { border-color: var(--ink-4);
  }
}

.sp__opt:has(input:checked) { border-color: var(--ink); color: var(--ink); font-weight: 500; }

.sp__gapwrap { margin: 28px 0; padding-top: 24px; border-top: 1px solid var(--border); }

.sp__gaplist { list-style: none; display: flex; flex-direction: column; gap: 10px; margin-top: 12px; }

.sp__gaplist li {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 12px;
  font-size: 14px;
  line-height: 1.55;
  color: var(--ink-2);
}

.sp__flip { font-size: 12.5px; }


.sp__vendors { margin: 28px 0; padding-top: 24px; border-top: 1px solid var(--border); }

.sp__msg { margin-top: 28px; padding-top: 24px; border-top: 1px solid var(--border); }

.sp__message {
  width: 100%;
  margin-top: 12px;
  padding: 14px 16px;
  border: 1px solid var(--border-2);
  border-radius: var(--radius);
  background: var(--bg-2);
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 1.6;
  color: var(--ink-2);
  resize: vertical;
}

.sp__msgfoot { display: flex; flex-wrap: wrap; align-items: center; gap: 14px; margin-top: 12px; }

@media (max-width: 720px) {
  .sp__row { grid-template-columns: 1fr; }
  .sp__opts { flex-wrap: wrap; }
}

/* ── Discovery questionnaire ── */

.dq__handover {
  margin-top: 26px;
  padding-top: 22px;
  border-top: 1px solid var(--border);
}

.dq__handover .tool__hint { margin-top: 10px; max-width: 62ch; }

.dq__questions {
  margin-top: 12px;
  padding-left: 20px;
  display: flex;
  flex-direction: column;
  gap: 9px;
}

.dq__questions li { font-size: 14.5px; line-height: 1.6; color: var(--ink-2); }

.dq__worth {
  margin-left: 9px;
  font-size: 12.5px;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}

.dq__intro { font-size: 13.5px; line-height: 1.65; color: #333; margin-bottom: 14px; }

.dq__brieflist {
  padding-left: 20px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.dq__brieflist li { font-size: 13.5px; line-height: 1.6; color: #111; }

/* ── Project profit ── */

.pf__tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 16px;
  margin-bottom: 30px;
}

.pf__tile {
  padding: 20px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
}

.pf__tile.is-good { border-color: var(--ok-line); background: var(--ok-wash); }
.pf__tile.is-warn { border-color: var(--warn-line); background: var(--warn-wash); }
.pf__tile.is-bad { border-color: var(--bad-line); background: var(--bad-wash); }

.pf__tile .tool__price { font-size: clamp(30px, 4vw, 44px); }
.pf__tile .tool__range strong { color: var(--ink-2); }

.pf__table td { vertical-align: top; }
.pf__why { color: var(--ink-4); font-size: 12.5px; line-height: 1.5; padding-right: 18px; }
.pf__table .tool__amt { text-align: right; white-space: nowrap;
                        font-variant-numeric: tabular-nums; }

.pf__table tr.pf__start td { color: var(--ink-3); }

.pf__table tr.pf__sub td {
  border-top: 1px solid var(--border-2);
  color: var(--ink-2);
  font-weight: 500;
}

.pf__table tr.pf__total td {
  border-top: 2px solid var(--ink);
  border-bottom: 0;
  color: var(--ink);
  font-weight: 600;
  font-size: 15px;
}

.pf__table tr.pf__free td { color: var(--warn); }   /* work given away: a caution */

.pf__gap-top { margin-top: 30px; }

.pf__delay {
  margin-top: 20px;
  padding: 14px 16px;
  border-radius: var(--radius);
  background: var(--bg-2);
  color: var(--ink-3);
  line-height: 1.65;
}

/* ── Service packages ── */

.pk__editor {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(255px, 1fr));
  gap: 18px;
  margin: clamp(26px, 3vw, 38px) 0;
}

.pk__tier {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 20px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  min-width: 0;
}

.pk__tier-head { display: flex; justify-content: space-between; align-items: baseline; }

.pk__tier-n {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
}

.pk__field { min-width: 0; }

.pk__field label, .pk__label {
  display: block;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 6px;
}


.pk__name { font-weight: 600 !important; }

.pk__rows { display: flex; flex-direction: column; gap: 8px; margin-bottom: 10px; }

.pk__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 62px 30px;
  gap: 7px;
  align-items: center;
}


.pk__qty { font-variant-numeric: tabular-nums; text-align: center; }


.pk__pair { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }

.pk__suggest { font-size: 12px; color: var(--ink-4); line-height: 1.5; }

.pk__tier-sum {
  margin-top: auto;
  padding-top: 12px;
  border-top: 1px solid var(--border);
  font-size: 13.5px;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}

.pk__tier-sum.is-good { color: var(--ok); }
.pk__tier-sum.is-warn { color: var(--warn); }
.pk__tier-sum.is-bad { color: var(--bad); }

.pk__bank { margin-top: 28px; padding-top: 24px; border-top: 1px solid var(--border); }

.pk__finding.is-bad::before { background: var(--bad); }
.pk__finding.is-warn::before { background: var(--warn-mark); }
.pk__finding.is-good::before { background: var(--ok); }

/* ── The client-facing price list ── */

.pkg__cols {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 18px;
  margin: 30px 0;
}

.pkg__col {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 22px 18px;
  border: 1px solid #e3e3e3;
  border-radius: 8px;
  min-width: 0;
}

.pkg__col.is-rec { border-color: #111; border-width: 1.5px; }

.pkg__flag {
  position: absolute;
  top: -9px; left: 18px;
  padding: 3px 9px;
  border-radius: 3px;
  background: var(--accent);
  color: #fff;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.pkg__name {
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: #111;
}

.pkg__promise { margin-top: 5px; font-size: 12.5px; line-height: 1.5; color: #666; }

.pkg__price {
  margin-top: 14px;
  font-family: var(--font-display);
  font-size: 25px;
  font-weight: 600;
  letter-spacing: -0.03em;
  color: #111;
  font-variant-numeric: tabular-nums;
}

.pkg__allin { font-size: 11.5px; color: #777; margin-top: 2px; }

.pkg__prev {
  margin-top: 14px;
  font-size: 11.5px;
  font-weight: 600;
  color: #555;
}

.pkg__list {
  list-style: none;
  margin-top: 12px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.pkg__list li {
  position: relative;
  padding-left: 14px;
  font-size: 12.5px;
  line-height: 1.5;
  color: #333;
}

.pkg__list li::before {
  content: "";
  position: absolute;
  left: 0; top: 7px;
  width: 4px; height: 4px;
  border-radius: 50%;
  background: var(--accent);
}

@media (max-width: 720px) {
  .pkg__cols { grid-template-columns: 1fr; }
  .pk__pair { grid-template-columns: 1fr; }
}

/* ── Quotation export panel ── */

.qx {
  margin-top: clamp(40px, 5vw, 72px);
  padding-top: clamp(32px, 4vw, 48px);
  border-top: 1px solid var(--border);
}

.qx__intro { max-width: 60ch; margin-bottom: clamp(24px, 3vw, 34px); }

.qx__title {
  font-family: var(--font-display);
  font-size: clamp(22px, 2.6vw, 30px);
  font-weight: 600;
  letter-spacing: -0.03em;
  color: var(--ink);
  margin-bottom: 8px;
}

.qx__sub { font-size: 15.5px; line-height: 1.65; color: var(--ink-3); }

.qx__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 20px 24px;
}

.qx__field--wide { grid-column: 1 / -1; }

.qx__field label {
  display: block;
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 7px;
}


#q-gstin { text-transform: uppercase; letter-spacing: 0.04em; }

.qx__logo {
  display: flex;
  align-items: center;
  gap: clamp(18px, 2.5vw, 28px);
  margin-top: 26px;
  padding: 20px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
}

.qx__logo-box {
  flex: 0 0 auto;
  width: 104px; height: 104px;
  display: grid;
  place-items: center;
  padding: 10px;
  border: 1px dashed var(--border-2);
  border-radius: var(--radius);
  background: #fff;
}

.qx__logo-img { max-width: 100%; max-height: 100%; object-fit: contain; }

.qx__logo-empty { font-size: 12.5px; color: var(--ink-4); text-align: center; }

.qx__logo-ctrl { min-width: 0; }

.qx__logo-btns { display: flex; align-items: center; gap: 14px; margin-bottom: 10px; }

.qx__link {
  border: 0; background: none; padding: 0;
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--ink-4);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}
@media (hover: hover) and (pointer: fine) {
  .qx__link:hover { color: var(--bad);
  }
}


.qx__warn {   /* info by default; .is-ok, .is-warn, .is-bad: see Status */
  margin-top: 20px;
  padding: 13px 16px;
  border-radius: var(--radius);
  font-size: 14.5px;
  line-height: 1.6;
}

.qx__actions { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 26px; }

/* Service lines */

.qxl__label {
  display: block;
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 7px;
}

.qxl { display: flex; flex-direction: column; gap: 10px; }

.qxl__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 170px 34px;
  gap: 10px;
  align-items: center;
}


.qxl__money { min-width: 0; }

.qxl__amt {
  width: 100%;
  min-width: 0;
  padding: 12px 14px;
  border: 1px solid var(--border-2);
  border-left: 0;
  border-radius: 0 var(--radius) var(--radius) 0;
  background: var(--bg);
  font-family: var(--font-body);
  font-size: 15.5px;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.qxl__del {
  width: 34px; height: 34px;
  display: grid;
  place-items: center;
  border: 1px solid var(--border-2);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--ink-4);
  font-size: 19px;
  line-height: 1;
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
@media (hover: hover) and (pointer: fine) {
  .qxl__del:hover { color: var(--bad); border-color: var(--bad);
  }
}


.qxl__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px 18px;
  margin-top: 12px;
}

.qxl__tally { font-size: 13.5px; line-height: 1.6; color: var(--ink-4); }
.qxl__tally .qx__link { font-size: 13.5px; }
.qxl__ok { color: var(--ok); }
.qxl__gap { color: var(--warn); }

@media (max-width: 560px) {
  
  .qxl__money { grid-column: 1; }
  /* Scoped: .pk__row, .rp__row and .apv__row also hold a .qxl__del
     and are not quote-line rows. */
  .qxl__row .qxl__del { grid-row: 1 / span 2; grid-column: 2; align-self: start; }
}

/* ── The quotation document ──
   A direct child of <body> so the print rule can hide its siblings with one
   selector. On screen it reads as a sheet of paper; in print it IS the page. */

.doc-sheet {
  padding: clamp(24px, 4vw, 56px) var(--pad-x) clamp(48px, 6vw, 80px);
  background: var(--bg-2);
}

.doc {
  max-width: 820px;
  margin: 0 auto;
  padding: clamp(28px, 4.5vw, 56px);
  background: #fff;
  color: #111;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  font-size: 14.5px;
  line-height: 1.6;
}

.quote__top {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 28px;
  padding-bottom: 24px;
  border-bottom: 2px solid #111;
}

.quote__brand { display: flex; align-items: flex-start; gap: 16px; min-width: 0; }

.quote__logo { max-width: 132px; max-height: 76px; object-fit: contain; }

.quote__biz-name {
  font-family: var(--font-display);
  font-size: 19px;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: #111;
}

.quote__biz-gstin {
  margin-top: 4px;
  font-size: 12.5px;
  color: #555;
  letter-spacing: 0.02em;
}

.quote__ident { text-align: right; flex: 0 0 auto; }

.quote__doctype {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 12px;
}

.quote__ref { font-size: 12.5px; }
.quote__ref > div { display: flex; justify-content: flex-end; gap: 10px; padding: 2px 0; }
.quote__ref dt { color: #666; }
.quote__ref dd { color: #111; font-weight: 500; font-variant-numeric: tabular-nums; }

.quote__party { padding: 24px 0; }

.quote__party-label {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #777;
  margin-bottom: 6px;
}

.quote__party-name { font-size: 17px; font-weight: 500; color: #111; }
.quote__party-role { margin-top: 3px; font-size: 13px; color: #555; }

.quote__items { width: 100%; border-collapse: collapse; margin-top: 8px; }

.quote__items th {
  text-align: left;
  padding: 0 0 9px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: #777;
  border-bottom: 1px solid #ddd;
}

.quote__items th:last-child, .quote__amt { text-align: right; }

.quote__items td {
  padding: 16px 0;
  border-bottom: 1px solid #eee;
  color: #111;
}

.quote__desc { padding-right: 24px; }
.quote__amt { font-variant-numeric: tabular-nums; white-space: nowrap; }

.quote__items tfoot td { border-bottom: 0; padding: 10px 0; color: #555; }

.quote__total td {
  padding-top: 14px;
  border-top: 2px solid #111;
  font-size: 18px;
  font-weight: 600;
  color: #111;
}

.quote__terms { margin-top: 32px; }

.quote__terms-title {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #777;
  margin-bottom: 10px;
}

.quote__terms-list { list-style: none; display: flex; flex-direction: column; gap: 7px; }

.quote__terms-list li {
  position: relative;
  padding-left: 16px;
  font-size: 13.5px;
  color: #333;
}

.quote__terms-list li::before {
  content: "";
  position: absolute;
  left: 0; top: 9px;
  width: 4px; height: 4px;
  border-radius: 50%;
  background: var(--accent);
}

.quote__foot { margin-top: 36px; padding-top: 20px; border-top: 1px solid #eee; }

.quote__sig { font-size: 13.5px; color: #111; margin-bottom: 14px; }

.quote__legal { font-size: 11.5px; line-height: 1.6; color: #777; max-width: 62ch; }

@media (max-width: 620px) {
  .quote__top { flex-direction: column; }
  .quote__ident { text-align: left; }
  .quote__ref > div { justify-content: flex-start; }
}

/* ── Print ──
   Only engages once a quotation has been built, so Ctrl+P on the calculator
   still prints the calculator. */

@media print {
  /* Zero page margin, with the real margin moved into the sheet's own padding.
     This is the only lever that exists: Chromium draws its injected header and
     footer -- the page URL, the date, "1/1" -- inside the page margin box, so a
     page with no margin has nowhere to put them. There is no CSS property for
     it and no meta tag; every other browser still draws them, which is why the
     button also tells the user where the checkbox is. */
  @page { size: A4; margin: 0; }

  /* body carries overflow-x:hidden (line 69) and the launch curtain sets
     overflow:hidden on html and body. Both propagate to the print viewport and
     clip anything reaching the page edge, with no scrollbar to hint at it. */
  html, body {
    overflow: visible !important;
    background: #fff !important;
  }

  body.has-doc > *:not(.doc-sheet) { display: none !important; }

  body.has-doc .doc-sheet {
    padding: 15mm 14mm !important;
    background: #fff !important;
  }

  body.has-doc .doc {
    max-width: none;
    margin: 0;
    padding: 0;
    border: 0;
    border-radius: 0;
    font-size: 11pt;
  }

  body.has-doc .doc,
  body.has-doc .doc * {
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }

  body.has-doc .quote__terms,
  body.has-doc .quote__foot,
  body.has-doc .quote__party { break-inside: avoid; page-break-inside: avoid; }

  body.has-doc .quote__items tr { break-inside: avoid; page-break-inside: avoid; }

  /* Twelve services can push onto a second page, and a column of amounts with
     no header above it is unreadable. Safari ignores modern break-* in paged
     media, so the legacy aliases ship alongside. */
  body.has-doc .quote__items thead { display: table-header-group; }
  body.has-doc .quote__items tfoot { display: table-footer-group;
                                       break-inside: avoid; page-break-inside: avoid; }
}

/* ═══════════════════════════════════════════
   LEGAL PAGES
   ═══════════════════════════════════════════ */

/* A single measured column. Legal text is read, not scanned, and a 70ish
   character line is the difference between reading it and giving up. */
.legal { max-width: 760px; margin-inline: auto; }

.legal__updated {
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-4);
  padding-bottom: 22px;
  border-bottom: 1px solid var(--border);
}

.legal__toc {
  padding: 26px 30px 30px;
  margin: 36px 0 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--bg-2);
}

.legal__toc-title {
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-4);
  margin-bottom: 14px;
}

.legal__toc ol {
  columns: 2;
  column-gap: 32px;
  list-style: none;
  counter-reset: toc;
}

.legal__toc li { counter-increment: toc; break-inside: avoid; margin-bottom: 8px; }

.legal__toc a {
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--ink-2);
  transition: color 0.2s var(--ease);
}

.legal__toc a::before {
  content: counter(toc, decimal-leading-zero) '  ';
  font-variant-numeric: tabular-nums;
  color: var(--ink-4);
}
@media (hover: hover) and (pointer: fine) {
  .legal__toc a:hover { color: var(--accent);
  }
}


.legal__block { padding-top: 44px; scroll-margin-top: calc(var(--nav-h) + 24px); }

.legal__h {
  font-family: var(--font-display);
  font-size: clamp(21px, 2.1vw, 26px);
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.026em;
  margin-bottom: 16px;
}

.legal p {
  font-size: 16px;
  line-height: 1.78;
  color: var(--ink-2);
  margin-bottom: 18px;
}

.legal a { color: var(--accent); font-weight: 500; }
@media (hover: hover) and (pointer: fine) {
  .legal a:hover { text-decoration: underline;
  }
}


.legal__list { margin: 0 0 18px; padding-left: 0; list-style: none; }

.legal__list li {
  position: relative;
  padding-left: 22px;
  margin-bottom: 11px;
  font-size: 16px;
  line-height: 1.7;
  color: var(--ink-2);
}

.legal__list li::before {
  content: '';
  position: absolute;
  left: 0; top: 13px;
  width: 9px; height: 1.5px;
  background: var(--accent);
}

.legal__dl { margin-bottom: 18px; border-top: 1px solid var(--border); }

.legal__dl > div {
  display: grid;
  grid-template-columns: 230px 1fr;
  gap: 24px;
  padding: 16px 0;
  border-bottom: 1px solid var(--border);
}

.legal__dl dt {
  font-size: 14px;
  font-weight: 600;
  line-height: 1.5;
  color: var(--ink);
}

.legal__dl dd { font-size: 15.5px; line-height: 1.7; color: var(--ink-3); }

.legal__foot {
  margin-top: 56px;
  padding-top: 28px;
  border-top: 1px solid var(--border);
}

.legal__cross { font-size: 14.5px; color: var(--ink-4); }

@media (max-width: 680px) {
  .legal__toc ol { columns: 1; }
  .legal__dl > div { grid-template-columns: 1fr; gap: 5px; }
}

/* ═══════════════════════════════════════════
   CASE STUDIES
   ═══════════════════════════════════════════ */

/* A jump list, because five long studies is more than one screen and a
   visitor usually arrives wanting one particular trade. */
.case-index {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 0;
  border-top: 1px solid var(--border);
  margin-bottom: clamp(48px, 7vw, 96px);
}

.case-index a {
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 20px 22px 20px 0;
  border-bottom: 1px solid var(--border);
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -0.018em;
  color: var(--ink);
  transition: color 0.2s var(--ease);
}

.case-index a span {
  font-family: var(--font-body);
  font-size: 12.5px;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--ink-4);
}
@media (hover: hover) and (pointer: fine) {
  .case-index a:hover { color: var(--accent);
  }
}


.case {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(32px, 5vw, 72px);
  align-items: start;
  scroll-margin-top: calc(var(--nav-h) + 32px);
}


.case__outcome {
  padding: 16px 20px;
  border-radius: var(--radius);
  background: var(--bg-2);
  border: 1px solid var(--border);
  color: var(--ink) !important;
  font-weight: 500;
}

@media (max-width: 900px) {
  .case { grid-template-columns: 1fr; }
}


/* ═══════════════════════════════════════════
   STOREFRONT
   ═══════════════════════════════════════════ */


/* A no-JS visitor already has every card, so the button would do nothing. */


/* ── Auth feedback ── */

.auth-feedback {
  margin-top: 18px;
  padding: 13px 16px;
  border-radius: var(--radius);
  font-size: 14.5px;
  line-height: 1.55;
}

/* Its colours, by role (--success, --error, --info, --warning): see Status. */

.account__reset { text-align: right; margin-top: 12px; }
.account__reset a { color: var(--ink-3); }
@media (hover: hover) and (pointer: fine) {
  .account__reset a:hover { color: var(--accent); text-decoration: underline;
  }
}


.account__form .cf-note a { color: var(--accent); font-weight: 500; }
@media (hover: hover) and (pointer: fine) {
  .account__form .cf-note a:hover { text-decoration: underline;
  }
}


/* ── Sign-in methods ── */

/* Google sits above the fold on its own: it is one tap, so burying it under
   a form would be backwards for most visitors. */
.auth-social {
  width: 100%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 11px;
  padding: 15px 20px;
  border: 1px solid var(--border-2);
  border-radius: var(--radius);
  background: var(--bg);
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 500;
  color: var(--ink);
  cursor: pointer;
  transition: border-color 0.2s var(--ease), background 0.2s var(--ease),
              transform 0.2s var(--ease);
}
@media (hover: hover) and (pointer: fine) {
  .auth-social:hover:not(:disabled) {
    border-color: var(--ink-4);
    background: var(--bg-2);
    transform: translateY(-1px);
  }
}


.auth-social:disabled { opacity: 0.55; cursor: default; }
.auth-social svg { flex: 0 0 auto; }

.auth-or {
  position: relative;
  text-align: center;
  margin: 26px 0 22px;
}

.auth-or::before {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 50%;
  border-top: 1px solid var(--border);
}

.auth-or span {
  position: relative;
  padding: 0 14px;
  background: var(--bg);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-4);
}

/* Paired fields. The row's gap does the spacing, so the fields' own bottom
   margin is dropped to stop the two adding up. */
.cf-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 20px;
}

.cf-check {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  margin: 4px 0 28px;
  font-size: 14px;
  line-height: 1.6;
  color: var(--ink-3);
  cursor: pointer;
}

.cf-check input {
  flex: 0 0 auto;
  width: 17px;
  height: 17px;
  margin-top: 2px;
  accent-color: var(--accent);
  cursor: pointer;
}

/* The invisible reCAPTCHA renders nothing, but a challenge badge can appear
   here; keep it from butting against the button. */
#recaptcha-holder:not(:empty) { margin-top: 18px; }

@media (max-width: 560px) {
  .cf-row { grid-template-columns: 1fr; }
}

/* Signed-in state in the nav */
.nav__account {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  font-size: 14.5px;
  font-weight: 500;
  color: var(--ink-2);
  border-radius: var(--radius);
  transition: color 0.2s var(--ease), background 0.2s var(--ease);
}
@media (hover: hover) and (pointer: fine) {
  .nav__account:hover { color: var(--ink);
  }
}


/* ── Nav account control (replaces the phone CTA) ── */
.nav__account-cta { gap: 8px; }
.nav__account-cta svg { color: var(--accent); flex-shrink: 0; }

.nav__signed {
  display: inline-flex;
  align-items: center;
  margin-left: 10px;
  padding: 9px 16px;
  border: 1px solid var(--border-2);
  border-radius: 100px;
  font-size: 14px;
  line-height: 1.6;                 /* the sign-in pill's height, 42px */
}

.nav__signed .nav__account {
  padding: 0;
  max-width: 150px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 14px;
}
@media (hover: hover) and (pointer: fine) {
  .nav__signed .nav__account:hover { background: none;
  }
}

/* ══════════════════════════════════════════════
   Press feedback

   Deliberately NOT inside the hover query. A mouse user gets the lift on
   hover; a finger gets nothing at all unless the press state is reachable on
   touch, and touch is where the confirmation matters most -- there is no
   cursor to show the interface noticed.

   Everything here is transform and opacity only, 120ms, and small enough that
   it reads as the surface giving way rather than as an animation.
   ══════════════════════════════════════════════ */

.svc-card:active,
.value-card:active,
.auth-social:active:not(:disabled) {
  transform: scale(0.985);
  transition-duration: 0.12s;
}

.social-link:active svg { transform: scale(0.94); }
.nav__link:active { opacity: 0.7; }

/* Anything with a tap target that is not otherwise styled: the surface dips
   without moving, so a long list of rows does not appear to jitter. */
.lad__del:active,
.pz-linkbtn:active,
.tool__field button:active { opacity: 0.6; }

@media (prefers-reduced-motion: reduce) {
  .svc-card:active,
  .value-card:active,
  .auth-social:active:not(:disabled),
  .social-link:active svg {
    transform: none;
    opacity: 0.75;
  }
}

/* ══════════════════════════════════════════════
   Translucent surfaces, when translucency is unwanted

   Three surfaces use backdrop-filter. Two accessibility settings ask for it
   to stop: one because the blur makes text hard to read, one because the
   whole effect is disorienting. Both want a solid surface, and the contrast
   case wants a border so the edge is still findable.
   ══════════════════════════════════════════════ */

@media (prefers-reduced-transparency: reduce) {
  .nav,
  .mobile-menu {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    background: var(--bg);
  }
}

@media (prefers-contrast: more) {
  .nav,
  .mobile-menu {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    background: var(--bg);
    border-color: var(--ink);
  }

  .btn,
  .tool__field input,
  .tool__field select,
  .tool__field textarea { border-color: var(--ink); }
}

/* ══════════════════════════════════════════════
   Resting elevation

   The cards carried a shadow only on :hover, so at rest the page was flat and
   a visitor on a phone -- most of them -- never saw depth at all. Depth moves
   to the resting state here, and hover raises by one step rather than
   conjuring a shadow from nothing.

   The border stays. A shadow separates a surface from the page; a border
   defines its edge. They are not the same job, and dropping the border for a
   shadow is how a card turns into a smudge on a light background.
   ══════════════════════════════════════════════ */

.svc-card,
.vm-card,
.value-card,
.audit__card,
.lad__big,
.lad__row {
  box-shadow: var(--elev-2);
  transition: box-shadow var(--dur) var(--ease),
              transform var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}

/* The summary panel is the thing the tool exists to show, so it sits a step
   above the rows it summarises. Depth as hierarchy, not decoration. */
.lad__big--accent { box-shadow: var(--elev-3); }

/* ══════════════════════════════════════════════
   Scroll edge

   A 1px rule across the viewport under a floating bar announces the bar. A
   short gradient where the chrome actually overlaps the content says the same
   thing without drawing a line through the design -- and it only appears once
   there is something scrolled underneath it to separate from.
   ══════════════════════════════════════════════ */

.nav.scrolled { border-bottom-color: transparent; }

.nav::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  height: 14px;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--dur) var(--ease);
  background: linear-gradient(to bottom,
                              rgba(10, 10, 10, 0.055),
                              rgba(10, 10, 10, 0));
}

.nav.scrolled::after { opacity: 1; }

/* Under a contrast preference the soft edge is the wrong answer: what is
   wanted there is a findable line, so the rule comes back and the fade goes. */
@media (prefers-contrast: more) {
  .nav.scrolled { border-bottom-color: var(--ink); }
  .nav::after { display: none; }
}

@media (prefers-reduced-transparency: reduce) {
  .nav.scrolled { border-bottom-color: var(--border-2); }
  .nav::after { display: none; }
}


/* ══════════════════════════════════════════════
   One page, one language

   The hero is left-aligned, labels its facts in grey and uses no accent
   colour at all. Leaving the sections below it centred under red eyebrows
   made the page read as two designs stacked, which is why changing the hero
   alone made everything under it look older rather than better.

   Red is not decoration any more. It stays in the logo, the footer rule and
   the audit card's failing values, where it marks a problem. A heading is
   not a problem.
   ══════════════════════════════════════════════ */

/* Three sections ran 2,350px of unbroken white between the marquee and the
   audit band. Alternating one of them gives the page a pulse instead of a
   sprawl, and it uses the token the hero and the audit already share. */
.section--band { background: var(--bg-2); }

/* The section head sat in a centred 780px column while the content under it
   started at the left edge of a 1320px container -- a heading that does not
   line up with what it introduces. It lines up now. */
.section-head > * { margin-left: 0; margin-right: 0; }

.section-head p {
  max-width: 62ch;
  margin-left: 0;
}

/* ══════════════════════════════════════════════
   Content must exist at rest

   Ten elements on this page were at opacity 0 until a scroll observer fired.
   main.js already handles reduced motion and a missing IntersectionObserver,
   but not print -- so the page printed blank through the middle, and every
   full-page capture, link preview and thumbnail showed empty space where the
   services are.

   The animation is a nicety. The content is the page. When the two disagree
   the content wins.
   ══════════════════════════════════════════════ */

@media print {
  .js .reveal,
  .js .reveal.visible,
  .js .animate-1, .js .animate-2, .js .animate-3,
  .js .animate-4, .js .animate-5,
  .js .line-mask > span {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
}

/* ══════════════════════════════════════════════
   The other fifty-five pages

   The homepage was left-aligned, grey-labelled and banded, and every other
   page still opened centred under a red eyebrow -- which made the homepage
   look like it belonged to a different site than the one it links to. Same
   three moves, applied to the shared page hero.

   The band matters more here than it looks: .page-hero carries a
   border-bottom, and a hairline between two identical whites is a line for
   its own sake. Between a tinted band and the white below it, the same line
   is the edge of something.
   ══════════════════════════════════════════════ */

.page-hero {
  background: var(--bg-2);
  border-bottom-color: var(--border);
}

.page-hero__inner {
  max-width: 900px;
  margin-inline: 0;
  text-align: left;
}

.page-hero__title { letter-spacing: var(--track-tight); }

.page-hero__sub { margin-inline: 0; }

/* The Plus tool pages put their controls directly under this hero, so the
   heading and the first field now start on the same left edge. */
.page-hero--plus .page-hero__inner { max-width: 820px; }


/* ══════════════════════════════
   Website check

   Answers are buttons, not radios. A radio on a phone is a 14px target next
   to a label you must also hit; a full-width button is the whole row. The
   person using this is holding the phone in one hand.
   ══════════════════════════════ */

.ck__progress {
  font-size: 12px;
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  color: var(--ink-4);
  margin-bottom: 20px;
}

.ck__n {
  display: inline-block;
  min-width: 1.6em;
  color: var(--ink-4);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.ck__result {
  margin-top: 32px;
  padding: clamp(24px, 3.4vw, 36px);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--bg-2);
}

.ck__head {
  font-family: var(--font-display);
  font-size: clamp(22px, 3vw, 30px);
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: var(--track-tight);
  color: var(--ink);
}

.ck__lead {
  margin-top: 10px;
  font-size: clamp(15.5px, 1.7vw, 17px);
  line-height: 1.6;
  color: var(--ink-2);
  max-width: 58ch;
}

.ck__fixes {
  margin: 24px 0 0;
  padding: 0;
  list-style: none;
  counter-reset: fix;
}

.ck__fix {
  counter-increment: fix;
  position: relative;
  padding: 16px 0 16px 34px;
  border-top: 1px solid var(--border);
}

.ck__fix::before {
  content: counter(fix);
  position: absolute;
  left: 0;
  top: 16px;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-4);
  font-variant-numeric: tabular-nums;
}

.ck__fix-what { font-size: 15.5px; line-height: 1.6; color: var(--ink); }
.ck__fix-act {
  margin-top: 5px;
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--ink-3);
}

.ck__note {
  margin-top: 18px;
  font-size: 14px;
  line-height: 1.6;
  color: var(--ink-4);
}

.ck__end {
  margin-top: 26px;
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
}

.ck__endnote {
  margin-top: 14px;
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--ink-4);
  max-width: 56ch;
}

@media (max-width: 560px) {
  .ck__end .btn { width: 100%; }
}

/* ══════════════════════════════
   Website check — one screen, fourteen times

   This page stopped borrowing the layout of an article. Everything here
   exists so the question and its three buttons are on screen together, every
   time, without scrolling. The design rests on the thumb learning where the
   buttons are; it cannot learn a position it has to scroll to find.
   ══════════════════════════════ */

/* A label, not a hero. It is read once and never again. */
.page-hero--tool {
  padding-top: calc(var(--nav-h) + clamp(16px, 2.6vw, 28px));
  padding-bottom: clamp(12px, 1.8vw, 18px);
}

.page-hero--tool .page-hero__title { font-size: clamp(24px, 3vw, 33px); }

.page-hero--tool .page-hero__sub {
  margin-top: 8px;
  margin-bottom: 0;
  font-size: clamp(14.5px, 1.2vw, 16px);
}

/* --section-y is a rhythm for prose, and here it spent 128px pushing the
   first question off a phone screen. */
.section--tool { padding: clamp(16px, 2.2vw, 24px) 0 clamp(40px, 6vw, 72px); }

/* A button 1200px wide is not a button, it is a bar. */
.ck { max-width: 640px; }

.ck__progress { margin-bottom: 12px; }


/* ── Website check: the brief for an assistant ──

   Restored after a rewrite dropped it. It sits beside the WhatsApp hand-off
   rather than instead of it: one goes to the person who built the site, the
   other to a machine, and which of those she has is not something this page
   can know. */

.ck__askai {
  margin-top: 26px;
  padding-top: 24px;
  border-top: 1px solid var(--border);
}

.ck__askai-title {
  font-family: var(--font-display);
  font-size: clamp(18px, 2.2vw, 22px);
  font-weight: 600;
  letter-spacing: var(--track-tight);
  color: var(--ink);
}

.ck__askai-lead {
  margin-top: 7px;
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--ink-3);
}

.ck__askai-label {
  margin-top: 18px;
  margin-bottom: 9px;
  font-size: 14px;
  font-weight: 500;
  color: var(--ink-2);
}

.ck__chips { display: flex; flex-wrap: wrap; gap: 8px; }

/* 44px stated rather than inferred from padding, because a fingertip does
   not get smaller when the font does. */
.ck__chip {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 9px 16px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--bg);
  font: inherit;
  font-size: 14px;
  color: var(--ink-2);
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease-out),
              background var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out);
}

@media (hover: hover) and (pointer: fine) {
  .ck__chip:hover { border-color: var(--border-2); background: var(--bg-2); }
}

.ck__chip:active { transform: scale(0.98); }
.ck__chip.is-on { border-color: var(--ink); background: var(--ink); color: var(--bg); }

.ck__promptwrap {
  margin-top: 18px;
  border: 1px solid var(--border-2);
  border-radius: var(--radius);
  background: var(--bg);
  overflow: hidden;
}

.ck__prompt {
  display: block;
  width: 100%;
  border: 0;
  padding: 15px;
  resize: vertical;
  background: transparent;
  color: var(--ink-2);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12.5px;
  line-height: 1.6;
}

.ck__prompt:focus { outline: 2px solid var(--ink); outline-offset: -2px; }

.ck__promptbar {
  padding: 11px 13px;
  border-top: 1px solid var(--border);
  background: var(--bg-2);
}

@media (max-width: 560px) {
  .ck__promptbar .btn { width: 100%; }
}

/* ══════════════════════════════
   Website check — all fourteen, grouped

   Replaces the one-card-at-a-time flow. The card hid how much was left,
   forced an order on checks that have none, and made correcting an answer a
   hunt for a Change link. A list shows the shape of the job, lets her answer
   whichever she happens to be looking at, and turns changing her mind into
   tapping the other button.

   What survives from the card, because it was right: three buttons, never
   more, never different, in the same place on every row, Yes always the good
   answer. The thumb still learns one position — down a list now, rather
   than on a card that reloads.
   ══════════════════════════════ */

.ck__group {
  margin: 30px 0 10px;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  color: var(--ink-4);
}

.ck__group:first-child { margin-top: 0; }

.ck__row {
  padding: 16px 0 18px;
  border-bottom: 1px solid var(--border);
}

.ck__row:last-child { border-bottom: 0; }

/* An answered row marks itself and does not move. A row that reorders or
   collapses once answered takes the next one with it and costs her the
   place she had. */
.ck__row.is-done .ck__rowq { color: var(--ink-3); }
.ck__row.is-done .ck__n { color: var(--ink-4); }

.ck__rowq {
  font-size: 16px;
  line-height: 1.45;
  color: var(--ink);
  font-weight: 500;
  letter-spacing: -0.008em;
}

.ck__rowq .ck__n {
  display: inline-block;
  min-width: 1.7em;
  color: var(--ink-4);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.ck__rowhint {
  margin-top: 5px;
  margin-left: 1.7em;
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--ink-4);
}

/* Equal thirds, so the three targets are identical on every row and the
   thumb does not have to aim. 44px is a fingertip, stated rather than
   inferred from padding. */
.ck__opts {
  margin-top: 12px;
  margin-left: 1.7em;
  display: flex;
  gap: 8px;
}

.ck__opt {
  flex: 1 1 0;
  min-height: 44px;
  padding: 10px 6px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  font: inherit;
  font-size: 14.5px;
  color: var(--ink-2);
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease-out),
              background var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out);
}

@media (hover: hover) and (pointer: fine) {
  .ck__opt:hover { border-color: var(--border-2); background: var(--bg-2); }
}

.ck__opt:active { transform: scale(0.98); }

.ck__opt.is-on {
  border-color: var(--ink);
  background: var(--ink);
  color: var(--bg);
  font-weight: 500;
}

/* The verdict is about what she has answered so far, so while checks remain
   it must not read as final. */
.ck__partial {
  margin-top: 6px;
  font-size: 13.5px;
  color: var(--ink-4);
}

.ck__result {
  margin-top: 30px;
  padding-top: 26px;
  border-top: 2px solid var(--ink);
}

.ck__result.is-ok { border-top-color: var(--ok); }
.ck__result.is-warn { border-top-color: var(--warn-mark); }
.ck__result.is-bad { border-top-color: var(--bad); }

@media (max-width: 420px) {
  .ck__rowhint, .ck__opts { margin-left: 0; }
  .ck__opt { font-size: 14px; }
}


/* ═══════════════════════════════════════════════════════════════
   THE FIELD
   One system, replacing eleven. Append at the END of styles.css.

   Every selector here is at least as specific as the rule it
   supersedes and comes later in the file, so the old blocks can be
   deleted in a second pass without this one changing.

   Three numbers, none of them taste:
     16px  iOS Safari zooms the layout viewport when a focused
           control computes under 16px, and does not zoom back. Every
           field on the site was 13-15.5px. This is a bug fix.
     48px  the standalone field height, stated the way .btn and
           .ck__chip already state theirs. 44px in a repeating grid
           cell, which is the house floor and never lower.
     2px   the focus ring. Seven rules did outline:none plus a border
           colour change, which is colour alone at 1px.
   ═══════════════════════════════════════════════════════════════ */

:root {
  --field-h: 48px;
  --field-h-sm: 44px;               /* one cell in a repeating grid */
  --field-py: 13px;                 /* 13 + 13 + 20 line + 2 border = 48 */
  --field-py-sm: 11px;              /* 11 + 11 + 20 line + 2 border = 44 */
  --field-px: 14px;                 /* what .tool__field already used */
  --field-fs: max(16px, 1rem);      /* floor, never a cap */
  --field-lh: 1.25;
  --field-bd: var(--border-2);
  --field-bd-on: var(--ink);
  --field-ring: 2px;
  --field-gap: var(--space-2);
  /* A data URI cannot read a custom property, so --ink-4 is written
     out once, here, and nowhere else. */
  --field-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'%3E%3Cpath d='M1 1.5 6 6.5l5-5' stroke='%236b6b75' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

/* The base. The enumerated input types are the whole point: styles.css
   named only input[type="number"] and select inside .tool__field, so
   43 text inputs, 7 dates and 2 months fell through to the browser's
   own 13.3px, 19px-tall control. That is the owner's complaint. */
.tool__field input[type="text"],
.tool__field input[type="number"],
.tool__field input[type="date"],
.tool__field input[type="month"],
.tool__field input[type="email"],
.tool__field input[type="tel"],
.tool__field input[type="url"],
.tool__field select,
.tool__field textarea,
.qx__field input[type="text"],
.qx__field input[type="number"],
.qx__field input[type="date"],
.qx__field input[type="month"],
.qx__field select,
.qx__field textarea,
.pk__field input[type="text"],
.pk__field input[type="number"],
.pk__field select,
.pk__field textarea,
.pk__row select,
.pk__qty,
.ld__cell input,
.bd__in,
.at__num input,
.qxl__desc,
.qxl__amt,
.sp__payer,
.sp__message,
.cf-field input,
.cf-field textarea,
.ck__mail-row input,
.cur__pick,
.cur__rateinput {
  width: 100%;
  min-width: 0;
  min-height: var(--field-h);
  padding: var(--field-py) var(--field-px);
  border: 1px solid var(--field-bd);
  border-radius: var(--radius);
  background: var(--bg);
  box-shadow: var(--elev-1);
  font-family: var(--font-body);
  font-size: var(--field-fs);
  line-height: var(--field-lh);
  color: var(--ink);
  box-sizing: border-box;
  transition: border-color var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-fast) var(--ease-out);
}

/* Height comes from padding as well as min-height on purpose: Safari
   sizes a native select from its padding and clamps a bare height. */
.tool__field textarea,
.qx__field textarea,
.pk__field textarea,
.cf-field textarea,
.sp__message {
  min-height: calc(var(--field-h) * 2);
  line-height: 1.6;
  resize: vertical;
}

/* .sp__message and .ck__prompt are readonly output surfaces; --bg-2
   is what marks them as output rather than input. readonly does not
   exempt a control from iOS focus zoom, so they take the 16px floor
   with everything else. */
.sp__message { background: var(--bg-2); color: var(--ink-2); }
.ck__prompt { font-size: var(--field-fs); line-height: 1.55; }

/* The UA select arrow is the single most dated pixel in these tools. */
.tool__field select,
.qx__field select,
.pk__field select,
.pk__row select,
.cur__pick,
.sp__payer {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  padding-right: calc(var(--field-px) + 18px);
  background-image: var(--field-chevron);
  background-repeat: no-repeat;
  background-position: right var(--field-px) center;
  background-size: 12px 8px;
  text-overflow: ellipsis;
}

/* A number field is the same box as a text field. What it needs is
   digits that do not re-flow while a live total recalculates. */
.tool__field input[type="number"],
.qx__field input[type="number"],
.pk__field input[type="number"],
.pk__qty,
.ld__cell input,
.at__num input,
.qxl__amt,
.bd__in {
  font-variant-numeric: tabular-nums;
}

/* Firefox dims ::placeholder to 54%, which drops --ink-4 on white to
   about 2.9:1. opacity: 1 is the fix, not decoration. */
input::placeholder,
textarea::placeholder { color: var(--ink-4); opacity: 1; }

@media (hover: hover) and (pointer: fine) {
  .tool__field input:hover:not(:disabled),
  .tool__field select:hover:not(:disabled),
  .tool__field textarea:hover:not(:disabled),
  .qx__field input:hover:not(:disabled),
  .qx__field select:hover:not(:disabled),
  .pk__field input:hover:not(:disabled),
  .pk__field select:hover:not(:disabled),
  .pk__row select:hover,
  .pk__qty:hover,
  .ld__cell input:hover,
  .bd__in:hover,
  .at__num input:hover,
  .qxl__desc:hover,
  .qxl__amt:hover,
  .sp__payer:hover,
  .cf-field input:hover,
  .cf-field textarea:hover {
    border-color: var(--ink-4);
    box-shadow: var(--elev-2);
  }
}

/* Focus is an outline, not a box-shadow ring. A shadow is clipped by
   .tool__scroll and by .ck__promptwrap's overflow:hidden; an outline
   is not, and it is the one property forced-colors keeps. The border
   still darkens, so the cue is a shape change and a colour change. */
.tool__field input:focus,
.tool__field select:focus,
.tool__field textarea:focus,
.qx__field input:focus,
.qx__field select:focus,
.qx__field textarea:focus,
.pk__field input:focus,
.pk__field select:focus,
.pk__field textarea:focus,
.pk__row select:focus,
.pk__qty:focus,
.ld__cell input:focus,
.bd__in:focus,
.at__num input:focus,
.qxl__desc:focus,
.qxl__amt:focus,
.sp__payer:focus,
.sp__message:focus,
.cf-field input:focus,
.cf-field textarea:focus,
.ck__mail-row input:focus {
  outline: var(--field-ring) solid var(--field-bd-on);
  outline-offset: 2px;
  border-color: var(--field-bd-on);
  box-shadow: none;
}

/* Inset where an outset ring would land on a neighbour: an 8px grid
   gap, a table cell, or the seam beside the rupee prefix. */
.pk__row select:focus,
.pk__qty:focus,
.ld__cell input:focus,
.bd__in:focus,
.at__num input:focus,
.qxl__amt:focus { outline-offset: -2px; }

/* :user-invalid, not :invalid. Every number field here carries
   min/max, so :invalid fires on an untouched empty field and would
   paint the form red before anyone did anything wrong. */
.tool__field input:user-invalid,
.tool__field select:user-invalid,
.qx__field input:user-invalid,
.pk__field input:user-invalid,
.cf-field input:user-invalid,
.cf-field textarea:user-invalid,
.tool__field input[aria-invalid="true"],
.qx__field input[aria-invalid="true"],
.pk__field input[aria-invalid="true"],
.cf-field input[aria-invalid="true"],
.cf-field textarea[aria-invalid="true"] {
  border-color: var(--bad);
}

/* Dashed is the cue that is not colour; dropping the shadow puts the
   field back on the page plane. No opacity, which would compound with
   the ink tokens and break their contrast. */
.tool__field input:disabled,
.tool__field select:disabled,
.qx__field input:disabled,
.qx__field select:disabled,
.pk__field input:disabled,
.pk__field select:disabled,
.pk__row select:disabled,
.pk__qty:disabled,
.ld__cell input:disabled,
.bd__in:disabled,
.at__num input:disabled,
.cf-field input:disabled {
  background: var(--bg-2);
  border-color: var(--border);
  border-style: dashed;
  color: var(--ink-4);
  box-shadow: none;
  cursor: not-allowed;
}

/* The AI card shrank its fields to 14px at (0,2,1). Reclaim the font
   size only, at matching specificity. */
.ai__card .pk__field input,
.ai__card .pk__field select { font-size: var(--field-fs); }

/* Labels were already sentence case and already left-aligned; only
   the four sizes and three gaps are reconciled. --track-caps stays
   where it belongs, on .tool__label and the .ld__head / .at__head
   column spans, which are not labels and are not touched. */
.tool__field label,
.qx__field label,
.pk__field label,
.pk__label {
  font-size: 14.5px;
  font-weight: 600;
  line-height: 1.45;
  color: var(--ink);
  margin-bottom: var(--field-gap);
}

.tool__hint { margin-top: 6px; font-size: 13px; line-height: 1.55; color: var(--ink-4); }

/* ── Affix group ─────────────────────────────────────────────
   The rupee prefix was three borders on a span, one on the input, and
   an !important to stitch them. The wrapper becomes the field: it
   owns the border, the radius, the elevation and the focus ring, and
   the control inside is bare. The DOM does not change.
   ───────────────────────────────────────────────────────────── */
.tool__money {
  display: flex;
  align-items: stretch;
  width: 100%;
  min-width: 0;
  min-height: var(--field-h);
  border: 1px solid var(--field-bd);
  border-radius: var(--radius);
  background: var(--bg);
  box-shadow: var(--elev-1);
  overflow: hidden;
  transition: border-color var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-fast) var(--ease-out);
}

.tool__money > span {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  padding: 0 var(--field-px);
  border: 0;
  border-right: 1px solid var(--border);
  border-radius: 0;
  background: var(--bg-2);
  color: var(--ink-3);
  font-size: var(--field-fs);
}

.tool__money > input,
.tool__money > .qxl__amt,
.tool__field .tool__money > input,
.qx__field .tool__money > input,
.pk__field .tool__money > input {
  flex: 1 1 auto;
  width: 100%;
  min-width: 0;
  min-height: 0;
  border: 0;
  background: transparent;
  box-shadow: none;
}

@media (hover: hover) and (pointer: fine) {
  .tool__money:hover { border-color: var(--ink-4); box-shadow: var(--elev-2); }
  .tool__money:hover > input { box-shadow: none; }
}

.tool__money:focus-within {
  outline: var(--field-ring) solid var(--field-bd-on);
  outline-offset: 2px;
  border-color: var(--field-bd-on);
}

.tool__money > input:focus,
.tool__field .tool__money > input:focus,
.qx__field .tool__money > input:focus { outline: none; box-shadow: none; }

.ck__promptwrap:focus-within { outline: var(--field-ring) solid var(--ink); outline-offset: 2px; }

/* ── Compact variant ─────────────────────────────────────────
   Declared on the CONTAINER as custom properties, so a grid row asks
   for a shorter field and there is no specificity fight with the base
   rule. Applies where a field is one cell in a repeating grid of
   cells, and nowhere else. Type stays at 16px in every variant;
   horizontal padding is what gives way.
   ───────────────────────────────────────────────────────────── */
.ld__head, .ld__row,
.at__head, .at__row,
.pk__row,
.bd__table,
.apv__row {
  --field-h: var(--field-h-sm);
  --field-py: var(--field-py-sm);
  --field-px: 10px;
}

/* 62px minmax floor, 4 tabular digits need about 38px: 8px padding
   leaves a 44px content box. The grid is inside .tool__scroll behind
   a 720px min-width, so its scroll is contained and never reaches the
   page. Do not raise .ld__grid's min-width. */
.ld__head, .ld__row { --field-px: 8px; }

/* 68px fixed track at 560px and no scroller: 6px leaves a 54px
   content box, which clears a 5-digit value at 16px. */
.at__head, .at__row { --field-px: 6px; }

/* The board tables are table-layout:auto, so a field change
   REDISTRIBUTES the columns instead of overflowing them -- the text
   inputs halve and nothing reports it. A min-width on the control
   raises the column's min-content instead, so the table grows inside
   its scroller. Stated per control, not per column, because the two
   tables have six and seven columns. */
.bd__table .bd__in { min-width: 108px; }
.bd__table select.bd__in { min-width: 136px; }
.bd__table .bd__in[type="date"] { min-width: 150px; }

/* The spinner is a 12px pair of arrows, far under 44px, invisible on
   touch, and drawn over the value in a 44-92px cell. Off on every
   coarse pointer, and off in the narrow cells at all times. */
@media (pointer: coarse) {
  input[type="number"] { appearance: textfield; -moz-appearance: textfield; }
  input[type="number"]::-webkit-outer-spin-button,
  input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
}

.ld__cell input, .at__num input, .pk__qty, .qxl__amt, .bd__in {
  appearance: textfield;
  -moz-appearance: textfield;
}

.ld__cell input::-webkit-outer-spin-button,
.ld__cell input::-webkit-inner-spin-button,
.at__num input::-webkit-outer-spin-button,
.at__num input::-webkit-inner-spin-button,
.pk__qty::-webkit-outer-spin-button,
.pk__qty::-webkit-inner-spin-button,
.qxl__amt::-webkit-outer-spin-button,
.qxl__amt::-webkit-inner-spin-button,
.bd__in::-webkit-outer-spin-button,
.bd__in::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* ── Row furniture ───────────────────────────────────────────
   A 30px bin beside a 48px field reads as broken, and both bins were
   already under the house's own 44px floor. Sizing the track from
   --field-h means the two can never disagree again, including inside
   the compact variant where both become 44px.

   .qxl__row is shared by .pr__steprow and .pr__riskrow at the same
   specificity, so every .qxl__row rule is followed by its two
   variants at (0,2,0) or it eats them.
   ───────────────────────────────────────────────────────────── */
.qxl__del { width: var(--field-h); height: var(--field-h); font-size: 19px; }
.pk__row .qxl__del { width: var(--field-h); height: var(--field-h); font-size: 18px; }
.apv__row .qxl__del { width: var(--field-h); height: var(--field-h); }

.qxl__row { grid-template-columns: minmax(0, 1fr) 170px var(--field-h); }
.qxl__row.pr__steprow { grid-template-columns: 26px minmax(0, 1fr) var(--field-h); }
.qxl__row.pr__riskrow { grid-template-columns: minmax(0, 1fr) 180px var(--field-h); }
.pk__row { grid-template-columns: minmax(0, 1fr) 62px var(--field-h); }
.rp__row { grid-template-columns: minmax(0, 1fr) 84px auto var(--field-h); }
.apv__row { grid-template-columns: 26px minmax(0, 1fr) 140px 140px 78px var(--field-h); }

@media (max-width: 760px) {
  .apv__row { grid-template-columns: 26px minmax(0, 1fr) var(--field-h); }
}

@media (max-width: 640px) {
  .rp__row { grid-template-columns: minmax(0, 1fr) 70px var(--field-h); }
}

@media (max-width: 620px) {
  .qxl__row.pr__riskrow { grid-template-columns: minmax(0, 1fr) var(--field-h); }
}

/* The bin used to be pinned into column 2 of every row type on a
   phone, because the rule doing it was scoped to nothing -- .pk__qty
   rendered 30px wide and to the RIGHT of its own bin, .rp__hrs clipped
   its value. That rule is now scoped to .qxl__row, so what is left here
   is placement, not repair: .rp__row and .apv__row drop a column below
   560px and the bin has to be told where to sit. */
@media (max-width: 560px) {
  .qxl__row { grid-template-columns: minmax(0, 1fr) var(--field-h); }
  .qxl__row.pr__steprow { grid-template-columns: 26px minmax(0, 1fr) var(--field-h); }
  .qxl__row.pr__steprow .qxl__del { grid-row: 1; grid-column: 3; align-self: stretch; }
  .rp__row .qxl__del { grid-row: 1; grid-column: 3; align-self: stretch; }
  .apv__row .qxl__del { grid-row: 1; grid-column: 3; align-self: stretch; }
}

/* ── Targets that are not fields ─────────────────────────────
   Four controls sat under 44px beside fields that now clear it. The
   checkbox box itself stays small and its LABEL carries the target:
   a 44px checkbox looks like a mistake, a 44px label looks like
   nothing. .qx__link is inline text, so it gets an invisible
   expander rather than a 44px line box. */
.tool__check { min-height: var(--field-h-sm); align-items: center; }
.tool__check input { width: 20px; height: 20px; flex: 0 0 20px; }
.bd__tab { min-height: var(--field-h-sm); }

.qx__link { position: relative; }
.qx__link::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: var(--field-h-sm);
  transform: translateY(-50%);
}
.qxl__tally .qx__link::after { content: none; }
.qxl__foot { row-gap: 14px; }

/* The nav is fixed and 68px tall, and nothing on the site carries
   scroll-margin. A phone scrolling a focused field into view puts it
   under the nav. */
input, select, textarea { scroll-margin-top: calc(var(--nav-h) + 12px); scroll-margin-bottom: 96px; }

@media (prefers-reduced-motion: reduce) {
  .tool__field input, .tool__field select, .tool__field textarea,
  .qx__field input, .qx__field select, .qx__field textarea,
  .pk__field input, .pk__field select,
  .pk__row select, .pk__qty, .ld__cell input, .bd__in, .at__num input,
  .qxl__desc, .qxl__amt, .sp__payer, .sp__message,
  .cf-field input, .cf-field textarea, .tool__money { transition: none; }
}

@media (prefers-contrast: more) {
  :root { --field-bd: var(--ink); }
  .tool__field input, .tool__field select, .tool__field textarea,
  .qx__field input, .qx__field select, .qx__field textarea,
  .pk__field input, .pk__field select,
  .pk__row select, .pk__qty, .ld__cell input, .bd__in, .at__num input,
  .qxl__desc, .qxl__amt, .sp__payer, .sp__message,
  .cf-field input, .cf-field textarea, .tool__money { box-shadow: none; }
  .tool__field input:focus, .tool__field select:focus, .tool__field textarea:focus,
  .qx__field input:focus, .qx__field select:focus,
  .pk__field input:focus, .pk__field select:focus,
  .pk__row select:focus, .pk__qty:focus,
  .ld__cell input:focus, .bd__in:focus, .at__num input:focus,
  .qxl__desc:focus, .qxl__amt:focus, .sp__payer:focus,
  .cf-field input:focus, .cf-field textarea:focus, .ck__mail-row input:focus,
  .tool__money:focus-within { outline-width: 3px; }
}

@media (prefers-reduced-transparency: reduce) {
  /* Nothing here is translucent; the elevation tokens are the only
     alpha and they are shadow, not surface. Pinned so a future
     translucent field cannot land without someone reading this. */
  .tool__money > span, .ck__promptwrap { background-color: var(--bg-2); }
}

@media (forced-colors: active) {
  .tool__field select, .qx__field select, .pk__field select,
  .pk__row select, .sp__payer {
    -webkit-appearance: auto;
    appearance: auto;
    background-image: none;
    padding-right: var(--field-px);
  }
  .tool__field input:focus, .tool__field select:focus, .tool__field textarea:focus,
  .qx__field input:focus, .qx__field select:focus,
  .pk__field input:focus, .pk__field select:focus,
  .ld__cell input:focus, .bd__in:focus, .at__num input:focus,
  .qxl__desc:focus, .qxl__amt:focus, .sp__payer:focus,
  .cf-field input:focus, .cf-field textarea:focus, .ck__mail-row input:focus,
  .tool__money:focus-within { outline-color: Highlight; }
}

/* .rp__vis is the monthly report's own checkbox, and the field pass did not
   know about it: 15px box, 20px tap target, 12.5px label. Every other
   checkbox on the site went to a 20px box inside a 44px target and this one
   would have been the only one left that a thumb misses. Same numbers, same
   reasons, stated here rather than by widening the .tool__check selector,
   because the two live in different layouts and one of them is a grid cell. */

.rp__vis {
  min-height: var(--field-h-sm);
  font-size: 14px;
  gap: 9px;
}

.rp__vis input {
  width: 20px;
  height: 20px;
  flex: 0 0 20px;
}


/* ── The work strip ───────────────────────────────────────────
   mountWork injects this bar at the top of every tool that keeps
   its own state, and until now it had no CSS whatsoever -- not a
   single .wk rule has ever existed in this file. What shipped was
   three default grey browser buttons, 13.3px type in a 20px box,
   run together with the sentence beside them and no space between
   any of it. On six tool pages, as the first thing under the hero.

   Quiet by design. Export, import and start-new are reached for
   before beginning or after finishing; they are not the point of
   the page, and a loud bar at the top would say otherwise. So it
   reads as a shelf the tool sits on rather than a toolbar.

   The buttons borrow .btn's geometry so they line up with every
   other control in the workspace, and take their height from
   --field-h-sm, which is the same 44px floor the field pass set.
   ───────────────────────────────────────────────────────────── */
.wk {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin: 0 0 24px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-2);
}

/* Its own line: the sentence is context for the buttons, not a
   label on the first one, and inline it read as exactly that. */
.wk__lead {
  flex: 1 1 100%;
  margin: 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink-4);
}

.wk__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: var(--field-h-sm);
  padding: 0 16px;
  border: 1px solid var(--border-2);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 14.5px;
  font-weight: 500;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  transition: border-color 0.2s var(--ease), color 0.2s var(--ease),
              background 0.2s var(--ease), transform 0.2s var(--ease);
}

/* A label wrapping a hidden file input. Without this it keeps the
   baseline alignment of text and sits a few pixels low beside the
   real buttons. */
.wk__file { margin: 0; }

/* Start new destroys work. It should be reachable, not inviting. */
.wk__quiet {
  border-color: transparent;
  color: var(--ink-4);
}

.wk__msg {
  font-size: 13px;
  line-height: 1.4;
  color: var(--ink-3);
}

.wk__msg.is-bad { color: var(--bad); }

@media (hover: hover) and (pointer: fine) {
  .wk__btn:hover { border-color: var(--ink); }
  .wk__quiet:hover { border-color: var(--border-2); color: var(--ink); }
}

.wk__btn:active { transform: translateY(1px); }

.wk__btn:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

/* On a phone the three buttons share the row rather than wrapping
   one lonely button onto a line of its own. */
@media (max-width: 560px) {
  .wk { gap: 8px; }
  .wk__btn { flex: 1 1 0; padding: 0 10px; }
  .wk__msg { flex: 1 1 100%; }
}


/* ── My work ─────────────────────────────────────────────────
   The band at the top of /plus/. It lists what is saved in this
   browser and nothing else, so it stays quiet: a returning user
   should find their work immediately, and a first-time visitor
   should be able to read past it in one glance to the editions.

   Rows are a list, not cards. Cards would make six pieces of work
   look like six products, and the editions below are the products.
   ───────────────────────────────────────────────────────────── */
.pz-work__head { max-width: 62ch; }

.pz-work__title {
  margin: 10px 0 8px;
  font-size: clamp(22px, 3.4vw, 30px);
  line-height: 1.2;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

.pz-work__sub {
  margin: 0;
  font-size: 15px;
  line-height: 1.6;
  color: var(--ink-3);
}

.pz-work__sub code {
  padding: 1px 5px;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--bg-2);
  font-size: 0.92em;
}

.pz-work__empty {
  margin: 18px 0 0;
  padding: 16px 18px;
  border: 1px dashed var(--border-2);
  border-radius: var(--radius);
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--ink-4);
}

.pz-work__list {
  margin: 18px 0 0;
  padding: 0;
  list-style: none;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}

.pz-work__row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 16px;
  background: var(--bg);
}

.pz-work__row + .pz-work__row { border-top: 1px solid var(--border); }

.pz-work__main {
  display: flex;
  min-width: 0;
  flex-direction: column;
  gap: 2px;
}

.pz-work__name {
  font-size: 15.5px;
  font-weight: 500;
  line-height: 1.35;
  color: var(--ink);
  overflow-wrap: anywhere;
}

.pz-work__meta {
  font-size: 13px;
  line-height: 1.4;
  color: var(--ink-4);
}

.pz-work__acts {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

/* Same 44px the field pass set, so these line up with every other
   control in the workspace rather than being their own size. */
.pz-work__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: var(--field-h-sm);
  padding: 0 14px;
  border: 1px solid var(--border-2);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 500;
  line-height: 1;
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  transition: border-color 0.2s var(--ease), color 0.2s var(--ease),
              transform 0.2s var(--ease);
}

/* Delete is destructive, so it is reachable rather than inviting. */
.pz-work__btn--quiet {
  border-color: transparent;
  color: var(--ink-4);
}

@media (hover: hover) and (pointer: fine) {
  .pz-work__btn:hover { border-color: var(--ink); }
  .pz-work__btn--quiet:hover { border-color: var(--border-2); color: var(--bad); }
}

.pz-work__btn:active { transform: translateY(1px); }

.pz-work__btn:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

/* On a phone the name needs the whole width, and the three actions
   share the row under it rather than wrapping one at a time. */
@media (max-width: 560px) {
  .pz-work__row { align-items: stretch; }
  .pz-work__main { flex: 1 1 100%; }
  .pz-work__acts { flex: 1 1 100%; }
  .pz-work__btn { flex: 1 1 0; padding: 0 8px; }
}


/* ── The cost table ───────────────────────────────────────────
   Item, quantity, unit cost, and a bin. Four columns, which is one
   more than the quote row has, so it owns its own grid rather than
   borrowing one that is nearly right.

   The header strip is aria-hidden: every input in the row already
   carries its own label, and a screen reader reading "Item Qty Unit
   cost" before each of four rows is noise. It is there for the eye.

   Children come from .qxl__* and are already styled -- only the grid
   and the labels are new.
   ───────────────────────────────────────────────────────────── */
.cst { margin: 6px 0 4px; }

.cst__head { margin-bottom: 12px; }

.cst__labels,
.cst__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 84px 110px var(--field-h);
  gap: 10px;
  align-items: center;
}

.cst__labels {
  margin-bottom: 8px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-4);
}

.cst__row + .cst__row { margin-top: 10px; }

/* Right-aligned figures in the printed estimate, so the column of
   amounts reads down as a column rather than as ragged text. */
.cst__figure { text-align: right; font-variant-numeric: tabular-nums; }

/* On a phone the item needs the whole width and the two numbers share
   the line under it. The bin keeps its own column beside the item so
   it never lands under a number field and gets hit by mistake. */
@media (max-width: 560px) {
  .cst__labels { display: none; }
  .cst__row {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) var(--field-h);
    gap: 8px;
  }
  .cst__row > .qxl__desc { grid-row: 1; grid-column: 1 / span 2; }
  .cst__row > .qxl__del { grid-row: 1; grid-column: 3; }
}


/* The three input blocks are one column, not three grid children. */
.cst__left {
  display: flex;
  flex-direction: column;
  gap: clamp(24px, 3vw, 32px);
  min-width: 0;
}

/* mountWork inserts the work strip as the first child of [data-tool].
   In a two-column tool that lands it in a cell; it belongs across the
   top, above both. */
.tool > .wk { grid-column: 1 / -1; }

/* The figure follows you down the cost table rather than scrolling off
   it -- which is the whole reason for putting it in the second column.
   Only where there are two columns to speak of. */
@media (min-width: 981px) {
  .cst__left ~ .tool__out {
    position: sticky;
    top: 24px;
  }
}


/* ── Cover letter ─────────────────────────────────────────────
   The left column is a sequence of small jobs -- read the advert,
   correct the list, name your evidence, write three paragraphs --
   so each is a labelled block with air around it rather than one
   long form. The requirement rows are the centre of the tool and
   get the only visual weight on the page: a must-have carries a
   left rule so the two halves of an advert can be told apart at a
   glance while scrolling.
   ───────────────────────────────────────────────────────────── */
.cl__block + .cl__block {
  margin-top: clamp(26px, 3.4vw, 38px);
  padding-top: clamp(22px, 3vw, 30px);
  border-top: 1px solid var(--border);
}

.cl__block .tool__field { margin-top: 12px; }

.cl__req {
  padding: 12px;
  border: 1px solid var(--border);
  border-left: 3px solid transparent;
  border-radius: var(--radius);
  background: var(--bg);
}

.cl__req + .cl__req { margin-top: 10px; }

/* A must-have is the half the reader decides on, so it is the half
   you can find without reading. */
.cl__req.is-must { border-left-color: var(--accent); }

.cl__reqtop {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto var(--field-h);
  gap: 8px;
  align-items: center;
}

.cl__must {
  height: var(--field-h-sm);
  padding: 0 12px;
  border: 1px solid var(--border-2);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--ink-4);
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
  transition: border-color 0.2s var(--ease), color 0.2s var(--ease);
}

.cl__must.is-on {
  border-color: var(--accent);
  color: var(--accent);
}

.cl__ev { margin-top: 8px; }

.cl__addev {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 10px;
  align-items: end;
}

.cl__addev .tool__field { margin-top: 0; }

.cl__para {
  margin-top: 14px;
  padding: 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
}

.cl__pick { margin-bottom: 10px; }

.cl__text { width: 100%; }

/* The scorer names the first thing missing rather than grading, so
   it reads as an instruction and is quiet once it has nothing to
   say. */
.cl__score {
  margin: 8px 0 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--warn);
}

.cl__score.is-ok { color: var(--ok); }

@media (max-width: 560px) {
  .cl__reqtop {
    grid-template-columns: minmax(0, 1fr) var(--field-h);
  }
  .cl__reqtop > .qxl__desc { grid-row: 1; grid-column: 1; }
  .cl__reqtop > .qxl__del { grid-row: 1; grid-column: 2; }
  .cl__must { grid-row: 2; grid-column: 1 / -1; width: 100%; }
  .cl__addev { grid-template-columns: 1fr; }
}


/* ── The invoice line ─────────────────────────────────────────
   Six columns: what you delivered, how many, at what, less what,
   taxed at what, and a bin. Wider than the cost table because tax
   is per line here -- one invoice can carry an 18% service and a
   5% printed item, and a single blended rate on the footer is the
   thing that gets questioned.
   ───────────────────────────────────────────────────────────── */
.iv__labels,
.iv__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 62px 96px 72px 72px var(--field-h);
  gap: 8px;
  align-items: center;
}

.iv__labels {
  margin-bottom: 8px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-4);
}

.iv__row + .iv__row { margin-top: 10px; }

.iv__import { display: inline-flex; margin-top: 4px; }

/* Below the two-column breakpoint the description takes the row and
   the four figures share the one under it. The bin stays beside the
   description so it is never under a number field, where it gets hit
   by a thumb aiming at the rate. */
@media (max-width: 900px) {
  .iv__labels { display: none; }
  .iv__row {
    grid-template-columns: repeat(4, minmax(0, 1fr)) var(--field-h);
    gap: 8px;
  }
  .iv__row > .qxl__desc { grid-row: 1; grid-column: 1 / span 4; }
  .iv__row > .qxl__del { grid-row: 1; grid-column: 5; }
}


/* ── The change-request history row ───────────────────────────
   What changed, what it cost, how many days. Narrower than an
   invoice line because there is no tax and no quantity -- a change
   either happened or it did not.
   ───────────────────────────────────────────────────────────── */
.ch__labels,
.ch__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 110px 78px var(--field-h);
  gap: 8px;
  align-items: center;
}

.ch__labels {
  margin-bottom: 8px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-4);
}

.ch__row + .ch__row { margin-top: 10px; }

@media (max-width: 560px) {
  .ch__labels { display: none; }
  .ch__row {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) var(--field-h);
  }
  .ch__row > .qxl__desc { grid-row: 1; grid-column: 1 / span 2; }
  .ch__row > .qxl__del { grid-row: 1; grid-column: 3; }
}


/* ── Viva drill ───────────────────────────────────────────────
   One question at a time, in a card, because a list is something
   you skim and a card is something you answer. Show answer sits
   beside the two verdict buttons rather than above them: you say
   whether you could answer BEFORE you are allowed to look, and
   the layout should not make peeking the easy path.
   ───────────────────────────────────────────────────────────── */
.vv__card {
  margin: 20px 0;
  padding: clamp(18px, 2.6vw, 24px);
  border: 1px solid var(--ink);
  border-radius: var(--radius-lg);
  background: var(--bg);
}

.vv__meta {
  margin: 0 0 10px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-4);
}

.vv__q {
  margin: 0 0 14px;
  font-size: clamp(17px, 2.2vw, 20px);
  line-height: 1.4;
  letter-spacing: -0.01em;
  text-wrap: balance;
}

.vv__a {
  margin: 0 0 14px;
  padding: 12px 14px;
  border-left: 3px solid var(--accent);
  background: var(--bg-2);
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--ink-3);
}

.vv__acts { display: flex; flex-wrap: wrap; gap: 10px; }

.vv__cut {
  margin: 10px 0 0;
  padding-left: 20px;
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--ink-3);
}

.vv__cut li + li { margin-top: 10px; }

/* A module row: what it is called, whether you wrote it, and a bin. */
.vv__mod {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto var(--field-h);
  gap: 10px;
  align-items: center;
}

.vv__mod + .vv__mod { margin-top: 10px; }

.vv__mine {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: var(--field-h-sm);
  font-size: 14px;
  white-space: nowrap;
  color: var(--ink-3);
  cursor: pointer;
}

@media (max-width: 560px) {
  .vv__mod { grid-template-columns: minmax(0, 1fr) var(--field-h); }
  .vv__mod > .qxl__desc { grid-row: 1; grid-column: 1; }
  .vv__mod > .qxl__del { grid-row: 1; grid-column: 2; }
  .vv__mine { grid-row: 2; grid-column: 1 / -1; }
  .vv__acts > .btn { flex: 1 1 100%; }
}


/* ── Report chapters and front matter ─────────────────────────
   A chapter row is a number, a title, a page count and two
   controls. The number is printed rather than typed: chapters are
   numbered by their position, and letting somebody type "3" next to
   the fourth row is how a contents page stops being true.
   ───────────────────────────────────────────────────────────── */
.pr2__labels,
.pr2__row {
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr) 78px var(--field-h) var(--field-h);
  gap: 8px;
  align-items: center;
}

.pr2__labels {
  margin-bottom: 8px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-4);
}

.pr2__row + .pr2__row { margin-top: 10px; }

.pr2__n {
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  color: var(--ink-4);
  text-align: right;
}

.pr2__move { font-size: 15px; }

/* The contents list is long, so it scrolls in its own box rather
   than pushing the print button off the screen. */
.pr2__toc {
  max-height: 340px;
  overflow-y: auto;
}

.pr2__toc dd { font-variant-numeric: tabular-nums; }

/* The cover page is the one part of a report with a fixed shape. */
.pr2__cover { text-align: center; }

.pr2__covertitle {
  margin: 0 0 18px;
  font-size: 20px;
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: 0.02em;
}

.pr2__names { list-style: none; margin: 10px 0; padding: 0; }

.pr2__signs {
  display: flex;
  flex-wrap: wrap;
  gap: 40px;
  margin-top: 36px;
  font-size: 13.5px;
  line-height: 1.7;
}

@media (max-width: 560px) {
  .pr2__labels { display: none; }
  .pr2__row {
    grid-template-columns: 24px minmax(0, 1fr) var(--field-h);
    row-gap: 8px;
  }
  .pr2__row > .qxl__desc { grid-row: 1; grid-column: 2; }
  .pr2__row > .qxl__amt { grid-row: 2; grid-column: 2; }
  .pr2__row > .pr2__move { grid-row: 2; grid-column: 3; }
  .pr2__row > .qxl__del { grid-row: 1; grid-column: 3; }
}


/* ── Slide rows ───────────────────────────────────────────────
   Number, title, who speaks, how much there is to say, bin. The
   two selects are narrow on purpose: they are settings on a row,
   not the row's subject.
   ───────────────────────────────────────────────────────────── */
.dk__row {
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr) 150px 160px var(--field-h);
  gap: 8px;
  align-items: center;
}

.dk__row + .dk__row { margin-top: 10px; }

@media (max-width: 1100px) {
  .dk__row {
    grid-template-columns: 24px minmax(0, 1fr) var(--field-h);
    row-gap: 8px;
  }
  .dk__row > .qxl__desc { grid-row: 1; grid-column: 2; }
  .dk__row > .qxl__del { grid-row: 1; grid-column: 3; }
  .dk__row > .dk__who { grid-row: 2; grid-column: 2; }
  .dk__row > .dk__w { grid-row: 3; grid-column: 2; }
}


/* ── Role rows ────────────────────────────────────────────────
   Role, what it costs you, what you bill, hours. Four figures
   because costing a project in one blended number is the thing
   this tool exists to stop.
   ───────────────────────────────────────────────────────────── */
.es__labels,
.es__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 96px 96px 78px var(--field-h);
  gap: 8px;
  align-items: center;
}

.es__labels {
  margin-bottom: 8px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-4);
}

.es__row + .es__row { margin-top: 10px; }

/* A role under 15% margin is the finding, so it is coloured. */
.es__bad { color: var(--bad); }

@media (max-width: 900px) {
  .es__labels { display: none; }
  .es__row {
    grid-template-columns: repeat(3, minmax(0, 1fr)) var(--field-h);
    row-gap: 8px;
  }
  .es__row > .qxl__desc { grid-row: 1; grid-column: 1 / span 3; }
  .es__row > .qxl__del { grid-row: 1; grid-column: 4; }
}


/* ── Minute lines ─────────────────────────────────────────────
   Kind, what was said, who owns it, by when. The owner and date
   fields are disabled on anything that is not an action, because
   a note does not have a deadline and offering one invites
   somebody to fill it in.
   ───────────────────────────────────────────────────────────── */
.mn__row {
  display: grid;
  grid-template-columns: 124px minmax(0, 1fr) 120px 150px var(--field-h);
  gap: 8px;
  align-items: center;
}

.mn__row + .mn__row { margin-top: 10px; }

/* A decision is the line people come back to, so it is the line
   you can find without reading. */
.mn__row.is-decision > .qxl__desc { border-left: 3px solid var(--accent); }
.mn__row.is-risk > .qxl__desc { border-left: 3px solid var(--ink-3); }

.mn__who:disabled,
.mn__by:disabled { opacity: 0.4; }

@media (max-width: 1100px) {
  .mn__row {
    grid-template-columns: minmax(0, 1fr) var(--field-h);
    row-gap: 8px;
  }
  .mn__row > .mn__kind { grid-row: 1; grid-column: 1; }
  .mn__row > .qxl__del { grid-row: 1; grid-column: 2; }
  .mn__row > .qxl__desc { grid-row: 2; grid-column: 1 / -1; }
  .mn__row > .mn__who { grid-row: 3; grid-column: 1; }
  .mn__row > .mn__by { grid-row: 3; grid-column: 2 / -1; }
}


/* ── Certificates ─────────────────────────────────────────────
   One to a page, landscape, and centred, because that is what a
   certificate is. The issuer and the signatory are on the face of
   every one: a certificate nobody can be asked about is not a
   certificate.
   ───────────────────────────────────────────────────────────── */
.ct__doc {
  text-align: center;
  padding: 48px 56px;
  page-break-after: always;
}

.ct__doc:last-child { page-break-after: auto; }

.ct__issuer {
  margin: 0 0 4px;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.ct__kicker {
  margin: 0 0 32px;
  font-size: 12.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #555;
}

.ct__lead { margin: 0 0 8px; font-size: 14px; }

.ct__name {
  margin: 0 0 14px;
  font-size: 30px;
  font-weight: 600;
  line-height: 1.2;
}

.ct__body {
  margin: 0 auto 44px;
  max-width: 46ch;
  font-size: 15px;
  line-height: 1.6;
}

.ct__sig {
  margin: 0 0 4px;
  padding-top: 8px;
  border-top: 1px solid #999;
  display: inline-block;
  min-width: 240px;
  font-size: 14px;
}

.ct__ref {
  margin: 28px 0 0;
  font-size: 11px;
  letter-spacing: 0.04em;
  color: #666;
}

/* ── README blockers ──────────────────────────────────────────
   Grouped by who is stopped rather than by section, because the
   order the groups appear in is the advice.
   ───────────────────────────────────────────────────────────── */
.rd__group {
  margin: 16px 0 6px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-4);
}

.rd__list {
  margin: 0;
  padding-left: 20px;
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--ink-3);
}

.rd__list li + li { margin-top: 8px; }


/* ── Portfolio ────────────────────────────────────────────────
   A project is a small stack of fields rather than a row: six
   things, three of them long, and a row would make every one of
   them too narrow to read back.
   ───────────────────────────────────────────────────────────── */
.pf__proj {
  padding: 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
}

.pf__proj + .pf__proj { margin-top: 14px; }

.pf__proj .tool__field + .tool__field { margin-top: 12px; }

/* The preview is the actual file, rendered. Sandboxed, because it
   is a document built out of somebody's own typing. */
.pf__frame {
  width: 100%;
  height: 460px;
  margin: 14px 0;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: #fff;
}


/* ── A guide you work through ─────────────────────────────────
   The specification's test for a guide is that it should never
   look like an article. Three things do that work here and none
   of them is decoration: the setup block, which tells you whether
   to start at all; the contents, which is also the progress; and
   a step that visibly changes state when you tick it.
   ───────────────────────────────────────────────────────────── */

/* ── Before you start ── */
.guide__setup {
  margin: 22px 0 8px;
  padding: 18px 20px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--bg-2);
}

.guide__badges {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.guide__badge {
  display: inline-flex;
  align-items: center;
  padding: 5px 12px;
  border: 1px solid var(--border-2);
  border-radius: 999px;
  background: var(--bg);
  font-size: 12.5px;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--ink-3);
}

.guide__needs { margin-top: 16px; }

.guide__needs-tag,
.guide__toctag,
.guide__nexttag {
  display: block;
  margin-bottom: 8px;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
}

.guide__needs ul {
  margin: 0;
  padding-left: 20px;
  font-size: 15px;
  line-height: 1.65;
  color: var(--ink-3);
}

.guide__needs li + li { margin-top: 6px; }

/* ── The contents, which is the progress ── */
.guide__toc {
  margin: 28px 0 8px;
  padding: 20px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}

.guide__tochead {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
}

.guide__toccount {
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  color: var(--ink-4);
}

.guide__track {
  height: 4px;
  margin: 12px 0 10px;
  border-radius: 999px;
  background: var(--border);
  overflow: hidden;
}

.guide__bar {
  display: block;
  width: 0;
  height: 100%;
  border-radius: 999px;
  background: var(--ok);
  transition: width 0.3s var(--ease);
}

.guide__leadline {
  margin: 0 0 14px;
  font-size: 14px;
  line-height: 1.6;
  color: var(--ink-4);
}

.guide__toclist {
  margin: 0 0 12px;
  padding: 0;
  list-style: none;
}

.guide__tocrow {
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr);
  gap: 10px;
  align-items: baseline;
  padding: 7px 0;
}

.guide__tocrow + .guide__tocrow { border-top: 1px solid var(--border); }

.guide__tocrow a {
  font-size: 15px;
  line-height: 1.45;
  color: var(--ink);
  text-decoration: none;
}

.guide__tocrow.is-done a { color: var(--ink-4); }

.guide__tocnum {
  margin-right: 8px;
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
  color: var(--ink-4);
}

/* Done, current, not started. The three states the specification
   draws as a tick, an arrow and an empty circle. */
.guide__mark {
  font-size: 14px;
  line-height: 1.5;
  /* Was --border-2, which is a border colour and came out at 1.48:1
     against the page. This glyph is not a border; it says whether a
     step has been done. */
  color: var(--ink-4);
}

.guide__mark.is-done { color: var(--ok); }
.guide__mark.is-now { color: var(--ink); font-weight: 600; }

/* ── A step ── */
.guide__step {
  margin-top: clamp(32px, 4vw, 48px);
  padding-top: clamp(24px, 3vw, 32px);
  border-top: 1px solid var(--border);
  scroll-margin-top: 24px;
}

.guide__stepnum {
  margin: 0 0 6px;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-4);
}

.guide__step.is-now .guide__stepnum { color: var(--accent); }

/* A finished step recedes rather than disappearing: you still want
   to be able to read it, you just do not want to be looking at it. */
.guide__step.is-done { opacity: 0.62; }
.guide__step.is-done:hover,
.guide__step.is-done:focus-within { opacity: 1; }

.guide__outcome {
  margin: 0 0 16px;
  padding: 12px 14px;
  border-left: 3px solid var(--accent);
  background: var(--bg-2);
  font-size: 15px;
  line-height: 1.6;
}

.guide__outcome span {
  display: block;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-4);
  margin-bottom: 4px;
}

/* Nothing ticks this but the person who did the work, so it is a
   real target rather than a decoration at the end of a section. */
.guide__done {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: var(--field-h-sm);
  margin-top: 18px;
  padding: 0 16px 0 14px;
  border: 1px solid var(--border-2);
  border-radius: var(--radius);
  background: var(--bg);
  font-size: 14.5px;
  font-weight: 500;
  color: var(--ink-3);
  cursor: pointer;
  transition: border-color 0.2s var(--ease), color 0.2s var(--ease);
}

.guide__step.is-done .guide__done {
  border-color: var(--ok);
  color: var(--ok);
}

.guide__done input { accent-color: var(--ok); }

/* ── The completion checklist ── */
.guide__checklist label {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  cursor: pointer;
}

.guide__checklist input {
  margin-top: 4px;
  accent-color: var(--ok);
  flex: none;
}

.guide__checklist input:checked + span {
  color: var(--ink-4);
  text-decoration: line-through;
  text-decoration-thickness: 1px;
}

/* ── Never a dead end ── */
.guide__next {
  margin-top: clamp(32px, 4vw, 48px);
  padding: clamp(22px, 3vw, 30px);
  border: 1px solid var(--accent);
  border-radius: var(--radius-lg);
  background: var(--bg-2);
}

.guide__nextline {
  margin: 0 0 16px;
  font-size: clamp(18px, 2.4vw, 22px);
  line-height: 1.3;
  letter-spacing: -0.01em;
  text-wrap: balance;
}

@media (max-width: 560px) {
  .guide__tocrow { grid-template-columns: 20px minmax(0, 1fr); }
  .guide__done { width: 100%; justify-content: center; }
  .guide__next .btn { width: 100%; }
}


/* ── Tools and Guides, the two areas ──────────────────────────
   Section 9 asks for two expandable areas rather than one shelf,
   because a four-minute calculator and a two-hour guide are not
   the same offer and mixed together nothing told them apart.

   <details> does the toggling, so the marker is a rotating caret
   rather than a scripted one and the content stays in the DOM
   when closed -- still crawlable, still findable with the
   browser's own find.
   ───────────────────────────────────────────────────────────── */
.pz-area + .pz-area {
  margin-top: clamp(32px, 4vw, 46px);
  padding-top: clamp(26px, 3vw, 34px);
  border-top: 1px solid var(--border);
}

.pz-area__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 14px;
  padding-right: 28px;
  position: relative;
  cursor: pointer;
  list-style: none;
}

/* Safari still paints its own triangle unless this is said twice. */
.pz-area__head::-webkit-details-marker { display: none; }

.pz-area__head::after {
  content: "";
  position: absolute;
  top: 0.35em;
  right: 4px;
  width: 9px;
  height: 9px;
  border-right: 1.5px solid var(--ink-4);
  border-bottom: 1.5px solid var(--ink-4);
  transform: rotate(45deg);
  transition: transform 0.2s var(--ease);
}

.pz-area[open] > .pz-area__head::after { transform: rotate(-135deg); }

.pz-area__count {
  font-size: 13.5px;
  color: var(--ink-4);
}

.pz-area__head:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 4px;
  border-radius: 4px;
}

/* ── A guide row ──
   Carries what it costs you. The decision here is whether to start
   two hours of work, which is not the decision a tool row asks for,
   so the row says difficulty, steps and minutes rather than just a
   name. */
.pz-guides {
  margin: 18px 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 10px;
}

/* The li is the grid cell; the link fills it, or rows come out
   ragged wherever a guide name runs to one line. */
.pz-guide { display: flex; }

.pz-guide__link {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-height: 62px;
  padding: 13px 15px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  text-decoration: none;
  transition: border-color 0.2s var(--ease);
}

.pz-guide__name {
  font-size: 15.5px;
  font-weight: 500;
  line-height: 1.35;
  color: var(--ink);
}

.pz-guide__meta {
  font-size: 12.5px;
  line-height: 1.4;
  color: var(--ink-4);
}

@media (hover: hover) and (pointer: fine) {
  .pz-guide__link:hover { border-color: var(--ink); }
}

.pz-guide__link:active { transform: translateY(1px); }

.pz-guide__link:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}


/* The utilisation table is the argument, so the row you are actually
   on is marked rather than left for the reader to find. */
.rt2__table tr.is-now td {
  font-weight: 600;
  color: var(--ink);
  background: var(--bg-2);
}


/* ── Six shapes ───────────────────────────────────────────────
   Each one is a box with its own limit on it. The count is the
   whole interface: it is the thing nobody knows and the reason
   the tool exists, so it sits beside the name rather than under
   the field where it would be read after the damage.
   ───────────────────────────────────────────────────────────── */
.cr__shape {
  padding: 15px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
}

.cr__shape + .cr__shape { margin-top: 12px; }

.cr__shape.is-over { border-color: var(--bad); }

.cr__shapehead {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
}

.cr__shapename {
  font-size: 15.5px;
  font-weight: 500;
  color: var(--ink);
}

.cr__count {
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
  color: var(--ink-4);
}

.cr__count.is-ok { color: var(--ok); }
.cr__count.is-over { color: var(--bad); font-weight: 600; }

.cr__text {
  width: 100%;
  margin-top: 10px;
}

.cr__miss {
  margin: 8px 0 0;
  font-size: 13px;
  line-height: 1.55;
  color: var(--ink-4);
}

.cr__miss.is-bad { color: var(--bad); }
.cr__miss.is-ok { color: var(--ok); }


/* Import, on My Work itself. The per-tool strip can already take a
   file, but only if you remember which tool made it -- and somebody
   arriving on a new laptop with a .sowthzide file has no reason to. */
.pz-work__import {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  margin: 16px 0 0;
}

.pz-work__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: var(--field-h-sm);
  margin: 0;
  padding: 0 16px;
  border: 1px solid var(--border-2);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--ink);
  font-size: 14px;
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
  transition: border-color 0.2s var(--ease);
}

.pz-work__msg {
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--ink-4);
}

.pz-work__msg.is-bad { color: var(--bad); }

@media (hover: hover) and (pointer: fine) {
  .pz-work__btn:hover { border-color: var(--ink); }
}

.pz-work__btn:focus-within {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}


/* The name of the thing you were last working on, which is the only
   line on the Continue card anybody reads. */
.pz-continue__project {
  margin: 4px 0 2px;
  font-size: clamp(19px, 2.4vw, 24px);
  font-weight: 500;
  line-height: 1.25;
  letter-spacing: -0.01em;
}


/* ── Give the text room ───────────────────────────────────────
   Three separate faults, all of which read as "congested".

   ONE: ORPHANS. "Price a job before you quote, not / after."
   "Learn the workflows rather than the / hype." A single short
   word alone on a line looks like an extra line that should not
   be there, because that is exactly what it is. text-wrap: pretty
   tells the browser to pull a word back rather than strand one.
   Thirteen of them across the plus pages.

   TWO: HEADINGS THAT WRAP AND TOUCH. A 27px card title at 1.16
   leading is fine on one line and collides on two, and the
   workspace cards all wrap to two. Display type wants tight
   leading only while it stays on one line.

   THREE: INSIDE TIGHTER THAN OUTSIDE. Where the gap between two
   items is close to the gap between two lines of one item, a
   wrapped item reads as two items. The separation between things
   has to beat the separation inside them.

   text-wrap: pretty is ignored by browsers that do not have it,
   which costs those readers nothing they have today.
   ───────────────────────────────────────────────────────────── */

/* ── One: no stranded words ── */
p,
li,
dd,
figcaption,
blockquote,
.tool__hint,
.tool__note,
.tool__floor,
.guide__outcome,
.cl__score,
.cr__miss {
  text-wrap: pretty;
}

/* A heading balances instead: even line lengths matter more than
   the last line on two or three words of display type. */
h1, h2, h3,
.pz-path__name,
.guide__h2,
.tool__label {
  text-wrap: balance;
}

/* ── Two: headings that wrap need leading ── */
.pz-path__name { line-height: 1.26; }

.guide__h2 { line-height: 1.3; }

.pz-work__title { line-height: 1.24; }

.vv__q { line-height: 1.45; }

/* A big figure only ever wraps when the label beside it is long,
   and at 1.00 the second line touches the first. */
.tool__price { line-height: 1.08; }

.cl__block .tool__label,
.pz-shelf__name { line-height: 1.35; }

/* ── Three: separate things more than their own lines ──
   The bullets on a workspace card run at 1.6, so two lines of one
   bullet sit about 9px apart. A 10px margin between bullets made a
   wrapped bullet read as two. */
.pz-path__list li { margin-bottom: 16px; }

.pz-path__list li:last-child { margin-bottom: 0; }

.guide__list { gap: 13px; }

.guide__needs li + li { margin-top: 9px; }

/* ── And the gap nobody chose ──
   The work strip sits 78px above the first field on seven tools,
   because its own bottom margin stacks under the grid gap. */
.tool > .wk { margin-bottom: 4px; }


/* ── Vertical rhythm on the dashboard ─────────────────────────
   Measured, not guessed. Every one of these pairs was sitting at
   ZERO pixels apart:

     TOOLS / 20 things you can do  ->  the explaining line   0px
     the explaining line           ->  "Your project"        0px
     PICK UP WHERE YOU LEFT OFF    ->  "Onboarding SOP"      0px
     "Onboarding SOP"              ->  "Guide"               0px
     "Guide"                       ->  the Continue button   0px

   Four separate things stacked with nothing between them read as
   one block of text with odd line breaks in it, which is exactly
   what it looked like. The elements had no margins of their own
   and nothing above them supplied any.

   The spacing is set by what the gap has to SEPARATE: a label
   from its own heading is the smallest step, a paragraph from the
   next section heading is the largest.
   ───────────────────────────────────────────────────────────── */

/* ── The Tools / Guides areas ── */
.pz-area__head { margin-bottom: 14px; }

.pz-shelves__note {
  margin: 0 0 30px;
  max-width: 68ch;
}

/* A group heading inside a shelf: clear of what came before it,
   close to the rows it names. */
.pz-shelf__name {
  margin: 0 0 14px;
  line-height: 1.35;
}

.pz-shelf + .pz-shelf { margin-top: 12px; }

.pz-shelf__list li { padding: 11px 0; }

/* ── The Continue card ──
   Label, name, what it is, and the way back in. Four things, and
   they were flush against each other. */
.pz-continue__head { margin-bottom: 10px; }

.pz-continue__project { margin: 0 0 6px; }

.pz-continue__next {
  margin: 0 0 20px;
  color: var(--ink-4);
}

.pz-continue [data-pz-resume] { margin-top: 0; }

/* ── The intent cards ── */

/* ══════════════════════════════════════════════
   The gaps the entrance was standing in for

   Measured at rest across all fifty-nine Plus pages, against the type
   each gap separates rather than a flat pixel count -- a 62px heading
   and a 15px hint cannot share one number. A gap under half its type
   size reads as congested. Most of what that test flags is correct and
   stays: a label belongs to its number, a hint belongs to its field,
   a term belongs to its definition. Tightening those apart would
   break the pairing and read worse, not better.

   What is left is the hero, where 20px under a 62px heading was doing
   the work of 34, and one heading in the guides.
   ══════════════════════════════════════════════ */


.page-hero__title { margin-bottom: 32px; }


.page-hero--tool .page-hero__sub { margin-top: 12px; }

/* The tool hero is deliberately compact -- its heading is 33px, not 62
   -- so it cannot inherit the 32px the dashboards need. Raising the
   shared rule had pushed it to a gap wider than its own type. */
.page-hero--tool .page-hero__title { margin-bottom: 18px; }

/* Eighty-five of these across the guides: the mistake and the
   explanation of it ran together at six pixels. */
.guide__mistake h3 { margin-bottom: 10px; }

/* A link is a target, not a caption. Four pixels below the field it
   acts on put it inside the field's own optical block. */
.tool__field + .qx__link,
.tool__money + .qx__link,
.tool__scroll + .qx__link,
.qx__actions + .qx__link,
.qxl + .qx__link,
.qa__why + .qx__link { margin-top: 7px; }

/* A hint ends a thought; the next block starts another

   A hint sits six pixels under the field it explains, which is right,
   and then the next control group starts against it at zero, which is
   not -- the explanation of one thing and the label of the next were
   sharing an edge on nineteen pages. The same happened to every
   section label in an output panel: the result, then immediately the
   heading of whatever follows it.

   Both are the same mistake. Tight means belongs-to; these do not
   belong to what is above them. */
.tool__hint + div,
.tool__note + div { margin-top: 13px; }

.tool__out > * + .tool__label,
.tool__hint + .tool__label,
.tool__note + .tool__label { margin-top: 18px; }

.dq__handover + div { margin-top: 18px; }

/* A name and the line under it are a pair, but at zero they were one
   block of text rather than two lines of it. */
.pz-work__name + .pz-work__meta { margin-top: 3px; }

/* ══════════════════════════════
   Currency

   It sits at the top of the output panel because that is what it
   governs -- every figure below it -- and because a control that
   changes the meaning of the numbers has to be read before them,
   not found afterwards.
   ══════════════════════════════ */
.cur {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 10px;
  margin: 0 0 18px;
  padding: 0 0 16px;
  border-bottom: 1px solid var(--border);
}

.cur__label {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: var(--track-caps, 0.1em);
  text-transform: uppercase;
  color: var(--ink-4);
}

/* width and height now come from the shared field rule, below. */

.cur__rate {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 13px;
  color: var(--ink-3);
}


/* The whole line, under both controls rather than beside them: it is
   a caveat about the number, and a caveat set in a column beside the
   thing it qualifies gets skipped. */
.cur__note {
  flex: 1 0 100%;
  margin: 0;
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--ink-4);
  text-wrap: pretty;
}

@media (max-width: 560px) {
  .cur__pick { min-width: 0; width: 100%; }
  .cur__rate { width: 100%; }
}

/* The currency control's own controls are fields

   They were built by script rather than written into a .tool__field,
   so they came out as bare browser defaults: a 19px select at 13.3px
   beside the site's 48px at 16px. Two real faults in that, not one.
   Nineteen pixels is half the minimum tap target, and anything under
   16px makes iOS zoom the page on focus -- which the rest of this
   stylesheet goes out of its way to avoid.

   The widths are overridden back down because these two sit on a row
   together rather than filling a column. */
.cur__pick { width: auto; min-width: 210px; flex: 0 1 auto; }
.cur__rateinput { width: 104px; flex: 0 0 auto; }

@media (max-width: 560px) {
  .cur__pick { min-width: 0; width: 100%; }
  .cur__rate { width: 100%; }
  .cur__rateinput { width: 120px; }
}

/* ══════════════════════════════════════════════
   Free, and the ask

   Six pages open without an account. The rest carry a card above the
   tool -- above it, not over it, because the tool works either way and
   a card that covered it would be claiming otherwise.
   ══════════════════════════════════════════════ */

/* A tag, not a badge. It marks three items on a shelf of twenty, and
   the point is that they are open rather than that they are lesser,
   so it sits quietly after the name instead of shouting before it. */
.pz-free {
  margin-left: 8px;
  padding: 2px 7px;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-4);
  white-space: nowrap;
  vertical-align: 1px;
}

/* -- The buy card on a locked tool --
   It sits above the tool rather than over it. An overlay would cover
   the thing it is trying to sell, which is the one mistake this
   design cannot afford to make. */
.pz-buy {
  margin: 0 0 clamp(20px, 3vw, 30px);
  padding: clamp(18px, 2.4vw, 26px);
  border: 1px solid var(--border-2);
  border-radius: var(--radius-lg);
  background: var(--bg-2);
}

.pz-buy__tag {
  display: block;
  margin-bottom: 10px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: var(--track-caps, 0.1em);
  text-transform: uppercase;
  color: var(--ink-3);
}

.pz-buy__lead {
  margin: 0 0 8px;
  font-family: var(--font-display);
  font-size: clamp(19px, 2vw, 23px);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.3;
  color: var(--ink);
  text-wrap: balance;
}

.pz-buy__note {
  margin: 0 0 18px;
  max-width: 60ch;
  font-size: 15px;
  line-height: 1.6;
  color: var(--ink-3);
  text-wrap: pretty;
}

.pz-buy__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 14px;
}

.pz-buy__all { font-size: 14px; color: var(--ink-4); }

/* -- The locked tool itself --
   Readable, obviously inert, and NOT faded into illegibility: the
   whole argument for showing it is that somebody can read it. So the
   controls recede and the prose does not. */
.pz-locked {
  position: relative;
}

.pz-locked input,
.pz-locked select,
.pz-locked textarea,
.pz-locked button {
  cursor: not-allowed;
  opacity: 0.75;
  background-image: repeating-linear-gradient(
    -45deg,
    transparent 0 7px,
    rgba(10, 10, 10, 0.028) 7px 14px);
}

/* A disabled control in most browsers greys its own text to somewhere
   near unreadable. These are examples worth reading -- the whole point
   of showing the page -- so the colour is put back. */
.pz-locked input:disabled,
.pz-locked select:disabled,
.pz-locked textarea:disabled {
  -webkit-text-fill-color: var(--ink-2);
  color: var(--ink-2);
}

.pz-locked button:disabled {
  -webkit-text-fill-color: currentColor;
}

@media (max-width: 560px) {
  .pz-buy__actions > .btn { width: 100%; }
  .pz-buy__all { margin-top: 2px; }
}

/* The offer, above the prices

   A price is only readable by somebody who has used the thing. This
   sits between the heading and the three cards so the sentence they
   read first is what they can have now, not what it will cost. */
.pz-trial {
  margin: 0 0 clamp(26px, 3.4vw, 40px);
  padding: clamp(18px, 2.4vw, 26px) clamp(20px, 2.6vw, 28px);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--bg-2);
}

.pz-trial__lead {
  margin: 0 0 8px;
  font-family: var(--font-display);
  font-size: clamp(18px, 1.9vw, 21px);
  font-weight: 600;
  letter-spacing: -0.018em;
  line-height: 1.3;
  color: var(--ink);
  text-wrap: balance;
}

.pz-trial__note {
  margin: 0;
  max-width: 72ch;
  font-size: 15px;
  line-height: 1.6;
  color: var(--ink-3);
  text-wrap: pretty;
}

/* ══════════════════════════════════════════════
   The analytics choice

   A card, not a bar across the whole viewport, and it does not block
   the page: the site works identically whichever button is pressed,
   so covering the content to insist on an answer would be theatre.
   Both buttons are real buttons of the same weight, because one of
   them being a grey word is how a consent prompt becomes a dark
   pattern.
   ══════════════════════════════════════════════ */
.consent {
  position: fixed;
  left: max(16px, env(safe-area-inset-left, 0px));
  right: auto;
  bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  z-index: 60;
  width: min(420px, calc(100vw - 32px));
  padding: 18px 20px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--bg);
  box-shadow: 0 10px 34px rgba(0, 0, 0, 0.13);
}

.consent__text {
  margin: 0 0 14px;
  font-size: 14px;
  line-height: 1.6;
  color: var(--ink-3);
  text-wrap: pretty;
}

.consent__text a { text-decoration: underline; text-underline-offset: 2px; }

.consent__actions { display: flex; flex-wrap: wrap; gap: 10px; }
.consent__actions .btn { flex: 1 1 auto; }

@media (max-width: 420px) {
  .consent { left: 8px; width: calc(100vw - 16px); }
}

/* The way back to that choice, in the footer of every page. A choice
   you cannot find again is not revocable. */
.footer__choice {
  padding: 0;
  border: 0;
  background: none;
  font-family: inherit;
  font-size: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* ══════════════════════════════════════════════
   Checkout

   One column, one decision. The state block is the page: it says
   what is happening now, and the button appears only in the state
   where pressing it means something.
   ══════════════════════════════════════════════ */
/* Buy sits under Open, quieter than it, because while Plus is in
   preview the honest primary action is to go and use the thing. */
.pz-path__buy {
  margin-top: 10px;
  width: 100%;
  justify-content: center;
}

/* ── Checkout ───────────────────────────────────────────────────
   Two panes: what is being bought, and the button that buys it. The
   summary is not decoration. A checkout whose only statement of the
   price is inside the payment provider's own window is asking for a
   card before it has said the number. */
.co {
  max-width: 980px;
  margin-inline: auto;
}

.co__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--space-7);
  align-items: start;
}

@media (max-width: 860px) {
  .co__grid { grid-template-columns: minmax(0, 1fr); gap: var(--space-6); }
}

/* ── The order ── */
.co__summary {
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--bg-2);
  padding: var(--space-6);
}

.co__eyebrow {
  margin: 0 0 10px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  color: var(--ink-4);
}

.co__edition {
  font-family: var(--font-display);
  font-size: clamp(20px, 2.2vw, 25px);
  line-height: 1.2;
  letter-spacing: -0.024em;
  margin: 0 0 6px;
  text-wrap: balance;
}

.co__tagline {
  margin: 0 0 20px;
  font-size: 15px;
  line-height: 1.55;
  color: var(--ink-3);
  text-wrap: pretty;
}

.co__includes {
  list-style: none;
  display: grid;
  gap: 9px;
  margin: 0 0 22px;
  padding: 0;
}

.co__includes li {
  position: relative;
  padding-left: 22px;
  font-size: 14px;
  line-height: 1.55;
  color: var(--ink-2);
}

/* A rule, not a tick. One accent used sparingly is the house style,
   and a column of green check marks is somebody else's. */
.co__includes li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 10px;
  width: 10px;
  height: 1px;
  background: var(--accent);
}

.co__lines {
  margin: 0;
  padding-top: 14px;
  border-top: 1px solid var(--border-2);
  display: grid;
  gap: 8px;
}

.co__line {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
}

.co__line dt {
  font-size: 14px;
  line-height: 1.5;
  color: var(--ink-3);
}

.co__line dd {
  margin: 0;
  font-size: 14px;
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.co__line--total {
  margin-top: 6px;
  padding-top: 12px;
  border-top: 1px solid var(--border-2);
}

.co__line--total dt {
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
}

.co__line--total dd {
  font-family: var(--font-display);
  font-size: 26px;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--ink);
}

.co__once {
  margin: 14px 0 0;
  font-size: 13px;
  line-height: 1.6;
  color: var(--ink-4);
  text-wrap: pretty;
}

.co__switch {
  margin: 10px 0 0;
  font-size: 13px;
  line-height: 1.6;
  color: var(--ink-4);
}

.co__switch a { text-decoration: underline; text-underline-offset: 3px; }

/* ── The action ── */
.co__pane { padding-top: 4px; }

.co__h1 {
  font-family: var(--font-display);
  font-size: clamp(24px, 3vw, 32px);
  line-height: 1.15;
  letter-spacing: -0.028em;
  margin: 0 0 12px;
  text-wrap: balance;
}

.co__state { margin: 0 0 20px; }

.co__note {
  margin: 0;
  font-size: 16px;
  line-height: 1.65;
  color: var(--ink-3);
  text-wrap: pretty;
}

.co__note a { text-decoration: underline; text-underline-offset: 3px; }

/* Waiting is a state with a shape, not a spinner. The border says
   something is happening without pretending to know how long. */
/* Every state but the plain ones is a box; its colour says which:
   waiting, ready, anon and info are info, slow is a warning, done is a
   success, bad an error. See Status. */
.co__state--waiting .co__note,
.co__state--slow .co__note,
.co__state--bad .co__note,
.co__state--done .co__note,
.co__state--info .co__note {
  padding: 16px 18px;
  border-radius: var(--radius);
}

.co__account {
  margin: 0 0 18px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink-4);
  overflow-wrap: anywhere;
}

/* The one paragraph on this page arguing against the purchase, so it
   is set as a note rather than a banner -- quiet, but not hidden. */
.co__preview {
  margin: 0 0 20px;
  padding: 13px 0 13px 16px;
  border-left: 2px solid var(--border-2);
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--ink-3);
  text-wrap: pretty;
}

.co__preview a { text-decoration: underline; text-underline-offset: 3px; }

.co__actions {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
}

.co__actions .btn { min-width: 200px; }

.co__methods { margin-top: 24px; }

.co__methods-h {
  margin: 0 0 8px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  color: var(--ink-4);
}

.co__chips {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0 0 10px;
  padding: 0;
}

.co__chips li {
  padding: 4px 11px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  font-size: 12px;
  color: var(--ink-3);
}

.co__methods-n {
  margin: 0;
  font-size: 13px;
  line-height: 1.6;
  color: var(--ink-4);
  text-wrap: pretty;
}

.co__terms {
  margin: 16px 0 0;
  font-size: 13px;
  line-height: 1.6;
  color: var(--ink-4);
  text-wrap: pretty;
}

.co__terms a { text-decoration: underline; text-underline-offset: 2px; }

/* ── What happens after you pay ──
   The gap between the payment succeeding and the workspace opening is
   the webhook, it is real, and a buyer who has not been told about it
   reads ten seconds of "confirming" as a failure. */
.co__after {
  margin-top: var(--space-8);
  padding-top: var(--space-6);
  border-top: 1px solid var(--border);
}

.co__after-h {
  margin: 0 0 22px;
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  color: var(--ink-4);
}

.co__steps {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-6);
  margin: 0 0 var(--space-6);
  padding: 0;
}

@media (max-width: 720px) {
  .co__steps { grid-template-columns: minmax(0, 1fr); gap: var(--space-5); }
}

.co__step-n {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  margin-bottom: 10px;
  border: 1px solid var(--border-2);
  border-radius: 50%;
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-4);
  font-variant-numeric: tabular-nums;
}

.co__step-t {
  margin: 0 0 5px;
  font-size: 15px;
  font-weight: 600;
  line-height: 1.35;
  color: var(--ink);
  text-wrap: balance;
}

.co__step-b {
  margin: 0;
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--ink-3);
  text-wrap: pretty;
}

.co__assure {
  list-style: none;
  display: grid;
  gap: 10px;
  margin: 0;
  padding: 18px 0 0;
  border-top: 1px solid var(--border);
}

.co__assure li {
  font-size: 13px;
  line-height: 1.6;
  color: var(--ink-4);
  text-wrap: pretty;
}

.co__assure strong { color: var(--ink-2); font-weight: 600; }
.co__assure a { text-decoration: underline; text-underline-offset: 2px; }

@media (max-width: 480px) {
  .co__actions .btn { width: 100%; min-width: 0; }
}

/* ═══════════════════════════════════════════════════════════════
   THE REBUILT PAGES
   Everything the October 2026 redesign added, each thing once.

   Order: the type roles the new components share; the motion they
   share; then the home page top to bottom; then the components the
   inner pages reuse; then Works, Plus and Contact. Media queries sit
   with the component they change. Reduced motion is last, in one
   place, because it has to win.
   ═══════════════════════════════════════════════════════════════ */

/* ── Type roles ────────────────────────────────────────────────
   One size per job across every rebuilt section, so eight rows, four
   services, four steps and eight questions read as one page. Layout
   lives with each component below; only the type lives here. */

/* A title inside a section: a row, a service, a step, a feature, a
   question. */
.strip__name,
.step__title,
.valuelist__what,
.four__name,
.faq__q {
  font-family: var(--font-display);
  font-size: clamp(18px, 1.9vw, 21px);
  font-weight: 600;
  line-height: 1.26;
  letter-spacing: -0.022em;
  color: var(--ink);
}

/* The line of copy under it. */
.strip__desc,
.step__text,
.valuelist__why,
.four__desc,
.faq__a,
.ledger__real {
  font-size: 15.5px;
  line-height: 1.62;
  color: var(--ink-3);
}

/* A large numeral used as structure. */
.strip__num,
.steps--big .step__num {
  font-family: var(--font-display);
  font-size: clamp(36px, 4.2vw, 56px);
  font-weight: 400;
  line-height: 1;
  letter-spacing: -0.04em;
  color: var(--ink-4);
  font-variant-numeric: tabular-nums;
}

/* A band's title that is not a .section-title, held to the same
   size as one. */
.plusband__title,
.ask__title {
  font-family: var(--font-display);
  font-size: clamp(28px, 3.6vw, 44px);
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: var(--track-tight);
  color: var(--ink);
  max-width: 22ch;
  margin-bottom: 16px;
  text-wrap: balance;
}

/* An intro paragraph that is not a .section-body, held to that. */
.plusband__text,
.ask__text,
.hp-close {
  font-size: 16.5px;
  line-height: 1.62;
  max-width: 56ch;
}

/* ── Motion the rebuilt pages share ───────────────────────────── */

/* Letter by letter. main.js splits a heading into words (nowrap, so
   lines still break between words) and letters, each with a running
   index. Letters rise half an em and fade in, 18ms apart, capped so
   the whole heading lands inside 800ms. */
.js .letters .w { display: inline-block; white-space: nowrap; }

.js .letters .c {
  display: inline-block;
  opacity: 0;
  transform: translateY(0.5em);
  transition: opacity 0.5s var(--ease), transform 0.65s var(--ease);
  transition-delay: calc(var(--n, 0) * var(--step, 18ms) + 60ms);
  will-change: opacity, transform;
}

.js.is-ready .letters .c { opacity: 1; transform: none; }
.js .letters.is-done .c { will-change: auto; }

/* The canvas. The head script sets html.intro on a first load in a
   session; while it is set the page cannot scroll, the hero stands at
   the viewport's height, and the nav and the offer bar are held
   invisible with no transition, so they come in together
   when the class goes. The H1 is invisible until main.js has moved
   it to the middle (is-placed). On release the hero's extra height
   drains (its min-height transition, below), which is what brings
   the rest of the page up under the settling sentence. */
html.intro { overflow: hidden; }
.js.intro .home-hero { min-height: 100vh; }
.js.intro .home-hero__title { opacity: 0; will-change: transform; }
.js.intro .home-hero__title.is-placed { opacity: 1; }
.js.intro .nav { opacity: 0; transition: none; }
.js.intro .home-hero__row { opacity: 0; transition: none; }
.js.intro .animate-1, .js.intro .animate-3,
.js.intro .animate-4, .js.intro .animate-5 {
  opacity: 0 !important;
  transition: none !important;
}

/* A screenshot settles from 1.06 to 1 as it enters, driven by the
   scroll position and not a timer; browsers without the timeline get
   the still image. */
@supports (animation-timeline: view()) {
  .js .shot__frame img,
  .js .work__shot img {
    animation: shot-settle linear both;
    animation-timeline: view();
    animation-range: entry 0% entry 100%;
  }
}

@keyframes shot-settle {
  from { transform: scale(1.06); }
  to   { transform: scale(1); }
}

/* The FAQ: main.js animates the height; this clips during it, and
   turns the caret at the START of a close rather than when the open
   attribute is removed at the end. */
.faq__item.is-animating { overflow: hidden; }
.faq__item.is-closing > .faq__q::after {
  transform: rotate(45deg);
  border-color: var(--ink-4);
}

/* Page to page: a 220ms crossfade on same-origin navigation where
   cross-document view transitions exist, nothing where they do not.
   The launch curtain is decided before first paint, so what is
   captured is the real page either way. */
@view-transition { navigation: auto; }

::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 0.22s;
  animation-timing-function: var(--ease);
}

/* ── Home: the hero ────────────────────────────────────────────
   The sentence on three lines, centred, then one bar beneath it: the
   offer on the left, the one action on the right. */
/* The full height of the screen, its content centred in what is
   left under the nav. (The intro's 100vh drains to this.) */
.home-hero {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 100vh;
  min-height: 100svh;
  padding-top: calc(var(--nav-h) + clamp(32px, 4vw, 64px));
  padding-bottom: clamp(48px, 6vw, 80px);
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  transition: min-height 0.85s var(--ease);
}

/* A flex item with auto side margins (the container's centring) is
   sized to its content, not stretched: without this the container
   takes the heading's unbroken width and the page runs off a phone. */
.home-hero > .container { width: 100%; }

/* 40px floor, 96px ceiling; 6.9vw meets the ceiling at 1390px. The
   block hugs its own text (max-content) so its centre is the text's
   centre, which is what the canvas measures. */
.home-hero__title {
  width: max-content;
  max-width: 100%;
  margin: 0 auto clamp(28px, 3.6vw, 48px);
  font-family: var(--font-display);
  font-size: clamp(2.5rem, 6.9vw, 6rem);
  text-align: center;
  font-weight: 400;
  line-height: 1.0;
  letter-spacing: -0.038em;
  color: var(--ink);
  text-wrap: balance;
  transform-origin: 50% 50%;
}

/* Four words in a second typeface: the sans for the sentence, a
   retro serif italic for Building, people, something and own --
   Behind The Nineties, by Casloop Studio.

   Licensed for this site (Sowthzide bought the commercial licence on
   6 October 2026; the free download is personal use only). Served from
   assets/fonts like Inter: the italic alone, cut to the same Latin
   range by fontTools (65 KB OTF -> 24 KB WOFF2). Every visitor gets this
   file -- no local() first -- so what the owner sees is what everyone
   sees. The home page preloads it, so the heading does not swap faces.

   size-adjust lives in the face, so it only applies when the serif is
   actually the one drawing. */
@font-face {
  font-family: 'Sowthzide Accent';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/behind-the-nineties-400-italic-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+20B9, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
  size-adjust: 104%;
}

.home-hero__title .accent {
  font-family: 'Sowthzide Accent', var(--font-display);
  font-style: italic;
  font-weight: 400;
}

/* Three lines, broken at the phrases, from 900px up. Below that the
   breaks are switched off and the sentence wraps as it must. */
.home-hero__title br { display: none; }

/* ── The offer, two ways in ──
   A switch (two radio buttons dressed as a segmented control) and the
   bar it chooses, as wide as the heading's middle line. The checked
   radio picks the bar through :has(), so nothing here needs a script.
   Each bar is a field and its button in one tray: the web address and
   the audit button, or a line about the business and the project
   button. The tray is the field's frame and takes the focus ring.
   Stacks on a phone. */
.home-hero__row {
  display: grid;
  justify-items: center;
  gap: 14px;
  width: min(100%, 860px);
  margin: clamp(36px, 5vw, 64px) auto 0;
  transition: opacity 0.5s var(--ease);
}

.offer__switch {
  display: inline-flex;
  gap: 2px;
  padding: 4px;
  background: var(--fill);
  border-radius: 999px;
}

.offer__opt { position: relative; }

/* The radio itself, invisible but there: it takes the click, the
   arrow keys and the focus. */
.offer__opt input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.offer__opt span {
  display: block;
  padding: 8px 18px;
  border-radius: 999px;
  font-size: 14px;
  font-weight: 500;
  color: var(--ink-3);
  transition: background-color 0.2s var(--ease-out), color 0.2s var(--ease-out),
              box-shadow 0.2s var(--ease-out);
}

.offer__opt input:checked + span {
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--elev-2);
}

.offer__opt input:focus-visible + span { outline: 2px solid var(--ink); outline-offset: 2px; }

@media (hover: hover) and (pointer: fine) {
  .offer__opt input:not(:checked):hover + span { color: var(--ink); }
}

.offer__bar {
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: 100%;
  padding: 10px;
  background: var(--bg);
  border: 1px solid var(--border-2);
  border-radius: var(--radius-xl);
  transition: border-color 0.2s var(--ease-out), box-shadow 0.2s var(--ease-out);
}

.offer__bar:focus-within {
  border-color: var(--ink);
  box-shadow: var(--elev-3);
}

.offer__field {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 52px;
  padding: 0 14px;
  border: 0;
  background: transparent;
  font-family: var(--font-body);
  font-size: var(--field-fs);
  color: var(--ink);
}

/* The tray draws the focus; a second ring inside it would be noise. */
.offer__field:focus { outline: none; }
.offer__field::placeholder { color: var(--ink-4); }

.offer__bar .btn { width: 100%; }

.offer__note {
  max-width: 56ch;
  font-size: 14px;
  line-height: 1.55;
  color: var(--ink-4);
  text-align: center;
  text-wrap: balance;
}

/* Which bar shows. */
.offer__bar--need,
.offer__note--need { display: none; }
.offer:has(input[value="need"]:checked) .offer__bar--have,
.offer:has(input[value="need"]:checked) .offer__note--have { display: none; }
.offer:has(input[value="need"]:checked) .offer__bar--need { display: flex; }
.offer:has(input[value="need"]:checked) .offer__note--need { display: block; }

@media (min-width: 760px) {
  .offer__bar {
    flex-direction: row;
    align-items: center;
    padding: 8px 8px 8px 10px;
  }
  .offer__bar .btn { flex: none; width: auto; }
}

@media (min-width: 900px) {
  .home-hero__title br { display: inline; }
}

/* ── Home: the quiet part ──────────────────────────────────────
   On white, joined to the hero by its rule: the lead, the four rows,
   the closing line, spaced by the container rather than by their own
   margins. (A black band, then a two-by-two of italic quotes, until
   6 October 2026.) */
.quiet {
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}

.quiet > .container {
  display: flex;
  flex-direction: column;
  gap: clamp(56px, 7vw, 104px);
}

.quiet .section-head { margin-bottom: 0; }

/* Four rows of two columns under hairlines: what the visitor sees in
   the ink, what you see in the grey with its first sentence in the ink.
   No italics, no rules beside the text; a small numeral to start each
   row. The column labels are one header on a wide screen and a small
   label inside each cell on a phone. */
.ledger__head { display: none; }

.ledger__list { list-style: none; border-bottom: 1px solid var(--border); }

.ledger__row {
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr);
  gap: 10px 16px;
  padding: clamp(24px, 3vw, 36px) 0;
  border-top: 1px solid var(--border);
}

.ledger__num {
  grid-row: 1 / span 2;
  padding-top: 3px;
  font-size: 13px;
  font-weight: 500;
  color: var(--ink-4);
  font-variant-numeric: tabular-nums;
}

.ledger__k {
  display: block;
  margin-bottom: 4px;
  font-family: var(--font-body);
  font-size: 12.5px;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--ink-4);
}

.ledger__seen {
  font-family: var(--font-display);
  font-size: clamp(18px, 1.5vw, 20px);
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: -0.012em;
  color: var(--ink);
  text-wrap: pretty;
}

.ledger__real {
  max-width: 48ch;
  font-size: 15.5px;
  line-height: 1.6;
  color: var(--ink-3);
  text-wrap: pretty;
}

.ledger__real strong { font-weight: 600; color: var(--ink); }

@media (min-width: 860px) {
  .ledger__head,
  .ledger__row {
    display: grid;
    grid-template-columns: 56px minmax(0, 1fr) minmax(0, 1fr);
    column-gap: clamp(32px, 5vw, 80px);
  }
  .ledger__head {
    padding-bottom: 14px;
    font-size: 12.5px;
    font-weight: 500;
    letter-spacing: 0.02em;
    color: var(--ink-4);
  }
  .ledger__row { align-items: baseline; }
  .ledger__num { grid-row: auto; padding-top: 0; }
  .ledger__k { display: none; }
}

/* A closing paragraph that lands an argument after a list; --wide is
   the one under the quiet part's rows, set a size up, since it is the
   point of it. The rows' last hairline is the only rule it needs. */
.hp-close { color: var(--ink-2); text-wrap: pretty; }

.hp-close--wide {
  max-width: 62ch;
  font-size: clamp(16.5px, 1.35vw, 18.5px);
  line-height: 1.6;
}

/* ── Home: the eight things, as Apple-style cards ─────────────
   Tall white cards in a row that starts on the content's left edge
   and runs off the right edge of the screen, so the next card is
   always part in view. Each holds a category in the red, the thing
   we do, what it is for, and at its foot a large ghosted numeral.
   The cards are not buttons and do not lift on hover. The row snaps
   to a card; the arrows are main.js (14); nothing moves by itself.

   The bleed: the track widens to the viewport with negative margins
   and pads itself back to the container, and the section clips the
   sideways overflow (100vw counts the scrollbar on Windows). */
.section--bleed { overflow-x: clip; }

.acards__track {
  list-style: none;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: min(78vw, 300px);
  gap: 16px;
  margin-inline: calc(50% - 50vw);
  padding-inline: calc(50vw - 50%);
  /* Where a card snaps to: the container's left edge. A percentage
     here would be of the track itself, so it is worked out from the
     container's own tokens; main.js sets the exact pixel value. */
  scroll-padding-inline: calc(max((100vw - var(--max-w)) / 2, 0px) + var(--pad-x));
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  /* A scrolling box clips on both axes: room for the cards' shadow.
     The top is given back; the bottom is the gap above the buttons. */
  padding-block: 12px 28px;
  margin-top: -12px;
}

.acards__track::-webkit-scrollbar { display: none; }

.acards__track:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: -2px;
}

.acard {
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: clamp(420px, 34vw, 500px);
  padding: clamp(24px, 2.4vw, 32px);
  background: var(--surface);
  border-radius: var(--radius-xl);
  box-shadow: var(--elev-2);
  scroll-snap-align: start;
}

.acard__cat {
  margin-bottom: 10px;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: -0.005em;
  color: var(--accent);
}

.acard__title {
  font-family: var(--font-display);
  font-size: clamp(22px, 1.9vw, 27px);
  font-weight: 600;
  line-height: 1.16;
  letter-spacing: -0.026em;
  color: var(--ink);
  text-wrap: balance;
}

.acard__why {
  margin-top: 14px;
  font-size: 15px;
  line-height: 1.6;
  color: var(--ink-3);
  text-wrap: pretty;
}

.acard__foot {
  margin-top: auto;
  padding-top: 24px;
}

.acard__num {
  font-family: var(--font-display);
  font-size: clamp(84px, 8vw, 120px);
  font-weight: 500;
  line-height: 0.74;
  letter-spacing: -0.06em;
  color: var(--ink-ghost);
  font-variant-numeric: tabular-nums;
}

.acards__nav {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
}

.acards__btn {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--fill);
  color: var(--ink);
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out),
              opacity var(--dur-fast) var(--ease-out),
              transform 0.12s var(--ease-out);
}

.acards__btn:active:not(:disabled) { transform: scale(0.94); }
.acards__btn:disabled { opacity: 0.4; cursor: default; }
.acards__btn:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

@media (hover: hover) and (pointer: fine) {
  .acards__btn:hover:not(:disabled) { background: var(--ink); color: var(--surface); }
}

@media (min-width: 900px) {
  .acards__track {
    grid-auto-columns: clamp(300px, 24vw, 360px);
    gap: 20px;
  }
}

/* ── Home: the four services as four columns ─────────────────── */
.strip {
  display: grid;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}

.strip__item {
  display: block;
  padding: clamp(24px, 3vw, 40px) clamp(16px, 2vw, 28px);
  border-bottom: 1px solid var(--border);
  transition: background var(--dur-fast) var(--ease-out);
}

.strip__num { display: block; margin-bottom: 18px; }
.strip__name { display: block; margin-bottom: 8px; }
.strip__desc { display: block; margin-bottom: 16px; }

.strip__price {
  display: block;
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.strip__price em { font-style: normal; font-weight: 500; color: var(--ink-4); }

.strip__item:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

@media (min-width: 640px) {
  .strip { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .strip__item:nth-child(odd) { border-right: 1px solid var(--border); }
}

@media (min-width: 1024px) {
  .strip { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .strip__item { border-bottom: 0; border-right: 1px solid var(--border); }
  .strip__item:last-child { border-right: 0; }
}

@media (hover: hover) and (pointer: fine) {
  .strip__item:hover { background: var(--bg); }
  .strip__item:hover .strip__name { color: var(--accent); }
}

/* ── Steps ─────────────────────────────────────────────────────
   Four numbered steps: the home page's "Nothing to sign", the AI
   page's method, Contact's "after you press send". Two-up from
   760px, four-up from 1100px; --big gives the numeral its size on
   the home page; --stack keeps one column inside a narrow column. */
.steps {
  list-style: none;
  display: grid;
  gap: clamp(28px, 3.4vw, 40px) clamp(28px, 3.4vw, 44px);
}

.step {
  padding-top: 18px;
  border-top: 2px solid var(--ink);
}

.step__num {
  display: block;
  margin-bottom: 12px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.12em;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}

.step__title { margin-bottom: 9px; text-wrap: pretty; }
.step__text { text-wrap: pretty; }

.steps--big .step { padding-top: 22px; border-top: 1px solid var(--border); }
.steps--big .step__num { margin-bottom: 18px; }

.steps.steps--stack { grid-template-columns: minmax(0, 1fr); gap: 22px; }

@media (min-width: 760px) {
  .steps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 1100px) {
  .steps { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* ── The FAQ ───────────────────────────────────────────────────
   Native <details>, the same disclosure the Plus pages use, so
   there is no JavaScript to load for it. The first is open. */
.faq {
  max-width: 78ch;
  border-top: 1px solid var(--border);
}

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

.faq__q {
  position: relative;
  display: block;
  padding: clamp(18px, 2.1vw, 22px) 44px clamp(18px, 2.1vw, 22px) 0;
  cursor: pointer;
  list-style: none;
  transition: color var(--dur-fast) var(--ease-out);
  text-wrap: pretty;
}

/* Safari paints its own triangle unless this is said a second time. */
.faq__q::-webkit-details-marker { display: none; }

.faq__q::after {
  content: "";
  position: absolute;
  top: calc(clamp(18px, 2.1vw, 22px) + 0.4em);
  right: 6px;
  width: 10px;
  height: 10px;
  border-right: 1.6px solid var(--ink-4);
  border-bottom: 1.6px solid var(--ink-4);
  transform: rotate(45deg);
  transition: transform var(--dur) var(--ease);
}

.faq__item[open] > .faq__q::after {
  transform: rotate(-135deg);
  border-color: var(--accent);
}

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

.faq__a {
  padding: 0 44px clamp(20px, 2.4vw, 26px) 0;
  max-width: 66ch;
}

.faq__a p { text-wrap: pretty; }

.faq__a a,
.valuelist__why a {
  color: var(--accent);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
}

@media (hover: hover) and (pointer: fine) {
  .faq__q:hover { color: var(--accent); }
  .faq__q:hover::after { border-color: var(--accent); }
}

/* ── The Plus band ─────────────────────────────────────────────
   The product business at the size it was scored: one paragraph,
   two links, hairline above, no cards. */
.plusband {
  padding: clamp(40px, 5vw, 64px) 0;
  background: var(--bg);
  border-top: 1px solid var(--border);
}

.plusband__inner {
  display: grid;
  gap: clamp(24px, 3vw, 40px);
  align-items: start;
}

.plusband__text { color: var(--ink-3); text-wrap: pretty; }

.plusband__links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px 20px;
}

.plusband__free {
  font-size: 14.5px;
  font-weight: 500;
  color: var(--accent);
  transition: opacity var(--dur-fast) var(--ease-out);
}

@media (min-width: 900px) {
  .plusband__inner {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
  }
  .plusband__links { flex-direction: column; align-items: flex-end; }
}

@media (hover: hover) and (pointer: fine) {
  .plusband__free:hover { opacity: 0.72; }
}

/* ── Feature-and-benefit list ──────────────────────────────────
   The thing we do, then what the reader gets out of it. Two-up on a
   desktop so eight items read as four rows. No cards: a number, a
   line and a hairline is enough structure to scan. */
.valuelist {
  list-style: none;
  display: grid;
  gap: 0;
}

.valuelist__item {
  padding: clamp(24px, 2.8vw, 30px) 0;
  border-top: 1px solid var(--border);
}

.valuelist__num {
  display: block;
  margin-bottom: 14px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.12em;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}

.valuelist__what { margin-bottom: 9px; text-wrap: pretty; }
.valuelist__why { max-width: 46ch; text-wrap: pretty; }

@media (min-width: 760px) {
  .valuelist {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: clamp(32px, 4.5vw, 72px);
  }
}

/* ── Four rows: a name, a line, a price ────────────────────────
   The services on the hub and the service pages, the six free tools
   on /plus. All rows share ONE set of columns through subgrid, so a
   wider price in one row cannot push its description out of line
   with the others. The whole row is the link. */
.four {
  list-style: none;
  border-top: 1px solid var(--border);
}

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

.four__link {
  display: grid;
  gap: 6px 24px;
  padding: clamp(20px, 2.4vw, 26px) clamp(12px, 1.5vw, 18px);
  margin-inline: clamp(-18px, -1.5vw, -12px);
  border-radius: var(--radius);
  transition: background var(--dur-fast) var(--ease-out);
}

.four__desc { max-width: 52ch; }

.four__price {
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.four__price em { font-style: normal; font-weight: 500; color: var(--ink-4); }

.four__link:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* The chooser: the reader's situation leads the row, the service
   follows in the description. */
.four--chooser .four__name { font-weight: 500; letter-spacing: -0.02em; }

.four--chooser .four__desc strong {
  display: block;
  margin-bottom: 2px;
  font-family: var(--font-display);
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -0.014em;
  color: var(--ink);
}

@media (min-width: 860px) {
  .four {
    display: grid;
    grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.25fr) max-content;
  }
  .four__row {
    grid-column: 1 / -1;
    display: grid;
    grid-template-columns: subgrid;
  }
  .four__link {
    grid-column: 1 / -1;
    grid-template-columns: subgrid;
    align-items: baseline;
  }
  .four__price { text-align: right; }
}

@media (hover: hover) and (pointer: fine) {
  .four__link:hover { background: var(--bg-2); }
  .four__link:hover .four__name { color: var(--accent); }
}

/* ── The ask: a panel with one question and one action ───────── */
.ask {
  display: grid;
  gap: 24px 48px;
  align-items: center;
  padding: clamp(28px, 4vw, 52px);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--elev-2);
}

.ask__text { margin-top: 16px; color: var(--ink-3); text-wrap: pretty; }
.ask__actions { display: flex; flex-wrap: wrap; gap: 12px; }

@media (min-width: 860px) {
  .ask { grid-template-columns: minmax(0, 1fr) auto; }
}

/* The home page's ask keeps a card beside its copy (.audit__inner,
   with the base styles); the copy's measure is set here. */
.audit__copy { max-width: 72ch; }

/* ── A shot: one real build leading a service page ─────────────
   The screenshot is the photography this site has, printed with its
   host so it is checkable. */
.shot { margin: 0; }

.shot__frame {
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  box-shadow: var(--elev-3);
}

.shot__frame img { display: block; width: 100%; height: auto; }

.shot__bar {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px 24px;
  padding: 16px 4px 0;
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--ink-3);
}

.shot__host { font-weight: 500; color: var(--ink); }
.shot__links { display: flex; flex-wrap: wrap; gap: 6px 20px; }
.shot__links a { font-weight: 500; color: var(--accent); }

@media (hover: hover) and (pointer: fine) {
  .shot__links a:hover { text-decoration: underline; text-underline-offset: 3px; }
}

/* ── Spec rows: real detail as design material (About) ───────── */
.specrows { max-width: 64ch; border-top: 1px solid var(--border); }

.specrows > div {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 4px 24px;
  padding: 14px 0;
  border-bottom: 1px solid var(--border);
}

.specrows dt {
  padding-top: 3px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  color: var(--ink-4);
}

.specrows dd {
  font-size: 15.5px;
  line-height: 1.55;
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}

.specrows dd a { color: var(--ink); }

@media (min-width: 560px) {
  .specrows > div { grid-template-columns: minmax(130px, 0.32fr) minmax(0, 1fr); }
}

/* ── Split: a lead that stays while the column beside it passes ──
   About's founder note. position: sticky with a tall parent;
   nothing is hijacked. */
.split {
  display: grid;
  gap: clamp(32px, 5vw, 72px);
  align-items: start;
}

.split__lead .section-head { margin-bottom: 0; }

@media (min-width: 980px) {
  .split { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); }
  .split__lead { position: sticky; top: calc(var(--nav-h) + 40px); }
}

/* ── Works ─────────────────────────────────────────────────────
   One case per sheet: a large numeral and the name across the top
   with the sector and host as text in the name line, then the site
   beside its words -- the screenshot in the left column, where it
   stays while the problem, what was built and the facts pass on the
   right. Half the width a screenshot used to take, and the page is
   not five screenshots deep. */
.work-list { display: grid; gap: 0; }

.work {
  padding: clamp(48px, 6vw, 96px) 0;
  border-top: 1px solid var(--border);
}

.work:first-child { border-top: 0; padding-top: 0; }

.work__head {
  display: grid;
  gap: 16px 48px;
  align-items: end;
  margin-bottom: clamp(24px, 3vw, 40px);
}

.work__num {
  font-family: var(--font-display);
  font-size: clamp(48px, 6vw, 96px);
  font-weight: 400;
  line-height: 0.9;
  letter-spacing: -0.045em;
  color: var(--ink-4);
  font-variant-numeric: tabular-nums;
}

.work__name {
  font-size: clamp(30px, 3.6vw, 52px);
  font-weight: 600;
  line-height: 1.02;
  letter-spacing: -0.036em;
  color: var(--ink);
}

.work__meta {
  margin-top: 10px;
  font-size: 15px;
  color: var(--ink-3);
}

.work__meta a { color: var(--accent); font-weight: 500; }

.work__lede {
  font-size: clamp(17px, 1.5vw, 19px);
  line-height: 1.55;
  color: var(--ink-2);
  max-width: 52ch;
  text-wrap: pretty;
}

.work__shot {
  display: block;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  box-shadow: var(--elev-3);
  transition: box-shadow var(--dur) var(--ease-out), transform var(--dur) var(--ease-out);
}

.work__shot img { display: block; width: 100%; height: auto; }

.work__shot:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }

.work__body {
  display: grid;
  gap: clamp(24px, 3vw, 40px);
}

.work__text {
  display: grid;
  gap: clamp(20px, 2.4vw, 28px);
  align-content: start;
}

.work__sub {
  margin-bottom: 10px;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  color: var(--ink-4);
}

.work__text p {
  font-size: 15.5px;
  line-height: 1.64;
  color: var(--ink-3);
  text-wrap: pretty;
}

/* Label over value, not beside it: the column is half a page wide
   and a value like "Racks, book shelves, benches and desks..." needs
   the whole line. */
.work__facts > div {
  display: grid;
  gap: 3px;
  padding: 10px 0;
  border-bottom: 1px solid var(--border);
  font-size: 14.5px;
}

.work__facts > div:last-child { border-bottom: 0; }
.work__facts dt { font-size: 13px; color: var(--ink-4); }
.work__facts dd { color: var(--ink); font-weight: 500; text-wrap: pretty; }

.work__note {
  margin-top: 0;
  padding-left: 16px;
  border-left: 2px solid var(--accent);
  font-size: 15.5px;
  line-height: 1.62;
  color: var(--ink-2);
  max-width: 64ch;
  text-wrap: pretty;
}

@media (min-width: 1100px) {
  .work__body {
    grid-template-columns: minmax(0, 11fr) minmax(0, 9fr);
    column-gap: clamp(40px, 4vw, 72px);
    align-items: start;
  }
  .work__shot {
    position: sticky;
    top: calc(var(--nav-h) + 24px);
  }
}

@media (min-width: 980px) {
  .work__head { grid-template-columns: auto minmax(0, 1fr) minmax(0, 1fr); }
}

@media (hover: hover) and (pointer: fine) {
  .work__meta a:hover { text-decoration: underline; text-underline-offset: 3px; }
  .work__shot:hover { box-shadow: var(--elev-4); transform: translateY(-2px); }
}

/* ── Plus: the names that used to be eyebrows ────────────────── */
.pz-continue__title {
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.012em;
  color: var(--ink);
}

.pz-area__name {
  font-family: var(--font-display);
  font-size: clamp(20px, 2vw, 24px);
  font-weight: 600;
  letter-spacing: -0.024em;
  color: var(--ink);
}

.pz-path__tag {
  margin: 6px 0 16px;
  font-size: 15.5px;
  line-height: 1.5;
  color: var(--ink-3);
}

/* ── Contact: the form stays, the column passes ────────────────
   The grid row is as tall as the taller column, so a sticky form
   pins at the nav once it reaches it and releases on its own where
   the right column ends. Two columns only, and only on a viewport
   tall enough to show the whole form. */
@media (min-width: 901px) and (min-height: 760px) {
  .contact-grid { align-items: start; }
  .contact-form-col {
    position: sticky;
    top: calc(var(--nav-h) + 24px);
  }
}

/* ── Detail ───────────────────────────────────────────────────
   The layer nobody notices: what loads, what waits, what a cursor
   is told, what a press feels like. Each thing here is small. The
   aggregate is the difference between a page that works and one
   that feels finished. */

/* Form controls, scrollbars and the browser's own surfaces take the
   page's scheme instead of guessing from the OS. */
:root { color-scheme: light; }

/* The nav is fixed, so a scroll target under it would land hidden. */
section[id], article[id], h2[id], h3[id], details[id] {
  scroll-margin-top: calc(var(--nav-h) + 24px);
}

/* No grey flash on tap, and no wait for a double-tap that is never
   coming. */
a, button, label, summary, [role="button"] {
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}

/* The pill takes the name's own width; a name is one line, centred. */
.nav__signed .nav__account { white-space: nowrap; font-size: 14px; line-height: 1.6; }

/* ── Busy ──
   A button that has been pressed and is waiting says so: the label
   changes to what is happening, a ring turns beside it, and it cannot
   be pressed twice. The ring is quick on purpose; a slow one makes the
   wait feel longer than it is. */
.btn[aria-busy="true"],
.wk__btn[aria-busy="true"],
.pz-work__btn[aria-busy="true"] {
  pointer-events: none;
  opacity: 0.85;
}

.btn[aria-busy="true"]::before {
  content: "";
  flex: none;
  width: 14px;
  height: 14px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: busy-ring 0.6s linear infinite;
}

@keyframes busy-ring { to { transform: rotate(360deg); } }

/* ── Skeleton ──
   The shape of what is coming, in the surface's own grey, with a
   sheen that passes every 1.6s so it reads as waiting and not as
   broken. Only where something is genuinely being fetched: the
   account on the profile page, the checkout's state, the live site
   inside the preview. Static content never wears one. */
.skel {
  position: relative;
  display: block;
  width: 100%;
  height: 14px;
  overflow: hidden;
  border-radius: 4px;
  background: rgba(10, 10, 10, 0.06);
}

.skel::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent 0%, rgba(255, 255, 255, 0.6) 50%, transparent 100%);
  transform: translateX(-100%);
  animation: skel-sheen 1.6s linear infinite;
}

@keyframes skel-sheen { to { transform: translateX(100%); } }

.skel--title { height: 22px; width: 42%; }
.skel--short { width: 32%; }
.skel--mid { width: 58%; }
.skel--long { width: 84%; }
.skel--btn { height: 44px; width: 164px; border-radius: var(--radius); }
.skel--field { height: var(--field-h, 48px); border-radius: var(--radius); }

.skel-rows { display: grid; gap: 10px; }
.skel-rows--loose { gap: 16px; }
.skel-rows + .skel-rows { margin-top: 26px; }

/* The profile's account card, before Firebase has answered: four
   facts, a field, a button, in the places they will take. */
.pf__skel .skel-rows > div {
  display: flex;
  justify-content: space-between;
  gap: 24px;
  padding: 9px 0;
  border-bottom: 1px solid var(--border);
}

.pf__skel .skel-rows > div .skel:first-child { width: 26%; }
.pf__skel .skel-rows > div .skel:last-child { width: 40%; }

/* The checkout's state block: a sentence and a button that depend on
   who is signed in, which the summary beside them does not. */
.co__skel { margin: 4px 0 24px; }

/* Waiting for the webhook: a line that keeps moving under the note,
   because "a few seconds" should look like time passing. */
.co__state--waiting .co__note {
  position: relative;
  overflow: hidden;
}

.co__state--waiting .co__note::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--ink-4), transparent);   /* waiting is not an alarm: ink, not red */
  transform: translateX(-100%);
  animation: co-progress 1.6s var(--ease-in-out) infinite;
}

@keyframes co-progress { to { transform: translateX(100%); } }

/* The live preview: a page-shaped placeholder sits over the frame
   until the real site has loaded, then fades off it. */
.webmodal__viewport {
  position: relative;
  overscroll-behavior: contain;
}

.webmodal__skel {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-rows: 60px 1fr;
  background: #fff;
  transition: opacity 0.25s var(--ease), visibility 0s linear 0.25s;
}

.webmodal__viewport.is-ready .webmodal__skel {
  opacity: 0;
  visibility: hidden;
}

.webmodal__skel-bar {
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 0 28px;
  border-bottom: 1px solid var(--border);
}

.webmodal__skel-bar .skel { width: 88px; height: 16px; }
.webmodal__skel-bar .skel + .skel { width: 54px; height: 10px; }
.webmodal__skel-bar .skel:nth-child(2) { margin-left: auto; }

.webmodal__skel-hero {
  padding: clamp(32px, 8%, 72px) 28px;
  max-width: 560px;
}

.webmodal__skel-hero .skel--title { height: 30px; width: 70%; }
.webmodal__skel-hero .skel--btn { margin-top: 10px; }

/* ── Tooltip ──
   One for the whole site. Anything with data-tip, and any button
   whose only label is its aria-label, gets one: it says the name.
   Opens after 400ms the first time and instantly from one control
   to the next, so a toolbar reads as fast as the hand moves; sits
   above, or below when there is no room; grows from the side it is
   anchored to. Hover only on a fine pointer; focus always. */
.tip {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 1200;
  max-width: 260px;
  padding: 6px 9px;
  border-radius: 6px;
  background: var(--ink);
  color: var(--on-dark);
  font-size: 12.5px;
  font-weight: 500;
  line-height: 1.35;
  letter-spacing: 0.005em;
  white-space: nowrap;
  box-shadow: 0 4px 14px rgba(10, 10, 10, 0.18);
  pointer-events: none;
  opacity: 0;
  transform: translateY(2px) scale(0.97);
  transform-origin: var(--cx, 50%) 100%;
  transition: opacity 0.125s var(--ease-out), transform 0.125s var(--ease-out);
}

.tip::after {
  content: "";
  position: absolute;
  left: var(--cx, 50%);
  bottom: -4px;
  width: 8px;
  height: 8px;
  margin-left: -4px;
  background: inherit;
  transform: rotate(45deg);
}

.tip--below {
  transform: translateY(-2px) scale(0.97);
  transform-origin: var(--cx, 50%) 0;
}

.tip--below::after { bottom: auto; top: -4px; }

.tip.is-on { opacity: 1; transform: none; }
.tip.is-instant { transition-duration: 0s; }

.tip__key {
  margin-left: 7px;
  padding: 1px 5px;
  border: 1px solid rgba(248, 248, 247, 0.28);
  border-radius: 4px;
  font-family: inherit;
  font-size: 11px;
  font-weight: 500;
  color: var(--on-dark-2);
}

/* ── My Work: the dialog asks, then an Undo ── */
.pz-work__undo {
  margin-left: 8px;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  font-weight: 600;
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

.pz-work__row {
  transition: opacity 0.18s var(--ease-out), transform 0.18s var(--ease-out);
}

.pz-work__row.is-leaving {
  opacity: 0;
  transform: translateX(-6px);
  pointer-events: none;
}

/* ── Images arrive; they do not pop ──
   A picture that has not decoded yet is held at nothing and comes up
   over 350ms once it has, on its container's grey. Cached pictures
   never wear the class, so a return visit shows no fade at all. */
main img { transition: opacity 0.35s var(--ease); }
.js main img.img-wait { opacity: 0; }

/* ── Dialogs ──
   The site's own, for every question a page asks: a delete, a reset,
   a tool that wants an account. Native <dialog>, so focus, Esc and
   the inert page come from the browser; the look is ours. Enters at
   200ms from 0.96 with the backdrop, leaves in 150. */
.dlg {
  /* The reset's margin: 0 would pin it to the corner; the browser's
     own centring is inset 0 and margin auto, restated here. */
  position: fixed;
  inset: 0;
  margin: auto;
  width: min(440px, calc(100% - 32px));
  max-width: none;
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
  opacity: 0;
  transform: translateY(6px) scale(0.96);
  transition: opacity 0.2s var(--ease-out), transform 0.2s var(--ease-out);
}

.dlg:not([open]) { display: none; }
.dlg.is-open { opacity: 1; transform: none; }

.dlg::backdrop {
  background: rgba(10, 10, 10, 0.42);
  animation: dlg-backdrop 0.2s var(--ease-out);
}

@keyframes dlg-backdrop { from { opacity: 0; } }

.dlg__panel {
  padding: clamp(24px, 3vw, 32px);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--elev-5);
}

.dlg__title {
  margin: 0 0 8px;
  font-family: var(--font-display);
  font-size: clamp(20px, 2vw, 23px);
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -0.022em;
  color: var(--ink);
  text-wrap: balance;
}

.dlg__text {
  margin: 0 0 22px;
  font-size: 15.5px;
  line-height: 1.6;
  color: var(--ink-3);
  text-wrap: pretty;
}

.dlg__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 10px 14px;
}

/* A destructive answer is the primary button in the brand red. */
.dlg__danger { background: var(--bad); }

/* The quiet way out sits on the left, as text. */
.dlg__link {
  margin-right: auto;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: 14.5px;
  font-weight: 500;
  color: var(--ink-3);
  text-decoration: underline;
  text-decoration-color: var(--border-2);
  text-underline-offset: 4px;
  cursor: pointer;
}

@media (hover: hover) and (pointer: fine) {
  .dlg__danger:hover { background: var(--bad-strong); }
  .dlg__link:hover { color: var(--ink); text-decoration-color: var(--ink); }
}

/* The free tools' card asks for an account, not money: the buy card's
   shape, with the tag in ink rather than the price colour. */
.pz-buy--free .pz-buy__tag { color: var(--ink-3); }

/* A free tool is withheld, not previewed. The page carries free-tool
   on <html> from the generator, so this holds before any script runs;
   signed-in arrives from main.js when a sign-in is remembered and from
   plus.js when Firebase confirms one. Signed out, the hero, the card
   and the ask are the page. (Not pz-free: that is the shelf tag's
   class, and on <html> it set the whole page in capitals.) */
html.free-tool:not(.signed-in) [data-tool],
html.free-tool:not(.signed-in) [data-guide-root] { display: none; }

/* ── Nav: the studio's pages, then Plus set apart ──
   Plus is a product, not a page of the studio. It sits after a
   hairline, in the accent, so the bar reads as two things. */
.nav__link--plus {
  margin-left: 10px;
  padding-left: 22px;
  border-left: 1px solid var(--border-2);
  border-radius: 0;
  color: var(--accent);
  font-weight: 600;
}

.nav__mobile .nav__mobile--plus { color: var(--accent); font-weight: 600; }

/* Its underline starts where its text does, past the hairline. */
.nav__link--plus::after { left: 22px; }

/* Just above the phone menu (tablets, iPad portrait) the bar is a few
   pixels too wide for its links; it tightens instead of running off the
   right edge, and Sign in keeps its icon and its accessible name. */
@media (min-width: 769px) and (max-width: 860px) {
  .nav__link { padding: 8px 9px; }
  .nav__link--plus { margin-left: 6px; padding-left: 14px; }
  .nav__link--plus::after { left: 14px; }
  .nav__phone { margin-left: 6px; padding: 9px 11px; }
  .nav__account-cta span { display: none; }
}
@media (min-width: 769px) and (max-width: 840px) {
  .nav__link { padding: 8px 7px; font-size: 14px; }
}

/* ── A head beside its list ──
   The FAQ and About's record: the section head on the left, where it
   stays while the list on the right passes, so a long list does not
   leave the right half of a wide page empty. */
@media (min-width: 1024px) {
  .split-head {
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    column-gap: clamp(48px, 6vw, 112px);
    align-items: start;
  }
  .split-head > .section-head {
    margin-bottom: 0;
    position: sticky;
    top: calc(var(--nav-h) + 40px);
  }
  .split-head > .faq,
  .split-head > .specrows { max-width: none; }
}

/* ── The 404's list of ways on ── */
.lost__links {
  list-style: none;
  max-width: 52ch;
  border-top: 1px solid var(--border);
}

.lost__links li { border-bottom: 1px solid var(--border); }

.lost__links a {
  display: block;
  padding: 14px 0;
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -0.018em;
  color: var(--ink);
  transition: color var(--dur-fast) var(--ease-out);
}

@media (hover: hover) and (pointer: fine) {
  .lost__links a:hover { color: var(--accent); }
}

/* ── The Plus waitlist (/plus while Plus is closed) ── */
.wl { max-width: 640px; margin: 0 auto clamp(56px, 7vw, 96px); }
.wl__card { text-align: left; }
.wl__card .pz-gate__note { margin-left: 0; margin-right: 0; max-width: 52ch; }
.wl__card .pz-gate__actions { justify-content: flex-start; }
.wl__news { margin: 0 0 18px; }
.wl__msg { margin-top: 14px; font-size: 14px; color: var(--ink-3); }
.wl__msg.is-bad { color: var(--bad); }
.wl__head { margin-top: 0; }

/* ── The website check: email the results ── */
.ck__mail {
  margin-top: clamp(28px, 3.4vw, 40px);
  padding-top: clamp(20px, 2.4vw, 28px);
  border-top: 1px solid var(--border);
}

.ck__mail-title {
  margin-bottom: 12px;
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.016em;
  color: var(--ink);
}

.ck__mail-row { display: flex; gap: 10px; margin-bottom: 12px; }
.ck__mail-row input { flex: 1 1 auto; min-width: 0; }
.ck__mail-row .btn { flex: none; min-height: var(--field-h); }
.ck__mail-msg { margin-top: 10px; font-size: 14px; color: var(--ink-3); }
.ck__mail-msg.is-bad { color: var(--bad); }

/* ── Status: one look per role ─────────────────────────────────
   Every message box on the site, whatever its own class, takes its
   colour from here: a wash, a hairline in the role's line colour, text
   in the role's colour and an icon in front, so the meaning reads
   without the words and without colour alone. Each box keeps its own
   size and spacing; this adds only the room for the icon. The roles
   and their tokens are at the top of the file (Status).

     info  .cf__context, .notice, .cf-feedback--info, .auth-feedback--info,
           .qx__warn, .tool__floor, .cp-boost__result, and checkout's
           waiting / ready / anon / info states
     ok    --success, .is-ok, checkout's done
     warn  --warning, .is-warn (and the older .tool__floor.is-late),
           the in-app browser note, checkout's slow
     bad   --error, .is-bad, checkout's bad

   The rules run info, ok, warn, bad, at equal weight, so a box with a
   role modifier always beats its own info default. */
:root {
  --icon-info: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Ccircle cx='8' cy='8' r='6.9' fill='none' stroke='%23000' stroke-width='1.6'/%3E%3Cpath d='M8 7.3v3.9' stroke='%23000' stroke-width='1.7' stroke-linecap='round'/%3E%3Ccircle cx='8' cy='4.9' r='1.05'/%3E%3C/svg%3E");
  --icon-ok: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Ccircle cx='8' cy='8' r='6.9' fill='none' stroke='%23000' stroke-width='1.6'/%3E%3Cpath d='M5.1 8.3l2 2 3.9-4.2' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  --icon-warn: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 1.9l6.6 11.8H1.4z' fill='none' stroke='%23000' stroke-width='1.5' stroke-linejoin='round'/%3E%3Cpath d='M8 6.4v3.4' stroke='%23000' stroke-width='1.7' stroke-linecap='round'/%3E%3Ccircle cx='8' cy='11.7' r='1'/%3E%3C/svg%3E");
  --icon-bad: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Ccircle cx='8' cy='8' r='6.9' fill='none' stroke='%23000' stroke-width='1.6'/%3E%3Cpath d='M5.7 5.7l4.6 4.6M10.3 5.7l-4.6 4.6' stroke='%23000' stroke-width='1.7' stroke-linecap='round'/%3E%3C/svg%3E");
}

:is(.cf__context, .notice, .cf-feedback--info, .auth-feedback--info, .qx__warn, .tool__floor,
    .cp-boost__result, .co__state--waiting .co__note, .co__state--info .co__note) {
  --s-text: var(--info); --s-wash: var(--info-wash); --s-line: var(--info-line);
  --s-mark: var(--ink-3); --s-strong: var(--ink); --s-icon: var(--icon-info);
}

:is(.cf-feedback--success, .auth-feedback--success, .qx__warn.is-ok, .tool__floor.is-ok,
    .co__state--done .co__note) {
  --s-text: var(--ok); --s-wash: var(--ok-wash); --s-line: var(--ok-line);
  --s-mark: var(--ok); --s-strong: var(--ok); --s-icon: var(--icon-ok);
}

:is(.cf-feedback--warning, .auth-feedback--warning, .qx__warn.is-warn, .tool__floor.is-warn,
    .tool__floor.is-late, .auth-inapp, .co__state--slow .co__note) {
  --s-text: var(--warn); --s-wash: var(--warn-wash); --s-line: var(--warn-line);
  --s-mark: var(--warn-mark); --s-strong: var(--warn); --s-icon: var(--icon-warn);
}

:is(.cf-feedback--error, .auth-feedback--error, .qx__warn.is-bad, .tool__floor.is-bad,
    .co__state--bad .co__note) {
  --s-text: var(--bad); --s-wash: var(--bad-wash); --s-line: var(--bad-line);
  --s-mark: var(--bad); --s-strong: var(--bad); --s-icon: var(--icon-bad);
}

/* The box itself. The in-app note and the plain notice had no box of
   their own; they get the site's message-box padding here. */
.auth-inapp { padding: 11px 14px; border-radius: var(--radius); font-size: 14px; }
.notice { --s-pt: 18px; }
.co__state .co__note { --s-pt: 16px; }
.auth-inapp { --s-pt: 11px; }

:is(.cf__context, .notice, .cf-feedback--info, .auth-feedback--info, .qx__warn, .tool__floor,
    .cp-boost__result, .co__state--waiting .co__note, .co__state--info .co__note,
    .cf-feedback--success, .auth-feedback--success, .co__state--done .co__note,
    .cf-feedback--warning, .auth-feedback--warning, .auth-inapp, .co__state--slow .co__note,
    .cf-feedback--error, .auth-feedback--error, .co__state--bad .co__note) {
  position: relative;
  padding-left: 42px;
  border: 1px solid var(--s-line);
  background: var(--s-wash);
  color: var(--s-text);
}

:is(.cf__context, .notice, .cf-feedback--info, .auth-feedback--info, .qx__warn, .tool__floor,
    .cp-boost__result, .co__state--waiting .co__note, .co__state--info .co__note,
    .cf-feedback--success, .auth-feedback--success, .co__state--done .co__note,
    .cf-feedback--warning, .auth-feedback--warning, .auth-inapp, .co__state--slow .co__note,
    .cf-feedback--error, .auth-feedback--error, .co__state--bad .co__note)::before {
  content: "";
  position: absolute;
  left: 15px;
  top: 15px;                                           /* before lh units */
  top: calc(var(--s-pt, 13px) + (1lh - 16px) / 2);     /* centred on the first line */
  width: 16px;
  height: 16px;
  background: var(--s-mark);
  -webkit-mask: var(--s-icon) center / contain no-repeat;
  mask: var(--s-icon) center / contain no-repeat;
}

:is(.cf__context, .notice, .cf-feedback--info, .auth-feedback--info, .qx__warn, .tool__floor,
    .cp-boost__result, .co__state--waiting .co__note, .co__state--info .co__note,
    .cf-feedback--success, .auth-feedback--success, .co__state--done .co__note,
    .cf-feedback--warning, .auth-feedback--warning, .auth-inapp, .co__state--slow .co__note,
    .cf-feedback--error, .auth-feedback--error, .co__state--bad .co__note) strong {
  color: var(--s-strong);
}

/* Status said in a line of text, with no box: the colour only. */
:is(.tool__hint, .tool__note, .wk__msg, .pz-work__msg, .wl__msg, .ck__mail-msg).is-ok { color: var(--ok); }
:is(.tool__hint, .tool__note, .wk__msg, .pz-work__msg, .wl__msg, .ck__mail-msg).is-warn { color: var(--warn); }
:is(.tool__hint, .tool__note, .wk__msg, .pz-work__msg, .wl__msg, .ck__mail-msg).is-bad { color: var(--bad); }

/* ── Reduced motion, for everything above ─────────────────────
   Last, so it wins. The text is simply there; nothing settles,
   nothing crosses, nothing scales. */
@media (prefers-reduced-motion: reduce) {
  .js .letters .c { opacity: 1; transform: none; transition: none; will-change: auto; }
  .js .shot__frame img,
  .js .work__shot img { animation: none; }
  .webmodal__panel { transform: none; transition: none; }
  .acards__btn:active:not(:disabled) { transform: none; }
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) { animation: none !important; }
  .skel::after { animation: none; }
  .btn[aria-busy="true"]::before { display: none; }
  .co__state--waiting .co__note::after { animation: none; transform: none; opacity: 0.45; }
  .tip { transform: none; transition: opacity 0.12s var(--ease-out); }
  .pz-work__row { transition: opacity 0.18s var(--ease-out); }
  .pz-work__row.is-leaving { transform: none; }
  .dlg { transform: none; transition: opacity 0.15s var(--ease-out); }
  .dlg::backdrop { animation: none; }
}
