/* =========================================================
   Devoted Books & Tax Prep
   Design system: "the ledger, kept by hand"

   Linen paper, ruled hairlines, ink, brass, moss green, and a
   bookkeeper's pencil in the margin. Every color on the site is a
   token declared here. No page markup carries a raw hex value.

   Contrast law (the values are measured, not guessed):
     ink on linen      16.6:1   body text anywhere on light
     fern on linen      5.1:1   secondary text on light
     fern on sand       4.6:1   secondary text on the tint ground
     copper on linen    5.7:1   the pencil, safe at body size
     moss on linen      8.5:1   headings that need emphasis
     paper on moss      9.2:1   body text on the dark ground
     brass on moss      3.4:1   LARGE TEXT ONLY on moss, plus hairlines
     ink on brass       6.0:1   the solid button in a moss context
   Brass is never body-size text on a light ground (2.6:1). It is a
   hairline, a tick, an underline, or a button ground, and nothing else.
   Focus rings are ink on light and brass on moss.
   ========================================================= */

/* The wordmark script. It arrives by @import rather than by a link
   tag in the head so the lockup could land without touching the head
   of thirteen already-built pages. It is the only import in the file
   and the only font not in the page head. */
@import url("https://fonts.googleapis.com/css2?family=Pinyon+Script&display=swap");

/* =========================================================
   1. Tokens
   ========================================================= */
:root{
  /* Palette, from the spec table. Do not add a tenth color. */
  --linen:  #F4EFE6;   /* page ground */
  --paper:  #FBF8F2;   /* panels and dialogs */
  --sand:   #EAE2D3;   /* alternating tint ground */
  --ink:    #1E1B17;   /* primary text, solid buttons on light */
  --moss:   #2F4A3A;   /* dark grounds, emphatic headings */
  --fern:   #4E6B57;   /* secondary text on light, hover states */
  --brass:  #B8935A;   /* hairlines, ticks, underlines, quote marks */
  --copper: #94482F;   /* the pencil: hand notes, one warm accent */
  --rose:   #D9B2A3;   /* decoration only, at most twice per page */

  /* One hover step off ink and off brass. Not new colors: the same
     two, lifted, so a button has somewhere to go under the cursor. */
  --ink-lift:   #34302A;
  --brass-lift: #C9A76F;

  /* rgb triples for the few places an alpha is needed */
  --ink-rgb:    30, 27, 23;
  --moss-rgb:   47, 74, 58;
  --brass-rgb:  184, 147, 90;
  --copper-rgb: 148, 72, 47;
  --rose-rgb:   217, 178, 163;
  --paper-rgb:  251, 248, 242;
  --sand-rgb:   234, 226, 211;

  /* Semantic roles.

     Every component reads these and never a palette token directly,
     which is what lets a surface change the whole cast of a subtree
     in one place. A dark ground redefines them; a paper panel
     sitting on that dark ground redefines them straight back, so a
     footnote inside a panel on moss is never paper on paper. */
  --ground:        var(--linen);
  --ground-panel:  var(--paper);
  --text:          var(--ink);      /* body */
  --text-soft:     var(--fern);     /* secondary prose */
  --text-fine:     var(--fern);     /* captions, labels, footnotes */
  --heading:       var(--ink);
  --link:          var(--copper);
  --link-hover:    var(--ink);
  --hand-ink:      var(--copper);   /* the pencil */
  --tick-ink:      var(--copper);
  /* The wordmark ink. Ink, not fern: the brief asked for a soft warm
     charcoal and ink is exactly that, a near-black carrying brown
     rather than blue. Fern is a green and would read as a green
     wordmark, not a charcoal one. Pinyon Script is a hairline script,
     so ink at full strength still lands soft on linen. */
  --wordmark-ink:       var(--ink);
  --wordmark-ink-hover: var(--fern);
  --rule:          rgba(var(--ink-rgb), .16);
  --rule-brass:    rgba(var(--brass-rgb), .55);
  --rule-strong:   rgba(var(--ink-rgb), .28);
  --focus:         var(--ink);

  --solid-bg:       var(--ink);
  --solid-fg:       var(--paper);
  --solid-bg-hover: var(--moss);
  --ghost-fg:       var(--ink);
  --ghost-border:   var(--rule-strong);
  --ghost-wash:     rgba(var(--ink-rgb), .04);

  /* type */
  --font-display: "Fraunces", "Iowan Old Style", Georgia, "Times New Roman", serif;
  --font-script: "Pinyon Script", "Snell Roundhand", "Apple Chancery", Georgia, serif;
  --font-body: "Figtree", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-hand: "Nanum Pen Script", "Bradley Hand", "Segoe Script", cursive;

  /* Fluid scale. Every step is a clamp, so nothing is set twice. */
  --fs-hero:  clamp(2.75rem, 1.9rem + 3.7vw, 5.25rem);
  --fs-h1:    clamp(2.25rem, 1.72rem + 2.3vw, 3.75rem);
  --fs-h2:    clamp(1.75rem, 1.42rem + 1.45vw, 2.75rem);
  --fs-h3:    clamp(1.1875rem, 1.09rem + 0.42vw, 1.5rem);
  --fs-lede:  clamp(1.0625rem, 1rem + 0.45vw, 1.3125rem);
  --fs-body:  clamp(1rem, 0.965rem + 0.16vw, 1.0625rem);
  --fs-small: 0.875rem;
  --fs-fine:  0.8125rem;
  --fs-fig:   clamp(2rem, 1.5rem + 2.1vw, 3.25rem);
  --fs-hand:  clamp(1.375rem, 1.2rem + 0.75vw, 1.75rem);

  --lh-tight: 1.08;
  --lh-head:  1.14;
  --lh-body:  1.68;

  /* measure */
  --measure:      64ch;
  --measure-tight: 48ch;

  /* spacing */
  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px;
  --s5: 24px; --s6: 32px; --s7: 48px; --s8: 64px;
  --s9: 96px;
  --section-y: clamp(56px, 4.5vw + 34px, 116px);
  --inner: 1180px;
  --gutter: clamp(20px, 4vw, 56px);

  /* the one shadow allowed */
  --shadow: 0 6px 18px rgba(var(--ink-rgb), .12);

  --radius: 3px;          /* buttons and inputs: squared, never pills */
  --radius-pill: 999px;   /* the hero sticker, and nothing else */

  --ease-out: cubic-bezier(.22, .61, .36, 1);
  --ease-pen: cubic-bezier(.6, 0, .3, 1);
}

