/* ============================================================================
   Global Office: Sync, the marketing website.

   The look is the app's look on purpose, so the tokens below are lifted from
   the app's own stylesheet rather than invented:
   the same near black ground, the same Inter and Roboto Mono, the same ledger
   accent hues. Somebody who arrives here and then opens the app should not feel
   they changed products.

   The fonts are served from this site rather than from Google, so the content
   security policy needs no external font host.

   site/js/zoom.js opens a screenshot at a size worth reading. It is a file rather
   than an inline script because the policy on this site is script-src 'self' with no
   'unsafe-inline', which is the whole reason the policy is worth having.

   HOUSE RULES THAT APPLY TO EVERY LINE OF COPY ON THIS SITE:
     - No em dashes, anywhere a person reads. Comma, colon, brackets, or two
       sentences.
     - American spelling. Labor, color, categorize, gray.
     - Never "receipt scanner". Never name Wave. Never name W-2 in copy.
     - Never imply the AI files anything by itself: it proposes, you approve.
   ========================================================================== */

/* TWO FILES, WHICH IS WHAT DESIGN_RULES.md SECTION 5 ALLOWS, and it used to be seven.
   Five weights of Inter and two of Roboto Mono as TrueType came to 1.7MB; these two variable
   woff2 faces, subset to latin, come to 124KB and cover every weight either one is used at.

   Both are SIL Open Font License 1.1, checked against google/fonts rather than assumed, so
   self hosting and shipping the file alongside the site is what the license is for. They are
   served from here rather than from Google because this site's policy is font-src 'self'.

   Roboto Mono is gone rather than replaced. It was only ever used at 10 to 13px for eyebrows
   and small labels, where the machine's own monospace face reads at least as well and costs
   nothing, and keeping it would have meant three files to say what two can. */
@font-face {
  font-family:'Inter';
  src:url('../fonts/inter.woff2') format('woff2-variations'), url('../fonts/inter.woff2') format('woff2');
  font-weight:300 700; font-style:normal; font-display:swap;
}
@font-face {
  font-family:'Bricolage Grotesque';
  src:url('../fonts/bricolage-grotesque.woff2') format('woff2-variations'), url('../fonts/bricolage-grotesque.woff2') format('woff2');
  font-weight:400 800; font-style:normal; font-display:swap;
}

/* ============================================================================
   EVERY COLOR, TYPE AND SPACING VALUE IN THE SITE LIVES HERE.

   DESIGN_RULES.md section 5: "A raw hex or px value outside :root is a bug."
   Enforced by tools/check_design_rules.js rather than by anybody remembering.

   The palette is the app's, by Steve's instruction: "use that from the app. The
   site is for the app, so it should be similar." Checked against the app's own
   src/style-v2-src.css rather than assumed. The ground, the alt band, the muted
   text and all eight ledger hues agree with it exactly.
   ========================================================================== */
:root{
  /* ---- ground and paper, straight from the app's :root ---- */
  --bg:#0A090E;
  --bg-alt:#0A0C10;
  --card:#0E1117;
  --card-2:#12161E;
  --card-lift:#101821;      /* a card that is being singled out */
  --ink-on-accent:#031009;  /* the only text color that sits ON the accent */
  --shadow:#000000;

  /* ---- rules and edges ---- */
  --line:#1E2530;
  --line-soft:#171C25;
  --line-lit:#2C3644;       /* a rule that is being hovered or focused */
  --line-warm:#2A3A44;      /* the edge of a singled-out card */
  --line-mid:#33404F;
  --scroll-thumb:#2A3341;

  /* ---- text ---- */
  --text:#FFFFFF;
  --lede:#D3DBE6;
  --body:#C6CFDB;
  --muted:#94A3B8;
  --dim:#6B7889;
  --faint:#4C5867;          /* a deliberate absence, as in a comparison table */
  --ink-on-taxdocs:#1A1400;
  /* ---- each edition's own color, sampled off its logo in public/ (2026-09-14) ---- */
  --ed-full:#10B981;        /* SYNC in the wordmark */
  --ed-contractor:#BF021D;  /* the CONTRACTORS EDITION stamp */
  --ed-solo:#F9C31F;        /* the Solo Edition line */
  --ed-full-hover:#34CD9A;
  --ed-contractor-hover:#D61A34;
  --ed-solo-hover:#FBD155;
  --paper:#ECEFF3;          /* Tailored Light's own ground, only on the button that names it */
  --paper-ink:#0E1A2B;      /* and its ink */

  /* ---- the ledger accents, hue for hue with the app ---- */
  --receipts:hsl(345,80%,60%);
  --income:hsl(150,70%,55%);
  --utilities:hsl(25,90%,55%);
  --mileage:hsl(180,80%,50%);
  --taxdocs:hsl(45,95%,55%);
  --compliance:hsl(220,85%,60%);
  --quotes:hsl(270,80%,65%);
  --donations:hsl(270,80%,65%);   /* the app's purple, which Donations shares with Quotes */
  --red:hsl(0,85%,60%);

  /* THE ONE ACCENT, per section 0. Actions only: buttons, links, focus rings.
     Never a divider, never an icon fill, never a background wash. The seven
     above are not decoration either; each one NAMES a ledger and is used only
     where that ledger is what the reader is looking at. */
  --accent:var(--income);

  /* ---- spacing, section 0's scale. 8px base ---- */
  --s-1:4px;
  --s-2:8px;
  --s-3:16px;
  --s-4:24px;
  --s-5:40px;
  --s-6:64px;
  --s-7:96px;

  /* THE ONE TRANSITION DURATION. Section 2: "Transitions, where used, are short
     (<=150ms) and apply to colour only." Naming it once is what makes that true by
     construction, and it is also what lets prefers-reduced-motion turn every
     transition on the site off by redefining a single value, with no !important and
     no specificity fight. Section 5 bans !important; section 6 requires reduced
     motion to be respected. This is how both are satisfied at once. */
  --t:150ms;

  --maxw:1120px;
  --radius:14px;

  /* Roboto Mono is gone; this is the machine's own monospace face and it costs
     no file. It is used at 10 to 13px for eyebrows and labels and nowhere else. */
  --mono:ui-monospace,SFMono-Regular,Menlo,Consolas,"Liberation Mono",monospace;
  --sans:'Inter',-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
  /* Section 0's display face, Steve's pick, taken from the header type on
     features-overview.html. Headings only, never body copy. */
  --display:'Bricolage Grotesque','Inter',-apple-system,BlinkMacSystemFont,sans-serif;
}

*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
/* CLIP, NOT HIDDEN. `hidden` makes the body a scroll box of its own, and a sticky element
   sticks to its nearest scroll box: the header was written sticky from the first day and
   scrolled away with the page in every browser, because the box it was sticking to never
   scrolls. `clip` cuts the sideways overflow the same way without making a scroll box.
   `hidden` stays first for any browser too old to know `clip`. Measured, 2026-09-12. */
html,body{max-width:100%;overflow-x:hidden;overflow-x:clip}
body{
  margin:0;
  background:var(--bg);
  color:var(--body);
  font-family:var(--sans);
  font-weight:300;
  font-size:16.5px;
  line-height:1.62;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}
img{max-width:100%;height:auto;display:block}
a{color:inherit}

.wrap{max-width:var(--maxw);margin:0 auto;padding:0 24px}
.narrow{max-width:760px}

/* ---------------------------------------------------------------- headings */
/* SECTION 0'S DISPLAY FACE, ON HEADINGS AND NOWHERE ELSE. Bricolage Grotesque is
   Steve's pick, taken from the header type on features-overview.html. It is a variable
   face with an optical size axis, so the size it is set at is fed to it and the letter
   shapes change with it: tighter and more compact large, looser and more open small.
   That is the thing a static face cannot do and it is most of why this reads as drawn
   for the size rather than scaled to it.

   Section 2: "Don't build hierarchy out of size alone. Use weight, colour, spacing,
   rules, and case." The change of FACE between headings and body is part of that
   hierarchy too, and it is doing work that another four pixels of font-size would not. */
h1,h2,h3,h4{
  font-family:var(--display);
  font-variation-settings:'opsz' 40;
  color:var(--text);font-weight:700;letter-spacing:-.022em;line-height:1.08;margin:0;
}
h1{font-variation-settings:'opsz' 96}
h2{font-variation-settings:'opsz' 64}
h3,h4{font-variation-settings:'opsz' 24}
h1{font-size:clamp(34px,6.2vw,62px)}
h2{font-size:clamp(26px,3.8vw,40px);letter-spacing:-.02em;line-height:1.12}
h3{font-size:clamp(18px,2.2vw,21px);letter-spacing:-.012em;line-height:1.25;font-weight:600}
p{margin:0 0 16px}
p:last-child{margin-bottom:0}
strong,b{color:var(--text);font-weight:600}

.eyebrow{
  font-family:var(--mono);
  font-size:11px;letter-spacing:.2em;text-transform:uppercase;
  color:var(--dim);margin:0 0 18px;font-weight:400;
}
/* A HYPHEN IN TRACKED-OUT CAPITALS READS AS A LONG DASH, and Steve will not have one on the site:
   "Absolutely NO em dashes!!!!" The character is and always was a plain hyphen; .2em of tracking on
   each side is what made it look like one, so the hyphen keeps none of it. */
.eyebrow .hy{
  /* The mono face draws a hyphen almost as wide as its cell, which is what makes it read as a
     dash in tracked-out capitals. The text face's hyphen is short, so the hyphen alone is set in
     it, at the same size, and the tracking around it is taken off. */
  /* The tracking sits AFTER each letter, so the E left a gap before the hyphen and the hyphen's
     own zero tracking left none after it: a space on one side only. Both sides are closed up now,
     which is the "neither" of Steve's "both or neither". */
  font-family:var(--sans);letter-spacing:0;margin:0 0 0 -.2em;
}
.lede{font-size:clamp(17px,2.2vw,19.5px);line-height:1.55;color:var(--lede);font-weight:300}

/* ------------------------------------------------------------------ header */
.site-head{
  position:sticky;top:0;z-index:50;
  /* SOLID, NOT FROSTED. Section 2 bans backdrop-filter blur, and section 2's own
     advice for separating regions is "a 1px rule or a background-colour change",
     which is exactly what a sticky header needs anyway. */
  background:var(--bg);
  border-bottom:1px solid var(--line);
}
.site-head .wrap{display:flex;align-items:center;gap:22px;height:64px;position:relative}
.brand{display:flex;align-items:center;text-decoration:none;flex:0 0 auto}
.brand img{height:23px;width:auto}
.nav{display:flex;align-items:center;gap:24px;margin-left:auto}
.nav a{
  text-decoration:none;color:var(--muted);font-size:14.5px;font-weight:400;
  transition:color var(--t) ease;
}
.nav a:hover,.nav a[aria-current="page"]{color:var(--text)}
/* THE BUY BUTTON'S LABEL WAS INVISIBLE, and it is the one control the whole site is
   pointing at. `.nav a` is two classes' worth of specificity and `.btn-primary` is one,
   so the muted grey below won every time: near black text became grey text on a bright
   green button. Measured in a real browser, not guessed: the computed color came
   back rgb(148,163,184). Anything that puts a button inside the nav needs this. */
.nav a.btn-primary{color:var(--ink-on-accent)}
.nav a.btn-ghost{color:var(--text)}
/* BUY IT IS OFF UNTIL THE BETA IS OVER, Steve 2026-10-05: "dimmed and unclickable for now. Maybe
   a darker, less active looking green". It's a <span> on every page, not a link, so nothing can
   follow it; this makes it look the part. Put the <a href="pricing.html"> back to switch it on. */
/* Steve, same day: "nowhere near dim enough and it still clicks, the button animates." The rule
   sat above .btn and .btn-primary:hover, which won on order; it's doubled up so it wins, and
   pointer-events:none means no hover, no press and no animation at all. */
.btn.btn-off,.btn.btn-off:hover,.btn.btn-off:active{
  background:hsl(152,18%,17%);border-color:hsl(152,14%,24%);color:hsl(150,8%,42%);
  opacity:.55;cursor:default;pointer-events:none;transform:none;transition:none;
}
.nav .sep{width:1px;height:20px;background:var(--line);flex:0 0 auto}
.nav-links{display:flex;align-items:center;gap:24px}

/* ------------------------------------------------------------ the phone menu */
/* Steve, 2026-09-12: on a phone the header was too crowded and two links had been dropped to
   make it fit. So on a phone the links live behind a hamburger, beside the logo, and "Buy it"
   stays on the right. On the front page they start out laid along the top and fold into the
   hamburger as the wordmark flies in (js/logo-dock.js); every other page opens folded. */
.menu{display:none}
.menu summary{
  list-style:none;cursor:pointer;display:flex;align-items:center;justify-content:center;
  width:36px;height:36px;margin-left:-8px;border-radius:8px;
}
.menu summary::-webkit-details-marker{display:none}
.menu summary:focus-visible{outline:2px solid var(--income);outline-offset:2px}
.burger,.burger::before,.burger::after{
  display:block;width:20px;height:2px;border-radius:1px;background:var(--text);
  transition:transform var(--t) ease,background var(--t) ease;
}
.burger{position:relative}
.burger::before,.burger::after{content:"";position:absolute;left:0}
.burger::before{top:-6px}
.burger::after{top:6px}
.menu[open] .burger{background:transparent}
.menu[open] .burger::before{top:0;transform:rotate(45deg)}
.menu[open] .burger::after{top:0;transform:rotate(-45deg)}
.menu-panel{
  position:absolute;left:0;right:0;top:100%;z-index:1;
  display:flex;flex-direction:column;padding:4px 16px 12px;
  background:var(--bg);border-bottom:1px solid var(--line);
}
.menu-panel a{
  padding:13px 0;font-size:17px;color:var(--text);text-decoration:none;
  border-bottom:1px solid var(--line-soft);
}
.menu-panel a:last-child{border-bottom:0}
.menu-panel a[aria-current="page"]{color:var(--accent)}
/* The head is one flex row, and at 390px nothing in it was allowed to give, so the row
   overflowed and took the last item with it. The brand is what yields: it shrinks, and
   the nav never does. */
@media (max-width:800px){
  .site-head .wrap{height:58px;gap:12px;padding:0 16px}
  .brand{min-width:0;overflow:hidden}
  .brand img{height:20px}
  .nav{gap:16px;flex:0 0 auto}
  .nav .hide-sm{display:none}
  .nav a{font-size:13.5px}
  .menu{display:block;flex:0 0 auto}
  .nav-links{display:none}

  /* THE FOLD, front page only. At the top of the page the links lie along the left of the
     header, where the hamburger and the logo will be. --dock runs from 0 to 1 as the wordmark
     flies in, and the row of links shrinks toward the hamburger over that WHOLE run, so it ends
     the moment the logo lands; --ox is where the hamburger's bars start, measured by
     js/logo-dock.js. The whole row scales as one, so the links never slide into each other.

     ONE MOTION, at Steve's word, 2026-09-12. The first version folded the links in the first
     half of the run and faded the hamburger in from the middle, and on his phone the hamburger
     was already there while the logo was still below the bar. The logo only enters the bar at
     about 0.6 of the run, so that is where the hamburger starts to appear, and the links are
     gone just before the logo lands. Only transforms and opacity change, never layout, so the
     logo's landing spot is where it always was. */
  .logo-docking .nav-links{
    display:flex;position:absolute;left:16px;top:0;height:100%;gap:14px;
    transform-origin:var(--ox,0px) 50%;
    transform:scale(calc(1 - var(--dock,0) * .92));
    opacity:clamp(0, calc(1 - (var(--dock,0) - .45) * 2.2), 1);
  }
  .logo-docking .menu{opacity:clamp(0, calc((var(--dock,0) - .6) * 2.5), 1)}
  .logo-docking:not(.logo-half) .menu{visibility:hidden}
  .logo-half .nav-links{pointer-events:none}
  .logo-docked .nav-links{visibility:hidden}
}
@media (max-width:420px){
  .site-head .wrap{gap:10px}
  .logo-docking .nav-links{gap:11px}
  .brand img{height:16px}
  .nav{gap:12px}
  .nav a{font-size:12.5px}
  .btn-sm{padding:8px 12px;font-size:13px}
}

/* ------------------------------------------------------------------ button */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:9px;
  font-family:var(--sans);font-size:15px;font-weight:600;letter-spacing:-.005em;
  text-decoration:none;cursor:pointer;
  padding:12px 22px;border-radius:10px;
  border:1px solid transparent;
  transition:background var(--t) ease, border-color var(--t) ease;
}
.btn:active{transform:translateY(1px)}
/* ONE FLAT COLOR, no gradient and no glow under it. DESIGN_RULES.md section 2, and
   section 0 makes this the site's single accent: it appears on actions and nowhere
   else. The hover is a color change, which is also the only hover section 2 allows. */
.btn-primary{
  background:var(--accent);
  color:var(--ink-on-accent);
}
.btn-primary:hover{background:hsl(150,70%,62%)}
.btn-ghost{background:transparent;border-color:var(--line);color:var(--text)}
.btn-ghost:hover{border-color:var(--line-lit);background:rgba(255,255,255,.03)}
.btn-sm{padding:9px 16px;font-size:14px;border-radius:9px}
.btn-row{display:flex;flex-wrap:wrap;gap:12px;align-items:center}
/* TWO BUTTONS STAY SIDE BY SIDE ON A PHONE, at Steve's word, 2026-09-12. They used to wrap to
   one per row. A row of two no longer wraps; each button takes the width of its own words and a
   little less padding, and the words never break inside a button. Only rows of exactly two:
   the rows of three (the editions page's opening, the 404) would not fit one line on a phone,
   so they still wrap. A browser without :has() wraps as before, which is still correct. */
@media (max-width:560px){
  .btn-row:not(:has(> :nth-child(3))){flex-wrap:nowrap;gap:10px}
  .btn-row:not(:has(> :nth-child(3))) > .btn{
    flex:0 1 auto;min-width:0;white-space:nowrap;padding:12px 16px;font-size:14.5px;
  }
}

/* ------------------------------------------------------------------- bands */
.band{padding:76px 0;border-top:1px solid var(--line-soft)}
.band.tight{padding:56px 0}
.band.alt{background:var(--bg-alt)}
.band-head{max-width:720px;margin:0 0 40px}
.band-head p{margin-top:14px}
@media (max-width:800px){ .band{padding:54px 0} .band-head{margin-bottom:30px} }

