/* Self-hosted Archivo superfamily, SIL Open Font License 1.1, free for
     commercial use. These were previously local()-only, which meant any device
     without Arial Black, Bahnschrift or Corbel fell straight through to generic
     sans-serif. That is every phone, and the generic fallback is wider than the
     condensed faces this layout was measured against, which pushed the Free
     Consult button off the right edge on mobile.
     local() is kept first so a machine that already owns the face skips the
     download entirely. */
@font-face {
    font-family: "GDisplay";
    src: local("Archivo Black"),
         url("/assets/fonts/ArchivoBlack-400.woff2") format("woff2");
    font-weight: 400 900; font-display: swap;
  }
  @font-face {
    font-family: "GBody";
    src: local("Archivo"),
         url("/assets/fonts/Archivo-400.woff2") format("woff2");
    font-weight: 400; font-display: swap;
  }
  @font-face {
    font-family: "GBody";
    src: url("/assets/fonts/Archivo-700.woff2") format("woff2");
    font-weight: 700; font-display: swap;
  }
  @font-face {
    font-family: "GLabel";
    src: url("/assets/fonts/ArchivoNarrow-600.woff2") format("woff2");
    font-weight: 400 600; font-display: swap;
  }
  @font-face {
    font-family: "GLabel";
    src: url("/assets/fonts/ArchivoNarrow-700.woff2") format("woff2");
    font-weight: 700; font-display: swap;
  }

  /* Palette pulled from the bookkeeping logo itself: the honey of the bee,
     the ink of the polo and outlines, and the moss of the desk plant. */
  :root {
    --ink:        #14100A;
    --honey:      #E8BC3E;
    --honey-deep: #C99A1E;
    --bronze:     #A07A2C;
    --moss:       #46583A;
    --moss-mid:   #6E8757;

    --ground:     #FAF3E4;
    --surface:    #FFFDF7;
    --sunk:       #F3E9D4;
    --edge:       #E2D5B8;
    --edge-firm:  #C9B48A;
    --text:       #221B10;
    --text-dim:   #6A5F4B;
    --accent:     #8A6114;
    --on-dark:    #FAF3E4;

    /* Nav gold, tuned per theme. On cream, full honey (#E8BC3E) is about 1.8:1
       and unreadable, so light mode uses a deep gold and darkens on hover.
       Dark mode uses the bright honey and gets brighter. */
    --nav-idle:   #8A6114;
    --nav-on:     #5E400C;
    --nav-line:   #C99A1E;

    --shell:  min(1120px, 90vw);
    --narrow: min(760px, 90vw);
  }

  @media (prefers-color-scheme: dark) {
    :root {
      --ground:    #12100A;
      --surface:   #1B1710;
      --sunk:      #231E15;
      --edge:      #322B1E;
      --edge-firm: #4A4130;
      --text:      #F3EADA;
      --text-dim:  #A2967E;
      --accent:    #E8BC3E;
      --nav-idle:  #E8BC3E;
      --nav-on:    #FFDD7A;
      --nav-line:  #E8BC3E;
      --moss:      #7E9865;
      --moss-mid:  #9DB487;
    }
  }
  :root[data-theme="dark"] {
    --ground:    #12100A;
    --surface:   #1B1710;
    --sunk:      #231E15;
    --edge:      #322B1E;
    --edge-firm: #4A4130;
    --text:      #F3EADA;
    --text-dim:  #A2967E;
    --accent:    #E8BC3E;
    --nav-idle:  #E8BC3E;
    --nav-on:    #FFDD7A;
    --nav-line:  #E8BC3E;
    --moss:      #7E9865;
    --moss-mid:  #9DB487;
  }
  :root[data-theme="light"] {
    --ground:    #FAF3E4;
    --surface:   #FFFDF7;
    --sunk:      #F3E9D4;
    --edge:      #E2D5B8;
    --edge-firm: #C9B48A;
    --text:      #221B10;
    --text-dim:  #6A5F4B;
    --accent:    #8A6114;
    --nav-idle:  #8A6114;
    --nav-on:    #5E400C;
    --nav-line:  #C99A1E;
    --moss:      #46583A;
    --moss-mid:  #6E8757;
  }

  * { box-sizing: border-box; }

  /* Base link color, added 2026-09-01. Every link on the site is already
     covered by a more specific rule (.foot a, .card a, .post a, .nav__links a
     and so on), and this catches anything that is not. Without it a new link
     placed outside those containers falls through to the browser default blue,
     which is exactly what happened to the review-source link when the .quote
     component was first used. Specificity 0,0,1, so it never overrides an
     existing rule and never touches .btn. */
  a { color: var(--accent); }

  body {
    margin: 0;
    background: var(--ground);
    color: var(--text);
    font-family: "GBody", system-ui, sans-serif;
    font-size: 1.02rem;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
  }

  .wrap   { width: var(--shell);  margin: 0 auto; }
  .narrow { width: var(--narrow); margin: 0 auto; }

  h1, h2, h3 { font-family: "GDisplay", Impact, sans-serif; text-wrap: balance; margin: 0; }
  p { margin: 0; }

  .eyebrow {
    font-family: "GLabel", "Segoe UI", sans-serif;
    font-size: 0.76rem; font-weight: 700;
    letter-spacing: 0.18em; text-transform: uppercase;
    color: var(--accent);
  }

  /* ---------- nav ---------- */
  .nav {
    position: sticky; top: 0; z-index: 50;
    background: var(--surface);
    border-bottom: 2px solid var(--ink);
  }
  .nav__in {
    width: var(--shell); margin: 0 auto;
    display: flex; align-items: center; gap: 1rem;
    padding: 0.55rem 0;
  }
  .brand { display: flex; align-items: center; gap: 0.6rem; text-decoration: none; color: inherit; }
  .brand img { width: 44px; height: 44px; object-fit: contain; display: block; }
  .brand b {
    font-family: "GDisplay", Impact, sans-serif;
    font-size: 1.02rem; letter-spacing: 0.01em; text-transform: uppercase; line-height: 1;
  }
  .brand span {
    display: block;
    font-family: "GLabel", "Segoe UI", sans-serif;
    font-size: 0.63rem; letter-spacing: 0.19em; text-transform: uppercase;
    color: var(--text-dim); margin-top: 2px;
  }

  /* Nav links are <a> in the deployed build and <button> in the single-file
     preview. Style both, or the live site falls back to default link styling. */
  .nav__links {
    margin-left: auto;
    display: flex; align-items: center; flex-wrap: wrap;
    /* Flat 1rem so MENU -> Free Guide -> Free Quiz matches the
       Free Quiz -> Free consult gap (that one comes from .nav__in's
       own gap: 1rem, below) - Ethan asked for all three gaps to read
       as the same distance. Was clamp(1rem, 2.6vw, 2.4rem), which grew
       past 1rem on wide screens and made the row look uneven. */
    gap: 1rem;
  }
  .nav__links a,
  .nav__links button {
    font-family: "GLabel", "Segoe UI", sans-serif;
    font-size: clamp(0.95rem, 0.9rem + 0.2vw, 1.08rem);
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    background: none; border: 0; cursor: pointer;
    padding: 0.55rem 0.1rem;
    color: var(--nav-idle);
    text-decoration: none;
    border-bottom: 3px solid transparent;
    transition: color 0.15s ease, border-color 0.15s ease;
  }
  .nav__links a:hover,
  .nav__links button:hover,
  .nav__links a[aria-current="page"],
  .nav__links button[aria-current="page"] {
    color: var(--nav-on);
    border-bottom-color: var(--nav-line);
  }
  .nav__links a:focus-visible,
  .nav__links button:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

  .btn {
    display: inline-flex; align-items: center; gap: 0.45rem;
    padding: 0.72rem 1.35rem;
    font-family: "GLabel", "Segoe UI", sans-serif;
    font-size: 0.88rem; font-weight: 700;
    letter-spacing: 0.1em; text-transform: uppercase;
    border-radius: 2px; border: 2px solid var(--ink);
    cursor: pointer; text-decoration: none;
    background: var(--honey); color: #14100A;
    box-shadow: 4px 4px 0 0 var(--bronze);
    transition: transform 0.18s ease, box-shadow 0.18s ease;
  }
  .btn:hover { transform: translate(-2px, -2px); box-shadow: 6px 6px 0 0 var(--bronze); }
  .btn:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }
  .btn--ghost {
    background: transparent; color: var(--text);
    border-color: var(--edge-firm); box-shadow: none;
  }
  .btn--ghost:hover { border-color: var(--ink); transform: translate(-1px, -1px); box-shadow: none; }
  .btn--sm { padding: 0.5rem 0.9rem; font-size: 0.78rem; box-shadow: 3px 3px 0 0 var(--bronze); }
  /* `.nav__links a` above is (0,1,1) and sets its own padding/font-size, which
     beats a bare .btn--sm (0,1,0) and made Free Guide/Free Quiz render taller
     and larger-text than Free consult (outside .nav__links, so unaffected).
     Restating .btn--sm's sizing here at (0,2,0) wins it back for every button
     in the nav, at every width - the existing mobile overrides below share
     this same selector and correctly win the tie by appearing later. */
  .nav .btn--sm { flex: 0 0 auto; padding: 0.5rem 0.9rem; font-size: 0.78rem; }

  @media (max-width: 860px) {
    .nav__in { flex-wrap: wrap; }
    .nav__links {
      width: 100%; margin-left: 0; order: 3;
      justify-content: space-between;
      gap: 0.5rem;
      border-top: 1px solid var(--edge);
      padding-top: 0.2rem;
    }
    .nav .btn--sm { margin-left: auto; }
  }
  @media (max-width: 560px) {
    /* Five nav items plus the consult button will not fit beside the brand on a
       phone. Before this, the Free Consult button was pushed off the right edge
       entirely, which killed the only conversion path on mobile. Shrink the
       brand block so the row-one pair fits, and stop space-between from
       stranding a lone item on a wrapped row. */
    .nav__in { gap: 0.5rem; }
    .brand img { width: 34px; height: 34px; }
    .brand b { font-size: 0.9rem; }
    .brand span { font-size: 0.54rem; letter-spacing: 0.13em; }
    .nav .btn--sm { padding: 0.42rem 0.66rem; font-size: 0.71rem; }
    .nav__links {
      justify-content: flex-start;
      gap: 0.3rem 0.95rem;
    }
    /* Thumb-sized header controls on a phone (2026-09-20). The three buttons
       measured 35-36px tall and Menu 39px; 44px is the common touch guideline.
       min-height keeps the lettering, padding and widths exactly as they were;
       inline-flex centers the label in the taller box. */
    .nav .btn--sm {
      min-height: 44px; display: inline-flex;
      align-items: center; justify-content: center;
    }
    .nav .menu__btn { min-height: 44px; }
  }
  @media (max-width: 420px) {
    /* four uppercase words will not sit on one line on a small phone */
    .nav__links a, .nav__links button {
      font-size: 0.86rem; letter-spacing: 0.08em;
    }
  }

  /* ---------- page mechanics ---------- */
  .page { display: none; }
  .page.on { display: block; animation: fade 0.3s ease both; }
  @keyframes fade { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

  section { padding: clamp(2.6rem, 5vw, 4.2rem) 0; }
  .band  { background: var(--surface); border-block: 1px solid var(--edge); }
  .band--ink {
    background: var(--ink); color: var(--on-dark);
    border-block: 0;
  }
  .band--ink .eyebrow { color: var(--honey); }
  .band--ink p { color: rgba(250, 243, 228, 0.82); }

  .head { display: grid; gap: 0.7rem; margin-bottom: 2rem; max-width: 62ch; }
  .head h1, .head h2 { font-size: clamp(1.5rem, 1.15rem + 1.6vw, 2.2rem); line-height: 1.06; text-transform: uppercase; }
  .head p { color: var(--text-dim); }
  .band--ink .head p { color: rgba(250, 243, 228, 0.8); }

  /* ---------- hero ---------- */
  .hero { padding: clamp(2.8rem, 6vw, 5rem) 0 clamp(2rem, 4vw, 3rem); }
  .hero__grid { display: grid; gap: clamp(1.6rem, 4vw, 3rem); align-items: center; }
  @media (min-width: 900px) { .hero__grid { grid-template-columns: 1.25fr 0.75fr; } }

  .hero h1 {
    font-size: clamp(2.1rem, 1.3rem + 3.7vw, 4rem);
    line-height: 0.98; text-transform: uppercase; margin: 0.5rem 0 0;
  }
  .hero__lead {
    margin-top: 1.1rem; font-size: 0.95rem;
    /* Fixed, not clamped, and no ch-based max-width: this line is meant to
       hold on one line at real desktop widths (tested 1000px-1400px). A
       ch-based max-width was fighting that regardless of font-size. Only
       wraps below ~960px, right at the edge of the two-column breakpoint. */
    color: var(--text-dim);
  }
  .hero__lead strong { color: var(--text); }
  .hero__acts { display: flex; gap: 0.7rem; flex-wrap: wrap; margin-top: 1.7rem; }
  .hero__where {
    margin-top: 1.1rem; font-size: 0.92rem; color: var(--text-dim);
  }
  .hero__art {
    background: var(--sunk);
    border: 2px solid var(--ink);
    border-radius: 3px;
    padding: 1.4rem;
    box-shadow: 8px 8px 0 0 var(--bronze);
  }
  .hero__art img { width: 100%; height: auto; display: block; }

  /* ---------- trust strip ---------- */
  .trust {
    background: var(--ink); color: var(--on-dark);
    padding: 0.9rem 0;
  }
  .trust ul {
    list-style: none; margin: 0; padding: 0;
    display: flex; flex-wrap: wrap; gap: 0.5rem 1.6rem; justify-content: center;
    font-family: "GLabel", "Segoe UI", sans-serif;
    font-size: 0.8rem; letter-spacing: 0.11em; text-transform: uppercase;
  }
  .trust li { display: flex; align-items: center; gap: 0.5rem; }
  .trust li::before {
    content: ""; width: 7px; height: 7px; background: var(--honey);
    transform: rotate(45deg); flex: 0 0 auto;
  }

  /* ---------- lists / cards ---------- */
  .gap { display: grid; gap: 1.1rem; }
  .cols-2 { display: grid; gap: 1.1rem; }
  .cols-3 { display: grid; gap: 1.1rem; }
  @media (min-width: 720px) { .cols-2 { grid-template-columns: 1fr 1fr; } }
  @media (min-width: 900px) { .cols-3 { grid-template-columns: repeat(3, 1fr); } }

  .card {
    background: var(--surface);
    border: 1px solid var(--edge-firm);
    border-top: 4px solid var(--honey);
    border-radius: 3px;
    padding: 1.3rem;
    display: grid; gap: 0.5rem; align-content: start;
  }
  .card h3 { font-size: 1.05rem; text-transform: uppercase; letter-spacing: 0.01em; }
  .card p { color: var(--text-dim); font-size: 0.96rem; }
  .card--moss { border-top-color: var(--moss); }
  .pkg-dot { display: inline-block; width: 12px; height: 12px; border-radius: 50%; margin-right: 0.55rem; vertical-align: middle; background: var(--honey); }
  .pkg-dot--moss { background: var(--moss); }

  /* One bordered box holding every term as a row, divided by horizontal
     rules - a clean spec-sheet look. Replaces both the boxed-card grid
     (looked broken with an odd item count) and the borderless divider
     grid tried right after (read as too plain). */
  .terms-box { padding: 0; }
  .terms-row { padding: 1.15rem 1.5rem; border-bottom: 1px solid var(--edge-firm); display: grid; gap: 0.3rem; }
  .terms-row:last-child { border-bottom: none; }
  .terms-row h3 { font-size: 0.95rem; text-transform: uppercase; letter-spacing: 0.02em; margin: 0; }
  .terms-row p { color: var(--text-dim); font-size: 0.96rem; margin: 0; }
  @media (min-width: 720px) {
    .terms-row { grid-template-columns: 210px 1fr; align-items: center; gap: 1.6rem; }
  }
  .card--soon { border-top-style: dashed; border-top-color: var(--edge-firm); }
  .card--soon p { opacity: 0.85; }

  .soon {
    display: inline-block; vertical-align: middle;
    margin-left: 0.45rem;
    font-family: "GLabel", "Segoe UI", sans-serif;
    font-size: 0.62rem; font-weight: 700;
    letter-spacing: 0.13em; text-transform: uppercase;
    padding: 0.16rem 0.45rem; border-radius: 2px;
    background: var(--sunk); color: var(--accent);
    border: 1px solid var(--edge-firm);
  }

  .pain { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.7rem; max-width: 60ch; }
  .pain li {
    padding-left: 1.9rem; position: relative;
  }
  .pain li::before {
    content: ""; position: absolute; left: 0; top: 0.55em;
    width: 11px; height: 2px; background: var(--moss);
  }

  /* numbered steps: a real sequence, so numbers carry meaning */
  .steps { list-style: none; margin: 0; padding: 0; display: grid; gap: 1.1rem; counter-reset: s; }
  @media (min-width: 900px) { .steps { grid-template-columns: repeat(3, 1fr); } }
  .steps li {
    counter-increment: s;
    background: var(--surface);
    border: 1px solid var(--edge-firm);
    border-radius: 3px;
    padding: 1.3rem 1.3rem 1.3rem 1.3rem;
    display: grid; gap: 0.45rem; align-content: start;
  }
  .steps li::before {
    content: counter(s);
    font-family: "GDisplay", Impact, sans-serif;
    font-size: 1.5rem; line-height: 1;
    width: 2.2rem; height: 2.2rem;
    display: grid; place-items: center;
    background: var(--honey); color: #14100A;
    border: 2px solid var(--ink); border-radius: 2px;
  }
  .steps h3 { font-size: 1rem; text-transform: uppercase; }
  .steps p { color: var(--text-dim); font-size: 0.95rem; }

  /* ---------- service detail ---------- */
  /* .svc itself is retired - the service list now uses .card (see the
     cols-3/.card rules above) to match the homepage. .svc__inc survives
     because the Catch-up & cleanup card still uses it for its pricing
     note, which is real information, not a restated feature list. */
  .svc__inc {
    font-size: 0.92rem; color: var(--text);
    background: var(--sunk); border-left: 3px solid var(--moss);
    padding: 0.7rem 0.9rem; border-radius: 2px; max-width: 68ch;
  }

  /* ---------- price ---------- */
  .price {
    background: var(--surface);
    border: 2px solid var(--ink);
    border-radius: 3px;
    box-shadow: 8px 8px 0 0 var(--bronze);
    overflow: hidden;
  }
  .price__top {
    background: var(--ink); color: var(--on-dark);
    padding: 1.3rem 1.4rem;
    display: flex; align-items: baseline; gap: 0.6rem; flex-wrap: wrap;
  }
  .price__num {
    font-family: "GDisplay", Impact, sans-serif;
    font-size: clamp(2rem, 1.4rem + 2.4vw, 3rem); line-height: 1;
    color: var(--honey);
  }
  .price__per { font-size: 0.95rem; color: rgba(250, 243, 228, 0.75); }
  .price table { width: 100%; border-collapse: collapse; }
  .price td { padding: 0.75rem 1.4rem; border-top: 1px solid var(--edge); vertical-align: top; }
  .price tr td:first-child {
    font-family: "GLabel", "Segoe UI", sans-serif;
    font-size: 0.78rem; letter-spacing: 0.11em; text-transform: uppercase;
    color: var(--text-dim); width: 1%; white-space: nowrap;
    /* .price td sets vertical-align:top for every cell, which reads fine
       for the paragraph in the second column but stranded the one-line
       label at the top of a row that the paragraph made two lines tall.
       Center just the label column against the row's real height. */
    vertical-align: middle;
  }
  .price tr:first-child td { border-top: 0; }
  .tbl-scroll { overflow-x: auto; }

  /* The Free Guide nav button is .btn .btn--sm .btn--ghost. `.btn--ghost` sets
     box-shadow:none, but `.btn--sm` appears LATER in this file at equal
     specificity and puts the bronze drop shadow back. The result was a
     transparent button carrying a shadow and no border, which reads as a
     rendering glitch rather than a button. Restore ghost's intent in the nav
     and give it a real outline so it is visibly a button. */
  .nav__links .btn--ghost {
    box-shadow: none;
    border: 1px solid var(--edge-firm);
    color: var(--text);
  }
  .nav__links .btn--ghost:hover { border-color: var(--ink); }

  /* On a phone the two-column terms table is the worst of both worlds: the
     nowrap label column takes roughly half the width and the sentences beside
     it wrap into three-word ribbons. Below 640px each row stacks instead,
     label above value, both full width. */
  @media (max-width: 640px) {
    .price table, .price tbody, .price tr, .price td { display: block; width: auto; }
    .price tr { border-top: 1px solid var(--edge); padding: 0.85rem 0; }
    .price tr:first-child { border-top: 0; }
    .price td { border-top: 0; padding: 0 1.1rem; }
    .price tr td:first-child {
      width: auto; white-space: normal; padding-bottom: 0.3rem;
    }
  }

  /* ---------- reviews ---------- */
  .quote {
    background: var(--surface);
    border: 1px solid var(--edge-firm);
    border-left: 5px solid var(--honey);
    border-radius: 3px; padding: 1.3rem;
    display: grid; gap: 0.8rem; align-content: start;
  }
  .quote__body { font-size: 1.02rem; }
  .quote__who {
    font-family: "GLabel", "Segoe UI", sans-serif;
    font-size: 0.78rem; letter-spacing: 0.1em; text-transform: uppercase;
    color: var(--text-dim);
  }
  /* Without this the review-source link falls back to the browser default blue,
     which is the one unstyled link on the site. --accent is theme-aware and is
     what body links already use. Found 2026-09-01 on the first real use of
     .quote, which had been written months earlier and never placed on a page. */
  .quote__who a { color: var(--accent); }
  .quote--pending { border-left-style: dashed; border-left-color: var(--edge-firm); }
  .quote--pending .quote__body { color: var(--text-dim); font-style: italic; }
  .pending-tag {
    display: inline-block;
    font-family: "GLabel", "Segoe UI", sans-serif;
    font-size: 0.66rem; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase;
    padding: 0.14rem 0.45rem; border-radius: 2px;
    background: var(--sunk); color: var(--accent); border: 1px solid var(--edge-firm);
  }

  /* ---------- contact ---------- */
  .facts { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.9rem; }
  .facts li { display: grid; gap: 0.15rem; }
  .facts dt, .facts .k {
    font-family: "GLabel", "Segoe UI", sans-serif;
    font-size: 0.74rem; letter-spacing: 0.13em; text-transform: uppercase; color: var(--text-dim);
  }
  .facts .v { font-size: 1.05rem; }
  .facts a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 3px; }
  .card a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 3px; }
  .sales a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 3px; }
  /* A .btn inside .sales must keep the button's OWN ink label. Without this,
     .sales a (specificity 0,1,1) outranks .btn (0,1,0) and repaints the label
     var(--accent), which in dark mode is the same #E8BC3E as the button's own
     background - a 1.0:1 gold-on-gold label, completely invisible. Hit the
     "Get the free guide instead" button in the sales page's no-QuickBooks
     branch. Found 2026-08-31. Same bug family as the .head/.legal fix. */
  .facts a.btn, .card a.btn, .sales a.btn,
  .post a.btn, .head a.btn, .form__note a.btn { color: #14100A; }
  .post a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 3px; }
  .head a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 3px; }

  /* Badge crossfade on the About page. Stacked absolutely, one visible
     (.on) at a time, JS swaps which one carries .on every few seconds.
     Deliberately a fade, not a spin - Intuit's own guidelines say not to
     rotate or distort the badge. */
  .badges { position: relative; width: 190px; height: 190px; margin: 1.8rem auto 0; }
  .badges img {
    position: absolute; inset: 0; width: 100%; height: 100%;
    object-fit: contain; opacity: 0; transition: opacity 1s ease;
  }
  .badges img.on { opacity: 1; }

  .form { display: grid; gap: 0.9rem; }
  .form label { display: grid; gap: 0.3rem; font-weight: 700; font-size: 0.93rem; }
  .form input, .form textarea, .form select {
    font: inherit; padding: 0.6rem 0.7rem;
    background: var(--surface); color: var(--text);
    border: 1px solid var(--edge-firm); border-radius: 2px;
  }
  .form textarea { min-height: 5rem; resize: vertical; }
  .form input:focus, .form textarea:focus, .form select:focus {
    outline: none; border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(138, 97, 20, 0.2);
  }

  /* Reserves the real Calendly footprint (min-width 320px, height 750px) so the
     page layout here matches what ships. The live widget cannot load in this
     preview: published pages block external hosts, and Calendly serves from
     assets.calendly.com. */
  .form__note {
    margin: 0.2rem 0 0;
    padding: 0.7rem 0.85rem;
    font-size: 0.92rem;
    background: var(--sunk);
    border-left: 3px solid var(--moss);
    border-radius: 2px;
    color: var(--text);
  }
  .form__note a { color: var(--accent); }
  .form__note--warn { border-left-color: var(--flag, #9A3412); }

  .slot {
    border: 2px dashed var(--edge-firm);
    border-radius: 3px; padding: 1.4rem 1.2rem;
    min-width: 320px; min-height: 460px;
    color: var(--text-dim); background: var(--sunk);
    display: grid; gap: 0.5rem; align-content: center; justify-items: center;
    text-align: center;
  }
  .slot b { color: var(--text); font-family: "GLabel", "Segoe UI", sans-serif; letter-spacing: 0.08em; text-transform: uppercase; font-size: 0.85rem; }
  .slot__grid {
    display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px;
    width: min(260px, 80%); margin-bottom: 0.4rem;
  }
  .slot__grid i {
    aspect-ratio: 1; border-radius: 2px;
    background: var(--edge); display: block;
  }
  .slot__grid i:nth-child(3n+2) { background: var(--honey); opacity: 0.55; }
  .slot__note { font-size: 0.8rem; max-width: 34ch; }

  /* ---------- apiary photos ---------- */
  /* grid-template-columns: 1fr is deliberate, not decorative - without it the
     implicit column auto-sizes to its widest CONTENT, and a video/img's
     intrinsic size counts as content even at width:100%. One 960px-wide
     video blew the whole grid out to 960px on a 375px phone. min-width: 0
     on .pic is the other half of the fix - a grid item's min-width defaults
     to auto (= its content's intrinsic size for replaced elements), which
     overrides width:100% and stops it from ever shrinking below that. Found
     2026-08-26 after it shipped broken on mobile; do not remove either rule. */
  .pics { display: grid; gap: 1rem; grid-template-columns: 1fr; }
  @media (min-width: 720px) { .pics { grid-template-columns: 1fr 1fr; } }

  .pic { margin: 0; display: grid; gap: 0.6rem; min-width: 0; }
  .pic img {
    width: 100%; height: auto; display: block;
    aspect-ratio: 3 / 4; object-fit: cover;
    border: 2px solid var(--ink);
    border-radius: 3px;
    box-shadow: 6px 6px 0 0 var(--bronze);
    background: var(--sunk);
  }
  .pic video {
    width: 100%; height: auto; display: block;
    aspect-ratio: 3 / 4; object-fit: cover;
    border: 2px solid var(--ink);
    border-radius: 3px;
    box-shadow: 6px 6px 0 0 var(--bronze);
    background: var(--sunk);
  }
  .pic figcaption {
    font-family: "GLabel", "Segoe UI", sans-serif;
    font-size: 0.78rem; letter-spacing: 0.06em;
    color: var(--text-dim);
  }

  /* ---------- Where we work: text beside the desk photo ---------- */
  /* Same text-left/image-right idea as .hero__grid. Below 900px this drops
     to one column and the photo stacks under the text, same as the hero
     does on a phone. Without this the section was just a 62ch text column
     with a huge dead gap beside it on anything wider than a phone - the
     photo belongs in that gap, not stacked under paragraphs nobody needs
     to scroll past to see it. */
  .work-split { display: grid; gap: clamp(1.6rem, 4vw, 3rem); align-items: center; }
  @media (min-width: 900px) { .work-split { grid-template-columns: 1.1fr 0.9fr; } }

  /* Same border/shadow language as .pic, but .pic locks a 3:4 PORTRAIT
     ratio for the honey gallery's phone photos - forcing a landscape shot
     into that crops both sides off, so this desk photo gets its own class
     at its native 3:2 landscape ratio instead. */
  .deskpic { margin: 0; }
  .deskpic img {
    width: 100%; height: auto; display: block;
    aspect-ratio: 3 / 2; object-fit: cover;
    border: 2px solid var(--ink);
    border-radius: 3px;
    box-shadow: 6px 6px 0 0 var(--bronze);
    background: var(--sunk);
  }
  .deskpic figcaption {
    font-family: "GLabel", "Segoe UI", sans-serif;
    font-size: 0.78rem; letter-spacing: 0.06em;
    color: var(--text-dim);
    margin-top: 0.6rem;
  }

  /* ---------- cross-link ---------- */
  .cross {
    display: grid; gap: 0.6rem;
    background: var(--sunk); border: 1px solid var(--edge-firm);
    border-radius: 3px; padding: 1.3rem;
  }
  .cross__tag {
    font-family: "GLabel", "Segoe UI", sans-serif;
    font-size: 0.68rem; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase;
    color: var(--ink); background: var(--honey);
    padding: 0.16rem 0.5rem; border-radius: 2px; justify-self: start;
  }

  /* ---------- footer ---------- */
  .foot {
    background: var(--ink); color: rgba(250, 243, 228, 0.72);
    padding: 2.2rem 0 2.6rem; font-size: 0.9rem;
  }
  .foot__in { display: grid; gap: 1.2rem; }
  @media (min-width: 760px) { .foot__in { grid-template-columns: 1.3fr 1fr 1fr; align-items: start; } }
  /* Footer link column. Added 2026-09-01: the footer carried contact info and
     an Apiary teaser and no way to reach any other page, so every route into
     About/Services/FAQ/Blog/Privacy ran through the hamburger menu alone. */
  .foot__links { margin-top: 0.4rem; display: grid; gap: 0.35rem; }
  /* Contact lines stack instead of running inline. Inline, the phone number
     broke mid-number ("(970) 880-" / "2028") once the footer went to three
     columns and each column got narrower. Added 2026-09-01. */
  .foot__contact { margin-top: 0.4rem; display: grid; gap: 0.35rem; }
  .foot__contact a, .foot a[href^="tel:"] { white-space: nowrap; }
  .foot b { color: var(--on-dark); font-family: "GDisplay", Impact, sans-serif; text-transform: uppercase; letter-spacing: 0.02em; }
  .foot a { color: var(--honey); }
  .foot__note { font-size: 0.82rem; color: rgba(250, 243, 228, 0.5); }
  /* Phone-width footer links. Added 2026-09-18: each link was 23px tall with
     about 6px between rows, so a thumb could land on the neighbor. Under 760px
     (where the footer is one stacked column) every link becomes a 44px-tall
     target. The rows' own gap drops to 0 because the padding now supplies it.
     Desktop is untouched. */
  @media (max-width: 759px) {
    .foot__links, .foot__contact { gap: 0; }
    .foot__links a, .foot__contact a { display: block; padding: 0.66rem 0; }
    .foot__contact span { padding-bottom: 0.35rem; }
  }

  .note {
    width: var(--shell); margin: 0 auto;
    padding: 0.6rem 0; font-size: 0.8rem; color: var(--text-dim);
    border-top: 1px solid var(--edge);
  }

  @media (prefers-reduced-motion: reduce) {
    *, .page.on { animation: none !important; transition: none !important; }
  }
  /* ---------- nav menu ----------
     Collapses the five section links behind one MENU button. Before this the
     nav carried six items plus the consult button; on a phone that row wrapped
     and pushed Free Consult off the edge, killing the only conversion path.
     Free Guide and Free Consult deliberately stay OUTSIDE the menu - they are
     the two things a visitor should be able to reach without a click first. */
  .menu { position: relative; }

  .menu__btn { display: inline-flex; align-items: center; gap: 0.55rem; }
  .menu__bars { display: grid; gap: 3px; width: 17px; flex: 0 0 auto; }
  .menu__bars i {
    display: block; height: 2px; background: currentColor; border-radius: 1px;
  }
  .menu__btn[aria-expanded="true"] {
    color: var(--nav-on); border-bottom-color: var(--nav-line);
  }

  .menu__panel {
    position: absolute; top: calc(100% + 0.45rem); left: 0;
    min-width: 14rem; max-width: min(20rem, 88vw);
    display: grid;
    padding: 0.3rem;
    background: var(--surface);
    border: 2px solid var(--ink);
    border-radius: 3px;
    box-shadow: 5px 5px 0 0 var(--bronze);
    z-index: 60;
  }
  /* display:grid above would otherwise defeat the hidden attribute */
  .menu__panel[hidden] { display: none; }

  .menu__panel a {
    padding: 0.62rem 0.85rem;
    border-bottom: 0;
    border-radius: 2px;
    white-space: nowrap;
  }
  .menu__panel a:hover,
  .menu__panel a[aria-current="page"] {
    background: var(--sunk);
    color: var(--nav-on);
    border-bottom-color: transparent;
  }

  @media (max-width: 860px) {
    /* nav__links becomes a full-width row below the brand, so anchor the panel
       to the left edge of that row rather than letting it hang off-screen. */
    .menu__panel { min-width: 13rem; }
  }
  /* Same trap as `.nav__links a` vs `.btn--sm` above, this time on color:
     removing .btn--ink from Free Guide leaves only bare `.btn` (0,1,0) to
     set its honey background/black text, and `.nav__links a` (0,1,1) beats
     that, so the button rendered transparent with dim nav-colored text.
     `.nav__links a.btn` at (0,2,1) wins it back. The .btn--ink rule below
     is extended with the same-strength `.nav__links a.btn--ink` and placed
     after this, so ink still wins the tie for Free Quiz. */
  .nav__links a.btn { background: var(--honey); color: #14100A; }

  /* ---------- Free Guide nav button ----------
     Was .btn--ghost: transparent with a hairline border, sitting next to the
     solid gold Free Consult button, so it read as the lesser option. It is
     actually the EASIER yes of the two and the one that builds the email list,
     which is the asset Ethan actually owns. Ink fill with honey text gives it
     the highest contrast on the row while staying inside the existing palette,
     and it does not fight the gold because it is a different value, not a
     different loudness.

     Declared at the end of the file on purpose: .btn--sm sets its own
     box-shadow at equal specificity earlier on, and would otherwise win. */
  /* SPECIFICITY, the trap this file already warns about once: `.nav__links a`
     is (0,1,1) and sets background:none, border:0 and color:var(--nav-idle).
     A bare `.btn--ink` is (0,1,0) and LOSES to it, so the button rendered
     transparent with nav-colored text. Scoping to `.nav__links .btn--ink`
     (0,2,0) is what actually makes it win. Verified in the browser, not
     assumed. */
  .btn--ink,
  .nav__links .btn--ink,
  .nav__links a.btn--ink {
    background: var(--ink);
    color: var(--honey);
    border: 2px solid var(--ink);
    border-bottom: 2px solid var(--ink);
    box-shadow: 4px 4px 0 0 var(--bronze);
  }
  .btn--ink:hover,
  .nav__links .btn--ink:hover {
    transform: translate(-2px, -2px);
    box-shadow: 6px 6px 0 0 var(--bronze);
    color: #FFDD7A;
    border-bottom-color: var(--ink);
  }
  .btn--ink:focus-visible,
  .nav__links .btn--ink:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }

  /* Same trap, one property left: .btn--ink's box-shadow (4px 4px, above) is
     also (0,2,0) and sits later in the file than .btn--sm, so it still won
     the shadow depth even after the padding/font-size fix near .btn--sm's
     definition. `.nav__links a.btn--sm` at (0,2,1) beats it outright. */
  .nav__links a.btn--sm { box-shadow: 3px 3px 0 0 var(--bronze); }