/* =========================================================
   2. Reset and base
   ========================================================= */
*, *::before, *::after{ box-sizing: border-box; }

html{
  /* Load-bearing for the header condense: scroll anchoring feeds the
     header height change back into scrollY and the bar oscillates. */
  overflow-anchor: none;
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}
@media (prefers-reduced-motion: reduce){
  html{ scroll-behavior: auto; }
}

body{
  margin: 0;
  background: var(--ground);
  color: var(--text);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  font-weight: 400;
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

img, svg, video{ max-width: 100%; }
img{ height: auto; display: block; }

h1, h2, h3, h4{
  font-family: var(--font-display);
  color: var(--heading);
  font-weight: 500;
  line-height: var(--lh-head);
  margin: 0 0 var(--s4);
  letter-spacing: -0.012em;
  /* opsz keeps the serifs open at display size; SOFT rounds the
     terminals, which is where the warmth in this face lives. */
  font-variation-settings: "opsz" 96, "SOFT" 60;
}
h1{ font-size: var(--fs-h1); line-height: var(--lh-tight); }
h2{ font-size: var(--fs-h2); }
h3{ font-size: var(--fs-h3); font-weight: 500; font-variation-settings: "opsz" 28, "SOFT" 40; }
h4{ font-size: 1.0625rem; font-variation-settings: "opsz" 18, "SOFT" 40; }

p{ margin: 0 0 var(--s4); }
p:last-child{ margin-bottom: 0; }

a{ color: var(--link); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover{ color: var(--link-hover); }

ul, ol{ margin: 0 0 var(--s4); padding-left: 1.15em; }
li{ margin-bottom: var(--s2); }

strong{ font-weight: 600; }
small{ font-size: var(--fs-small); }

hr{
  border: 0;
  border-top: 1px solid var(--rule);
  margin: var(--s6) 0;
}

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

::selection{ background: rgba(var(--brass-rgb), .34); }

/* =========================================================
   3. Utility text
   ========================================================= */
.lede{
  font-size: var(--fs-lede);
  line-height: 1.6;
  color: var(--text-soft);
  max-width: 52ch;
}
.measure{ max-width: var(--measure); }
.measure-tight{ max-width: var(--measure-tight); }
.prose{ max-width: var(--measure); }
.prose p + p{ margin-top: 0; }
.prose p{ margin-bottom: var(--s5); }

/* Two spacing utilities, so a page never carries an inline style */
.stack-top{ margin-top: var(--s7); }
.stack-top-sm{ margin-top: var(--s6); }

.soft{ color: var(--text-soft); }
.fine{ font-size: var(--fs-fine); color: var(--text-fine); line-height: 1.55; }

/* The label that goes wherever a figure or a price is an illustration
   rather than one of Rachel's own numbers. Never omit it. */
.sample-note{
  display: block;
  font-size: var(--fs-fine);
  line-height: 1.5;
  color: var(--text-fine);
  font-style: italic;
  margin-top: var(--s3);
}
.sample-note::before{
  content: "";
  display: inline-block;
  width: 18px;
  height: 1px;
  background: var(--brass);
  vertical-align: middle;
  margin-right: 8px;
}

.visually-hidden{
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* =========================================================
   4. Skip link
   ========================================================= */
.skip-link{
  position: absolute;
  top: -60px;
  left: var(--gutter);
  z-index: 200;
  background: var(--ink);
  color: var(--paper);
  padding: 10px 18px;
  border-radius: var(--radius);
  text-decoration: none;
  font-weight: 500;
  transition: top .18s var(--ease-out);
}
.skip-link:focus{ top: 12px; color: var(--paper); }

/* =========================================================
   5. Layout: sections and the three grounds
   ========================================================= */
.section{
  position: relative;
  padding: var(--section-y) 0;
  background: var(--linen);
}
.section-inner{
  width: 100%;
  max-width: var(--inner);
  margin: 0 auto;
  padding: 0 var(--gutter);
}
.section-inner--narrow{ max-width: 860px; }

/* Grounds alternate down a page so every seam is a change of paper.
   Declare one on every section, in the markup, so the sequence is
   readable without running the page. */
.ground-page{ background: var(--linen); }
.ground-tint{ background: var(--sand); }
.ground-paper{ background: var(--paper); }
/* The one dark ground. It changes nothing but the semantic tokens,
   so anything nested inside it follows without a rule of its own. */
.ground-moss,
.site-footer{
  background: var(--moss);
  color: var(--paper);
  --text: var(--paper);
  --text-soft: rgba(var(--paper-rgb), .86);
  --text-fine: rgba(var(--paper-rgb), .8);
  --heading: var(--paper);
  --link: var(--brass);
  --link-hover: var(--paper);
  --hand-ink: var(--brass);
  --tick-ink: var(--brass);
  --rule: rgba(var(--paper-rgb), .22);
  --rule-brass: rgba(var(--brass-rgb), .6);
  --rule-strong: rgba(var(--paper-rgb), .4);
  --focus: var(--brass);
  --solid-bg: var(--brass);
  --solid-fg: var(--ink);
  --solid-bg-hover: var(--brass-lift);
  --ghost-fg: var(--paper);
  --ghost-border: rgba(var(--paper-rgb), .42);
  --ghost-wash: rgba(var(--paper-rgb), .08);
  --wordmark-ink: var(--paper);
  --wordmark-ink-hover: var(--brass);
}

/* Paper surfaces take the light cast straight back, whatever ground
   they are standing on. Without this, a footnote inside the stat
   band on moss would be paper text on a paper panel. */
.balance,
.stat-band,
dialog.panel,
.chat-panel{
  color: var(--ink);
  --text: var(--ink);
  --text-soft: var(--fern);
  --text-fine: var(--fern);
  --heading: var(--ink);
  --link: var(--copper);
  --link-hover: var(--ink);
  --hand-ink: var(--copper);
  --tick-ink: var(--copper);
  --rule: rgba(var(--ink-rgb), .16);
  --rule-brass: rgba(var(--brass-rgb), .55);
  --rule-strong: rgba(var(--ink-rgb), .28);
  --focus: var(--ink);
  --solid-bg: var(--ink);
  --solid-fg: var(--paper);
  --solid-bg-hover: var(--moss);
  --ghost-fg: var(--ink);
  --ghost-border: rgba(var(--ink-rgb), .28);
  --ghost-wash: rgba(var(--ink-rgb), .04);
}

.section-head{ margin-bottom: var(--s7); max-width: 44ch; }
.section-head p{ color: var(--text-soft); font-size: var(--fs-lede); }

/* A hairline that opens a section, the ledger's rule above a column */
.rule-brass{
  border: 0;
  border-top: 1px solid var(--rule-brass);
  margin: 0 0 var(--s5);
  width: 64px;
}

/* =========================================================
   6. Breathing background
   ========================================================= */
.bg-breathe{
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  overflow: hidden;
}
.bg-blob{ position: absolute; border-radius: 50%; will-change: transform; }
.bg-blob--1{
  top: -24%; left: -16%;
  width: 58vmax; height: 58vmax;
  background: radial-gradient(circle, rgba(var(--moss-rgb), .13) 0%, rgba(var(--moss-rgb), 0) 66%);
}
.bg-blob--2{
  bottom: -28%; right: -14%;
  width: 52vmax; height: 52vmax;
  background: radial-gradient(circle, rgba(var(--sand-rgb), .9) 0%, rgba(var(--sand-rgb), 0) 66%);
}
.bg-blob--3{
  top: 28%; left: 54%;
  width: 44vmax; height: 44vmax;
  background: radial-gradient(circle, rgba(var(--brass-rgb), .12) 0%, rgba(var(--brass-rgb), 0) 66%);
}
html.has-fx .bg-blob--1{ animation: breathe-a 19s ease-in-out infinite alternate; }
html.has-fx .bg-blob--2{ animation: breathe-b 24s ease-in-out infinite alternate; }
html.has-fx .bg-blob--3{ animation: breathe-c 29s ease-in-out infinite alternate; }
@keyframes breathe-a{ from{ transform: translate(0,0) scale(1); } to{ transform: translate(4vw, 3vh) scale(1.12); } }
@keyframes breathe-b{ from{ transform: translate(0,0) scale(1.1); } to{ transform: translate(-3vw,-4vh) scale(.95); } }
@keyframes breathe-c{ from{ transform: translate(0,0) scale(.93); } to{ transform: translate(-4vw, 2vh) scale(1.1); } }

/* =========================================================
   7. The wordmark
   Typographic, set in HTML text so the header and the footer are the
   same two elements in the same face and can never drift apart. It
   takes its color from currentColor, so the footer needs no variant.
   ========================================================= */
/* Direction 1a, the pure wordmark: "Devoted" in Pinyon Script, a
   brass floret beneath it, then the caps line in Fraunces at a light
   weight, tracked wide and centered under the script. One lockup, one
   set of classes, driven entirely off --wordmark-size, so the header,
   the condensed header, the mobile sheet and the footer are four
   sizes of one thing.

   It is CSS only and it changes no markup, because thirteen pages
   already carry the header and footer from docs/SHELL.md. The floret
   is a pseudo-element on the caps line for the same reason. */
.wordmark{
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 0;
  text-decoration: none;
  color: var(--wordmark-ink);
  line-height: 1;
  transition: color .2s ease;
}
.wordmark-name{
  font-family: var(--font-script);
  font-weight: 400;
  font-size: var(--wordmark-size, 2.25rem);
  line-height: 1.05;
  letter-spacing: 0;
  /* Pinyon's cap D carries a swash that overhangs its sidebearing */
  padding: 0 .07em;
  transition: font-size .28s var(--ease-out);
}
.wordmark-sub{
  display: block;
  font-family: var(--font-display);
  font-weight: 300;
  font-size: calc(var(--wordmark-size, 2.25rem) * .2);
  font-variation-settings: "opsz" 9, "SOFT" 20;
  letter-spacing: .3em;
  /* the trailing letterspace is real width, so without this indent
     the caps line sits half a space left of the script above it */
  text-indent: .3em;
  text-transform: uppercase;
  line-height: 1.1;
  white-space: nowrap;
  color: inherit;
  transition: font-size .28s var(--ease-out);
}
/* The floret: a small brass heart with a dot, sitting between the
   script and the caps. Brass on both grounds, decoration, no text. */
.wordmark-sub::before{
  content: "";
  display: block;
  height: calc(var(--wordmark-size, 2.25rem) * .26);
  width: calc(var(--wordmark-size, 2.25rem) * .208);
  margin: calc(var(--wordmark-size, 2.25rem) * .1) auto calc(var(--wordmark-size, 2.25rem) * .11);
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 20'%3E%3Cpath d='M8 12.9C8 12.9 1 8.5 1 4.6 1 2.5 2.6 1 4.4 1 5.9 1 7.2 1.9 8 3 8.8 1.9 10.1 1 11.6 1 13.4 1 15 2.5 15 4.6 15 8.5 8 12.9 8 12.9Z' fill='%23B8935A'/%3E%3Ccircle cx='8' cy='17.6' r='1.5' fill='%23B8935A'/%3E%3C/svg%3E") center / contain no-repeat;
  transition: height .28s var(--ease-out), width .28s var(--ease-out), margin .28s var(--ease-out);
}
a.wordmark:hover{ color: var(--wordmark-ink-hover); }

/* The tagline is a variant, not part of the lockup. It rides under
   the wordmark in the footer, where the ground is moss and brass is
   legal at any size. On a light ground it takes copper instead,
   because brass is 2.6:1 there. */
.wordmark-tagline{
  display: block;
  font-family: var(--font-script);
  font-size: calc(var(--wordmark-size, 2.25rem) * .62);
  line-height: 1.2;
  color: var(--copper);
  text-align: center;
}
.ground-moss .wordmark-tagline,
.site-footer .wordmark-tagline{ color: var(--brass); }

/* =========================================================
   8. Header
   ========================================================= */
.site-header{
  position: sticky;
  top: 0;
  z-index: 60;
  background: rgba(var(--paper-rgb), .82);
  backdrop-filter: saturate(1.1) blur(7px);
  border-bottom: 1px solid transparent;
  transition: padding .28s var(--ease-out), background-color .28s ease, border-color .28s ease;
  padding: 12px 0;
}
.site-header.is-scrolled{
  padding: 6px 0;
  background: var(--paper);
  border-bottom-color: var(--rule-brass);
}
.header-inner{
  max-width: var(--inner);
  margin: 0 auto;
  padding: 0 var(--gutter);
  display: flex;
  align-items: center;
  gap: var(--s5);
}
.site-header .wordmark{ --wordmark-size: 2.2rem; margin-right: auto; }
.site-header.is-scrolled .wordmark{ --wordmark-size: 1.65rem; }

.primary-nav ul{
  list-style: none;
  display: flex;
  gap: clamp(14px, 1.6vw, 28px);
  margin: 0;
  padding: 0;
}
.primary-nav li{ margin: 0; }
.primary-nav a{
  display: inline-block;
  color: var(--ink);
  text-decoration: none;
  font-size: 0.9375rem;
  font-weight: 500;
  padding: 6px 2px;
  border-bottom: 1px solid transparent;
  transition: border-color .2s ease, color .2s ease;
}
.primary-nav a:hover,
.primary-nav a[aria-current="page"]{
  color: var(--fern);
  border-bottom-color: var(--brass);
}

.header-cta{ flex: none; }

.nav-toggle{
  display: none;
  align-items: center;
  gap: 9px;
  background: none;
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 0.9375rem;
  font-weight: 500;
  padding: 9px 14px;
  min-height: 44px;
  cursor: pointer;
}
.nav-toggle-bars{ display: inline-flex; flex-direction: column; gap: 4px; width: 18px; }
.nav-toggle-bars i{ display: block; height: 1.5px; background: currentColor; }

/* The .btn rule below sets display: inline-flex at the same
   specificity and later in the file, so the header CTA has to be
   hidden by a longer selector or it wins and crowds the bar. */
@media (max-width: 1000px){
  .primary-nav{ display: none; }
  .nav-toggle{ display: inline-flex; }
  .site-header .wordmark{ --wordmark-size: 1.75rem; }
  .site-header.is-scrolled .wordmark{ --wordmark-size: 1.42rem; }
  .site-header .header-cta{ display: none; }
}

/* Mobile navigation: a paper sheet over the page, focus trapped while
   it is open, Escape closes and focus returns to the button. */
.mobile-nav{
  position: fixed;
  inset: 0;
  z-index: 90;
  background: var(--paper);
  padding: 22px var(--gutter) var(--gutter);
  overflow-y: auto;
  display: flex;
  flex-direction: column;
}
.mobile-nav[hidden]{ display: none; }
.mobile-nav-top{ display: flex; align-items: center; justify-content: space-between; gap: var(--s4); }
.mobile-nav .wordmark{ --wordmark-size: 1.85rem; }
.mobile-nav-close{
  background: none;
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 0.9375rem;
  font-weight: 500;
  padding: 9px 14px;
  min-height: 44px;
  cursor: pointer;
}
.mobile-nav ul{ list-style: none; margin: var(--s6) 0 0; padding: 0; }
.mobile-nav li{ margin: 0; border-top: 1px solid var(--rule); }
.mobile-nav li:last-child{ border-bottom: 1px solid var(--rule); }
.mobile-nav a{
  display: block;
  padding: 16px 2px;
  font-family: var(--font-display);
  font-size: 1.4rem;
  font-variation-settings: "opsz" 40, "SOFT" 60;
  color: var(--ink);
  text-decoration: none;
}
.mobile-nav a:hover, .mobile-nav a[aria-current="page"]{ color: var(--fern); }
.mobile-nav .btn{ margin-top: var(--s6); }
.mobile-nav-tel{
  margin-top: var(--s5);
  font-size: var(--fs-small);
  color: var(--text-soft);
}
body.nav-open{ overflow: hidden; }

/* =========================================================
   9. Buttons: squared at 3px. No pills.
   ========================================================= */
.btn{
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 46px;
  padding: 12px 22px;
  border-radius: var(--radius);
  border: 1px solid transparent;
  font-family: var(--font-body);
  font-size: 0.9375rem;
  font-weight: 600;
  letter-spacing: .005em;
  text-decoration: none;
  cursor: pointer;
  transition: background-color .2s ease, color .2s ease, border-color .2s ease, transform .2s var(--ease-out);
}
.btn:active{ transform: translateY(1px); }

/* The contrast law, carried by the surface rather than by a
   descendant selector: ink with paper text on a light ground, brass
   with ink text on moss. */
.btn-solid{ background: var(--solid-bg); color: var(--solid-fg); }
.btn-solid:hover{ background: var(--solid-bg-hover); color: var(--solid-fg); }

.btn-ghost{ background: transparent; color: var(--ghost-fg); border-color: var(--ghost-border); }
.btn-ghost:hover{ border-color: var(--ghost-fg); color: var(--ghost-fg); background: var(--ghost-wash); }

.btn-brass{ background: var(--brass); color: var(--ink); }
.btn-brass:hover{ background: var(--brass-lift); color: var(--ink); }

.btn-row{ display: flex; flex-wrap: wrap; gap: var(--s3); align-items: center; }

/* A text link that reads as a link without a button around it */
.link-rule{
  display: inline-block;
  color: var(--text);
  text-decoration: none;
  font-weight: 500;
  border-bottom: 1px solid var(--brass);
  padding-bottom: 2px;
  transition: border-color .2s ease, color .2s ease;
}
.link-rule:hover{ color: var(--link); border-bottom-color: var(--link); }

/* =========================================================
   10. Ruled editorial lists
   A hairline per row, a serif name, one line of body, a hand note.
   This is what the site has instead of a grid of boxed cards.
   ========================================================= */
.ruled-list{ list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--rule); }
.ruled-list > li{ margin: 0; }
.ruled-row{
  display: grid;
  grid-template-columns: minmax(0, 18rem) minmax(0, 1fr);
  gap: var(--s4) var(--s7);
  align-items: baseline;
  padding: var(--s5) 0;
  border-bottom: 1px solid var(--rule);
  transition: border-color .25s ease;
}
.ruled-row:hover{ border-bottom-color: var(--rule-brass); }
.ruled-name{
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  font-weight: 500;
  font-variation-settings: "opsz" 34, "SOFT" 60;
  margin: 0;
  color: var(--heading);
  line-height: 1.2;
}
.ruled-name a{ color: inherit; text-decoration: none; border-bottom: 1px solid transparent; }
.ruled-name a:hover{ border-bottom-color: var(--brass); }
.ruled-body{ margin: 0; color: var(--text-soft); max-width: 46ch; }
.ruled-body p{ margin: 0; }
.ruled-price{
  display: block;
  font-family: var(--font-display);
  font-size: 1.0625rem;
  color: var(--text);
  margin-top: var(--s2);
  font-variation-settings: "opsz" 18, "SOFT" 40;
}
@media (max-width: 760px){
  .ruled-row{ grid-template-columns: 1fr; gap: var(--s2); }
}

/* =========================================================
   11. Hand notes: the pencil in the margin
   ========================================================= */
.hand{
  font-family: var(--font-hand);
  font-weight: 400;
  font-size: var(--fs-hand);
  line-height: 1.24;
  color: var(--hand-ink);
  width: fit-content;
  max-width: 34ch;
}
.hand--tilt-l{ transform: rotate(-1.4deg); }
.hand--tilt-r{ transform: rotate(1.1deg); }
.hand--block{ display: block; margin-top: var(--s3); }
.hand--lead{ margin-bottom: var(--s4); }
/* On moss the pencil would go muddy, so --hand-ink is brass there.
   Every hand note is 22px or larger, which is WCAG large text, and
   brass clears 3:1 on moss. */

/* Word-by-word variant. JS splits the text into .hw-word spans and
   writes the delays; the CSS only knows how one word strokes. */
.hw-word{ display: inline-block; }

/* =========================================================
   12. The hero sticker: the one pill on the site, and a real sticker
   ========================================================= */
.sticker{
  position: absolute;
  bottom: -16px;
  left: -18px;
  z-index: 3;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--font-hand);
  font-size: 1.5rem;
  line-height: 1.1;
  padding: 9px 22px 11px;
  border-radius: var(--radius-pill);
  transform: rotate(-4deg);
  box-shadow: var(--shadow);
  white-space: nowrap;
  text-align: center;
}
@media (max-width: 640px){
  .sticker{ left: 8px; bottom: -14px; font-size: 1.3rem; }
}

/* =========================================================
   13. Rotating words
   ========================================================= */
[data-rotate]{
  display: inline-grid;
  vertical-align: baseline;
  text-align: left;
}
[data-rotate] > span{
  grid-area: 1 / 1;
  white-space: nowrap;
  opacity: 0;
  transform: translateY(.42em);
  transition: opacity .5s ease, transform .5s var(--ease-out);
}
[data-rotate] > span:first-child{ opacity: 1; transform: translateY(0); }
html:not(.has-fx) [data-rotate] > span{ transition: none; }
.rotate-words > span{
  font-style: italic;
  font-weight: 500;
  color: var(--hand-ink);
  font-variation-settings: "opsz" 96, "SOFT" 90;
}
.sticker[data-rotate]{ text-align: center; }

/* =========================================================
   14. Ink ticks
   An inline SVG check per row, drawn with stroke-dasharray on first
   sight and staggered down the list, the way a reconciliation is
   ticked off. Decorative: the text beside it carries the meaning.
   ========================================================= */
.tick-list{ list-style: none; margin: 0; padding: 0; }
.tick-list > li{
  display: grid;
  grid-template-columns: 26px minmax(0, 1fr);
  gap: var(--s3);
  align-items: start;
  padding: var(--s3) 0;
  margin: 0;
  border-bottom: 1px solid var(--rule);
}
.tick-list > li:first-child{ border-top: 1px solid var(--rule); }
.tick{ width: 22px; height: 22px; margin-top: 2px; overflow: visible; }
.tick path{
  fill: none;
  stroke: var(--tick-ink);
  stroke-width: 2.1;
  stroke-linecap: round;
  stroke-linejoin: round;
}
html.has-fx .tick path{
  stroke-dasharray: 28;
  stroke-dashoffset: 28;
  transition: stroke-dashoffset .52s var(--ease-out);
}
html.has-fx .tick-list.is-drawn .tick path{ stroke-dashoffset: 0; }

/* =========================================================
   15. The balance line
   Two short columns of figures that count up, then a double hairline
   draws under the total the way a bookkeeper double-rules a balanced
   column. One instance, home page only, runs once.
   ========================================================= */
/* No panel, no box, no shadow. A ledger page is ruled, not boxed:
   one heavy rule at the top, a hairline under each column head, a
   hairline above the total, and the double rule beneath it. The
   ground it stands on shows through. */
.balance{
  margin: 0;
  background: none;
  border: 0;
  border-top: 2px solid var(--ink);
  padding: var(--s5) 0 0;
  max-width: 560px;
}
.balance-title{
  font-family: var(--font-display);
  font-size: 1.0625rem;
  font-variation-settings: "opsz" 18, "SOFT" 40;
  margin: 0 0 var(--s5);
  padding-bottom: var(--s3);
  border-bottom: 1px solid var(--rule-brass);
  color: var(--ink);
}
.balance-cols{
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s6);
}
.balance-col h3{
  font-size: var(--fs-small);
  font-family: var(--font-body);
  font-weight: 600;
  letter-spacing: .04em;
  color: var(--text-fine);
  margin: 0 0 var(--s3);
  padding-bottom: var(--s2);
  border-bottom: 1px solid var(--rule);
}
.balance-rows{ margin: 0; }
.balance-row{
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--s3);
  padding: 5px 0;
  font-size: var(--fs-small);
}
.balance-row dt{ color: var(--text-soft); }
.balance-row dd{
  margin: 0;
  font-family: var(--font-display);
  font-variation-settings: "opsz" 18, "SOFT" 30;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}