/* -------------------------------------------------------------------- hero */
.hero{
  /* 40px more below than the scale's 64, at Steve's ask, so the hero has room under it
     now that the screenshot has moved out of it and down into the section that argues
     for it. Written as the two scale steps it is made of rather than as 104. */
  position:relative;padding:var(--s-7) 0 calc(var(--s-6) + var(--s-5));overflow:hidden;
  /* NO GLOW. Section 2 names this one directly: "No dark hero with a blurred coloured
     glow behind the headline." Two radial washes in mint and blue were sitting here and
     they are gone. What separates the hero from the band under it now is a rule and a
     change of ground, which is what section 2 asks for everywhere else too. */
  background:var(--bg);
  border-bottom:1px solid var(--line-soft);
}
.hero::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background-image:linear-gradient(rgba(255,255,255,.016) 1px,transparent 1px),
                   linear-gradient(90deg,rgba(255,255,255,.016) 1px,transparent 1px);
  background-size:64px 64px;
  mask-image:radial-gradient(760px 460px at 50% 0%,var(--shadow),transparent 78%);
  -webkit-mask-image:radial-gradient(760px 460px at 50% 0%,var(--shadow),transparent 78%);
}
.hero .wrap{position:relative;z-index:1}
.hero h1{margin-bottom:20px}
.hero .three-lines{
  font-family:var(--mono);font-size:12.5px;letter-spacing:.02em;color:var(--muted);
  margin:0 0 22px;line-height:1.9;
}
.hero .three-lines b{color:var(--income);font-weight:500}
.hero .lede{max-width:60ch;margin-bottom:22px}
/* The second paragraph is the turn, and it is the reason anybody scrolls. It gets a little
   more weight than the mechanism above it without becoming a pull quote, because a pull
   quote here would read as an ad about itself. */
.hero .lede.turn{color:var(--text);margin-bottom:30px}
.hero .lede.turn::first-line{color:var(--text)}
.hero .btn-row{margin-bottom:14px}
.hero .fineprint{font-size:13.5px;color:var(--dim);margin:0}
@media (max-width:800px){ .hero{padding:56px 0 48px} }

/* THE LOGO THAT FLIES INTO THE HEADER. Steve, 2026-09-12: the page opens with the wordmark big
   and centered above the hero, and as it scrolls the wordmark travels up into the header,
   shrinking as it goes: the app's own opening, driven by the scroll instead of a timer.
   js/logo-dock.js does the moving. Without it (no script, or reduced motion asked for) the big
   mark simply stands here and the header keeps its own small one, so nothing is lost. */
/* 50px more under it than the scale gives, at Steve's word, 2026-09-12. */
.hero-mark{text-align:center;margin-bottom:calc(var(--s-6) + 50px)}
.hero-mark img{display:inline-block;width:min(100%,820px);height:auto;vertical-align:top}
@media (max-width:800px){ .hero-mark{margin-bottom:calc(var(--s-5) + 50px)} }
/* While the script runs, the in-page mark only holds its space and the header's own logo stays
   hidden until the flying one lands on it; the two are never seen at once. */
.logo-docking .hero-mark img{visibility:hidden}
.logo-docking:not(.logo-docked) .site-head .brand img{visibility:hidden}
.logo-fly{
  position:fixed;left:0;top:0;z-index:60;pointer-events:none;
  transform-origin:0 0;will-change:transform;height:auto;
}
.logo-docked .logo-fly{visibility:hidden}
/* At scroll 0 the copy rides in the page, so the bounce past the top carries it (js/logo-dock.js). */
.logo-at-top .logo-fly{position:absolute}

/* ---------------------------------------------------------------- contents */
/* Modeled on the contents at the head of the app's features page, and set tighter, at
   Steve's ask, 2026-09-12: three columns of short entries instead of wide ones that wrap. */
nav.toc{background:var(--bg-alt);border-bottom:1px solid var(--line-soft);padding:var(--s-5) 0}
nav.toc .eyebrow{margin-bottom:var(--s-3)}
/* Numbered DOWN each column, then across, at Steve's ask: 1 to 5 in the first column, 6 to 10
   in the second. That is what columns do and a grid does not. */
.toclist{
  list-style:none;margin:0;padding:0;counter-reset:toc;
  columns:4;column-gap:var(--s-4);
}
.toclist li{counter-increment:toc;break-inside:avoid}
.toclist a{
  display:flex;align-items:baseline;gap:10px;padding:4px 0;
  color:var(--muted);text-decoration:none;font-size:14.5px;line-height:1.35;
  transition:color var(--t) ease;
}
.toclist a::before{
  content:counter(toc);font-family:var(--mono);font-size:10.5px;color:var(--dim);min-width:16px;
}
.toclist a:hover{color:var(--text)}
@media (max-width:980px){ .toclist{columns:3} }
@media (max-width:660px){ .toclist{columns:2;column-gap:var(--s-3)} .toclist a{font-size:14px} }
@media (max-width:420px){ .toclist{columns:1} .toclist a{padding:6px 0} }

/* The way back to the contents, at the foot of every section. It says "Back to contents"
   rather than "Top" because it stops at the list, not at the top of the page. */
.backtoc{display:flex;justify-content:flex-end;margin:var(--s-5) 0 0}
.backtoc a{
  display:inline-flex;align-items:center;gap:10px;padding:6px 0;
  font-family:var(--mono);font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--dim);text-decoration:none;transition:color var(--t) ease;
}
.backtoc a::before{content:"";width:22px;height:2px;background:var(--line);transition:background var(--t) ease}
.backtoc a:hover{color:var(--text)}
.backtoc a:hover::before{background:var(--accent)}
/* Between two picture rows (the Centers), the link sits in the 112px that already separates
   them rather than adding to it: the row above keeps its 40, and the 46 below it plus the
   link's own height make up the rest. */
.split + .backtoc{margin-top:0}
.backtoc + .split{margin-top:46px}

/* --------------------------------------------------------------- shot / figure */
figure{margin:0;min-width:0;max-width:100%}
.shot,.soon-frame{
  border:1px solid var(--line);border-radius:var(--radius);
  background:var(--card);overflow:hidden;
  box-shadow:0 30px 70px -34px rgba(0,0,0,.9), 0 0 0 1px rgba(255,255,255,.02) inset;
  cursor:zoom-in;position:relative;
  transition:border-color var(--t) ease;
}
.shot:hover,.shot:focus-visible{border-color:var(--line-mid)}
.shot:focus-visible{outline:2px solid var(--income);outline-offset:3px}
/* A small hint that the picture opens, drawn rather than written, so it costs no
   line of copy and does not repeat itself down the page. */
.shot::after{
  content:"";position:absolute;right:12px;top:12px;
  width:30px;height:30px;border-radius:8px;pointer-events:none;
  background:rgba(10,9,14,.72);border:1px solid rgba(255,255,255,.14);
  background-image:
    linear-gradient(to right, rgba(255,255,255,.85) 2px, transparent 2px),
    linear-gradient(to bottom, rgba(255,255,255,.85) 2px, transparent 2px);
  background-size:11px 2px, 2px 11px;
  background-position:center, center;
  background-repeat:no-repeat;
  opacity:0;transition:opacity var(--t) ease;
}
.shot:hover::after,.shot:focus-visible::after{opacity:1}
@media (hover:none){ .shot::after{opacity:.85} }
.shot img{width:100%}

/* SOLO IS NOT BUILT, and its picture says so. Steve, 2026-09-12: blurred, dimmed, and "Coming
   Soon" on it. The same frame as every other screenshot but not one that opens: enlarging it would
   show the sharp picture the blur is there to hold back, so it is not a .shot and the zoom viewer
   never sees it. The words are the display face in Solo's own yellow, the color of the line under
   its logo, with the edition named small above them the way an eyebrow names a section. The
   picture is scaled up a touch so the blur has no soft light edge showing inside the frame. */
.soon-frame{cursor:default;position:relative}
.soon-frame img{
  display:block;width:100%;
  filter:blur(6px) saturate(.85) brightness(.66);
  transform:scale(1.06);
}
.soon-label{
  position:absolute;inset:0;margin:0;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;
  text-align:center;
}
.soon-label span{
  font-family:var(--mono);font-size:11px;letter-spacing:.24em;text-transform:uppercase;
  color:var(--muted);
}
.soon-label b{
  font-family:var(--display);font-weight:700;font-variation-settings:'opsz' 96;
  font-size:clamp(32px,5.4vw,58px);line-height:1;letter-spacing:-.025em;
  color:var(--taxdocs);text-shadow:0 2px 30px var(--shadow);
}
figcaption{
  /* The same color as the body text in the numbered steps, at Steve's ask: it was
     --dim and read as an afterthought under pictures that are carrying the argument.
     The SIZE stays smaller than that body text on purpose, because a caption that
     matches its paragraph in both weight and size stops reading as a caption. */
  font-size:13.5px;color:var(--muted);margin-top:12px;line-height:1.5;
  font-weight:300;
}

/* A DESKTOP SCREENSHOT SCALED TO 390px IS AN IMPRESSION OF DENSITY, NOT A PICTURE OF
   ANYTHING, AND THE ANSWER TO THAT CHANGED. It used to be that the frame scrolled
   sideways on a phone and the image kept a readable size inside it. Now the picture
   opens, so the phone shows it whole and a tap gives you the real thing, full size and
   pannable. That is better on two counts: nothing has to be discovered by swiping a
   thing that does not look swipeable, and a drag to pan no longer competes with a tap
   to open. The sideways scroll survives only where it is still the right answer, which
   is the comparison table on the editions page. */
@media (max-width:760px){
  .shot{min-width:0;max-width:100%}
  .swipe-hint{
    display:block;font-family:var(--mono);font-size:10.5px;letter-spacing:.14em;
    text-transform:uppercase;color:var(--dim);margin-top:9px;
  }
}
.swipe-hint{display:none}
/* The Information Center screenshot (the whole Contractor Edition screen). It used to sit
   under the hero and be called .hero-shot, then between the last example in the ledgers
   talking section and the line saying none of it was typed in. */
/* Since 2026-10-02 it opens the section instead, above the heading and right under the
   contents, at Steve's ask, so the room it needs is below it rather than above. */
.talk-shot{margin:0 0 calc(var(--s-5) + var(--s-2))}
@media (max-width:800px){ .talk-shot{margin-bottom:var(--s-4)} }
/* The Spending Center shot under the aside in the same section, Steve 2026-10-02. */
.talk-after{margin-top:calc(var(--s-5) + var(--s-2))}
@media (max-width:800px){ .talk-after{margin-top:var(--s-4)} }

/* ------------------------------------------------------------- split rows */
/* min-width:0 IS LOAD BEARING ON EVERY ONE OF THESE. A grid item defaults to
   min-width:auto, which means it refuses to shrink below its content: the 680px wide
   screenshot inside .shot stretched its whole column to 706px on a 390px phone, and
   `overflow-x:hidden` on the body then CLIPPED the overflow rather than revealing it.
   Everything past 390px was simply gone, and a check asking
   document.documentElement.scrollWidth reported no horizontal scroll, because there
   was none: the page was cut off instead. Measure body.scrollWidth and element rects. */
/* 40px of air above and below every picture row, at Steve's word, 2026-09-10.
   Adjacent margins collapse to the larger, so the 72px that already separated two
   rows carries the 40 above rather than adding to it: between-row spacing is written
   out as 112 so the 40 is actually there. */
/* 40px more under the bank-feed paragraph before the first picture row, at Steve's
   word. The 40px that .band-head already carried was being collapsed against the
   40px on .split below, so the gap was 40 and not 80; this states the whole 80. */
#contractors .band-head{margin-bottom:80px}
/* 30px further down for the lapsed-insurance row and its picture, at Steve's word.
   The band head's own 40 was collapsing with the 40 on the .split below it, so the
   whole 70 is stated here. */
#missing .band-head{margin-bottom:70px}
/* 50px of breathing room between the 1099 row and the box under it, at Steve's word.
   .apart carries 40 and the row above carries 40; they collapse to 40, so the whole
   90 is stated here. */
#missing .split + .notice.apart{margin-top:150px}
/* 30px of breathing room under "Both editions send to all three." before the first picture row,
   at Steve's word 2026-09-17. Same collapse as the two above: .band-head's own 40 collapses
   against the 40 on .split, so the whole 70 is stated here rather than added to. */
#export .band-head{margin-bottom:70px}
.split{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:52px;align-items:center;margin:40px 0}
.split > *{min-width:0}
.split + .split{margin-top:112px}
/* 40px of air under the LAST picture row, where the two cards follow it, at Steve's
   word. The row's own 40 below collapses into the 64 .break already carries, so the
   whole figure is stated here rather than added to. 40px, then another 30. Scoped to a picture row followed
   by cards so the other .break uses are untouched. */
.split + .cards.break{margin-top:134px}

/* A CARD THAT ALREADY HAS ITS OWN FRAME. The alert cutout carries the app's own red
   border and rounded corners in its alpha channel, so it gets no .shot around it;
   drop-shadow rather than box-shadow, because box-shadow would draw the shadow of the
   rectangle the picture sits in and this picture's corners are transparent. */
.card-shot{margin:0}
/* The headline sits over the picture in the left column, with the paragraphs beside
   them both, at Steve's word. Both columns start at the top rather than centring on
   each other, or the headline would float away from the picture it belongs to. */
/* THE HEADLINE SITS OVER THE PICTURE, AND THE PARAGRAPHS CENTRE ON THE PICTURE RATHER
   THAN ON THE COLUMN. Steve asked for the headline above the picture on the left and
   the picture's middle level with the middle of the paragraph text. Those two cannot
   both come out of one row: the headline is 164px tall and the picture 283, so putting
   the picture's centre at the paragraphs' centre would have run it up through the
   headline. So the left column is two rows, the picture and the paragraphs share the
   second one, and both centre in it. Two things centred in the same row have the same
   middle by construction, whichever of them is taller, at any width. */
.asking-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);column-gap:52px}
.asking-grid > *{min-width:0}
.asking-head{grid-column:1;grid-row:1}
.asking-grid .card-shot{grid-column:1;grid-row:2;align-self:center}
.asking-copy{grid-column:2;grid-row:2;align-self:center}
.asking-head .eyebrow{margin-bottom:12px}
@media (max-width:900px){
  .asking-grid{grid-template-columns:1fr;row-gap:26px}
  .asking-head,.asking-grid .card-shot,.asking-copy{grid-column:1;grid-row:auto}
}
.card-shot img{width:100%;height:auto;filter:drop-shadow(0 26px 54px rgba(0,0,0,.85))}
/* 15% off the 1099 card, at Steve's word. It is a card rather than a screenshot, so
   at full column width it was reading larger than the pictures around it. Its own
   text is 633px wide natively and it is shown at about 434, which is still more
   pixels than the screen it was taken from. */
.card-shot.reduced img{width:85%}

/* THREE PHONES, SIDE BY SIDE. They are cutouts with real alpha, so the shadow has to follow
   the phone's own rounded outline: box-shadow would draw the shadow of the rectangle the
   picture sits in, with corners the phone does not have. Same reason as the hero. */
.phones{ display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:var(--s-5);
         margin-top:var(--s-5); align-items:end }
.phones > *{ min-width:0; margin:0 }
.phones img{ width:100%; height:auto; display:block;
             filter: drop-shadow(0 10px 18px rgba(0,0,0,.55)) drop-shadow(0 44px 70px rgba(0,0,0,.75)) }
.phones figcaption{ text-align:center; text-wrap:balance }  /* no lone word on a second line, Steve 2026-10-06 */
/* Two phones instead of three (bookkeepers.html #advising, 2026-10-06): same size, centered. */
.phones.two{ grid-template-columns:repeat(2,minmax(0,1fr)); max-width:620px; margin-inline:auto }

/* A DETAIL PROJECTING OUT OF ITS OWN SCREENSHOT. The Audit Trail is a wide table and the panel
   that carries the whole point of the section is a narrow column on the right of it; at the
   width of a column on this page that panel is unreadable.
   The first attempt outlined the panel on the screenshot and put a copy beside it. Steve: *"it's
   a little confusing. It's two pictures stacked on top of one another. It needs to look like the
   audit information is projecting out of the underlying picture."* He was right: two equally
   sharp, equally bright pictures at the same distance read as two pictures. So the screen behind
   is dimmed and pushed slightly out of focus, the panel comes forward at half again the size it
   was, and the green edge moved off the screenshot and onto the panel, where it marks the thing
   being looked at rather than the place it came from. */
.magnify{ position:relative; margin:0; padding:56px 0 }

/* NOT backdrop-filter. That is glassmorphism, which section 2 bans, and it is a different thing:
   this blurs the picture itself to put it behind, rather than blurring whatever happens to be
   under a translucent card. Faint on purpose. Enough to sit back, not enough to look broken, and
   the picture is still its own unblurred self when it opens. */
.magnify .shot img{ filter:blur(1.8px) saturate(.8); opacity:.5; transition:none }
.magnify .shot:hover img,.magnify .shot:focus-visible img{ filter:blur(1.2px) saturate(.9); opacity:.62 }

.magnify-detail{
  position:absolute; right:4%; top:50%; transform:translateY(-50%);
  width:48%; height:auto; pointer-events:none;
  border:2px solid var(--income); border-radius:12px;
  /* Two shadows: a tight one that reads as a lifted edge, and a wide soft one that reads as
     distance from the surface behind. drop-shadow rather than box-shadow, because the panel's
     corners are rounded and a box shadow would outline a rectangle that is not there. */
  filter: drop-shadow(0 6px 12px rgba(0,0,0,.75)) drop-shadow(0 30px 56px rgba(0,0,0,.95));
}
@media (max-width:700px){
  /* KEPT ON A PHONE, at Steve's ask, 2026-09-12: "It's perfect on Desktop." This used to set
     the panel under the screenshot on its own below 700px, which lost the whole effect. On a
     phone the screenshot is short and the panel is tall, so the panel is drawn larger against
     it and the figure gets more room above and below for the panel to stand out into. */
  /* The panel is about 0.9 of the figure's width tall and the screenshot about 0.53, so the room
     above and below is written against the width, which is what a percentage padding measures. */
  .magnify{ padding:calc(18.5% + 16px) 0 }
  .magnify-detail{ right:3%; width:58%; border-radius:10px }
}
@media (max-width:860px){
  /* Two across, then one. Three phones at 300px each is three unreadable phones. */
  .phones{ grid-template-columns:repeat(2,minmax(0,1fr)); gap:var(--s-4) }
}
@media (max-width:560px){
  .phones{ grid-template-columns:1fr }
}
.split.flip .split-copy{order:2}
.split-copy h3{margin-bottom:12px}
.split-copy .eyebrow{margin-bottom:12px}