.balance-foot{
  margin-top: var(--s5);
  padding-top: var(--s4);
  border-top: 1px solid var(--rule);
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--s4);
}
.balance-foot-label{
  font-family: var(--font-body);
  font-size: var(--fs-small);
  font-weight: 600;
  color: var(--text-fine);
  margin: 0;
}
.balance-total{
  font-family: var(--font-display);
  font-size: var(--fs-fig);
  font-weight: 500;
  font-variation-settings: "opsz" 72, "SOFT" 60;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  color: var(--moss);
  margin: 0;
}
/* the double rule: two hairlines that draw left to right, the second
   a beat after the first */
.balance-rule{
  display: block;
  margin-top: 9px;
  margin-left: auto;
  width: 100%;
  max-width: 190px;
}
.balance-rule i{
  display: block;
  height: 1px;
  background: var(--ink);
  width: 100%;
  margin-left: auto;
}
.balance-rule i + i{ margin-top: 3px; }
html.has-fx .balance-rule i{
  width: 0;
  transition: width .55s var(--ease-pen);
}
html.has-fx .balance-rule i + i{ transition-delay: .22s; }
html.has-fx .balance.is-ruled .balance-rule i{ width: 100%; }

@media (max-width: 560px){
  .balance-cols{ grid-template-columns: 1fr; gap: var(--s5); }
  .balance-rule{ max-width: 150px; }
}

/* =========================================================
   16. Matted frames
   ========================================================= */
.frame{
  position: relative;
  overflow: hidden;
  background: var(--sand);
  border-radius: 2px;
}
.frame img{ width: 100%; height: 100%; object-fit: cover; }
.frame--mat{
  background: var(--paper);
  border: 1px solid var(--rule);
  padding: clamp(12px, 1.5vw, 20px);
  box-shadow: var(--shadow);
}
.frame--mat::after{
  content: "";
  position: absolute;
  inset: 7px;
  border: 1px solid var(--rule-brass);
  pointer-events: none;
}
.frame--tall{ aspect-ratio: 4 / 5; }
.frame--wide{ aspect-ratio: 3 / 2; }
.frame--tilt{ transform: rotate(-1.1deg); }

/* develop-in: the photograph arrives out of a blur, then the drift
   loop owns the transform */
html.has-fx .frame img{
  opacity: 0;
  transform: scale(1.06);
  filter: blur(10px);
  transition: opacity .8s ease, transform .8s var(--ease-out), filter .8s ease;
}
html.has-fx .frame img.is-loaded{
  opacity: 1;
  filter: none;
  transition: opacity .8s ease, filter .8s ease;
}

/* =========================================================
   17. Stat band
   A panel, which the site allows exactly here and in dialogs.
   ========================================================= */