/* A CAPTION MUST NOT DRAG THE COPY DOWN. Steve, of the paragraph beside the insurance
   picture: "it's more towards the bottom of that image whereas it needs to be
   equidistant between the bottom and top." It was centred on the FIGURE, and a figure
   is the picture PLUS its caption, so the figure's middle sits below the picture's
   middle by half the caption. Taking the figure's own box out of the grid makes the
   picture and the caption two rows of the split, and the copy then centres on the
   picture's row alone. The caption keeps its element and its meaning; only its box
   stops nesting. */
/* .split sets gap:52px, which is a ROW gap as well as a column one, so the caption
   landing in its own row picked up 52px it never used to have. The caption's own
   12px margin is the spacing it wants; the rows get none. */
.split.capped{row-gap:0}
.split.capped > figure{display:contents}
.split.capped .shot{grid-column:2;grid-row:1}
.split.capped figcaption{grid-column:2;grid-row:2}
.split.capped .split-copy{grid-column:1;grid-row:1;align-self:center}
.split.capped.flip .shot,.split.capped.flip figcaption{grid-column:1}
.split.capped.flip .split-copy{grid-column:2}
@media (max-width:900px){
  .split{grid-template-columns:1fr;gap:26px}
  .split.flip .split-copy{order:0}
  /* One column again, so the explicit placement above has to be undone or a
     grid-column:2 would invent a second column off the side of the phone. */
  .split.capped .split-copy,.split.capped .shot,.split.capped figcaption,
  .split.capped.flip .split-copy,.split.capped.flip .shot,.split.capped.flip figcaption
    {grid-column:1;grid-row:auto}
  /* One column, so the rows ARE the layout again and they want the gap back. The
     caption is the exception: it still belongs to the picture above it. */
  .split.capped{row-gap:26px}
  .split.capped figcaption{margin-top:-14px}
  .split + .split{margin-top:88px}
}

/* ------------------------------------------------------------------- cards */
.cards{display:grid;gap:18px}
.cards > *{min-width:0}
.cards.c2{grid-template-columns:repeat(2,minmax(0,1fr))}
.cards.c3{grid-template-columns:repeat(3,minmax(0,1fr))}
.cards.c4{grid-template-columns:repeat(4,minmax(0,1fr))}
@media (max-width:980px){ .cards.c3,.cards.c4{grid-template-columns:repeat(2,1fr)} }
@media (max-width:660px){ .cards.c2,.cards.c3,.cards.c4{grid-template-columns:1fr} }

.card{
  background:var(--card);border:1px solid var(--line);border-radius:var(--radius);
  padding:26px 24px;position:relative;overflow:hidden;
}
.card h3{margin-bottom:10px}
.card p{font-size:15.2px;line-height:1.58;color:var(--muted)}
/* Names the one edition a card is true of, 2026-09-17: the trip and receipt card on the front page
   is Contractor Edition only. Set like .tick, which it sits beside in spirit. */
.card .card-ed{
  font-family:var(--mono);font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--dim);margin:0 0 12px;line-height:1.3;
}
.card .tick{
  font-family:var(--mono);font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--dim);display:block;margin-bottom:14px;
}
/* THE EDITION'S OWN LOGO where its name used to be typed, at Steve's word. The three files
   were trimmed to their own edges and scaled to one width, so the GLOBAL OFFICE SYNC wordmark
   is the same size in all three and only the edition mark underneath differs. The box is a
   fixed height, set by the tallest logo, so the headings below still start on one line across
   the row: the Bookkeeper logo carries no edition stamp and is less than half as tall. */
.edition-mark{ height:44px; margin-bottom:var(--s-3); display:flex; align-items:flex-start }
.edition-mark img{ display:block; width:100%; max-width:296px; height:auto }
/* Centered in the front page's cards. On a desktop the card is about as wide as the logo, so
   it only LOOKED centered; on a phone the card is wider and the logo sat against the left. */
#editions .edition-mark{ justify-content:center }
/* The three cards sit side by side on the front page, so the plain wordmark takes the same room
   below it as the two stamped ones and the headings and text under all three start on one line.
   It sat 20px higher until Steve saw it, 2026-09-12. The editions page stacks its sections, so
   there is nothing there to line up with. */
#editions .edition-mark{ margin-bottom:calc(var(--s-3) + 20px) }
/* Solo's "Coming" lives INSIDE the room the other two cards leave under their logos, so its
   heading starts level with theirs instead of a line lower, and it is centered under the logo
   it belongs to. Steve, 2026-09-12. The 36px under a logo is split 9 above the word, its own 17,
   and 10 below it. */
#editions .card.soon .edition-mark{ margin-bottom:9px }
#editions .card.soon .tick{ margin-bottom:10px; text-align:center }
/* Every card's heading takes two lines' room, so the text under all three starts level even at a
   width where one heading happens to fit on one line. Steve: "I'm a stickler for symmetry." */
#editions .card h3{ min-height:calc(2em * 1.25) }
/* On a phone the editions page is one column, and each section's logo is centered on the page
   rather than sitting against the left, at Steve's word, 2026-09-12. Solo's "Coming" under its
   logo comes with it. 900px is where these rows fall to one column. */
@media (max-width:900px){
  .split-copy > .edition-mark{ justify-content:center }
  .split-copy > .edition-mark + .eyebrow{ text-align:center }
}
/* 20px more under the two logos that carry an edition stamp, at Steve's word, off the 8px
   scale on purpose. The stamp fills its box to the bottom edge, where the plain Bookkeeper
   wordmark leaves 25px of its own box empty, so without this the two stamped cards read as
   crowded against their headings. */
.edition-mark.stamped{ margin-bottom:calc(var(--s-3) + 20px) }
/* On the price list the mark IS the plan's heading, and it sits beside the flag in the corner,
   so it is drawn smaller than on the front page. */
.plan .edition-mark{ height:34px; margin-bottom:var(--s-3) }
.plan .edition-mark.stamped{ margin-bottom:calc(var(--s-3) + 14px) }
.plan .edition-mark img{ max-width:230px }
/* Centered on every card. The Coming flag is the only thing left in a corner, and the mark sits
   below it, so the padding the plan heading kept clear for a flag is not needed here. */
.plan .edition-mark{ justify-content:center; padding-right:0 }
/* The comparison table heads its columns with the marks rather than typed names. */
table.grid thead th.grid-mark{ vertical-align:top }
table.grid th.grid-mark img{ display:block; width:100%; max-width:200px; height:auto }

/* The connection's two screens at 85% of the column, at Steve's "make the pics smaller if
   you need to": each carries one paragraph and at full width outweighed it. */
.connect-shot{ margin:0 }
.connect-shot .shot{ width:85% }
/* 40px more above it than the scale gives, at Steve's word, 2026-09-12. */
/* Keeps its top gap and loses the centring. It is a .notice box now, which brings its own frame
   and left-aligned text; text-align:center here was the thing Steve asked to be rid of. */
.connect-close{ margin-top:calc(var(--s-6) + 40px) }
/* Asking a client for documents sits under the connection, 2026-09-17: the answer for a client who
   will never use Sync. Its head starts a new part of the section, so it gets a section's worth of air. */
.client-docs-head{ margin-top:140px }
.h-aside{ color:var(--dim); font-weight:400 }
@media (max-width:900px){ .connect-shot .shot{ width:100% } }

/* The client's document request page, shot at phone width. A phone screen in a full half column
   would stand taller than the whole page, so it is held to about the size a phone is in the hand
   and centered in its column. It is a real screen of the running app, framed like every other
   screenshot and never drawn into a phone. */
/* The caption sits beside the phone, and had no space from it: on a phone the words touched the
   frame. Steve, 2026-09-21: "give it some breathing room." */
.request-phone{ margin:0; display:flex; justify-content:center; gap:22px }
.request-phone .shot{ width:100%; max-width:300px }
.card::before{
  content:"";position:absolute;left:0;top:0;height:2px;width:52px;
  background:var(--accent,var(--line));
}

/* ------------------------------------------------------------- step list */
.steps{counter-reset:step;display:grid;gap:2px;margin:0;padding:0;list-style:none}
.steps li{
  counter-increment:step;position:relative;
  padding:22px 24px 22px 74px;
  background:var(--card);border:1px solid var(--line);
  border-radius:var(--radius);
}
.steps li::before{
  content:counter(step);position:absolute;left:24px;top:21px;
  font-family:var(--mono);font-size:12px;font-weight:500;
  color:var(--income);
  width:28px;height:28px;border-radius:8px;
  border:1px solid var(--line);background:var(--bg-alt);
  display:flex;align-items:center;justify-content:center;
}
.steps li b{display:block;margin-bottom:4px}
.steps li p{font-size:15.2px;color:var(--muted);margin:0}
@media (max-width:660px){ .steps li{padding:20px 18px 20px 62px} .steps li::before{left:18px} }

/* -------------------------------------------------------------- plain list */
ul.plain{list-style:none;margin:0;padding:0}
/* ul.plain zeroes its margin and outranks .next; a list that follows a picture still wants the gap. */
ul.plain.next{margin-top:var(--s-4)}
ul.plain li{
  position:relative;padding:0 0 0 18px;margin:0 0 11px;
  font-size:15.4px;line-height:1.56;color:var(--body);
}
ul.plain li::before{
  content:"";position:absolute;left:0;top:.66em;width:8px;height:2px;
  background:var(--accent,var(--dim));
}
ul.plain li b{color:var(--text)}
ul.plain.two{columns:2;column-gap:40px}
/* The 11px under each item is padding in a two-column list, not margin. Safari carries the margin
   of the item before a column break over to the top of the next column, so with seven boundaries
   on the front page (2026-09-23) the right column started 11px lower than the left. */
ul.plain.two li{break-inside:avoid;margin-bottom:0;padding-bottom:11px}
@media (max-width:760px){ ul.plain.two{columns:1} }

/* ------------------------------------------- headline and shout lines */
/* The second half of the headline carries the whole inversion, so it is the half that
   gets the color. "Everything else files your paper" is the setup; "This one puts it to
   work" is the turn. */
.hl{color:var(--income)}

/* "Ever." SITS ALONE ON ITS OWN LINE AND THAT IS DELIBERATE, from the approved copy: it
   is the only single word line on the page, so the eye stops there whether it meant to
   or not, and it stops on the promise that separates this from every automated
   competitor. Do not merge it into the sentence above it. */
.shout{
  font-size:clamp(20px,2.9vw,28px);line-height:1.2;letter-spacing:-.018em;
  /* 48px above, not 34. Steve: "add another 10px to 20px padding underneath 'It's what
     happens when the paper finally has something to talk to' so the next line doesn't
     look as crowded." That is the gap this margin makes, and 48 is 14 more than it was.
     Written as two scale steps rather than as 48, and the 34 it replaces was off the
     scale entirely. */
  color:var(--text);font-weight:600;margin:calc(var(--s-5) + var(--s-3)) 0 0;
}
.shout.ever{color:var(--income);margin-top:6px}

/* A line pulled out of running copy without breaking the column. */
.pull-inline{
  color:var(--text);font-size:clamp(17px,2.1vw,19.5px);font-weight:500;
  line-height:1.35;letter-spacing:-.012em;
  border-left:2px solid var(--income);padding-left:18px;
  margin:22px 0 22px;
}

/* An aside that deliberately does NOT match the cards above it. The approved ad this
   section comes from carries its own note about why: all four examples share the same
   shape, observation then consequence, four times running, and the reader locks onto that
   rhythm by the third, so the fourth arrives with less force than it deserves. Breaking
   the pattern on the last one is the lever, and this is that. */
/* IT RUNS THE FULL WIDTH OF THE THREE CARDS ABOVE IT, WITH THE SAME INSET ON BOTH
   SIDES. Steve: "it needs to run the full width of the three boxes above it, or rather
   they need the same margin on the right and the left. So if aside has it pushed over a
   little from the left, make sure there is an equal margin on the right."

   Two things were wrong and only one of them was the one that showed. The obvious one:
   a 66ch cap held the line short, so the paragraph broke to three lines and stopped well
   before the right edge of the cards, which made the whole block look like it had slid
   left. The real one: the rule and its padding inset the text 21px from the left with
   nothing answering it on the right, so the inset read as a misalignment rather than as
   a margin. Matching the right to the left makes it a frame, and dropping the cap lets
   the measure use the width the cards already establish. */
.aside{
  /* Room above and below, at his ask. The space BELOW is set on .talk-shot rather than
     here, because adjacent margins collapse to the larger of the two: a margin-bottom on
     this paragraph would have been swallowed by the figure's margin-top and changed
     nothing at all on the screen. */
  margin:calc(var(--s-4) + var(--s-2)) 0 0;
  padding:0 21px;
  border-left:1px solid var(--line);
  font-size:16px;line-height:1.62;color:var(--muted);font-style:normal;
}

/* ------------------------------------------------------------------ quote */
.pull{
  border-left:2px solid var(--income);
  padding:4px 0 4px 22px;margin:0;
  font-size:clamp(19px,2.6vw,25px);line-height:1.36;font-weight:300;
  letter-spacing:-.014em;color:var(--text);
}
.pull cite{
  display:block;font-style:normal;font-family:var(--mono);
  font-size:11.5px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--dim);margin-top:16px;
}

/* ------------------------------------------------------------------ prices */
.plans{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:18px;align-items:stretch}
.plans > *{min-width:0}
@media (max-width:940px){ .plans{grid-template-columns:1fr} }
.plan{
  display:flex;flex-direction:column;
  background:var(--card);border:1px solid var(--line);border-radius:var(--radius);
  padding:28px 26px 26px;position:relative;overflow:hidden;
}
.plan::before{content:"";position:absolute;left:0;top:0;height:3px;width:100%;background:var(--accent,var(--line));opacity:.85}
.plan.featured{border-color:var(--line-warm);background:linear-gradient(180deg,var(--card-lift),var(--card))}
.plan .flag{
  position:absolute;right:0;top:0;
  font-family:var(--mono);font-size:10px;letter-spacing:.15em;text-transform:uppercase;
  color:var(--ink-on-accent);background:var(--income);padding:5px 12px;border-bottom-left-radius:10px;font-weight:500;
}
.plan .who{
  font-family:var(--mono);font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--dim);margin:6px 0 12px;
  /* Two lines' worth, always, so the three prices sit on one line across the row
     however long one edition's description happens to be. */
  min-height:2.9em;
}
@media (max-width:940px){ .plan .who{min-height:0} }
/* The corner flag is absolutely positioned, so the title has to be told to stay out
   from under it. */
.plan h3{font-size:22px;margin-bottom:2px;padding-right:96px}
.plan .price{margin:18px 0 4px;display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}
.plan .price .amount{font-size:42px;font-weight:700;color:var(--text);letter-spacing:-.03em;line-height:1}
.plan .price .unit{font-size:14px;color:var(--muted)}
.plan .plus{font-size:14.5px;color:var(--muted);margin:0 0 18px}
.plan .plus b{color:var(--text)}
.plan .alt-price{
  border-top:1px solid var(--line-soft);border-bottom:1px solid var(--line-soft);
  padding:14px 0;margin:0 0 20px;font-size:14.5px;color:var(--muted);
}
.plan .alt-price b{color:var(--text)}
.plan ul.plain{margin-bottom:24px}
.plan ul.plain li{font-size:14.6px;color:var(--muted)}
.plan ul.plain li b{color:var(--body);font-weight:500}
.plan .plan-cta{margin-top:auto}
.plan .plan-cta .btn{width:100%}
/* A note beside the button is centered on it, at Steve's word, 2026-09-15 (it sits above the button since 2026-10-05). */
.plan .plan-cta .note{text-align:center}
.plan.soon{opacity:.92}
.plan.soon .flag{background:var(--taxdocs);color:var(--ink-on-taxdocs)}
/* THE BUY BUTTONS WEAR THEIR EDITION'S LOGO COLOR. Steve, 2026-09-14: Full Edition "the same
   green as the word Sync in the logo", Contractor "the same Red as Contractors Edition in the
   logo", and Solo "the same gold color as is in the logo". Each color is sampled off the logo file
   itself. Solo's waitlist button is filled like the other two now. Hover lightens, color only. */
#bookkeeper .plan-cta .btn{background:var(--ed-full);border-color:var(--ed-full);color:var(--ink-on-accent)}
#bookkeeper .plan-cta .btn:hover{background:var(--ed-full-hover);border-color:var(--ed-full-hover)}
#contractor .plan-cta .btn{background:var(--ed-contractor);border-color:var(--ed-contractor);color:var(--text)}
#contractor .plan-cta .btn:hover{background:var(--ed-contractor-hover);border-color:var(--ed-contractor-hover)}
#solo .plan-cta .btn{background:var(--ed-solo);border-color:var(--ed-solo);color:var(--ink-on-taxdocs)}
#solo .plan-cta .btn:hover{background:var(--ed-solo-hover);border-color:var(--ed-solo-hover)}
/* And the line across the top of each card, at his word the same day. */
#bookkeeper.plan::before{background:var(--ed-full)}
#contractor.plan::before{background:var(--ed-contractor)}
#solo.plan::before{background:var(--ed-solo)}

/* ------------------------------------------------------------------ notice */
.notice{
  border:1px solid var(--line);border-left:2px solid var(--taxdocs);
  border-radius:var(--radius);background:var(--card-2);
  padding:20px 22px;font-size:15px;color:var(--muted);
}
.notice b{color:var(--text)}

/* -------------------------------------------------------------- comparison */
.table-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch;border:1px solid var(--line);border-radius:var(--radius)}
table.grid{border-collapse:collapse;width:100%;min-width:640px;font-size:14.8px}
table.grid th,table.grid td{
  text-align:left;padding:14px 18px;border-bottom:1px solid var(--line-soft);
  color:var(--muted);font-weight:300;vertical-align:top;
}
table.grid thead th{
  color:var(--text);font-weight:600;font-size:14px;
  background:var(--card-2);border-bottom:1px solid var(--line);
  position:sticky;top:0;
}
table.grid tbody tr:last-child td{border-bottom:0}
/* THE ROW LABEL HAS TO STAY PUT WHILE THE TABLE IS SWIPED. On a phone this table is wider
   than the screen and scrolls inside its own frame, which is correct, but with the first
   column scrolling away too a reader ends up looking at a column of "yes" with nothing
   saying yes to what. It is pinned, and it needs its own background or the cells sliding
   under it show through. */
table.grid td:first-child,table.grid th:first-child{
  color:var(--body);
  position:sticky;left:0;z-index:1;
  background:var(--card);
  box-shadow:1px 0 0 var(--line-soft);
}
table.grid thead th:first-child{background:var(--card-2);z-index:2}
.table-scroll{position:relative}
table.grid td b{color:var(--text)}
.yes{color:var(--income);font-family:var(--mono);font-size:13px}
.no{color:var(--faint);font-family:var(--mono);font-size:13px}

/* --------------------------------------------------------------- footnotes -
   A claim with a number on it gets a footnote rather than a hedge inside the sentence.
   "About ten to twenty seconds depending on your document and connection" is a sentence
   nobody finishes; a small 1 costs the reader nothing and the qualification is there for
   whoever wants it. The number itself was measured, not estimated. */
.fn-mark{
  font-size:.62em;vertical-align:super;line-height:0;margin-left:1px;
  color:var(--income);text-decoration:none;font-weight:600;
}
.fn-mark:hover{text-decoration:underline}
ol.footnotes{
  list-style:none;counter-reset:fn;margin:0 0 26px;padding:0;
  border-top:1px solid var(--line-soft);padding-top:22px;
}
ol.footnotes li{
  counter-increment:fn;position:relative;padding-left:22px;
  font-size:13.4px;line-height:1.6;color:var(--dim);max-width:78ch;
}
ol.footnotes li::before{
  content:counter(fn);position:absolute;left:0;top:0;
  font-size:11px;color:var(--income);font-weight:600;
}
ol.footnotes li + li{margin-top:10px}
ol.footnotes li:target{color:var(--muted)}
.fn-back{margin-left:8px;color:var(--muted);font-size:12.5px}

/* ------------------------------------------------------------------ footer */
.site-foot{
  border-top:1px solid var(--line-soft);padding:52px 0 64px;
  background:var(--bg-alt);font-size:14.5px;color:var(--dim);
}
/* The link lists sit on the left under the logo and its line, at Steve's word, 2026-09-15, instead
   of in two columns off to the right of it: the left edge is where every section above starts. */
.site-foot .foot-grid{
  display:grid;grid-template-columns:repeat(2,max-content);justify-content:start;
  column-gap:88px;row-gap:28px;margin-bottom:40px;
}
.site-foot .foot-brand{grid-column:1 / -1}
@media (max-width:760px){ .site-foot .foot-grid{column-gap:48px} }
.site-foot img{height:22px;width:auto;margin-bottom:16px}
/* h2 SINCE 2026-09-17, h4 KEPT SO NOTHING BREAKS. A footer column heading was an h4 sitting
   under the page's h2 sections, which skips level 3 on every page of the site and has done
   since the footer was written. The tag changed and not one pixel did. */
.site-foot h4,.site-foot h2{font-family:var(--mono);font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--dim);margin:0 0 14px;font-weight:400;font-variation-settings:normal}
.site-foot ul{list-style:none;margin:0;padding:0}
.site-foot li{margin-bottom:9px}
.site-foot a{color:var(--muted);text-decoration:none}
.site-foot a:hover{color:var(--text)}
.site-foot .tagline{color:var(--muted);max-width:38ch;margin:0 0 10px}
.site-foot .legal{border-top:1px solid var(--line-soft);padding-top:22px;font-size:13.2px;line-height:1.7}

/* -------------------------------------------------------- reduced motion */
html{scroll-behavior:smooth}
/* Every transition on this site runs on --t and every one of them is a color change, so
   setting it to zero stops all of them. No blanket selector, no !important, nothing for a
   later rule to beat. scroll-behavior is turned off on its own line below, which wins
   because it comes later at equal specificity. */
@media (prefers-reduced-motion:reduce){
  :root{ --t:0s }
  html{ scroll-behavior:auto }
}
:target{scroll-margin-top:86px}

/* Focus that is visible without being ugly. */
a:focus-visible,.btn:focus-visible{outline:2px solid var(--income);outline-offset:3px;border-radius:8px}


/* ============================================================================
   THE PICTURE, OPENED. See site/js/zoom.js for the behavior and why each part
   of it is there.
   ========================================================================== */
/* THE ONE LINE BELOW IS WHY THE WHOLE SITE STOPPED RESPONDING, and it is worth a paragraph
   because it is invisible in every way something can be invisible.

   `.zoom-overlay` sets `display:flex`. The browser's own stylesheet says `[hidden]{display:
   none}`. A class selector has higher specificity than an attribute selector in the user
   agent sheet, so `display:flex` WON: setting `hidden = true` in script made no difference
   to the layout at all. From the first time anybody opened a picture, a fixed, full screen,
   z-index 200, fully transparent sheet sat over the page for the rest of the visit and
   swallowed every click on it. Steve: "once a modal has been opened then closed, NOTHING
   works. Links, nothing."

   It also explains why opening seemed to work "once in a blue moon": the first click landed,
   and every click after it hit the invisible sheet instead of the picture.

   THE BROWSER TEST PASSED THROUGH ALL OF THIS, three times, because it called `.click()` on
   the element from script. A synthetic click is dispatched straight at its target and never
   hit-tests, so it cannot see anything covering the page. It clicks at a POINT now, the way
   a person does, and it presses a link afterwards to prove the page still works. */
.zoom-overlay:not([hidden]){
  position:fixed;inset:0;z-index:200;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:14px;padding:56px 20px 24px;
  background:rgba(4,4,7,.975);
  opacity:0;transition:opacity var(--t) ease;
}
/* THE CASCADE IS FIXED RATHER THAN SHOUTED OVER, which is what section 5 asks for and
   what !important was doing here before. The display rule above is scoped to
   :not([hidden]), so when the attribute is present nothing sets display at all and the
   browser's own [hidden]{display:none} applies with nothing to beat.
   The fault this guards against is worth restating: `.zoom-overlay{display:flex}` used
   to win over the browser's rule, which left an invisible full screen sheet over the
   page after the first close, swallowing every click on the site. */
/* And a second, independent guard, because the fault was that ONE mechanism silently failed:
   even mid-fade, before `hidden` goes back on, nothing that is not open may take a click. */
.zoom-overlay:not(.is-open){pointer-events:none}
.zoom-overlay.is-open{opacity:1;pointer-events:auto}
/* IT FITS. `max-width:none` was on the image, which meant a 2400px wide screenshot stayed
   2400px wide and the frame had to be scrolled to see any of it. The whole picture is on
   screen at once now, and the frame is sized BY the image rather than the other way round,
   so there is no letterbox gap between the border and the picture.

   `min-height:0` on the frame is what lets a flex item shrink below its content, without
   which the image would push the frame past the bottom of the window and be cut off there
   instead. Same family of fault as the grid columns further up this file. */
.zoom-frame{
  flex:0 1 auto;min-width:0;min-height:0;
  /* THE CEILING IS ON THE FRAME, NOT ONLY ON THE IMAGE. Without it the frame simply grew to
     whatever the picture's natural size was when zoomed in, so scrollWidth equalled
     clientWidth, there was nothing to pan, and "zoomed in" did nothing visible at all. The
     frame is pinned to the window; the picture is what gets bigger inside it. */
  max-width:calc(100% - 2px);max-height:calc(100vh - 152px);
  /* CONTENT-BOX, SO THE SHAPE fitCheck() GIVES IT IS THE PICTURE'S. Under the site-wide
     border-box, aspect-ratio was applied to the frame INCLUDING its 1px border, so the inside
     came out a different shape from the picture: 7 or 8px of empty frame above and below the
     tall Information Center screenshot on the front page, at every size. Steve saw it once
     it was pointed out, 2026-09-29. The ceilings above lose 2px to keep the outside where
     it was. */
  box-sizing:content-box;
  /* CENTRED WITH AUTO MARGINS ON THE PICTURE, NOT WITH justify-content. A flex container
     that centres its items makes the overflow on the START side unreachable: scrolled all
     the way left, the first 500px of a zoomed screenshot simply could not be got at, and
     scrollWidth came back as 1899 on a 2400px image. Auto margins centre it and leave both
     ends reachable. */
  display:flex;overflow:hidden;
  border:1px solid var(--line);border-radius:12px;background:var(--card);
  box-shadow:0 40px 100px -40px var(--shadow);
}
.zoom-img{
  display:block;margin:auto;
  max-width:100%;max-height:100%;
  width:auto;height:auto;
  object-fit:contain;
  cursor:zoom-in;
}

/* CLICKING THE PICTURE GOES CLOSER, because "it fits" and "I can read the small print" are
   two different wants and a marketing screenshot has to serve both. Zoomed in, the frame is
   the thing that scrolls and the picture is at its own size. */
.zoom-frame.is-zoomed{overflow:auto;-webkit-overflow-scrolling:touch}
.zoom-frame.is-zoomed .zoom-img{
  max-width:none;max-height:none;width:auto;height:auto;cursor:zoom-out;
  /* `flex:0 0 auto` IS THE WHOLE ZOOM. The picture is a flex item, and a flex item shrinks
     to its container by default however large its own content is: lifting the max-width off
     it changed nothing at all, because flex-shrink went on squashing a 2400px image back to
     the 1339px frame. Measured, not guessed: shown stayed [1339, 848] after zooming and
     there was nothing to pan. */
  flex:0 0 auto;
}
.zoom-frame.at-size .zoom-img{cursor:default}
.zoom-frame::-webkit-scrollbar{width:8px;height:8px}
.zoom-frame::-webkit-scrollbar-thumb{background:var(--scroll-thumb);border-radius:4px}

@media (max-width:760px){
  .zoom-overlay{padding:52px 10px 14px}
}
.zoom-close{
  position:absolute;right:16px;top:14px;
  font-family:var(--sans);font-size:14px;font-weight:600;
  color:var(--text);background:rgba(255,255,255,.08);
  border:1px solid var(--line);border-radius:9px;
  padding:8px 16px;cursor:pointer;
}
.zoom-close:hover{background:rgba(255,255,255,.14)}
.zoom-close:focus-visible{outline:2px solid var(--income);outline-offset:3px}
.zoom-caption{
  margin:0;max-width:70ch;text-align:center;
  font-size:13.5px;color:var(--muted);
}
@media (prefers-reduced-motion:reduce){ .zoom-overlay{transition:none} }

/* ---------------------------------------------------------- run-on list ---
   Six short observations read as a human wrote them when they run as
   paragraphs with a lead phrase. Six identical cards in a grid, each with a
   three word title and two lines under it, is the shape of a generated page.
   Same content, and the difference is entirely in the reading. */
.runon{columns:2;column-gap:44px;margin:0}
.runon p{
  break-inside:avoid;margin:0 0 22px;font-size:15.6px;line-height:1.56;
  color:var(--muted);
}
.runon p .lead{color:var(--text);font-weight:600}
.runon p b{color:var(--body);font-weight:500}
@media (max-width:820px){ .runon{columns:1} .runon p{margin-bottom:18px} }

/* ============================================================================
   THE CLASSES THAT REPLACED 95 INLINE STYLE ATTRIBUTES.

   DESIGN_RULES.md section 5 bans inline styles, and it also bans utility-class
   soup, which rules out the obvious escape of `.mt-16 .mb-24 .text-center`. So
   these are named for WHAT THEY MEAN rather than for what they measure, which is
   also what section 2 asks of spacing: "Spacing should signal relationship,
   tighter where things belong together, looser at real breaks."

   Every value comes off section 0's 8px scale. Where one is off the scale it
   carries a comment saying why, which is the rule the scale came with.
   ========================================================================== */

/* ---- how far a thing sits from the thing above it ---- */
.close  { margin-top:var(--s-3) }   /* still the same thought */
.next   { margin-top:var(--s-4) }   /* the next thing in it */
.apart  { margin-top:var(--s-5) }   /* a real break inside a section */
.break  { margin-top:var(--s-6) }   /* a break between ideas */
.lead-in{ margin-bottom:var(--s-2) } /* a heading sitting directly on its list */
.trail  { margin-bottom:var(--s-4) }

/* ---- line length, which section 2 wants to VARY by context rather than be one
        max-width everywhere ---- */
.measure-s{ max-width:36ch }
.measure-m{ max-width:48ch }
.measure-l{ max-width:58ch }

/* ---- which ledger a thing is about ----
   Section 0's signature move. The accent is never decoration: an element carries
   one of these only when the reader is looking at that ledger, and the attribute
   says which so the markup means something a class name like `.blue` would not. */
[data-ledger="receipts"]  { --accent:var(--receipts) }
[data-ledger="income"]    { --accent:var(--income) }
[data-ledger="utilities"] { --accent:var(--utilities) }
[data-ledger="mileage"]   { --accent:var(--mileage) }
[data-ledger="taxdocs"]   { --accent:var(--taxdocs) }
[data-ledger="compliance"]{ --accent:var(--compliance) }
[data-ledger="quotes"]    { --accent:var(--quotes) }
[data-ledger="donations"] { --accent:var(--donations) }
[data-ledger="alert"]     { --accent:var(--red) }
[data-ledger="none"]      { --accent:var(--dim) }
.eyebrow[data-ledger]{ color:var(--accent) }

/* ---- small print under a picture or a figure ----
   Left aligned, because section 2 says paragraphs are left aligned and a centred
   caption under a left aligned page is the template habit it is warning about. */
.note{
  margin-top:var(--s-3);
  font-size:13.5px;color:var(--dim);
}
.subtle{ color:var(--muted) }

/* ---- the hero's two heights ---- */
.hero.tall { padding:var(--s-7) 0 var(--s-7) }
.hero.short{ padding-bottom:var(--s-6) }
/* The price list: the cards follow the headline directly, with no rule and no second band's
   worth of padding between them, so the headline reads as the cards' own heading. */
.hero.short.into-plans{ padding-bottom:var(--s-5); border-bottom:0 }
.band.from-hero{ padding-top:0; border-top:0 }

/* ---- one comparison column that must not collapse onto two lines ---- */
.col-name{ min-width:230px }

/* One band sits directly under the one above it with no rule between them, because the
   two are the same thought continued and a line there would say otherwise. */
.flush-top{ border-top:0; padding-top:0 }

/* ============================================================================
   THE HERO'S PHONE.

   Steve, 2026-09-10: *"I want one of the phone pics up next to the first hero
   text, the phone to the right. Add some perspective, or skew, or whatever to
   the phone and make it look cool."*

   IT IS A PHOTOGRAPH OF A PHONE, NOT A PHONE DRAWN IN CSS. The earlier attempt
   drew the device out of a rounded rectangle and a gradient and he threw the whole
   thing out for it: "the fake phones look terrible." He cut these out himself, so
   the file carries the real handset with real light on its edges and a real alpha
   channel, and this stylesheet's only job is to place it and tilt it.

   THE SHADOW IS A FILTER, NOT A BOX-SHADOW, and that is the one thing here that is
   not interchangeable. `box-shadow` draws the shadow of the element's RECTANGLE, so
   against this ground it would put a hard rectangular smudge behind a rounded
   phone and give the cutout away instantly. `drop-shadow` follows the alpha
   channel, so the shadow is the shape of the phone. Two of them stacked, a tight
   one for contact and a wide one for distance, which is how a real object sits.

   THE TILT IS A STATIC TRANSFORM AND NOT AN ANIMATION. DESIGN_RULES.md section 2
   bans motion, and this is not motion: it is the angle the thing is seen from, the
   same as if it had been photographed that way. Nothing moves on scroll or hover.
   ========================================================================== */
/* THE COLUMN WIDTHS ARE MEASURED, NOT CHOSEN. Steve: "make the phone smaller so that
   the hero text wraps like it did before adding the phone. The phone should be roughly
   the same height as the two smaller paragraphs."

   Measured in the browser at 1440 rather than estimated: "Everything else files your
   paper." needs 820px to sit on one line at 62px Bricolage.

   THE BUDGET IS 1072, NOT 1120, and getting that wrong once already cost a wrapped
   headline: .wrap is 1120 wide but carries 24px of padding on each side, so the grid only
   ever has 1072 to divide. 1072 less 224 of phone less 24 of gap leaves 824, which clears
   820 by four pixels. That is deliberately thin and it is why the phone column is capped
   rather than flexible: if the headline ever grows a word, this is the number to cut.

   224 sits between the 380 that was too big and the 152 that was too small, and it is
   also the widest this phone can be without breaking the headline he asked to keep.

   The paragraphs keep their own measure (60ch) whatever the column does, so widening the
   column does not change their height and the 385 stays true. */
.hero-split{
  display:grid;
  grid-template-columns:minmax(0,1fr) 224px;
  gap:var(--s-4);
  /* BOTTOM ALIGNED, NOT CENTRED, and that is the whole trick. Steve asked for the phone
     to "stretch down to be beside" the fineprint line at the foot of the copy. Centred,
     that is arithmetic: the phone has to be exactly as tall as the copy column or it
     lands somewhere else, and it stops being true the moment a word is added to a
     paragraph. Aligned to the end, the phone's foot sits on the fineprint's foot whatever
     either one does, and its height only decides how far UP it reaches. */
  align-items:end;
}
.hero-split > *{min-width:0}
/* THE PHONE COMES FIRST IN THE MARKUP, and the two columns are named here so the copy still sits
   on the left. It has to precede the copy for the phone layout below, where the words wrap around
   it: a float only wraps the text that follows it. */
/* BOTH IN ROW 1, NAMED. Without the row, the copy could not be placed back in column 1 of a row
   the phone had already started, so it fell to a row of its own and the desktop hero came apart. */
.hero-copy{grid-column:1;grid-row:1}
.hero-phone{grid-column:2;grid-row:1}

/* LIFTED SO THE LOW CORNER LANDS ON THE FINEPRINT. Steve: "move it up so that the
   bottom right of the phone is level with the bottom of the text 'You buy it once and
   own it...'. Maybe 15px." Measured rather than guessed: the tilt puts the phone's
   bottom right 27px below that line, because rotateZ turns the right edge downward and
   the bounding box grows with it. 27 is what makes them level. */
.hero-phone{ perspective:1200px; margin-bottom:27px }
.hero-phone img{
  display:block;width:100%;height:auto;
  transform:rotateY(-17deg) rotateZ(2.5deg) rotateX(3deg) scale(1.06);
  transform-origin:55% 50%;
  /* The shape of the phone, not the shape of its box. See the note above. */
  filter:
    drop-shadow(0 10px 18px rgba(0,0,0,.55))
    drop-shadow(0 44px 70px rgba(0,0,0,.75));
}

/* UNDER 980px THE TILT COMES OFF BEFORE THE LAYOUT DOES. A phone rotated 17 degrees
   in a column that is now narrow reads as a mistake rather than as a point of view,
   and it eats horizontal room it no longer has. */