.stat-band{
  background: var(--paper);
  border: 1px solid var(--rule);
  border-top: 2px solid var(--brass);
  padding: clamp(24px, 3vw, 40px);
  box-shadow: var(--shadow);
}
.stat-row{
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s6);
}
.stat{ margin: 0; }
.stat-figure{
  display: block;
  font-family: var(--font-display);
  font-size: var(--fs-fig);
  font-weight: 500;
  font-variation-settings: "opsz" 72, "SOFT" 60;
  line-height: 1;
  color: var(--moss);
  font-variant-numeric: tabular-nums;
  margin-bottom: var(--s3);
  padding-top: var(--s3);
  border-top: 1px solid var(--rule-brass);
}
.stat-figure--text{ font-size: clamp(1.3rem, 1.05rem + .9vw, 1.9rem); line-height: 1.14; }
.stat-label{ display: block; font-size: var(--fs-small); color: var(--text-soft); line-height: 1.5; margin: 0; }
@media (max-width: 720px){
  .stat-row{ grid-template-columns: 1fr; gap: var(--s5); }
}

/* =========================================================
   18. Two column prose split
   ========================================================= */
.split{
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s7) clamp(32px, 5vw, 84px);
}
.split-col h3{ margin-bottom: var(--s3); }
.split-col p{ color: var(--text-soft); }
@media (max-width: 800px){ .split{ grid-template-columns: 1fr; gap: var(--s6); } }

/* hero and other picture-beside-text layouts */
.duo{
  display: grid;
  grid-template-columns: minmax(0, 1.08fr) minmax(0, .92fr);
  gap: clamp(32px, 5vw, 80px);
  align-items: center;
}
.duo--text-right{ grid-template-columns: minmax(0, .92fr) minmax(0, 1.08fr); }
@media (max-width: 880px){
  .duo, .duo--text-right{ grid-template-columns: 1fr; gap: var(--s7); }
}

/* =========================================================
   19. Hero
   ========================================================= */
.hero{ padding-top: clamp(40px, 4vw, 72px); padding-bottom: var(--section-y); }
.hero h1{
  font-size: var(--fs-hero);
  font-weight: 400;
  font-variation-settings: "opsz" 144, "SOFT" 70;
  letter-spacing: -0.022em;
  margin-bottom: var(--s5);
}
.hero-media{ position: relative; }
.hero .lede{ max-width: 44ch; margin-bottom: var(--s6); }
.hero-tel{
  margin-top: var(--s5);
  font-size: var(--fs-small);
  color: var(--text-soft);
}
.hero-tel a{ color: var(--text); text-decoration: none; border-bottom: 1px solid var(--brass); }
.hero-tel a:hover{ color: var(--link); }

/* =========================================================
   20. Forms
   ========================================================= */