/* BELOW ABOUT 1180 THE HEADLINE CAN NO LONGER HOLD ITS LINE, because the wrap is
   shrinking with the viewport while the type is still pinned at its 62px ceiling. Rather
   than let it wrap into a shape nobody chose, the ceiling comes down here and the line
   survives another 200px of narrowing. */
@media (max-width:1180px){
  h1{font-size:clamp(34px,5.4vw,56px)}
  .hero-split{grid-template-columns:minmax(0,1fr) 208px}
  .hero-phone img{transform:rotateY(-14deg) rotateZ(2deg) scale(1.03)}
}
/* ON A PHONE IT KEEPS THE TILT, at Steve's word 2026-09-15: "on mobile it doesn't have that cool
   perspective pic of the phone next to the hero text... just a bummer." It lost the tilt here
   because a 17 degree rotation inside a narrow column read as a mistake. Centered in its own row
   and held to 320px it reads as deliberate again, so the angle comes back, gentler, with the
   shadow that makes it sit in the page rather than on it. The tilt swings the picture wider than
   its box, which is what the padding on each side is for. */
/* THE HERO ON A PHONE. Steve, 2026-09-15: "The first paragraph has to be higher. Drop the phone
   another 30px, and have the first paragraph start level with the top of the phone... The second
   paragraph has NO space after the first. That's terrible... the phone is cutting off some of the
   text and the shadow is impeding into the text as well. That second paragraph MUST be a good
   25-30px below the phone, at least!"

   Under 600px the headline keeps the full width, the first paragraph and the picture share the next
   row with their TOPS level, both 30px below the headline, and everything after clears the taller
   of the two by 30px. That needs the copy's children to be grid items, which is what
   display:contents does: the .hero-copy box stops generating anything and its children take its
   place. They are placed by hand because the picture comes first in the markup, which it has to,
   for the layout below.

   A float was tried first and thrown out. It wraps text, but its foot lands wherever its height
   puts it, and no width made that agree with the paragraph's last line. */
@media (max-width:520px){
  .hero-split{
    display:grid;grid-template-columns:minmax(0,1fr) 40%;
    column-gap:24px;row-gap:0;align-items:start;
  }
  .hero-copy{display:contents}
  .hero-copy .eyebrow{grid-column:1 / -1;grid-row:1;white-space:nowrap}
  .hero-copy h1{grid-column:1 / -1;grid-row:2;font-size:30px}
  .hero-copy .lede:not(.turn){grid-column:1;grid-row:3;margin:30px 0 0}
  .hero-copy .lede.turn{grid-column:1 / -1;grid-row:4;margin-top:30px}
  .hero-copy .btn-row{grid-column:1 / -1;grid-row:5}
  .hero-copy .fineprint{grid-column:1 / -1;grid-row:6}
  .hero-phone{
    grid-column:2;grid-row:3;
    /* The 16px under it is for the shadow, which a bounding box does not include: without it the
       next paragraph measured 30px clear and looked 10px clear. */
    width:auto;max-width:none;margin:30px -6px 16px 0;padding:0;perspective:900px;
  }
}

/* A TABLET UPRIGHT, AND A PHONE TURNED SIDEWAYS, get the two plain columns instead: every word in
   the left one, the picture in the right one, both starting at the top. Splitting the copy into
   rows at these widths leaves a hole beside the second paragraph, because the first is only three
   or four lines across a wide column. Landscape used to get the DESKTOP hero, where the picture is
   sized for a tall window: it hung off the foot of the screen with a hole above it. */
@media (min-width:521px) and (max-width:900px), (max-width:1024px) and (max-height:600px){
  .hero-split{
    /* THE COLUMNS WERE THE WRONG WAY ROUND until 2026-09-21: 300px for every word and the rest
       for the picture, so on an iPad upright the phone grew to 430px and its edge was cut off by
       the screen (it poked 6px past at 768, 17px at 900). The words take the room now and the
       picture is held to 40%, which is 288px at 768. */
    display:grid;grid-template-columns:minmax(0,1fr) min(300px,40%);
    column-gap:28px;align-items:start;
  }
  .hero-copy{display:block}
  .hero-copy h1{font-size:30px}
  .hero-phone{grid-column:2;grid-row:1;width:auto;max-width:none;margin:8px 8px 0 0;padding:0;perspective:900px}
}
/* Sideways there is less height than a phone picture wants, so the column is narrower again. */
@media (max-width:1024px) and (max-height:600px){
  /* 189px is a tenth off the 210 it was, at Steve's ask, so the picture stands about as tall as
     the two paragraphs beside it. The drop goes up with it, from 110 to 130, which keeps the foot
     on the Pricing button and now starts the top level with the first paragraph. */
  .hero-split{grid-template-columns:minmax(0,1fr) 189px;column-gap:26px}
  .hero-copy h1{font-size:27px}
  .hero-phone{margin-top:130px}
}

/* The tilt is the part he liked, and it stays at every size. The shadow is tighter here than on a
   desktop: a 52px blur beside a 190px column of text puts grey behind the words. */
@media (max-width:1024px){
  .hero-copy h1 .hl{display:block;margin-top:20px}   /* 20px between the white line and the green */
  .hero-phone img{
    transform:rotateY(-13deg) rotateZ(2deg) rotateX(2deg) scale(1.02);
    transform-origin:55% 50%;
    filter:
      drop-shadow(0 4px 7px rgba(0,0,0,.48))
      drop-shadow(0 12px 18px rgba(0,0,0,.62));
  }
}

/* THE HEADLINE IS TWO LINES AT EVERY WIDTH, AND SMALLER THAN THE WORDMARK. Steve, 2026-10-13, on
   "Your clients' paperwork knows things about their business": "The new headline MUST be two lines,
   not three... it's too large - it's bigger than the app logo." The wordmark's letters stand about
   50px on a laptop; at 62px this headline's capitals were about 43px in a far heavier weight, so it
   read as the bigger thing. 44px is the ceiling now.

   On his phone the size was right and only the line count was wrong ("just needs to be two lines
   instead of three"), so the break is after "knows": the two lines are nearly equal (12.8 and 11.4
   times the font size), which keeps a phone at about 27px instead of the 21px the other split needed.

   Each line is held together (nowrap) and the size comes from the room the copy column actually
   has: a thirteenth of the column always fits the longer line. That replaces every per-width size
   for this h1, including the tablet rule further down (hence .hero-split in the selector), and the
   green no longer drops to a line of its own below 1024. Under 520px the copy box is
   display:contents and can't be a container, so the size comes from the screen less the 24px
   gutters instead. */
.hero-copy{container-type:inline-size}
.hero-split .hero-copy h1{font-size:min(44px, calc(100cqi / 13))}
.hero-copy h1 .hl-line{white-space:nowrap}
.hero-copy h1 .hl{display:inline;margin-top:0}
@media (max-width:520px){ .hero-split .hero-copy h1{font-size:min(30px, calc((100vw - 48px) / 13))} }

/* THE ARROW THAT SAYS THERE'S MORE, front page only. Steve, 2026-10-13: "some kind of small
   downturned arrow at the bottom center, regardless of the viewport size that indicates there's
   more content. Maybe make it partially translucent and bouncy. People like bouncies. I like
   bouncies." Fixed to the window, centered by margin rather than transform so the bounce can own
   the transform. The translucency is on the chevron and the script's fade is on the link, so the
   two multiply and the fade starts from 60%. The bounce stops for anybody who has asked for less motion. */
.scroll-cue{
  position:fixed;left:0;right:0;bottom:calc(14px + env(safe-area-inset-bottom, 0px));
  margin:0 auto;width:48px;height:40px;z-index:20;
  display:flex;align-items:center;justify-content:center;
  animation:scroll-cue-bounce 1.8s ease-in-out infinite;
}
.scroll-cue span{
  display:block;width:16px;height:16px;margin-top:-8px;
  border-right:3px solid var(--accent);border-bottom:3px solid var(--accent);
  border-radius:2px;transform:rotate(45deg);opacity:.6;
}
.scroll-cue:hover span,.scroll-cue:focus-visible span{opacity:1}
@keyframes scroll-cue-bounce{
  0%,20%,55%,100%{transform:translateY(0)}
  38%{transform:translateY(9px)}
  46%{transform:translateY(3px)}
}
@media (prefers-reduced-motion:reduce){ .scroll-cue{animation:none} }

/* ---------------------------------------------- the closing passage of #talk */
/* LEFT ALIGNED, like the rest of the page. It was centered under the picture above it at
   Steve's ask on 2026-09-10; on 2026-09-12 he took it back: "I don't like it. Please left
   align it so it matches the rest of the page content." Nothing here now, on purpose. */

/* ------------------------------------------------------- the three engines */
/* The drop zone, the reading, and the review, in one row directly under the four
   numbered steps they illustrate. Each of the last two used to have a paragraph beside
   it repeating what step 2 and step 3 already said; Steve: "that's redundant
   information, not needed."

   All three pictures are 480 by 720, so at one shared column width the frames line up
   to the pixel with no aspect juggling. Under 900px they go two up and then one up,
   because three 340px screens on a phone is three postage stamps. */
.engines{
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  gap:var(--s-4);
  margin-top:var(--s-5);      /* room to breathe under the steps. It was 16 and crowded */
}
.engines > *{min-width:0}
.engines figcaption{text-align:center}
@media (max-width:900px){
  .engines{grid-template-columns:repeat(2,minmax(0,1fr))}
  /* width:100% IS LOAD BEARING. Centered with auto margins, the last frame sized itself to
     its picture, and a lazy picture has no size until it loads: on a phone the frame grew
     91px when it arrived and pushed the whole page down under the reader. Chrome hides that
     by holding the scroll still; Safari does not, so a jump from the contents to the next
     section landed 91px short. Measured in WebKit, 2026-09-12. */
  .engines > *:last-child{grid-column:1 / -1;width:100%;max-width:calc(50% - var(--s-2));margin:0 auto}
}
@media (max-width:620px){
  .engines{grid-template-columns:1fr;max-width:340px;margin-left:auto;margin-right:auto}
  .engines > *:last-child{max-width:none}
}

/* The filed record under the three engine screens. It was 2px, which is what he asked
   for when the row had no captions under it; with the captions in, 2px read as crowded
   and he said so: "let it breathe dude." 40px now, which is well past the 20 he set as
   the floor, and the four pictures still read as one sequence because the captions tie
   the row together and this one carries its own. */
.filed{margin-top:var(--s-5)}
.filed figcaption{text-align:center}

/* ------------------------------------------------------------- the menu bar */
/* The strip of eight buttons, under the paragraph listing what they read. */
/* Off the scale on both margins, at his ask: another 20 above and below what was here.
   36 and 52. Section 0 allows a break from the scale with a reason and that is the
   reason. */
.menubar{
  margin-top:61px;
  margin-bottom:52px;
  border:1px solid var(--line);
  border-radius:var(--radius);
  overflow:hidden;
  box-shadow:
    0 40px 90px -40px var(--shadow),
    0 0 0 1px rgba(255,255,255,.025) inset,
    0 1px 0 rgba(255,255,255,.05) inset;
}
.menubar img{width:100%;display:block}

/* THE KEYS over the picture. One real button over each of the eight, placed by measurement
   rather than by an even split: the icons in the picture are not evenly spaced. Each key runs
   from halfway to its left neighbor to halfway to its right one, the outer two as wide again
   on their open side, all in percentages of the picture so they stay put at any width. The one
   showing wears its ledger's rule along the top, the site's signature move and the app's own
   mark above a ledger button, and here it names the ledger it sits over. */
.menubar{position:relative}
.menubar-keys{position:absolute;inset:0}
.menubar-keys button{
  position:absolute;top:0;bottom:0;
  margin:0;padding:0;border:0;border-radius:0;background:transparent;cursor:pointer;
  transition:background-color var(--t) ease;
}
.menubar-keys button::before{
  content:"";position:absolute;top:0;left:50%;width:44%;height:2px;margin-left:-22%;
  background:var(--accent);opacity:0;transition:opacity var(--t) ease;
}
.menubar-keys button:hover{background-color:rgba(255,255,255,.035)}
.menubar-keys button:hover::before{opacity:.45}
.menubar-keys button[aria-pressed="true"]{background-color:rgba(255,255,255,.05)}
.menubar-keys button[aria-pressed="true"]::before{opacity:1}
.menubar-keys button:focus-visible{outline:2px solid var(--income);outline-offset:-3px}
.menubar-keys button:nth-child(1){left:5.32%;width:10.75%}
.menubar-keys button:nth-child(2){left:16.07%;width:10.94%}
.menubar-keys button:nth-child(3){left:27.01%;width:10.97%}
.menubar-keys button:nth-child(4){left:37.98%;width:10.70%}
.menubar-keys button:nth-child(5){left:48.68%;width:10.91%}
.menubar-keys button:nth-child(6){left:59.59%;width:11.77%}
.menubar-keys button:nth-child(7){left:71.36%;width:11.92%}
.menubar-keys button:nth-child(8){left:83.28%;width:11.56%}
/* The picture above changes with a short dip rather than a hard cut. */
#engine-view{transition:opacity var(--t) ease}
#engine-view.swapping{opacity:.25}

/* 35 more than the 24 .next gives, at his ask. */
.notice.coa-note{margin-top:100px}

/* ------------------------------------------------------------- two looks ---- */
/* Luminous Dark or Tailored Light. The switch sits above one frame holding the same window in
   both looks, the light picture laid exactly over the dark one, and the three screens under it are
   pairs the same way; js/looks.js flips data-look on the section and every light one fades in. Each side of the switch, when pressed, wears its own look:
   dark glass with the accent for Luminous Dark, the app's own paper and ink for Tailored Light. */
.looks{max-width:900px;margin:0 auto}
.look-switch{
  display:flex;width:max-content;max-width:100%;margin:0 auto var(--s-4);padding:4px;gap:4px;
  border:1px solid var(--line);border-radius:999px;background:var(--card);
}
.look-switch button{
  font:inherit;font-size:14px;font-weight:500;line-height:1;cursor:pointer;
  padding:11px 20px;border:0;border-radius:999px;background:transparent;color:var(--muted);
  transition:background-color var(--t) ease, color var(--t) ease;
}
.look-switch button:hover{color:var(--text)}
.look-switch button:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.look-switch button[data-look="dark"][aria-pressed="true"]{
  background:var(--card-2);color:var(--text);box-shadow:inset 0 0 0 1px var(--line-mid);
}
.look-switch button[data-look="light"][aria-pressed="true"]{background:var(--paper);color:var(--paper-ink)}
.look-frame img{display:block}
.look-frame .look-light{
  position:absolute;inset:0;height:100%;opacity:0;transition:opacity var(--t) ease;
}
#looks[data-look="light"] .look-frame .look-light{opacity:1}

.look-strip{
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s-4);
  margin-top:var(--s-6);
}
.look-strip .shot img{display:block;aspect-ratio:16/9;object-fit:cover;object-position:top center}
@media (max-width:760px){
  .look-strip{grid-template-columns:1fr;gap:var(--s-5);margin-top:var(--s-5)}
  .look-switch button{padding:10px 16px;font-size:13.5px}
}


/* ============================================================================
   THE RESTRUCTURE, 2026-09-17. The front page was 46 printed pages and every
   visitor had to walk all of it. Steve had it split into layers: the opening
   frame stays exactly as it was, a short front page under it, an audience page
   each, six pages for the parts of the product, and the whole of the old page
   preserved as tour.html.

   NOTHING ABOVE THIS LINE WAS CHANGED, on purpose. The opening frame had to come
   through the split pixel for pixel, and the surest way to promise that is to
   add rules rather than touch any. tools/check_site_first_frame.mjs proves it,
   element by element, at thirty widths in two browsers.
   ========================================================================== */

/* A heading that is in the document and not on the screen. The tour page begins
   at its table of contents with no hero over it, at Steve's word, so its h1 has
   nowhere to be drawn; it still has to exist for the outline and for a screen
   reader. Not display:none, which would take it out of the accessibility tree
   as well, and not a negative text-indent, which drags a focus ring off screen. */
.offscreen{
  position:absolute;width:1px;height:1px;margin:-1px;padding:0;
  overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0;
}

/* ---------------------------------------------------------------- the footer */
/* Three columns of links instead of two, because the deeper pages are findable
   from here and from the page bodies and NOT from the top navigation, which
   Steve kept as it was. At 760px it folds to two and at 480 to one, because
   "Information Center" and "If you keep books for others" are long labels and
   three of them will not sit side by side on a phone. */
.site-foot .foot-grid{grid-template-columns:repeat(3,max-content);column-gap:72px}
@media (max-width:980px){ .site-foot .foot-grid{grid-template-columns:repeat(2,max-content);column-gap:56px} }
/* ONE FLEXIBLE COLUMN AT THE BOTTOM END, NOT ONE max-content COLUMN, and that distinction
   IS the fix. A max-content track is as wide as its widest item will go without wrapping,
   and the item spanning every track here is the tagline, whose own max-width is 38ch: about
   300px. So the footer grid measured 340px inside a 320px phone. html,body{overflow-x:hidden}
   then CLIPPED the excess rather than scrolling it, which is why nothing ever looked wrong
   and the end of the tagline was simply not there.
   THIS WAS ALREADY TRUE BEFORE THE RESTRUCTURE, at 320px, on all three pages. It went
   unnoticed because check_site_renders.mjs measured one phone width, 390, and at 390 the two
   short columns fitted. The third column and the longer labels brought the same fault up to
   390, which is how it was found. 320 and 375 are in that harness now. */
@media (max-width:560px){ .site-foot .foot-grid{grid-template-columns:minmax(0,1fr);row-gap:26px} }

/* ------------------------------------------------------- the three paths */
/* The front page's three audience cards carry the same edition logos as the
   editions section further down the tour, so they need the same two fixes that
   section already has: the mark centered in a card that is wider than it, and
   the same room under every mark so the headings across the row start level.
   Those rules are scoped to #editions and this section is #choose, so they are
   restated rather than having the existing selector widened; #editions is on
   tour.html now and the two pages are free to drift. */
#choose .edition-mark{ justify-content:center; margin-bottom:calc(var(--s-3) + 20px) }
#choose .card.soon .edition-mark{ margin-bottom:9px }
#choose .card.soon .tick{ margin-bottom:10px; text-align:center }
/* Every card's heading takes two lines' room so the copy under all three starts
   level even where one heading happens to fit on one line. Three lines here
   rather than the two #editions needs: "I run a contracting or field service
   business" does not fit in two at every width. */