.form{ max-width: 34rem; }
.form-grid{ display: grid; gap: var(--s4); }
.form-grid--2{ grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (max-width: 620px){ .form-grid--2{ grid-template-columns: 1fr; } }

.field{ display: block; }
.field > span{
  display: block;
  font-size: var(--fs-small);
  font-weight: 600;
  color: var(--text-fine);
  margin-bottom: 6px;
}
.input, .textarea, .select{
  width: 100%;
  font-family: var(--font-body);
  font-size: 1rem;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid rgba(var(--ink-rgb), .28);
  border-radius: var(--radius);
  padding: 12px 14px;
  min-height: 46px;
  transition: border-color .2s ease, box-shadow .2s ease;
}
.textarea{ min-height: 140px; resize: vertical; line-height: 1.55; }
.input::placeholder, .textarea::placeholder{ color: rgba(var(--ink-rgb), .45); }
.input:hover, .textarea:hover, .select:hover{ border-color: var(--ink); }
.input, .textarea, .select{ --focus: var(--ink); }
.input:focus-visible, .textarea:focus-visible, .select:focus-visible{
  outline: 2px solid var(--focus);
  outline-offset: 1px;
  border-color: var(--ink);
}

/* The honeypot. Never display: none, which some autofill agents skip. */
.hp-field{
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.form-note{
  margin: var(--s3) 0 0;
  font-size: var(--fs-small);
  line-height: 1.5;
  color: var(--text-fine);
  min-height: 1.5em;
}
.form-note.is-error{ color: var(--note-error, var(--copper)); }
.form-note.is-ok{ color: var(--note-ok, var(--moss)); font-weight: 500; }

.form-fine{ font-size: var(--fs-fine); color: var(--text-fine); margin-top: var(--s3); }

/* =========================================================
   21. Newsletter capture
   ========================================================= */
.newsletter{ max-width: 36rem; }
.newsletter-form{
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--s3);
  align-items: start;
}
@media (max-width: 560px){ .newsletter-form{ grid-template-columns: 1fr; } }

/* =========================================================
   22. CTA band
   ========================================================= */
.cta-band{ text-align: left; }
.cta-band h2{ max-width: 22ch; }
.cta-band .lede{ max-width: 46ch; }
.cta-inner{
  display: flex;
  flex-wrap: wrap;
  gap: var(--s7);
  align-items: flex-end;
  justify-content: space-between;
}
.cta-copy{ max-width: 46ch; }

/* =========================================================
   23. Footer
   ========================================================= */
/* One compact band. No column stacks of repeated links, no second
   newsletter form, no prose. The wordmark, one NAP line, one row of
   links, the notes, and out. At 390 wide it is well under a screen. */
.site-footer{ padding: var(--s7) 0 var(--s6); }
.site-footer a{ color: var(--paper); text-decoration: none; }
.site-footer a:hover{ color: var(--brass); }

.footer-band{
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s4) var(--s6);
  padding-bottom: var(--s5);
  border-bottom: 1px solid rgba(var(--brass-rgb), .45);
}
/* The brand block centers on the lockup axis, so the tagline sits
   under the caps line rather than left of it. */
.footer-band > div{
  display: flex;
  flex-direction: column;
  align-items: center;
  width: fit-content;
}
.footer-band .wordmark{ --wordmark-size: 2.3rem; }
/* The tagline variant of the lockup, in the one place it belongs. */
/* 1.6rem is 25.6px, which clears the 24px large-text threshold.
   Brass on moss is 3.4:1, so the tagline has to be large text or it
   has to be copper, and copper on moss is not the design. */
.footer-tag{
  font-family: var(--font-script);
  font-size: 1.6rem;
  line-height: 1.25;
  color: var(--brass);
  text-align: center;
  margin: 10px 0 0;
}
.footer-nap{
  font-size: 0.9375rem;
  line-height: 1.7;
  color: rgba(var(--paper-rgb), .9);
  margin: 0;
  max-width: 46ch;
}
.footer-nap a{ border-bottom: 1px solid rgba(var(--brass-rgb), .6); }

.footer-links{
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 6px var(--s5);
  margin: var(--s5) 0 0;
  padding: 0;
  font-size: 0.9375rem;
}
.footer-links li{ margin: 0; }
.footer-links a{ border-bottom: 1px solid transparent; }
.footer-links a:hover{ border-bottom-color: var(--brass); }

.footer-fine{
  margin: var(--s5) 0 0;
  display: grid;
  gap: 6px;
  font-size: var(--fs-fine);
  line-height: 1.6;
  color: rgba(var(--paper-rgb), .78);
  max-width: 92ch;
}
.footer-fine p{ margin: 0; }
.footer-legal{
  display: flex;
  flex-wrap: wrap;
  gap: 4px var(--s4);
  align-items: baseline;
}
.footer-legal a{ border-bottom: 1px solid rgba(var(--brass-rgb), .55); }

/* =========================================================
   24. Dialog
   ========================================================= */