#choose .card h3{ min-height:calc(3em * 1.25) }
@media (max-width:660px){ #choose .card h3{ min-height:0 } }

/* ----------------------------------------------------- the way out of a section */
/* The link to the page that carries the whole answer, out of a card (.card-go) or
   out of the foot of a section (.go-row). Set as links rather than as buttons, and
   that was a correction, not a preference.
   THEY WERE GHOST BUTTONS IN A .btn-row FIRST, AND THAT BROKE THE PHONE. A .btn-row
   holding exactly two buttons is set flex-wrap:nowrap under 560px, at Steve's word
   from 2026-09-12, so that a pair of short labels stays on one line. These labels are
   not short: "See how documents get in" beside "See the whole handoff to accounting"
   measured 375px inside a 342px column, and html,body{overflow-x:hidden} clipped the
   overhang instead of scrolling it, so the second label simply had its end cut off.
   Steve asked for both things here: labels that say where they go, and no horizontal
   overflow on a phone. A button row can only have one of the two. A row of links can
   have both, because it is allowed to wrap.
   The arrow is drawn in --accent, which section 0 reserves for actions and links, and
   inside a card --accent is that card's own ledger colour. */
/* 9px of padding above and below the words, which is the whole point of it: it takes
   the tap target from about 19px tall to about 37px. Steve, that same morning, about a
   14px line of type that was the only way back to the practice dashboard on a phone:
   "hard to tap without giving it 2 or 3 tries." These are secondary links and they are
   wide, so the height was the only thing wrong with them. The margins are pulled in by
   the same 9px at each end so the space around the row looks exactly as it did. */
.card-go{ margin:calc(var(--s-4) - 9px) 0 -9px }
/* SYMMETRY, Steve 2026-10-06: "the colored links at the bottom of each box, those need to be even.
   Symmetry is a big thing for me so please make that a rule." A card that ends in a .card-go is a
   column, and the link takes the space left over above it, so every card in a row puts its link on
   the same line however long its copy is. check_site_renders.mjs fails if a row's links differ. */
.card:has(> .card-go){ display:flex; flex-direction:column }
.card > .card-go{ margin-top:auto; padding-top:calc(var(--s-4) - 9px) }
/* Centered inside the three edition cards on the front page, at Steve's ask 2026-09-17.
   The link is an inline-flex box, so it is the paragraph around it that does the centering.
   Only in #choose: everywhere else a .card-go sits under left-aligned copy. */
#choose .card-go{ text-align:center }
.go-row{
  display:flex;flex-wrap:wrap;gap:0 36px;
  margin:calc(var(--s-5) - 9px) 0 -9px;padding:0;list-style:none;
}
.go-row li{ margin:0 }
/* THE LINKS THAT CLOSE A SECTION SIT JUST ABOVE ITS RULE, Steve 2026-10-06: "The green links need to
   be much closer to these lines. Perhaps 15px above the lines in each case. Site-wide." Then, the same
   day: "I didn't want the lines moved up, I wanted the links moved down... to create a bit of
   breathing room so the links stand out a little more." So the section keeps its padding and its rule
   stays put; the closing .go-row takes the padding's height off below it and adds the same above it,
   which moves it down without changing the section's size. Then "add another 10px between the links
   and the lines": 25px. 55 = 76 padding - 21; 33 = 54 - 21 on a phone; a .band-head adds its own
   bottom margin (40, or 30 on a phone). */
.band > .wrap > .go-row:last-child,
.band > .wrap > :not(.band-head):last-child > .go-row:last-child{
  margin-top:calc(var(--s-5) - 9px + 55px); margin-bottom:calc(-9px - 55px)
}
.band > .wrap > .band-head:last-child > .go-row:last-child{
  margin-top:calc(var(--s-5) - 9px + 95px); margin-bottom:calc(-9px - 95px)
}
@media (max-width:800px){
  .band > .wrap > .go-row:last-child,
  .band > .wrap > :not(.band-head):last-child > .go-row:last-child{
    margin-top:calc(var(--s-5) - 9px + 33px); margin-bottom:calc(-9px - 33px)
  }
  .band > .wrap > .band-head:last-child > .go-row:last-child{
    margin-top:calc(var(--s-5) - 9px + 63px); margin-bottom:calc(-9px - 63px)
  }
}
.card-go a,.go-row a{
  display:inline-flex;align-items:baseline;gap:9px;padding:9px 0;
  color:var(--accent);font-size:14.8px;font-weight:500;text-decoration:none;
  transition:color var(--t) ease;
}
.card-go a::after,.go-row a::after{ content:"\2192"; font-weight:400 }
.card-go a:hover,.go-row a:hover{ color:var(--text) }

/* The product overview's six cards are h2 (they are the top level of that section,
   under the page's h1, with no h2 above them) and are drawn at the size a card
   heading is drawn at, which is what `.card h3` gave them before the tag changed
   for the sake of the heading order. */
#parts .card h2{
  font-size:clamp(18px,2.2vw,21px);font-variation-settings:'opsz' 40;
  letter-spacing:-.012em;line-height:1.25;font-weight:600;margin-bottom:10px;
}

/* --------------------------------------------------- the footer, as a tap target */
/* A footer link was 17px tall with a 9px gap under it, which was survivable while the
   footer held four links and is not now that it holds seventeen: a thumb that misses
   no longer lands on nothing, it lands on the wrong page. The padding makes each one
   about 33px and the margin it replaces kept the column the same height it was.
   Scoped to the three link lists: the "Back" link at the end of a footnote is part of
   a sentence and is left alone. */
.site-foot ul a{ display:inline-block; padding:8px 0 }
.site-foot ul li{ margin-bottom:0 }

/* ------------------------------------------- the closing section's buttons */
/* 60px between the last line and the row of buttons, at Steve's ask, 2026-09-17.
   It is set on the paragraph rather than on the row because .btn-row is used all
   over the site and this gap belongs to this one place. */
#next .lede.close + .btn-row{ margin-top:60px }

/* -------------------------------- a row of links under a row of columns */
/* THE SECOND LINK LINES UP WITH THE SECOND COLUMN. Steve, 2026-09-17: "Every time
   something like this - two columns with two green links underneath - happens, line
   up that second link with the right column. Right now this looks a bit sloppy."
   It was a flex row with a 36px gap, so the two links sat packed against the left
   while the text above them ran in two wide columns: nothing lined up with anything.
   A grid of the same two columns, with each block's OWN gutter (40px for a two
   column list, 44px for a run-on) and each block's OWN breakpoint back to one
   column, so the links fold at the same width the text above them does. */
.plain.two + .go-row,
.runon + .go-row{ display:grid; grid-template-columns:repeat(2,minmax(0,1fr)) }
.plain.two + .go-row{ column-gap:40px }
.runon + .go-row{ column-gap:44px }
.plain.two + .go-row > li,
.runon + .go-row > li{ min-width:0 }
/* ON THE TEXT, NOT ON THE BULLET. Steve, 2026-09-17: "Change the green link alignment to be
   with the text, not the bullets." Every `ul.plain li` sets `padding-left:18px` and hangs its
   dash in that space, so a link sitting flush with the column edge lines up with the dashes
   above it and not with a single word of the copy. The same 18px puts it under the text.
   The run-on paragraphs have no marker and are already flush, so this is not applied there. */
.plain.two + .go-row > li{ padding-left:18px }

/* AND WHERE THERE ARE NO COLUMNS TO LINE UP WITH, the pair spreads to the two edges of
   whatever is above it, which on the front page is a notice box running the full width.
   Steve: "please right align the second link so there's some symmetry." Only for a row of
   exactly two: a single link has nothing to be symmetrical with. (A row of three was left alone
   here until 2026-09-23, when Steve made left, center, right the rule; see the end of this file.) */
.go-row:has(> :nth-child(2)):not(:has(> :nth-child(3))){ justify-content:space-between }
/* EXCEPT IN A HERO, where they stack, one per line, left aligned, at Steve's ask 2026-09-17.
   Spreading them across the column had put the second link a clear 350px past the end of the
   paragraph it belongs to, because the hero copy is capped at 58 characters and the page column
   is not: a stray link rather than symmetry. Stacked, each one starts where the paragraph above
   it starts.
   THE 15px IS BETWEEN THE WORDS, NOT BETWEEN THE BOXES. Each link carries 9px of invisible
   padding above and below so that a thumb has something to hit, so a 15px row-gap would read as
   33px of space. The padding is trimmed to 7.5px here and the gap set to zero, which leaves
   exactly 15px of clear air and still gives a 34px target. */
.hero .go-row{ flex-direction:column; align-items:flex-start; justify-content:flex-start; row-gap:0 }
.hero .go-row a{ padding:7.5px 0 }
@media (max-width:820px){ .runon + .go-row{ grid-template-columns:minmax(0,1fr) } }
@media (max-width:760px){ .plain.two + .go-row{ grid-template-columns:minmax(0,1fr) } }


/* FOUR CHOICES AT THE TOP OF THE EDITIONS PAGE, 2026-09-18. A third edition made it four buttons,
   and on a phone they wrapped one, two, one. Steve: "4 on the phone looks sloppy." Where they do
   not fit on one line they stack, one per line, all the same width, so it reads as a list of
   choices rather than a row that ran out of room. */
@media (max-width:1100px){
  .btn-row.choose-four{ display:grid; grid-template-columns:minmax(0,1fr); max-width:420px; gap:12px }
  .btn-row.choose-four .btn{ width:100%; justify-content:center; text-align:center }
}

/* THE SECURITY PAGE, 2026-09-18. Each topic is a band-head holding its whole topic, so it lines up
   on the same left edge as the hero above it instead of sitting in a centered column, and every
   paragraph gets the band-head's space above it rather than landing on the heading. */
.band-head.sec-topic{ margin-bottom:0 }
.sec-topic ul.plain{ margin-top:14px }
.sec-topic .btn-row{ margin-top:30px }

/* The Information Center's cards beside the five points they illustrate (index #difference).
   Steve, 2026-09-21: the picture on the left with the points stacked beside it. It was tried on
   the right and put back: "That doesn't work either. Reverse them back". Each point is centered on the card it describes. On a phone the picture narrows and the text
   shrinks rather than stacking; see the 1000px block. */
.cards-beside{
  display:grid;grid-template-columns:300px minmax(0,1fr);
  gap:48px;align-items:stretch;
}
.cards-beside > figure{margin:0;grid-column:1;grid-row:1}
.cards-beside > ul{grid-column:2;grid-row:1}
/* Each point is a panel exactly as tall as its card, text centered in it, so the five read as
   rows of one table rather than paragraphs floating near the picture. Steve, looking at the
   first version: "make this so the text blocks don't look so.....sloppy". The rows are the card
   edges measured off the picture (tops 89, 228, 490, 747, 1043 and bottoms 220, 451, 681, 1004,
   1250 of 1288 pixels) as fr, so they scale with it. No edge bars: tried 2026-09-21 and Steve
   said "I don't like those bars at all", and they went; the picture stays on the left. */
.cards-beside ul.plain{
  display:grid;
  grid-template-rows:89fr 131fr 8fr 223fr 39fr 191fr 66fr 257fr 39fr 207fr 38fr;
}
.cards-beside ul.plain > li{
  margin:0;padding:0;display:flex;align-items:center;
}
.cards-beside ul.plain > li::before{display:none}
.cards-beside ul.plain > li:nth-child(1){grid-row:2}
.cards-beside ul.plain > li:nth-child(2){grid-row:4}
.cards-beside ul.plain > li:nth-child(3){grid-row:6}
.cards-beside ul.plain > li:nth-child(4){grid-row:8}
.cards-beside ul.plain > li:nth-child(5){grid-row:10}
@media (max-width:1000px){
  /* ON A PHONE THE PICTURE STAYS BESIDE THE TEXT. Stacked, the points lost the cards they
     describe; Steve 2026-09-21: "the text comes below the pic. This loses its effect." So the
     picture takes a bit under half the width, the type goes small, the "more" links go (they are
     what made the points too tall). Steve then had the points themselves cut short at every size, and each point is centered in a band whose middle is its
     card's middle: the bands split at the midpoints between card centres (154, 339.5, 585.5,
     875.5 and 1146.5 of 1288), doubled here to whole numbers. */
  .cards-beside{grid-template-columns:46% minmax(0,1fr);gap:12px}
  .cards-beside ul.plain{grid-template-rows:494fr 431fr 536fr 561fr 554fr}
  .cards-beside ul.plain > li:nth-child(1){grid-row:1}
  .cards-beside ul.plain > li:nth-child(2){grid-row:2}
  .cards-beside ul.plain > li:nth-child(3){grid-row:3}
  .cards-beside ul.plain > li:nth-child(4){grid-row:4}
  .cards-beside ul.plain > li:nth-child(5){grid-row:5}
  .cards-beside ul.plain > li{font-size:11px;line-height:1.36}
  .cards-beside ul.plain > li b{display:block}
  .cards-beside .more{display:none}
}
@media (max-width:359px){
  /* Under 360px (the first iPhone SE) even the short text runs taller than the picture, so the
     smallest screens keep the old stacked layout: picture first, every point in full under it. */
  .cards-beside{grid-template-columns:1fr;gap:var(--s-4)}
  .cards-beside > figure{width:100%;max-width:300px;margin:0 auto;grid-column:1;grid-row:1}
  .cards-beside > ul{grid-column:1;grid-row:2}
  .cards-beside ul.plain{display:block}
  .cards-beside ul.plain > li{display:block;margin:0 0 14px;font-size:15px;line-height:1.5}
  .cards-beside ul.plain > li b{display:inline}
  .cards-beside .more{display:inline}
}
@media (min-width:621px) and (max-width:1000px){
  /* A tablet has room for the full size and the links again. */
  .cards-beside{grid-template-columns:300px minmax(0,1fr);gap:32px}
  .cards-beside ul.plain > li{font-size:14px;line-height:1.45}
  .cards-beside .more{display:inline}
  .cards-beside ul.plain > li b{display:inline}
}

/* How it fits (index #how), 2026-09-23. Four jobs usually bought separately, drawn as four tiles
   with space between them, beside one box holding the same work as rows of one thing. The picture
   IS the argument, so it carries no icons and no color: the gaps on the left and the rules on the
   right are the whole difference. Nothing here uses a ledger hue, because no ledger is named. */
.fits{
  display:grid;grid-template-columns:minmax(0,5fr) minmax(0,7fr);
  column-gap:var(--s-5);row-gap:var(--s-3);align-items:start;
}
.fits-label{
  font-family:var(--mono);font-size:12.5px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--muted);margin:0 0 var(--s-3);
  /* Both labels are one fixed height with their contents centered in it, so the two columns'
     boxes start on the same line whether the label is words or the logo (symmetry, Steve). */
  height:18px;display:flex;align-items:center;
}
/* "Done separately" a little more prominent, and the Sync side labeled by the logo itself rather
   than its name typed out, Steve 2026-10-06. */
.fits-label img{height:14px;width:auto;display:block}
.fits-apart ol{list-style:none;margin:0;padding:0;display:grid;gap:var(--s-3)}
.fits-apart li{
  border:1px dashed var(--line-mid);border-radius:var(--radius);
  padding:var(--s-3) var(--s-4);color:var(--muted);font-size:15px;
}
.fits-one{grid-column:2;grid-row:1}
.fits-one ul{
  list-style:none;margin:0;padding:0;
  border:1px solid var(--line-lit);border-radius:var(--radius);background:var(--card);
}
.fits-one li{padding:var(--s-3) var(--s-4);border-top:1px solid var(--line);font-size:15px;color:var(--muted)}
.fits-one li:first-child{border-top:0}
.fits-one li b{color:var(--text);font-weight:600}
.fits-out{grid-column:2;margin:0;font-size:15px;color:var(--muted)}
.fits-out b{color:var(--text)}
.fits-out::before{content:"\2193\00a0\00a0";color:var(--dim)}
@media (max-width:760px){
  .fits{grid-template-columns:1fr}
  .fits-one,.fits-out{grid-column:1;grid-row:auto}
  .fits-apart ol{grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s-2)}
  .fits-apart li{padding:var(--s-2) var(--s-3);font-size:14px}
}
/* The contractor findings under the Information Center's cards: an eyebrow, not a heading, because
   they are more of the same section and not a new one. */
#difference #proof{margin-bottom:var(--s-4)}
/* "W-9s" broke after its hyphen in a phone-width tile, leaving "9s" alone on a line. */
.fits-apart li .nw{white-space:nowrap}
/* 40px between the hero's Pricing button and the line under it. Steve, 2026-09-23: "add 40px
   between the button and the you buy it once line". It was 14. */
.hero .btn-row{margin-bottom:var(--s-5)}
/* Steve, 2026-09-23, on #how: the four tiles "centered vertically with the Sync stack", 40px more
   air between "Then out to QuickBooks" and the Where this sits box, and the three links under it
   left, centered and right. The tiles center in the space BELOW their label, which is the box's own
   space, so the two labels still start on one line. Two columns only; on a phone it stacks. */
@media (min-width:761px){
  .fits-apart{align-self:stretch;display:flex;flex-direction:column}
  .fits-apart ol{margin:auto 0}
}
#how .fits + .notice{margin-top:var(--s-6)}
/* The arrow hangs in the margin so a wrapped second line starts under "Then", not under the arrow.
   Steve, 2026-09-23. */
.fits-out{position:relative;padding-left:var(--s-4)}
.fits-out::before{content:"\2193";position:absolute;left:0}
/* The five points beside the Information Center read as one voice since 2026-09-23: "Sync finds
   what is missing", then "...checks the paper against the paper" and so on, with no periods, at
   Steve's word. With no full stop to end it, a lead that ran on into its sentence read as one
   garbled line, so the lead is its own line at every width. */
.cards-beside ul.plain > li b{display:block}
/* 30px more above "And on a contractor's books", Steve 2026-09-23: "so there's a little breathing
   room". Off the scale on purpose; it was the 24 of .next. */
#difference #proof{margin-top:calc(var(--s-4) + 30px)}
/* ON A PHONE BOTH PARAGRAPHS SIT BESIDE THE PHONE, Steve 2026-09-23 from his iPhone: "the paragraph
   starting with 'Then the reviewed...' needs to be up next to the phone not below it." The new
   opening's paragraphs are short enough that the two together are about the phone's height. The
   picture spans both rows, and the button clears whichever is taller by the same 30px the second
   paragraph used to. */
@media (max-width:520px){
  .hero-copy .lede.turn{grid-column:1;grid-row:4;margin-top:var(--s-4)}
  .hero-phone{grid-row:3 / span 2}
  .hero-copy .btn-row{margin-top:30px}
}
/* "...and your books stay yours." stands 30px below the sentence it finishes, at every width.
   Steve, 2026-09-23. */
.hero .lede.turn .hl{display:block;margin-top:30px}
/* Half the room under "You buy it once" on a desktop, Steve 2026-09-23: 104px to 52px. */
@media (min-width:801px){ .hero{padding-bottom:52px} }
/* The new headline's two lines sit as close on a phone as on a desktop. Steve, 2026-09-23: "the
   space between the lines The paper chase and is over is too much... Not like that on DT". The 20px
   was set for the old headline, whose two lines were two sentences. */
@media (max-width:1024px){ .hero-copy h1 .hl{margin-top:0} }

/* The two looks beside "Serious work doesn't have to feel institutional." (index #look), 2026-09-23.
   Steve: the pictures and the switch "to the LEFT of the 'Serious work...' title and text - they'd
   have to be made smaller". Same parts as the tour's #looks at about half the width. On a phone the
   words come first, since the pictures are what they are talking about. */
[data-looks][data-look="light"] .look-frame .look-light{opacity:1}
.look-beside{
  display:grid;grid-template-columns:minmax(0,7fr) minmax(0,5fr);
  column-gap:var(--s-6);align-items:center;
}
.look-pics{grid-column:1;grid-row:1}
.look-copy{grid-column:2;grid-row:1}
.look-copy h3{margin:var(--s-5) 0 10px}
.look-copy p:not(.lede){color:var(--muted);font-size:15.2px;line-height:1.58}
.look-pics .look-switch{margin:0 0 var(--s-3)}
.look-pics .look-strip{gap:var(--s-3);margin-top:var(--s-3)}
.look-pics .look-strip figcaption{font-size:12.5px}
@media (max-width:900px){
  .look-beside{grid-template-columns:1fr;row-gap:var(--s-5)}
  .look-copy{grid-row:1;grid-column:1}
  .look-pics{grid-row:2;grid-column:1}
  .look-pics .look-switch{margin:0 auto var(--s-3)}
}
@media (max-width:760px){
  .look-pics .look-strip{grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s-2)}
  .look-pics .look-strip figcaption{display:none}
}
.look-copy h2{margin-bottom:var(--s-3)}
/* The switch centered over the large picture at every width, Steve 2026-09-23. */
.look-pics .look-switch{margin-left:auto;margin-right:auto}
/* Two lines, never three, Steve 2026-09-23: "force institutional onto the second line with have to
   feel. That really needs to be 2 lines max." The break is fixed, the second line never wraps, and
   the size follows the width so that line always fits its column (it needs 10.7 times the font
   size; the column is 420px at its widest and about 340 on a phone). */
.look-copy h2{font-size:clamp(28px,2.6vw,38px)}
.look-copy h2 span{white-space:nowrap}
/* The Business Centers paragraph under the two dashboards (index #dashboards), 2026-09-23. */

/* ONE RULE FOR EVERY ROW OF LINKS OUTSIDE A HERO, Steve 2026-09-23: "link 1 needs to be left
   aligned, 2 centered and 3 right aligned. Make this a rule sitewide. Symmetry. Symmetry. when
   there are only two links, one left and one right aligned on the element above them."
   Three links: three equal tracks, the middle one centered and the last against the right edge.
   Two links: the two edges, including under two columns of text, where the second link used to
   line up with the start of the right column (his 2026-09-17 ask, replaced by this one).
   Heroes keep their stacked links. Rows of one or of five are untouched. On a phone a row of
   three will not fit side by side, so it stacks, left aligned, like the text above it. */
.band .go-row:has(> :nth-child(3)):not(:has(> :nth-child(4))){
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));column-gap:var(--s-4);
}
.band .go-row:has(> :nth-child(3)):not(:has(> :nth-child(4))) > li:nth-child(2){justify-self:center;text-align:center}
.band .go-row:has(> :nth-child(3)):not(:has(> :nth-child(4))) > li:nth-child(3){justify-self:end;text-align:right}
.band .go-row:has(> :nth-child(2)):not(:has(> :nth-child(3))){display:flex;justify-content:space-between}
@media (max-width:760px){
  .band .go-row:has(> :nth-child(3)):not(:has(> :nth-child(4))){grid-template-columns:minmax(0,1fr)}
  .band .go-row:has(> :nth-child(3)):not(:has(> :nth-child(4))) > li{justify-self:start;text-align:left}
}
/* Under a bulleted list the first link keeps its 18px so it starts on the text, not the dash; the
   other two lose it, or the middle one sits 9px right of center. */
.plain.two + .go-row:has(> :nth-child(3)) > li:not(:first-child){padding-left:0}
/* The Jobs Center beside the Business Centers paragraph, Steve 2026-09-23: "needs a pic of one of
   the centers... Condense the horizontal width of the text to make it better fill the height of this
   pic... Always breathing room. Crowded is bad." The text runs narrow so it stands taller beside
   the picture, with a full step of air above and below. Its type is the dashboard blocks' own. */
.centers-beside{
  display:grid;grid-template-columns:minmax(0,4fr) minmax(0,5fr);
  column-gap:var(--s-7);align-items:center;margin:var(--s-7) 0;
}
.centers-beside figure{margin:0}
.centers-beside figcaption{margin-top:var(--s-3)}
@media (max-width:900px){
  .centers-beside{grid-template-columns:1fr;row-gap:var(--s-5);margin:var(--s-6) 0}
}
/* SAME COLUMN AS THE DASHBOARD PICTURES ABOVE IT, Steve 2026-09-23: "Same width as the other image"
   and its left edge not under the one before it. So on a wide screen this uses .split's own grid
   (two equal columns, 52px apart) and the picture fills the right column, exactly where the Full
   Edition dashboard sits, at every width. The words keep their narrow measure inside the left one. */
@media (min-width:901px){
  .centers-beside{grid-template-columns:minmax(0,1fr) minmax(0,1fr);column-gap:52px}
  .centers-beside .centers-note{max-width:23em}
}
/* THE WORDS ARE A .split-copy LIKE THE TWO DASHBOARD BLOCKS ABOVE THEM, Steve 2026-09-23: "the font
   sizes completely different than the preceeding section's text. They need to match, they're right
   next to each other." So the lead is that block's h3 and the rest is its paragraph, by the same
   rules, at every width. "Business Centers." never splits across lines. */
.centers-note{margin:0}
.centers-note h3 span{white-space:nowrap}
/* Cropped from the bottom to the dashboard pictures' own shape (2400 by 1500), so it stands exactly
   as tall as the one above it. Steve, 2026-09-23: "Don't resize the image any more - crop the
   vertical height (off of the bottom)". The zoom viewer still opens the whole picture. */
.centers-beside .shot img{display:block;width:100%;height:auto;aspect-ratio:2400 / 1500;object-fit:cover;object-position:top center}
/* EVERY CAPTION IS CENTERED ON ITS PICTURE, sitewide. Steve, 2026-09-23: "make sure the caption
   text of ALL images are centered on their image." */
figcaption{text-align:center}
/* The client's phone on intake.html had its caption BESIDE it (a flex row), so no alignment could
   center it on the picture. Under it now, the phone's own width, per the caption rule above. */
.request-phone{flex-direction:column;align-items:center;gap:0}
.request-phone figcaption{max-width:300px}

/* HOW IT FITS, SECOND PASS, Steve 2026-09-23. Five tiles on the left now, each with a stamp saying
   it is one more app, and "It never ends!" under them. The two sides are the same height, top and
   bottom: whichever side is naturally taller sets the height and the other spreads its rows to
   match, so the tiles and the Sync rows start and end on the same lines. */
.fits-apart{align-self:stretch;display:flex;flex-direction:column}
.fits-apart ol{flex:1;margin:0;display:flex;flex-direction:column;justify-content:space-between;gap:var(--s-3)}
.fits-one{align-self:stretch;display:flex;flex-direction:column}
.fits-one ul{flex:1;display:flex;flex-direction:column}
.fits-one li{flex:1;display:flex;align-items:center}
/* Each tile: the job, then its stamp on the line under it in the tile's bottom right corner, the
   same place in every tile, so five of them read as one repeated mark rather than five layouts. */
.fits-apart li{display:flex;flex-direction:column;justify-content:center;gap:var(--s-2)}
.fits-apart li .stamp{align-self:flex-end}
.fits-out{grid-row:2}
/* The stamp: a rubber stamp's red, a ruled border, capitals, a few degrees off true. No texture:
   section 2 bans grain overlays, and the tilt and the border are what read as "stamped". */
.stamp{
  font-family:var(--mono);font-size:10.5px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;
  color:var(--red);border:1.5px solid var(--red);border-radius:3px;padding:3px 8px;line-height:1.3;
  transform:rotate(-4deg);opacity:.85;white-space:nowrap;
}
.fits-apart li:nth-child(even) .stamp{transform:rotate(3deg)}
/* "It never ends!" in the hero's fine print style, right aligned under the last tile. */
.fits-never{grid-column:1;grid-row:2;margin:0;text-align:right;font-size:13.5px;color:var(--dim)}
@media (max-width:760px){
  .fits-apart ol{display:grid;grid-template-columns:1fr;gap:var(--s-2)}
  .fits-never{grid-row:auto}
  .fits-out{grid-row:auto}
}
@media (max-width:760px){ .fits-never{margin-bottom:var(--s-4)} }

/* The separate-tools price table on pricing.html (#stack), 2026-09-23. Figures right aligned so the
   columns of money line up; the two totals set apart by a rule and full-strength text; the Full
   Edition row last and in the text color, with nothing louder than that, because the gap in the
   numbers is the whole argument and needs no help. */
table.stack-cost{min-width:560px}
table.stack-cost td,table.stack-cost thead th:not(:first-child){text-align:right;white-space:nowrap;font-variant-numeric:tabular-nums}
table.stack-cost tbody th{font-weight:300;color:var(--body);text-align:left}
table.stack-cost tr.sum th,table.stack-cost tr.sum td{color:var(--text);font-weight:500}
table.stack-cost tr.sum:first-of-type th,table.stack-cost tr.sum:first-of-type td{border-top:1px solid var(--line-mid)}
table.stack-cost tr.ours th,table.stack-cost tr.ours td{color:var(--text);font-weight:700;border-top:1px solid var(--line-mid);border-bottom:0}
.stack-note{max-width:75ch;margin:var(--s-4) 0 0;font-size:13.5px;color:var(--dim)}
/* The left tiles 50px narrower on wide screens, Steve 2026-09-23, taken off their right side so
   the gap to the Sync box widens; "It never ends!" stays on the tiles' right edge. */
@media (min-width:761px){
  .fits-apart ol{margin-right:50px}
  .fits-never{margin-right:50px}
}
/* "It never ends!" in the same color as "Then out to", Steve 2026-09-23: "so it's more visible". */
.fits-never{color:var(--muted)}
/* 20px of that back: 30px narrower than the column, not 50. Steve: "That's too narrow." */
@media (min-width:761px){
  .fits-apart ol{margin-right:30px}
  .fits-never{margin-right:30px}
}
/* The stamps keep Steve's own case since 2026-09-23 ("Keep the case as I have it here"). */
.stamp{text-transform:none;letter-spacing:.06em}
/* THIRD PASS, Steve 2026-09-23: nine rows on the Sync side now, and the tiles are "center aligned
   with the ones on the right but that doesn't mean make the groups the same exact height. So don't
   grow that any more." So nothing stretches: each side keeps its natural height, and the tiles are
   centered on the Sync box. The closing line hangs under the last tile without counting toward the
   centering, so it is the tiles themselves that sit on the box's middle. */
.fits-one ul{flex:none;display:block}
.fits-one li{flex:none}
.fits-apart ol{flex:none;justify-content:flex-start;margin-right:0}
.fits-stack{margin:auto 0}
.fits-stack .fits-never{grid-row:auto;grid-column:auto;margin:var(--s-3) 0 0}
@media (min-width:761px){
  .fits-stack{position:relative;margin-right:30px}
  .fits-stack .fits-never{position:absolute;top:100%;right:0;white-space:nowrap}
}

/* EACH SYNC ROW IN ITS OWN SOFT COLOR, Steve 2026-09-23: "I want each line on the Sync side to be a
   different color. But I want softer colors so they're not rambunctious, just some soft color with
   some gradient touches." A NAMED EXCEPTION to section 0's rule that a ledger hue appears only where
   it names a ledger, at his word; DESIGN_RULES.md records it. The hues are the app's own, mixed down
   to a wash that fades out across the row, a thin edge on the left, and the bold words tinted a
   little toward their row's color. Nothing here is a button or a headline, which section 2 guards. */
.fits-one li{
  --tint:var(--muted);
  background:linear-gradient(90deg,
    color-mix(in srgb,var(--tint) 13%,transparent) 0%,
    color-mix(in srgb,var(--tint) 4%,transparent) 55%,
    transparent 100%);
  box-shadow:inset 2px 0 0 color-mix(in srgb,var(--tint) 55%,transparent);
}
.fits-one li b{color:color-mix(in srgb,var(--tint) 35%,var(--text))}
.fits-one li:nth-child(1){--tint:var(--compliance)}
.fits-one li:nth-child(2){--tint:var(--mileage)}
.fits-one li:nth-child(3){--tint:var(--income)}
.fits-one li:nth-child(4){--tint:var(--taxdocs)}
.fits-one li:nth-child(5){--tint:var(--utilities)}
.fits-one li:nth-child(6){--tint:var(--receipts)}
.fits-one li:nth-child(7){--tint:var(--quotes)}
.fits-one li:nth-child(8){--tint:var(--red)}
.fits-one li:nth-child(9){--tint:var(--muted)}
/* The box's rounded corners clip the first and last rows' washes. */
.fits-one ul{overflow:hidden}
/* "...and plenty more" right aligned in its row, Steve 2026-09-23. */
.fits-one li:last-child{justify-content:flex-end}
/* The wash moved to the RIGHT end of each row and the edge with it, Steve 2026-09-23: "it makes
   the text hard to read". The words now sit on plain ground. And "vary the colors more": the order
   below never puts two neighboring hues side by side (blue, gold, pink, cyan, orange, purple,
   green, red), and the ends are a touch stronger now that they are out from under the text. */
.fits-one li{
  background:linear-gradient(270deg,
    color-mix(in srgb,var(--tint) 20%,transparent) 0%,
    color-mix(in srgb,var(--tint) 6%,transparent) 35%,
    transparent 65%);
  box-shadow:inset -3px 0 0 color-mix(in srgb,var(--tint) 65%,transparent);
}
.fits-one li:nth-child(1){--tint:var(--compliance)}
.fits-one li:nth-child(2){--tint:var(--taxdocs)}
.fits-one li:nth-child(3){--tint:var(--receipts)}
.fits-one li:nth-child(4){--tint:var(--mileage)}
.fits-one li:nth-child(5){--tint:var(--utilities)}
.fits-one li:nth-child(6){--tint:var(--quotes)}
.fits-one li:nth-child(7){--tint:var(--income)}
.fits-one li:nth-child(8){--tint:var(--red)}
.fits-one li:nth-child(9){--tint:var(--muted)}
/* Back to the first pass's strength, from the right: "just a hint of the underlying colors".
   Steve, 2026-09-23. */
.fits-one li{
  background:linear-gradient(270deg,
    color-mix(in srgb,var(--tint) 13%,transparent) 0%,
    color-mix(in srgb,var(--tint) 4%,transparent) 45%,
    transparent 100%);
  box-shadow:inset -2px 0 0 color-mix(in srgb,var(--tint) 55%,transparent);
}
/* Barely there, Steve 2026-09-23: "the right side is too bright... In the original, the gradient was
   extremely slight over that one color." A faint tint over the box's own ground, no colored edge. */
.fits-one li{
  background:linear-gradient(270deg,
    color-mix(in srgb,var(--tint) 7%,transparent) 0%,
    color-mix(in srgb,var(--tint) 2%,transparent) 50%,
    transparent 100%);
  box-shadow:none;
}
/* Halved again: "still too much". */
.fits-one li{
  background:linear-gradient(270deg,
    color-mix(in srgb,var(--tint) 3.5%,transparent) 0%,
    color-mix(in srgb,var(--tint) 1%,transparent) 50%,
    transparent 100%);
}
/* THE FIVE POINTS BREAK ON PURPOSE, Steve 2026-09-23: "three of the lines have a link. The line
   should break at the link both on mobile and on DT. For the others, make the lines break at a
   point where they all feel and look even." So each link starts its own line wherever it is shown,
   the other two break between their two halves (a <br> in the markup), and whatever still wraps
   on a narrow screen is balanced rather than left with one word on its last line. */
.cards-beside .more{display:block}
.cards-beside ul.plain > li > div{text-wrap:balance}
/* Shown on a phone held upright too, since 2026-09-23: "please restore those so I can see how it
   looks now that we added the breaks." They were hidden under 620px on 2026-09-21, when the points
   were longer and ran taller than the picture. */
@media (max-width:1000px){ .cards-beside .more{display:block} }

/* THE PRICE TAGS on the left tiles, Steve 2026-09-23. The monthly fee sits on the job's own line,
   against the right edge, opposite the stamp below it: each tile reads "this job, this bill, another
   app". The running total under the tiles links to the table the figures come from. */
.tile-top{display:flex;justify-content:space-between;align-items:baseline;gap:var(--s-3)}
.fee{font-family:var(--mono);font-size:13px;color:var(--text);white-space:nowrap;font-variant-numeric:tabular-nums}
.fits-sum{margin:var(--s-1) 0 0;text-align:right;font-size:13.5px}
.fits-sum a{color:var(--accent)}
@media (min-width:761px){
  .fits-stack .fits-sum{position:absolute;right:0;top:calc(100% + var(--s-3) + 1.6em);white-space:nowrap}
}
.stack-sources{margin-top:var(--s-3)}
.stack-sources a{color:var(--muted)}
/* The price-tag drawing, its colors and the two-column tile tried after this were all taken back the
   same evening. Steve: "It was better without the tags." The fee is plain figures again with the
   stamp right below it. */

/* THE PRICE TABLE READS AS A BILL, THEN THE ANSWER, THEN WHAT YOU KEEP. Steve, 2026-09-23, "Do all
   three": the four separate tools a step quieter; the two "separate tools" totals in the stamps' red;
   the Global Office: Sync row wearing its own logo, a soft wash of the Full Edition green from the
   right and its figures in that green; and a last row for the difference. --ed-full outside a Buy
   button is a NAMED EXCEPTION, recorded in DESIGN_RULES section 0: this row names that edition. */