dialog.panel{
  border: 1px solid var(--rule);
  border-top: 2px solid var(--brass);
  border-radius: var(--radius);
  background: var(--paper);
  color: var(--ink);
  padding: clamp(22px, 3vw, 36px);
  max-width: 34rem;
  width: calc(100vw - 2 * var(--gutter));
  box-shadow: var(--shadow);
}
dialog.panel::backdrop{ background: rgba(var(--ink-rgb), .52); }
.panel-top{ display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s4); margin-bottom: var(--s4); }
.panel-close{
  background: none;
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--fs-small);
  font-weight: 500;
  min-height: 40px;
  padding: 8px 14px;
  cursor: pointer;
}
.panel-close:hover{ border-color: var(--ink); }

/* =========================================================
   25. Chat launcher
   The panel itself is built by /assets/js/chat.js, loaded on the
   first click. These are the styles for the launcher and for the
   shell the panel drops into.
   ========================================================= */
.chat-launcher{
  position: fixed;
  right: clamp(14px, 2.5vw, 28px);
  bottom: clamp(14px, 2.5vw, 28px);
  z-index: 70;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  min-height: 48px;
  padding: 12px 20px;
  border: 1px solid var(--brass);
  border-radius: var(--radius);
  background: var(--ink);
  color: var(--paper);
  font-family: var(--font-body);
  font-size: 0.9375rem;
  font-weight: 600;
  cursor: pointer;
  box-shadow: var(--shadow);
  transition: background-color .2s ease, transform .2s var(--ease-out);
}
.chat-launcher:hover{ background: var(--moss); }
.chat-launcher:active{ transform: translateY(1px); }
.chat-launcher[aria-expanded="true"]{ background: var(--moss); }
.chat-launcher-mark{
  display: inline-block;
  width: 9px; height: 9px;
  border-radius: 50%;
  background: var(--brass);
  flex: none;
}
.chat-panel{
  position: fixed;
  right: clamp(14px, 2.5vw, 28px);
  bottom: calc(clamp(14px, 2.5vw, 28px) + 60px);
  z-index: 71;
  width: min(380px, calc(100vw - 28px));
  max-height: min(560px, calc(100vh - 120px));
  display: flex;
  flex-direction: column;
  background: var(--paper);
  color: var(--ink);
  border: 1px solid var(--rule);
  border-top: 2px solid var(--brass);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow: hidden;
}
.chat-panel[hidden]{ display: none; }
.chat-status{
  font-size: var(--fs-fine);
  color: var(--text-soft);
  line-height: 1.5;
  padding: var(--s4);
  border-bottom: 1px solid var(--rule);
  margin: 0;
}

/* =========================================================
   26. Short pages: 404, accessibility, privacy
   ========================================================= */
.page-head{ padding: clamp(48px, 6vw, 96px) 0 var(--s7); }
.page-head h1{ max-width: 20ch; }
.page-body h2{ margin-top: var(--s8); }
.page-body h2:first-child{ margin-top: 0; }
.page-body ul{ color: var(--text-soft); max-width: var(--measure); }
.page-body li::marker{ color: var(--brass); }
.page-updated{ font-size: var(--fs-small); color: var(--text-fine); margin-top: var(--s7); padding-top: var(--s4); border-top: 1px solid var(--rule); }

.error-code{
  font-family: var(--font-display);
  font-size: clamp(4rem, 3rem + 6vw, 8rem);
  font-variation-settings: "opsz" 144, "SOFT" 90;
  font-weight: 400;
  line-height: 1;
  color: var(--brass);
  margin: 0 0 var(--s5);
  font-variant-numeric: tabular-nums;
}

/* =========================================================
   27. Scroll reveal
   Gated on has-fx, so a page whose JavaScript never runs shows every
   section at its final state rather than an empty column.
   ========================================================= */
html.has-fx .reveal{
  opacity: 0;
  transform: translateY(22px);
  transition: opacity .7s ease, transform .7s var(--ease-out);
}
html.has-fx .reveal.is-visible{ opacity: 1; transform: none; }

/* =========================================================
   28. Hand note writing
   The note wipes in left to right behind its own clip-path. An
   unwritten note has zero visible area, which is why the observer in
   main.js watches at threshold 0 with a negative bottom rootMargin.
   ========================================================= */
html.has-fx .hand:not(.hand--words){
  clip-path: inset(-28% 105% -28% -5%);
  transition: clip-path 1.05s var(--ease-pen) .12s;
}
html.has-fx .hand:not(.hand--words).is-written{
  clip-path: inset(-28% -5% -28% -5%);
}
/* An interactive hand note is clipped out of hit testing as well as
   out of sight, so a keyboard visitor who arrives before the scroll
   does gets it unclipped at once, with no wipe to wait through. */
html.has-fx .hand:focus-visible,
html.has-fx .hand:focus-within{
  clip-path: none;
  transition: none;
}
html.has-fx .hand--words .hw-word{
  clip-path: inset(-32% 105% -32% -8%);
  transition: clip-path .34s cubic-bezier(.55, 0, .45, 1);
}
html.has-fx .hand--words.is-written .hw-word{ clip-path: inset(-32% -8% -32% -8%); }

/* =========================================================
   29. Reduced motion and no JavaScript
   Neither path ever adds has-fx, so every rule above that hides
   something is simply not in play: notes are written, ticks are
   drawn, figures show their real number, photographs are sharp,
   sections are in place. These few belt-and-braces rules cover the
   animations declared outside the has-fx gate.
   ========================================================= */
@media (prefers-reduced-motion: reduce){
  *, *::before, *::after{
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

/* =========================================================
   30. Print
   ========================================================= */
@media print{
  .site-header, .mobile-nav, .chat-launcher, .chat-panel,
  .bg-breathe, .cta-band, .skip-link{ display: none !important; }
  body{ background: #FFFFFF; color: #000000; font-size: 11pt; }
  .section{ background: #FFFFFF !important; color: #000000 !important; padding: 12pt 0; }
  .site-footer{ background: #FFFFFF !important; color: #000000 !important; padding: 12pt 0; }
  .site-footer a, .ground-moss a{ color: #000000; }
  a[href^="http"]::after{ content: " (" attr(href) ")"; font-size: 9pt; }
  .balance, .stat-band, .frame--mat{ box-shadow: none; }
}