table.stack-cost tbody tr:not(.sum):not(.ours):not(.keep) td{color:var(--dim)}
table.stack-cost tr.sum td{color:color-mix(in srgb,var(--red) 80%,var(--text))}
table.stack-cost tr.ours th,table.stack-cost tr.ours td,table.stack-cost tr.keep th,table.stack-cost tr.keep td{
  background:linear-gradient(270deg,color-mix(in srgb,var(--ed-full) 12%,transparent),color-mix(in srgb,var(--ed-full) 3%,transparent));
}
table.stack-cost tr.ours th{background:color-mix(in srgb,var(--ed-full) 3%,transparent)}
table.stack-cost tr.ours td{color:var(--ed-full)}
table.stack-cost tr.ours th{display:flex;align-items:center;gap:var(--s-2);flex-wrap:wrap}
table.stack-cost .row-mark{display:block;width:200px;height:auto}
table.stack-cost tr.ours th span{font-weight:700;color:var(--text)}
table.stack-cost tr.keep th,table.stack-cost tr.keep td{color:var(--text);font-weight:700;font-size:15.5px;border-top:1px solid color-mix(in srgb,var(--ed-full) 40%,transparent)}
table.stack-cost tr.keep td{color:var(--ed-full-hover)}
table.stack-cost tr.keep th{background:color-mix(in srgb,var(--ed-full) 3%,transparent)}
/* One wash across each green row rather than one per cell, which banded. The logo carries only the
   wordmark, so the edition is named in words beside it. */
table.stack-cost tr.ours,table.stack-cost tr.keep{
  background:linear-gradient(270deg,color-mix(in srgb,var(--ed-full) 12%,transparent),color-mix(in srgb,var(--ed-full) 2%,transparent) 70%);
}
table.stack-cost tr.ours th,table.stack-cost tr.ours td,table.stack-cost tr.keep th,table.stack-cost tr.keep td{background:transparent}

/* THE REVELATION, Steve 2026-09-23: "make the what you keep look like a Revelation. Angels singing."
   The last row opens up: the display face at headline size, the edition's own green, a band of light
   falling from above onto the figures (a still radial wash, no motion, no blur behind any headline),
   and a bright green rule across its top like the edge of an opened door. */
table.stack-cost tr.keep{
  background:
    radial-gradient(ellipse 70% 140% at 65% 0%,color-mix(in srgb,var(--ed-full) 30%,transparent),transparent 70%),
    linear-gradient(180deg,color-mix(in srgb,var(--ed-full) 14%,transparent),color-mix(in srgb,var(--ed-full) 4%,transparent));
}
table.stack-cost tr.keep th,table.stack-cost tr.keep td{
  padding-top:var(--s-5);padding-bottom:var(--s-5);
  border-top:2px solid var(--ed-full);
}
table.stack-cost tr.keep th{
  font-family:var(--display);font-size:clamp(18px,1.7vw,22px);font-weight:700;color:var(--text);
  letter-spacing:-.01em;
}
table.stack-cost tr.keep td{
  font-family:var(--display);font-size:clamp(22px,2.4vw,32px);font-weight:800;letter-spacing:-.02em;
  color:color-mix(in srgb,var(--ed-full-hover) 70%,var(--text));
}
/* On a phone the table scrolls sideways; the labels keep a readable width and the revelation's
   figures come down a size so they do not squeeze the labels into a column of single words. */
@media (max-width:760px){
  table.stack-cost thead th:first-child,table.stack-cost tbody th{min-width:12em}
  table.stack-cost tr.keep td{font-size:21px}
  table.stack-cost tr.keep th{font-size:17px}
}
/* The revelation, taken down: "the revelation is too big. way too big." Same light and color, at
   the size of the totals above it, a step bolder. */
table.stack-cost tr.keep th,table.stack-cost tr.keep td{padding-top:var(--s-4);padding-bottom:var(--s-4)}
table.stack-cost tr.keep th{font-size:16px}
table.stack-cost tr.keep td{font-size:18px}
@media (max-width:760px){ table.stack-cost tr.keep td{font-size:17px} table.stack-cost tr.keep th{font-size:15.5px} }
/* ONE GREEN, NOT FIVE. Steve 2026-09-23: "it looks like we're in a race to see how many different
   shades of GREEN we can use... a bit too much green." The Global Office: Sync row goes back to plain
   white on the table's own ground; the only green in the table is What you keep, in the edition's
   one green (the same as its Buy button), with a softer wash and a thinner edge. */
table.stack-cost tr.ours{background:none}
table.stack-cost tr.ours th,table.stack-cost tr.ours td{background:none;color:var(--text)}
table.stack-cost tr.keep{
  background:linear-gradient(180deg,color-mix(in srgb,var(--ed-full) 9%,transparent),color-mix(in srgb,var(--ed-full) 3%,transparent));
}
table.stack-cost tr.keep th,table.stack-cost tr.keep td{border-top:1px solid color-mix(in srgb,var(--ed-full) 60%,transparent)}
table.stack-cost tr.keep td{color:var(--ed-full)}
/* THE THREE BUTTONS STAND LEVEL BY CONSTRUCTION, Steve 2026-09-23 and again 2026-10-05 ("It keeps
   happening every time a change is made... it's sloppy"). It used to be an invisible spacer line on
   Solo's card standing in for the "or $X a month" line the other two had, so the moment those lines
   changed, Solo's button moved. Now the button is always the LAST thing in its card: any note
   renders above it (column-reverse), and the block sits at the card's foot, so the three buttons
   share a bottom edge whatever text any card carries. check_site_renders.mjs fails if they don't. */
.plan .plan-cta{display:flex;flex-direction:column-reverse}
/* NOTHING SITS IN A CENTERED COLUMN, Steve 2026-09-23, on the pricing page: "that and the sections
   under it are all center aligned and shouldn't be." A .wrap.narrow was a 760px box centered on the
   page, so its left edge sat well inside every other section's. It now keeps the page's own left
   edge and holds its CONTENTS to the same 760px measure. Every page that used it gets the same. */
.wrap.narrow{max-width:var(--maxw)}
.wrap.narrow > *{max-width:760px}

/* THE HERO HEADLINE WAS SMALLER THAN THE NEXT SECTION'S (2026-09-23, Steve, phone sideways). The
   fixed 27px and 30px above were set when the hero sat alone; the section headings grow with the
   window (3.8vw), so on a phone turned sideways and on a tablet near 900px the "How it fits" heading
   out-sized "The paper chase". The hero now grows with the window too, always about a fifth larger. */
@media (min-width:521px) and (max-width:900px), (max-width:1024px) and (max-height:600px){
  .hero-copy h1{font-size:clamp(30px,4.6vw,42px)}
}
/* Sideways, the taller headline pushes the words down, so the picture drops by the same amount and
   still starts level with the first paragraph. */
@media (max-width:1024px) and (max-height:600px){
  .hero-phone{margin-top:calc(130px + max(0px, 9.06vw - 52px))}
}

/* THE TAGLINE above Where this sits, Steve 2026-09-23: "a 'tagline' right above the 'Where this
   sits' box", with 20-40px between them and breathing room all around. Sized by eye: filled to one
   line (22px), 30% down, 15% back up to about 17.8px, then set at 19px by Steve. The size is the
   column's width over a fixed divisor (100cqw / 56.4), 19px at full width and no more; on a
   phone it stops at 17px and wraps, balanced. The h3 size of "The whole practice, with no client
   picked" (21px) was tried after and was "just a shade too big". */
/* Breathing room all around (Steve): 84px above from "Then out to", 20px down to the box. The line
   was 64/40 until Steve moved it "about half as close to the box" with the box left where it was. */
.tagline-box{container-type:inline-size;margin-top:calc(var(--s-6) + 20px)}
.tagline-box .tagline{
  font-family:var(--display);font-variation-settings:'opsz' 40;font-weight:600;letter-spacing:-.015em;
  color:var(--text);line-height:1.2;margin:0;text-wrap:balance;
  font-size:clamp(17px,calc(100cqw / 56.4),19px);
}
#how .tagline-box + .notice{margin-top:20px}
/* Centered on the Where this sits box beneath it, Steve 2026-09-23. Both span the same column. */
.tagline-box .tagline{text-align:center}
/* On a phone the tagline takes two lines and no more, Steve 2026-09-23: the size is set from the
   column's width (twice the width over the line's measured length, with room for where the words
   break), so a narrower phone gets a slightly smaller line rather than a third one. */
@media (max-width:760px){ .tagline-box .tagline{font-size:min(17px,calc(200cqw / 51))} }
/* The italic leans into the space after it, so "disconnected per-client" read as one word (Steve,
   2026-09-23). A sliver of room on its right gives the space back; 0.15em is about 3px at 19px. */
.tagline-box .tagline em{margin-right:.15em}
/* "Sync" in the logo's own green inside a heading, Steve 2026-09-23, on the Contractors page's "So is
   Global Office: Sync". A named exception to --ed-full being for the buy buttons and the price
   table's What you keep row only; it is the wordmark's color on the wordmark's word. */
.logo-green{color:var(--ed-full)}
/* A phrase held on one line anywhere it is marked, not only in the front page tiles: the Contractors
   heading keeps "no problem" together on a phone (2026-09-23). */
.nw{white-space:nowrap}

/* "The receipt's in the van, no problem" on one line on a phone, Steve 2026-09-23: "It's sloppy
   looking as it is now." At heading size it needs about 400px and an iPhone column is about 340, so
   on a phone this one heading is sized from the column: the line measures 15.35 times its font size,
   and 15.6 leaves a little room. 26px wherever it already fits. */
@media (max-width:520px){ .van-head{font-size:min(26px,calc((100vw - 48px) / 15.6))} }

/* THE THREE PHONES STAY THREE ACROSS, Steve 2026-09-23: in landscape they fell to two and then one
   alone on the left. They now sit side by side in portrait and landscape, landscape a little larger
   because there's the width for it, and sized so the whole phone fits a sideways screen's height. */
@media (max-width:860px){
  .phones{grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s-3);align-items:start}  /* tops level: the captions differ in length */
  .phones figcaption{font-size:12px;line-height:1.4}
}
@media (max-width:1024px) and (max-height:600px){
  .phones{grid-template-columns:repeat(3,minmax(0,170px));justify-content:center;gap:var(--s-5)}
  .phones figcaption{font-size:12.5px}
}
/* THE FOOTER LINE ON TWO LINES, Steve 2026-09-23: "It needs to be no more than two lines and aligned
   with that little logo." It had picked up the front-page tagline's centered display type through the
   shared class name; that rule is scoped to .tagline-box now, so this is its own Inter again, left
   on the logo's edge, wide enough for two lines. On a phone it's set a touch smaller to keep two. */
.site-foot .tagline{max-width:60ch}
@media (max-width:560px){ .site-foot .tagline{font-size:12px;max-width:none} }
/* THE THREE PRICE CARDS START THEIR LINES LEVEL, Steve 2026-09-23: "make sure they're dead even."
   The Global Office: Sync wordmark is shorter than the two stamped ones, so its line sat 14px
   higher; it gets the same space under its logo as they do. */
.plan#bookkeeper .edition-mark{margin-bottom:calc(var(--s-3) + 14px)}

/* THE MIXED PILE on intake.html, 2026-09-23: the small upload card sits under its paragraph rather
   than as a third full-size picture, so the three screenshots read as drop, upload, choose. */
.pile-upload{max-width:360px;margin:var(--s-4) 0 0}
/* The drop box is a tall, narrow window: held to 380px so it doesn't tower over its paragraph. */
.pile-drop{max-width:380px;justify-self:center;width:100%}
.pile-drop .shot img{display:block;width:100%;height:auto}

/* The Information Center card that says a client's documents have arrived (Bookkeepers #client-docs,
   Tour). A narrow panel crop at 2x, so it is held near its natural width rather than stretched. */
.request-card{ margin:0; display:flex; justify-content:center }
.request-card .shot{ width:100%; max-width:400px }

/* A ROW OF FOUR LINKS, 2026-09-23, when "How Sync uses AI" became the fourth under the front page's
   boundaries. The same symmetry rule as three: first against the left edge, last against the right,
   the middle two spread evenly between. Below 1000px four labels this long don't fit on one line,
   so they stack, left aligned, as a row of three does on a phone. */
.band .go-row:has(> :nth-child(4)):not(:has(> :nth-child(5))){
  display:flex;flex-wrap:nowrap;justify-content:space-between;column-gap:var(--s-4);
}
@media (max-width:999px){
  .band .go-row:has(> :nth-child(4)):not(:has(> :nth-child(5))){flex-direction:column;align-items:flex-start}
  /* Stacked under a bulleted list, every link starts on the text, not only the first. */
  .plain.two + .go-row:has(> :nth-child(4)):not(:has(> :nth-child(5))) > li{padding-left:18px}
}

/* THE BETA TESTERS' HOME BASE (beta.html, betabuy.html until 2026-10-13), Steve 2026-10-06: an index testers come back to
   mid-task, mostly on a phone. Each line is the feature's name as a link, and under it the line or
   two that says what it does. */
.plain.home-base li{margin-bottom:14px}
.plain.home-base li a{color:var(--accent);font-weight:600;text-decoration:none}
.plain.home-base li a::after{content:"\00a0\2192";font-weight:400}
.plain.home-base li a:hover{color:var(--text)}
.plain.home-base li span{display:block;margin-top:2px}
/* The beta code box on beta.html, opened by either Buy button (Steve, 2026-10-06). */
.nav button.btn-primary{color:var(--ink-on-accent)}
.code-box{margin-top:var(--s-4);max-width:560px;padding:20px 22px;background:var(--card);border:1px solid var(--line);border-radius:var(--radius)}
.code-box label{display:block;font-weight:600;color:var(--text);margin-bottom:10px}
.code-row{display:flex;gap:10px;flex-wrap:wrap}
.code-row input{flex:1 1 200px;min-width:0;font:inherit;font-size:16px;color:var(--text);background:var(--bg-alt);border:1px solid var(--line);border-radius:10px;padding:11px 14px;letter-spacing:.04em}
.code-row input:focus{outline:2px solid var(--accent);outline-offset:1px;border-color:transparent}
.code-row .btn{flex:0 0 auto}
.code-row .btn[disabled]{opacity:.6;cursor:default}
.code-hint{margin-top:10px;font-size:14px;color:var(--muted)}
.code-error{margin-top:8px;font-size:14.5px;color:var(--text)}
@media (max-width:520px){ .code-row .btn{flex:1 1 100%} }
/* VIDEO 2 BESIDE THE WELCOME on beta.html, Steve 2026-10-10: the h1 keeps its full width, and
   under it the welcome text narrows to the left column with the video on the right. Stacked on a
   phone, the video comes first. The frame is a placeholder until the video is recorded. */
.hero-video{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:52px;align-items:start}
.hero-video > *{min-width:0}
/* The video sits in the middle of the left column's height, Steve 2026-10-10 ("bring the video down
   just a touch so it's roughly in the middle of that section"), not level with the first line. The
   lede's own 16px top margin moves to the grid so the left column's height is just its content. */
.hero-video{margin-top:16px}
.hero-video .lede{max-width:none;margin-top:0}
.hero-video .video-slot{align-self:center}
.video-slot{margin:0;position:relative;aspect-ratio:16/9;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:14px;background:var(--card);border:1px solid var(--line);border-radius:var(--radius)}
.video-play{width:64px;height:64px;border-radius:50%;border:2px solid var(--accent);position:relative}
.video-play::after{content:"";position:absolute;left:25px;top:19px;border-style:solid;border-width:13px 0 13px 21px;border-color:transparent transparent transparent var(--accent)}
.video-slot figcaption{font-size:14.5px;color:var(--muted)}
@media (max-width:900px){
  .hero-video{grid-template-columns:minmax(0,1fr);gap:var(--s-4)}
  .hero-video .video-slot{order:-1}
}
/* Trust and safety on beta.html stays the site's --taxdocs gold. Steve tried the app's brighter
   Tax Docs yellow and preferred the gold, 2026-10-06: "I like it better than that bright yellow". */
/* 2026-10-06: version bumped after the edge cached an older site.css under ?v=2fbde6f0. */

/* ------------------------------------------------ a beta tester's questionnaire */
/* beta-questions.html, at go-sync.app/beta/questions/, Steve 2026-10-13: "I want text boxes after
   every question so I can type the answers in detail." Long answers are expected, so each box starts
   about eleven lines tall, grows with what's typed (js/questions.js) and can be dragged taller. The
   save status is a quiet pill in the corner, never a banner. */
.q-intro .q-intro-more{margin-top:14px;color:var(--body);max-width:62ch}
.q-intro .lede{max-width:62ch}
.q-band{padding-top:var(--s-5)}
.q-group + .q-group{margin-top:var(--s-6)}
.q-item{margin-top:var(--s-5)}
.q-text{display:block;margin-bottom:12px;font-size:18px;line-height:1.5;font-weight:500;color:var(--text)}
.q-n{color:var(--accent);font-variant-numeric:tabular-nums}
.q-box{
  display:block;width:100%;min-height:11em;resize:vertical;
  font:inherit;font-size:17px;line-height:1.6;color:var(--text);
  background:var(--bg-alt);border:1px solid var(--line);border-radius:12px;padding:14px 16px;
}
.q-box:focus{outline:2px solid var(--accent);outline-offset:1px;border-color:transparent}
.q-box[readonly]{background:var(--card);color:var(--body);resize:none}
.q-box[readonly]:focus{outline-color:var(--line-mid)}
.q-hint{margin-top:12px;font-size:14.5px;color:var(--muted)}
.q-sheet{margin-top:var(--s-5);padding:24px 22px;background:var(--card);border:1px solid var(--line);border-radius:var(--radius)}
.q-sheet h2{font-size:clamp(22px,2.6vw,28px)}
.q-sheet-lede{margin-top:12px;color:var(--body);max-width:68ch}
.q-sheet .stack-note b{color:var(--text)}
.q-send{margin-top:var(--s-6);padding-top:var(--s-5);border-top:1px solid var(--line)}
.q-confirm p{color:var(--body)}
.q-confirm p b{color:var(--text)}
.q-confirm .btn-row{margin-top:16px}
.q-confirm .btn[disabled]{opacity:.6;cursor:default}
.q-send-error{margin-top:12px;font-size:15px;color:var(--text)}
.q-status{
  position:fixed;right:16px;bottom:calc(16px + env(safe-area-inset-bottom, 0px));z-index:30;margin:0;
  padding:7px 14px;font-size:14px;color:var(--muted);background:var(--card-2);
  border:1px solid var(--line);border-radius:999px;
}
@media (max-width:520px){ .q-sheet{padding:20px 16px} .q-text{font-size:17px} }
