/* ==========================================================================
   Chunk Chunk — landing page
   ==========================================================================

   Layered on ../brand/brand.css, which owns every colour, radius, shadow and
   the type stack. Nothing here introduces a new hue: if a value looks like a
   colour below, it is a token or an alpha of one.

   Rules inherited from the brand and enforced here:
   · --orange is UI and chart only. It is never a text colour on this page.
   · The banknote green is a STATUS colour, never a chart series.
   · Body copy uses --label, not --label-2 (4.29:1, under AA). Size and
     weight carry the hierarchy instead. --label-2 is captions only.
   · Every currency figure is tabular.
   · No webfonts. System stack, offline-capable, same as the app.
   ========================================================================== */

/* ── page scaffold ──────────────────────────────────────────────────── */

body { overflow-x: hidden; }

.wrap { max-width: 1120px; margin: 0 auto; padding: 0 24px; }
.wrap-narrow { max-width: 780px; }

.band { padding: 96px 0; }
.band-alt { background: var(--surface-2); }

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--surface); color: var(--blue);
  padding: 10px 16px; border-radius: var(--radius-sm);
  font-weight: 600;
}
.skip:focus { left: 12px; top: 12px; }

/* ── chrome ─────────────────────────────────────────────────────────── */

.site-chrome .chrome-inner {
  max-width: 1120px; margin: 0 auto;
  /* 14, not the old 10. The lockup is 48px where the mark was 28, and at 8px
     of clearance it measured correct and LOOKED crammed: every item in the
     row centres on exactly 32, but the nav text carries 15px of air and the
     artwork carried 8, so the dense art read as jammed against both edges.
     Four paddings were rendered and compared; this is the one where the
     lockup breathes without shrinking it, and its size is what makes the
     wordmark legible at all. Bar = 14 + 48 + 14 + 1px border = 77px. */
  padding: 14px 24px;
  display: flex; align-items: center; gap: 16px;
}
.chrome-brand {
  display: flex; align-items: center; gap: 10px;
  text-decoration: none; color: inherit;
}
.chrome-title { font-size: 15px; font-weight: 600; letter-spacing: -0.01em; }
/* The header lockup. Height-driven: the file is trimmed to its own ink, so
   width follows the art and never needs restating if the master changes. */
.chrome-lockup { height: 48px; width: auto; display: block; flex: none; }

/* The desktop bar, and below 900px the phone menu's panel — one set of
   elements, two layouts. It carries the auto margin .chrome-nav used to hold,
   which is what makes the desktop row render exactly as it did before the
   wrapper existed: nav, Log in, moon and CTA, all pushed right as one group. */
/* ONE LINE, OR THE MENU BUTTON. v2.10 added an eighth link, How-to videos,
   and on Vic's iPad in landscape (1024) every two-word label broke onto two
   lines: the row needed 1,069px of a 976px bar. It had been 3px from full at
   1440 all along, and it wrapped at 920 before v2.10 too. So the links carry
   6px a side, not 11, the gaps are 10px, not 16 and 2, and nothing may wrap:
   the whole bar measures 959px (963 on a touch screen) against 976 at 1024.
   Below 1020 the menu button takes over (the query further down). checkSiteMenu()
   counts the line boxes of every item, because a wrapped link is neither
   an overflow nor a page error and every gate here missed it. */
.chrome-menu-panel {
  margin-left: auto;
  display: flex; align-items: center; gap: 10px;
}
.chrome-nav { display: flex; gap: 0; }
.chrome-nav a {
  color: var(--label); text-decoration: none; white-space: nowrap;
  font-size: 13.5px; font-weight: 500;
  padding: 7px 6px; border-radius: var(--radius-sm);
  transition: background .2s var(--ease);
}
.chrome-nav a:hover { background: var(--surface-2); }
.chrome-cta { text-decoration: none; }
/* Both are phone-only. Hidden with `display`, never the `hidden` attribute:
   hidden carries !important and no media query could show them again.

   .site-chrome-prefixed, and it took two goes. a.btn further down this
   file is (0,1,1), so a bare .chrome-menu-cta at (0,1,0) loses outright
   and a.chrome-menu-cta at (0,1,1) TIES and then loses on source order,
   because every chrome rule here sits above line 147. Both times the
   panel's Get started rendered in the desktop bar as a second CTA, and
   both times it was measured rather than seen. (0,2,0) beats (0,1,1)
   outright, whatever the order. Same shape as the .btn-theme svg fault
   above, which drew a moon and a sun at once. */
.site-chrome .chrome-menu { display: none; }
.site-chrome .chrome-menu-cta { display: none; }

/* Styled as a nav link because that is what it is, but it lives outside
   <nav aria-label="Sections"> because it is a page and not a section. */
.chrome-login {
  color: var(--label); text-decoration: none; white-space: nowrap;
  font-size: 13.5px; font-weight: 600;
  padding: 7px 6px; border-radius: var(--radius-sm);
  transition: background .2s var(--ease);
}
.chrome-login:hover { background: var(--surface-2); }
.chrome-login:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--ring); }

/* The Day/Night toggle. Same shape as the app's — see styles.css — but the
   landing page loads brand.css and site.css, not the app's stylesheet, so the
   rule has to exist in both places. Kept byte-identical on purpose. */
.btn-theme {
  flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px;
  border: 0; border-radius: 999px;
  background: none; color: var(--label-2);
  cursor: pointer; padding: 0;
  transition: color .2s var(--ease), background .2s var(--ease);
}
/* No `display` here. It was `display: block` and that is 0,1,1 against
   .theme-sun's 0,1,0, so the hide rule below lost and the button rendered a
   moon AND a sun side by side. Caught by looking at the capture, not by any
   check — which is why checkThemeToggle() now counts the visible icons. */
.btn-theme svg { width: 18px; height: 18px; }
.btn-theme:hover { color: var(--blue); background: var(--surface-2); }
.btn-theme:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--ring); }
.btn-theme .theme-moon { display: block; }
.btn-theme .theme-sun { display: none; }
:root[data-theme="dark"] .btn-theme .theme-sun { display: block; }
:root[data-theme="dark"] .btn-theme .theme-moon { display: none; }

/* The phone menu. Everything up to 1020px since v2.10 (900 before it), which
   is below the width the one-line bar needs; see .chrome-menu-panel above.

   The panel is the SAME elements the desktop bar uses, absolutely positioned
   under the chrome. Not a second copy of the seven links: two lists is two
   places to edit and one to forget. */
@media (max-width: 1020px) {
  .site-chrome .chrome-menu {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 44px; min-height: 44px;
    flex: none;
    border: 0; background: none; padding: 0;
    color: var(--label-2);
    border-radius: var(--radius-sm); cursor: pointer;
    transition: color .2s var(--ease), background .2s var(--ease);
  }
  .chrome-menu svg { width: 22px; height: 22px; }
  .chrome-menu:hover { color: var(--blue); background: var(--surface-2); }
  .chrome-menu[aria-expanded="true"] { color: var(--blue); background: var(--surface-2); }
  .chrome-menu:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--ring); }

  /* Absolute against .chrome-inner, so it hangs under the bar rather than
     growing it. Out of flow, which is also why .btn-theme keeps the auto
     margin below: the panel is not a flex item here at all. */
  .site-chrome .chrome-inner { position: relative; }
  .chrome-menu-panel {
    display: none;
    /* 24px, not 0: an absolutely positioned box resolves `right` against
       the containing block's PADDING box, so right:0 sat flush with the
       bar's outer edge and overhung the menu button by the full 24px of
       .chrome-inner padding. It is 16px below 400, where that padding is. */
    position: absolute; top: calc(100% + 9px); right: 24px; z-index: 30;
    flex-direction: column; align-items: stretch; gap: 2px;
    min-width: 232px; margin: 0; padding: 8px;
    background: var(--surface);
    border: 1px solid var(--separator);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
  }
  .chrome-menu-panel.is-open { display: flex; }
  .chrome-nav { flex-direction: column; align-items: stretch; gap: 2px; }
  /* 44px, because a coarse pointer is the only thing that ever opens this.
     display:flex on the anchors for the same reason a.btn carries it in this
     file: an anchor does not centre its own text inside a min-height box the
     way a button does, and the two would sit 5.84px apart. */
  .chrome-nav a, .chrome-menu-panel .chrome-login {
    display: flex; align-items: center;
    min-height: 44px; padding: 10px 12px;
    font-size: 15px;
  }
  /* Log in is a page, not a section, so it reads as its own group. */
  .chrome-menu-panel .chrome-login {
    margin-top: 6px; padding-top: 14px;
    border-top: 1px solid var(--separator);
    border-radius: 0 0 var(--radius-sm) var(--radius-sm);
  }
  /* The auto margin sits on the TOGGLE, not on .chrome-cta. With it on the CTA
     the moon stayed parked where the nav used to start: measured at 390 it was
     16px from the logo with a 70.5px void to its right, which is the
     "alignment issue on mobile" Vic saw. Moving it makes the moon, the CTA and
     the menu button travel right together as one group.

     Only ONE item may carry it. Two auto margins in a flex row split the free
     space between them, which strands the moon in the middle instead: a
     different wrong answer, not a fix. */
  .btn-theme { margin-left: auto; }
}

/* At 320 the CTA wrapped to two lines and the bar grew 77 -> 94.5px, which
   left :target { scroll-margin-top: 98px } with 3.5px of clearance instead of
   21 and dropped anchor links under the header.

   nowrap alone overflows: 110 lockup + 16 gap + 32 moon + 16 gap + 113 CTA +
   48 padding = 335 in a 320 viewport. Giving back 16px of side padding and 8px
   of gap lands it at 311, so it fits with 9px spare and the bar holds at 77px
   across every phone width. */
@media (max-width: 400px) {
  .site-chrome .chrome-inner { padding: 14px 16px; gap: 12px; }
  .chrome-cta { white-space: nowrap; }
  /* Follows .chrome-inner's padding down, so the panel keeps lining up
     with the button that opens it. */
  .chrome-menu-panel { right: 16px; }
}

/* The menu button costs 44px plus a 12px gap, and the four measured widths do
   not all have it. Measured on the real bar, content box against items:

     320   288 available   291.4 used   OVER by 3.4     (and 335.4 with the CTA)
     360   328 available   335.4 used   OVER by 7.4
     390   358 available   335.4 used   22.6 spare
     430   382 available   347.4 used   34.6 spare

   So 390 and up keep the 48px lockup, which is what makes the wordmark legible
   at all, and only the widths that cannot afford it step down. 40px yields
   ~92px against 110.3 and buys back 18.4px, which clears 360 and 375. */
@media (max-width: 380px) {
  .chrome-lockup { height: 40px; }
}

/* THE ONE-LINE BAR'S TIGHT BAND, since 3.1.3. The lockup went from 110 to
   142px wide at 48 tall (Winnie beside the varsity wordmark), and swept a
   pixel at a time on the real bar, "Get started" wraps onto two lines from
   1021 to 1039px at 48: below 1021 the menu button takes over, and from 1040
   there is room. 1024 is an iPad held sideways. 40px (118px wide) clears it;
   42 cleared it by almost nothing. The band runs on to 1119 for margin, since
   Safari's text is not Chrome's. */
@media (min-width: 1021px) and (max-width: 1119px) {
  .chrome-lockup { height: 40px; }
}

/* 320 is still 29px short of holding both the CTA and the menu button, and no
   padding or gap left to give back. The CTA moves INTO the menu rather than
   shrinking: a primary action rendered at two different sizes depending on the
   phone is worse than one that is always full size and always one tap away. */
@media (max-width: 340px) {
  /* .site-chrome-prefixed for the specificity reason above. The bare
     class lost to a.btn and the button stayed on screen, overflowing 320
     by 13px with the menu button beside it. */
  .site-chrome .chrome-cta { display: none; }
  .site-chrome .chrome-menu-cta {
    display: flex; min-height: 44px;
    margin-top: 6px;
  }
}
/* ── buttons ────────────────────────────────────────────────────────── */

.btn-lg { font-size: 15px; padding: 12px 22px; border-radius: 12px; }

.btn-ghost {
  background: transparent;
  color: var(--blue);
  box-shadow: inset 0 0 0 1.5px currentColor;
}
.btn-ghost:hover { background: rgba(52, 96, 160, .08); }

a.btn { display: inline-flex; align-items: center; justify-content: center;
        text-decoration: none; }

/* ── hero ───────────────────────────────────────────────────────────── */

/* The illustration is the ground, not a decoration behind text. Its left
   two-thirds is flat blue by construction, which is where the copy sits —
   cream on that blue measures 6.42:1. */
.hero {
  position: relative;
  isolation: isolate;
  min-height: min(78vh, 720px);
  display: flex; align-items: center;
  overflow: hidden;
  background: #2D569B;              /* the illustration's own field, measured
                                       by hero-build.js — not picked by eye */
}
.hero-art { position: absolute; inset: 0; z-index: -2; }
.hero-art img {
  width: 100%; height: 100%;
  /* Biased upward: a centre crop on this aspect cuts her ears and clip off
     the top, which is the half that carries the mark's identity. */
  object-fit: cover; object-position: 100% 22%;
  display: block;
}
/* Insurance, not correction: at narrow widths the dog drifts left toward the
   copy. This keeps the text ground flat however the image crops. */
.hero::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(100deg,
    #2D569B 0%, #2D569B 34%, rgba(45,86,155,.92) 48%, rgba(45,86,155,0) 68%);
}

.hero-inner {
  position: relative;
  max-width: 1120px; margin: 0 auto; padding: 96px 24px;
  width: 100%;
}
.hero-eyebrow {
  margin: 0 0 14px;
  font-size: 12px; font-weight: 700; letter-spacing: .1em;
  text-transform: uppercase;
  color: rgba(250, 242, 232, .82);
}
.hero-title {
  margin: 0 0 18px;
  max-width: 16ch;
  font-size: clamp(38px, 5.4vw, 62px);
  font-weight: 700; letter-spacing: -0.028em; line-height: 1.06;
  color: #FAF2E8;
}
.hero-lede {
  margin: 0 0 30px; max-width: 46ch;
  font-size: 17px; line-height: 1.55;
  color: rgba(250, 242, 232, .92);
}
.hero-cta { display: flex; gap: 12px; flex-wrap: wrap; }

/* On the blue field the standard button colours would vanish, so the hero
   pair is inverted: cream fill, cream outline. */
.hero .btn-primary { background: #FAF2E8; color: #1C2A3D; }
.hero .btn-primary:hover { opacity: .9; }
.hero .btn-ghost { color: #FAF2E8; }
.hero .btn-ghost:hover { background: rgba(250, 242, 232, .14); }

.hero-note {
  margin: 22px 0 0;
  font-size: 13.5px;
  color: rgba(250, 242, 232, .78);
  font-variant-numeric: tabular-nums;
}

@media (max-width: 820px) {
  .hero { min-height: 0; }
  .hero-inner { padding: 72px 24px; }
  .hero-art img { object-position: 72% center; }
  /* Held near-opaque all the way down, not faded out. The copy stacks full
     width here, so the last line lands over her paw — at .72 the note
     measured 3.2:1, under AA. Glyph-accurate measurement, not the block box:
     a full-width <p> box spans the dog even when its text does not. */
  .hero::before {
    background: linear-gradient(180deg,
      rgba(36,88,156,.97) 0%, rgba(36,88,156,.95) 55%, rgba(36,88,156,.94) 100%);
  }
  .hero-note { color: rgba(250, 242, 232, .9); }
  .hero-title { max-width: none; }
}

/* ── the tour ───────────────────────────────────────────────────────── */

/* Lifts out of the hero. The video is a light composition — its luminance
   peaks at 1.0 right where a headline would sit — so it is shown as an
   artifact rather than used as a text ground. */
.tour { padding: 0 0 96px; margin-top: -72px; position: relative; z-index: 1; }
.tour-frame { margin: 0; }
.tour-bezel {
  position: relative;
  border-radius: 18px;
  overflow: hidden;
  background: var(--brand-ink);
  box-shadow: 0 2px 6px rgba(28,42,61,.18), 0 30px 70px rgba(28,42,61,.32);
  border: 1px solid rgba(250,242,232,.14);
}
.tour-video {
  display: block; width: 100%; height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  background: #24589C;
}

.tour-btn {
  position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  display: inline-flex; align-items: center; gap: 11px;
  padding: 13px 22px 13px 18px;
  border: 0; border-radius: 999px; cursor: pointer;
  font: inherit; font-size: 14.5px; font-weight: 600;
  color: #1C2A3D; background: rgba(250, 242, 232, .94);
  box-shadow: 0 2px 6px rgba(28,42,61,.2), 0 14px 34px rgba(28,42,61,.3);
  transition: opacity .28s var(--ease), transform .2s var(--ease);
}
@media (hover: hover) {
  .tour-btn:hover { transform: translate(-50%, -50%) scale(1.03); }
}
.tour-btn:focus-visible { outline: none; box-shadow: 0 0 0 4px var(--ring); }
.tour-btn-icon {
  width: 0; height: 0;
  border-left: 13px solid currentColor;
  border-top: 8px solid transparent;
  border-bottom: 8px solid transparent;
  margin-left: 3px;
}
/* Playing: the button retreats but stays reachable — it is the only pause.
   "Reachable" was a lie on a phone. It hid at opacity 0 with pointer-events
   off and came back only on :hover or :focus-visible, neither of which a
   touch tap produces — so the tour started and could not be stopped. Measured
   at 390px: after clicking play the computed style was opacity 0,
   pointer-events none, with no way back.

   So the retreat is now gated on a pointer that can hover. On touch it dims
   instead of vanishing and keeps its hits, which reads as a retreated control
   rather than a missing one. checkTourPausable() in preview.js gates it. */
@media (hover: hover) {
  .is-playing .tour-btn { opacity: 0; pointer-events: none; }
  .tour-bezel:hover .tour-btn { opacity: 1; pointer-events: auto; }
}
@media (hover: none) {
  .is-playing .tour-btn { opacity: .55; pointer-events: auto; }
  .is-playing .tour-btn:active { opacity: 1; }
}
.tour-btn:focus-visible { opacity: 1; pointer-events: auto; }
.is-playing .tour-btn-icon {
  width: 12px; height: 15px; border: 0; margin-left: 0;
  border-left: 4px solid currentColor;
  border-right: 4px solid currentColor;
}

.tour-cap {
  margin: 14px 2px 0;
  font-size: 13px; color: var(--label-2);
}


@media (max-width: 820px) {
  .tour { margin-top: -40px; padding-bottom: 72px; }
  .tour-btn-text { display: none; }
  .tour-btn { padding: 16px 18px; }
}

/* ── section heads ──────────────────────────────────────────────────── */

.sec-head { max-width: 62ch; margin-bottom: 44px; }
.eyebrow {
  margin: 0 0 12px;
  font-size: 11.5px; font-weight: 700; letter-spacing: .1em;
  text-transform: uppercase; color: var(--blue);
}
.sec-head h2 {
  margin: 0 0 14px;
  font-size: clamp(28px, 3.4vw, 40px);
  font-weight: 700; letter-spacing: -0.024em; line-height: 1.12;
}
.sec-lede { margin: 0; font-size: 17px; line-height: 1.55; color: var(--label); }

/* ── the wall ───────────────────────────────────────────────────────── */

.wall-grid {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 32px; align-items: start;
}
@media (max-width: 860px) { .wall-grid { grid-template-columns: minmax(0,1fr); } }

.receipt-list { margin: 0; }
/* AN AMOUNT IS NEVER BROKEN, AND NEVER LEAVES THE CARD (v3.1.2). The row
   used to squeeze the label to one word a line and let the amount run out
   of the card: at 250px (a 375pt iPhone with Larger Text on) $2,055.09 ran
   36px past the edge, and at 320 "−" wrapped away from "$1,294.91". Now
   the amount is nowrap, and when the label would get narrower than 6em the
   amount drops to its own line, right-aligned. 375 and wider look exactly as
   they did. */
.receipt-row {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between;
  gap: 4px 20px; padding: 13px 0;
  border-bottom: 1px solid var(--separator);
}
.receipt-row dt { font-size: 15px; flex: 1 1 6em; }
.receipt-row dd { margin: 0 0 0 auto; font-size: 16px; font-weight: 600; white-space: nowrap; text-align: right; }
.receipt-row dt span { color: var(--label-2); font-size: 13px; }
.receipt-total {
  border-bottom: 0; padding-top: 18px;
  border-top: 2px solid var(--label);
  margin-top: 4px;
}
.receipt-total dt { font-weight: 700; font-size: 16px; }
.receipt-total dd { font-size: 26px; font-weight: 700; letter-spacing: -.02em; }
.pos { color: var(--label); }
.neg { color: var(--label); }
.receipt-total .num { color: var(--green); }
.receipt-note {
  margin: 18px 0 0; font-size: 13.5px; line-height: 1.5; color: var(--label-2);
}

.wall-copy { display: flex; flex-direction: column; gap: 28px; padding-top: 6px; }
.pt h3 {
  margin: 0 0 8px; font-size: 19px; font-weight: 700; letter-spacing: -.015em;
}
.pt p { margin: 0; font-size: 15.5px; line-height: 1.6; color: var(--label); }

/* ── steps ──────────────────────────────────────────────────────────── */

/* Every auto-fit grid on this page takes min(N, 100%) as its floor, never a
   bare N (v3.1.1). A bare 272px floor made the page 296px wide at the 250px a
   375pt iPhone lays it out in under Larger Text, and iOS zooms the WHOLE page
   out to fit, which is what Vic saw: every section stopping at 84% of the
   screen. preview.js's site-zoom pass measures it. */

.steps {
  list-style: none; margin: 0 0 32px; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
  gap: 20px;
}
.step { position: relative; padding-top: 26px; }
.step-n {
  position: absolute; top: -16px; left: 20px;
  width: 34px; height: 34px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--blue); color: #fff;
  font-size: 15px; font-weight: 700;
  font-variant-numeric: tabular-nums;
  box-shadow: 0 3px 10px rgba(28,42,61,.2);
}
.step h3 { margin: 0 0 8px; font-size: 17px; font-weight: 700; }
.step p { margin: 0; font-size: 14.5px; line-height: 1.55; color: var(--label); }

.flow-svg svg { display: block; width: 100%; height: auto; }

/* ── product ────────────────────────────────────────────────────────── */

.tiles { margin-bottom: 24px; }

.chart-card { padding: 22px 24px 18px; }
.legend {
  display: flex; gap: 18px; flex-wrap: wrap;
  margin-bottom: 6px;
}
.legend-item {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 12.5px; font-weight: 600; color: var(--label);
}
.legend-swatch {
  width: 11px; height: 11px; border-radius: 3px; flex: none;
}
.chart { display: block; width: 100%; height: 300px; overflow: visible; }

/* ── strategies ─────────────────────────────────────────────────────── */

.strat { max-width: 860px; }
.strat .segmented { margin-bottom: 22px; }
.strat .segmented button { font-size: 13.5px; padding: 9px 6px; }

.strat-panel .card { padding: 26px 28px; }
.strat-note {
  margin: 0 0 22px; font-size: 17px; line-height: 1.5; color: var(--label);
}
.strat-stats {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr));
  gap: 22px;
}
.strat-stat dt {
  font-size: 11px; font-weight: 600; text-transform: uppercase;
  letter-spacing: .06em; color: var(--label-2); margin-bottom: 5px;
}
.strat-stat dd {
  margin: 0; font-size: 27px; font-weight: 600; letter-spacing: -.025em;
  font-variant-numeric: tabular-nums;
}
.strat-stat.is-best dd { color: var(--green); }
.strat-stat small {
  display: block; margin-top: 4px; font-size: 12px; font-weight: 400;
  letter-spacing: 0; color: var(--label-2);
}

/* ── the honest close ───────────────────────────────────────────────── */

.honest { background: var(--brand-ink); }
.honest-inner { max-width: 700px; margin: 0 auto; text-align: center; }
.honest-mark { margin-bottom: 22px; }
.honest h2 {
  margin: 0 0 20px;
  font-size: clamp(28px, 3.4vw, 40px);
  font-weight: 700; letter-spacing: -.024em; line-height: 1.12;
  color: #FAF2E8;
}
.honest p {
  margin: 0 0 16px; font-size: 17px; line-height: 1.6;
  color: rgba(250, 242, 232, .92);
}
.honest strong { color: #FAF2E8; white-space: nowrap; }
.honest-sub { font-size: 15px !important; color: rgba(250,242,232,.72) !important; }

/* ── pricing ────────────────────────────────────────────────────────── */

.tiers {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(272px, 100%), 1fr));
  gap: 20px; align-items: stretch;   /* equal height so the CTAs line up */
}
.tier { display: flex; flex-direction: column; padding: 28px 26px; }
.tier-feature {
  position: relative;
  box-shadow: 0 2px 6px rgba(28,42,61,.10), 0 20px 48px rgba(28,42,61,.16);
  outline: 2px solid var(--blue);
  outline-offset: -2px;
}
.tier-flag {
  position: absolute; top: -11px; left: 26px;
  background: var(--blue); color: #fff;
  font-size: 10.5px; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase;
  padding: 4px 10px; border-radius: 999px;
}
/* The Pro badge on the calculators section reuses .tier-flag's pill, but that
   rule is absolutely positioned for the pricing card's corner — dropped into
   an eyebrow it flies out of the section entirely. Scoped override only; the
   pricing cards are untouched. */
.eyebrow .tier-flag {
  position: static; display: inline-block;
  margin-left: 8px; vertical-align: 1px;
}

.tier-name {
  margin: 0 0 10px; font-size: 13px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .07em; color: var(--label-2);
}
.tier-price { margin: 0 0 6px; display: flex; align-items: baseline; gap: 4px; }
.tier-amt {
  font-size: 42px; font-weight: 700; letter-spacing: -.03em;
  font-variant-numeric: tabular-nums;
}
.tier-per { font-size: 15px; color: var(--label-2); }
.tier-note { margin: 0 0 22px; font-size: 13.5px; color: var(--label-2); }
.tier-list {
  list-style: none; margin: 0 0 26px; padding: 0;
  font-size: 14.5px; line-height: 1.5;
}
.tier-list li {
  position: relative; padding-left: 26px; margin-bottom: 11px;
}
.tier-list li::before {
  content: ""; position: absolute; left: 4px; top: 6px;
  width: 10px; height: 6px;
  border-left: 2px solid var(--green);
  border-bottom: 2px solid var(--green);
  transform: rotate(-45deg);
}
.tier-cta { margin-top: auto; width: 100%; }
.tiers-foot {
  margin: 26px 0 0; font-size: 13px; color: var(--label-2); text-align: center;
}

/* ── faq ────────────────────────────────────────────────────────────── */

.faq details {
  border-bottom: 1px solid var(--separator);
  padding: 4px 0;
}
.faq summary {
  cursor: pointer; list-style: none;
  padding: 18px 40px 18px 0; position: relative;
  font-size: 17px; font-weight: 600;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: ""; position: absolute; right: 8px; top: 50%;
  width: 9px; height: 9px; margin-top: -6px;
  border-right: 2px solid var(--label-2);
  border-bottom: 2px solid var(--label-2);
  transform: rotate(45deg);
  transition: transform .2s var(--ease);
}
.faq details[open] summary::after { transform: rotate(-135deg); margin-top: -2px; }
.faq summary:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--ring); border-radius: 6px; }
.faq details p {
  margin: 0 0 20px; padding-right: 40px;
  font-size: 15.5px; line-height: 1.6; color: var(--label);
}

/* ── closer + footer ────────────────────────────────────────────────── */

.closer { text-align: center; padding: 104px 0; }
.closer-inner h2 {
  margin: 0 0 12px;
  font-size: clamp(30px, 3.8vw, 44px);
  font-weight: 700; letter-spacing: -.026em;
}
.closer-inner p { margin: 0 0 28px; font-size: 17px; color: var(--label); }
.closer .hero-cta { justify-content: center; }

.foot { border-top: 1px solid var(--separator); padding: 44px 0 56px; }
.foot-inner { display: flex; flex-direction: column; gap: 18px; }
.foot-brand { display: flex; align-items: center; gap: 12px; }
.foot-name { margin: 0; font-size: 15px; font-weight: 600; }
.foot-tag { margin: 2px 0 0; font-size: 13px; color: var(--label-2); }
.foot-disclaimer {
  margin: 0; max-width: 72ch; font-size: 12.5px; line-height: 1.55;
  color: var(--label-2);
}
.foot-legal { margin: 0; font-size: 12.5px; color: var(--label-2); }

/* ── legal page ─────────────────────────────────────────────────────── */

/* legal.html only. The site had no prose styling at all before this — the
   only list rules were .tier-list (pricing) and .receipt-*. Body copy uses
   --label, never --label-2: that token is 4.29:1 on a light card and is for
   captions, not paragraphs a reader has to work through. */

.legal-toc {
  display: flex; flex-wrap: wrap; gap: 10px 20px;
  margin: 0 0 14px;
}
.legal-toc a {
  font-size: 15px; font-weight: 600; color: var(--blue);
  text-decoration: none;
}
.legal-toc a:hover { text-decoration: underline; }
.legal-toc a:focus-visible {
  outline: none; box-shadow: 0 0 0 3px var(--ring); border-radius: 6px;
}
.legal-meta { margin: 0; font-size: 13px; color: var(--label-2); }

.legal h3 {
  margin: 36px 0 10px;
  font-size: 19px; font-weight: 600; letter-spacing: -.012em;
}
.legal h3:first-of-type { margin-top: 8px; }
.legal p {
  margin: 0 0 14px; max-width: 68ch;
  font-size: 15.5px; line-height: 1.65; color: var(--label);
}
.legal ul {
  margin: 0 0 16px; padding: 0; list-style: none; max-width: 68ch;
}
.legal li {
  position: relative; padding-left: 20px; margin-bottom: 9px;
  font-size: 15.5px; line-height: 1.6; color: var(--label);
}
.legal li::before {
  content: ""; position: absolute; left: 4px; top: 10px;
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--label-2);
}
.legal a { color: var(--blue); }
.legal code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13.5px;
  padding: 1px 6px; border-radius: 6px;
  background: var(--surface-2); border: 1px solid var(--separator);
  white-space: nowrap;
}
/* Under Larger Text a phone lays this page out in about 250px, and
   chunk-chunk:restore-point:v1 is wider than that. Nowrap still keeps a short
   key whole; below 300px a key may break at any character rather than widen
   the page, which iOS answers by zooming the whole page out (v3.1.1). */
@media (max-width: 300px) { .legal code { white-space: normal; overflow-wrap: anywhere; } }

/* The two callouts. Padding matches .strat-panel .card so a legal page and a
   product section read as the same system. */
.legal-callout { padding: 26px 28px; margin: 0 0 30px; }
.legal-callout p:last-child { margin-bottom: 0; }
.legal-strong {
  font-weight: 600; font-size: 15.5px;
  margin: 0 0 8px !important; color: var(--label);
}
.legal-verbatim { font-size: 15.5px; line-height: 1.65; }

@media (max-width: 640px) {
  .legal-callout { padding: 20px; }
  .legal h3 { font-size: 17.5px; margin-top: 30px; }
}

/* ── footer legal links ─────────────────────────────────────────────── */

.foot-links { display: flex; flex-wrap: wrap; gap: 8px 18px; }
.foot-links a {
  font-size: 12.5px; color: var(--label-2); text-decoration: none;
}
.foot-links a:hover { color: var(--label); text-decoration: underline; }
.foot-links a:focus-visible {
  outline: none; box-shadow: 0 0 0 3px var(--ring); border-radius: 6px;
}

/* ── reveals ────────────────────────────────────────────────────────── */

/* Gated on .js — see the inline script in <head>. If scripting never runs,
   these rules never apply and everything is simply visible. */
.js .reveal {
  opacity: 0; transform: translateY(18px);
  transition: opacity .6s var(--ease), transform .6s var(--ease);
}
.js .reveal.is-in { opacity: 1; transform: none; }

/* Motion is decoration here — every reveal must be a no-op when it is not
   wanted, and the tour must not autoplay. */
@media (prefers-reduced-motion: reduce) {
  .js .reveal { opacity: 1; transform: none; transition: none; }
  .tour-btn { transition: none; }
  html { scroll-behavior: auto; }
}

html { scroll-behavior: smooth; }
/* Tracks the sticky chrome: 14 + 48 + 14 + 1px border = 77, plus breathing
   room. It was 76 against a 55px bar. Anchor links land UNDER the header if
   this is left behind when the bar grows — so it moves every time the
   padding or the lockup height does. */
:target { scroll-margin-top: 98px; }

/* ── phones ─────────────────────────────────────────────────────────────
   Everything below 640px. Driven at 360 / 390 / 430 with touch emulation
   before any of it was written — the page has no horizontal overflow at any
   of the three (measured with body's overflow-x:hidden lifted, so nothing is
   being masked). What was wrong was everything that assumed a mouse.

   Scoped here rather than in ../brand/brand.css on purpose: brand.css is the
   app's stylesheet too, and the app's density is a separate question that
   Vic has explicitly deferred.
   ─────────────────────────────────────────────────────────────────────── */

/* Apple's 44px minimum. Measured before: .btn 36px, the segmented controls
   38px, footer links 18px — every one of them under it. The footer links grow
   their hit box through padding, so the type stays the size it was.

   Keyed on the POINTER as well as the width, 27 August 2026. These were
   inside @media (max-width: 640px), so the landing page handed an iPad the
   same 36px buttons the desktop gets. styles.css carries the identical block
   for the app; the two must agree, because the tour link on this page opens
   that app on the same finger. */
@media (max-width: 640px), (hover: none) and (pointer: coarse) {
  .btn { min-height: 44px; padding: 11px 16px; }
  .btn-lg { min-height: 48px; padding: 13px 22px; }
  #stratControl button, #calcControl button { min-height: 44px; }
  /* 13, not 11: these links are 12.5px over an 18px line box, so 11px a
     side lands on 40 and the gate said so. */
  .foot-links a { padding: 13px 0; }
  /* Log in survives above 900px, which on a tablet is a coarse pointer at a
     desktop width — exactly the band that had no tap check until 27 August.
     Measured at 34px (7px a side over a 20px line box); 12 lands it on 44.
     The bar does not grow: .chrome-inner centres a 48px lockup beside it. */
  .chrome-login { padding-top: 12px; padding-bottom: 12px; }
  .legal-toc a { padding: 13px 0; display: inline-block; }
}

@media (max-width: 640px) {

  /* Stacked hero CTAs at matched width. Hugging their own text left "Get
     started" half the width of "Watch the 55-second tour" directly under it,
     which reads as a mistake rather than as a hierarchy. */
  .hero-cta { display: flex; flex-direction: column; align-items: stretch; gap: 10px; }
  .hero-cta .btn { width: 100%; }

  /* $49,100 needed 118px in a 112px tile at 360px and painted through the
     side of the card — the same content-length clip the app solved with size
     tiers in styles.css, which were never ported to brand.css. A clamp does
     the job here because the site's tiles are a fixed two-up. */
  .tiles { grid-template-columns: repeat(auto-fit, minmax(min(132px, 100%), 1fr)); gap: 10px; }
  .tile { padding: 14px 15px; }
  .tile-value { font-size: clamp(22px, 7.4vw, 30px); }

  /* ~12,000px of scroll at 390 with 96px of band padding at every seam.
     Nothing is hidden or cut — the rhythm just stops being a desktop one. */
  .band { padding: 60px 0; }
  .sec-head { margin-bottom: 32px; }
  .hero-inner { padding: 56px 24px; }
  .strat-panel .card { padding: 20px 18px; }
}

/* ── the login page ─────────────────────────────────────────────────── */

/* site.css had a full component set and ZERO form styling before this: not one
   input, label, ::placeholder or fieldset rule, because the landing page never
   had a field. These are not invented — they mirror the app's .input-money,
   which is the one field shape here that has survived a real iPad.

   Every value is a token or an alpha of one. No new hue. */

.auth-main {
  display: flex; align-items: flex-start; justify-content: center;
  padding: 56px 24px 88px;
  /* 77px is the chrome: 14 + 48 lockup + 14 + 1px border, measured. */
  min-height: calc(100vh - 77px);
}
.auth-col { width: 100%; max-width: 420px; }

.auth-card { padding: 32px 32px 26px; }

.auth-mark {
  display: block; margin: 0 auto 16px;
  width: 56px; height: 56px;
  filter: drop-shadow(0 6px 16px var(--hero-glow));
}
.auth-title {
  margin: 0 0 6px; text-align: center;
  font-size: 23px; font-weight: 700; letter-spacing: -0.021em; line-height: 1.2;
}
.auth-lede {
  margin: 0 0 24px; text-align: center;
  font-size: 14px; color: var(--label-2);
}

/* ── fields ─────────────────────────────────────────────────────────── */

.auth-form { display: grid; gap: 15px; }
.auth-field { display: grid; gap: 6px; }
.auth-field > label { font-size: 13px; font-weight: 600; }

.auth-input {
  display: flex; align-items: center; gap: 8px;
  background: var(--surface-2);
  border-radius: var(--radius-sm);
  /* The VERTICAL padding lives on the input, not here. Measured with it on the
     wrapper: the box was 45.2px but the input itself only 23.2px, so a thumb
     landing in the top or bottom 11px of a field hit nothing at all. Moving it
     makes the input fill its own box, with no JS and no label restructure. */
  padding: 0 12px;
  transition: background .2s var(--ease), box-shadow .2s var(--ease);
}
.auth-input:focus-within {
  background: var(--surface);
  box-shadow: 0 0 0 3px var(--ring);
}
.auth-input input {
  flex: 1 1 0; min-width: 0;
  border: 0; background: none; padding: 11px 0;
  font: inherit;
  /* 16, not the page's 15. Below 16px iOS Safari zooms the page on focus and
     never zooms back out. The one place on this site that must not inherit. */
  font-size: 16px;
  color: var(--label);
}
.auth-input input:focus { outline: none; }
.auth-input input::placeholder { color: var(--label-2); }
.auth-input.is-bad { box-shadow: inset 0 0 0 1.5px var(--red); }

/* "Where did you hear about us?" (v3.3.3). The select sits in the same
   .auth-input box as the text fields, at the same 16px so iOS does not zoom on
   focus, with the browser's own arrow replaced by a chevron in --label-2. */
.auth-optional { font-weight: 400; color: var(--label-2); }
.auth-input select {
  flex: 1 1 0; min-width: 0;
  appearance: none; -webkit-appearance: none;
  border: 0; background: none; padding: 11px 22px 11px 0;
  font: inherit; font-size: 16px; color: var(--label);
  cursor: pointer;
}
.auth-input select:focus { outline: none; }
.auth-select { position: relative; }
.auth-select::after {
  content: ''; position: absolute; right: 16px; top: 50%;
  width: 7px; height: 7px; margin-top: -5px; pointer-events: none;
  border-right: 2px solid var(--label-2); border-bottom: 2px solid var(--label-2);
  transform: rotate(45deg);
}

.auth-peek {
  flex: none; border: 0; background: none; cursor: pointer;
  font: inherit; font-size: 12.5px; font-weight: 600; color: var(--blue);
  padding: 4px 2px; border-radius: 6px;
}
.auth-peek:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--ring); }

.auth-hint { font-size: 12px; color: var(--label-2); }

.auth-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap;
}
.auth-link {
  font-size: 13px; font-weight: 600; color: var(--blue); text-decoration: none;
}
.auth-link:hover { text-decoration: underline; }

.auth-submit { width: 100%; margin-top: 3px; }
.auth-submit[aria-busy="true"] { opacity: .7; pointer-events: none; }

/* ── states ─────────────────────────────────────────────────────────── */

/* --red-wash, not an alpha of --red: --red is deepened until it can carry
   TEXT, and an alpha of a dark warm red over cream reads as dirt rather than
   as a warning. Same pairing the debts table settled on. Body copy stays
   --label, per the rule at the top of this file. */
.auth-msg {
  display: flex; gap: 9px; align-items: flex-start;
  border-radius: var(--radius-sm);
  padding: 11px 13px;
  font-size: 13.5px; line-height: 1.4; color: var(--label);
}
.auth-msg svg { flex: none; width: 17px; height: 17px; margin-top: 1px; }
.auth-msg-bad { background: var(--red-wash); }
.auth-msg-bad svg { color: var(--red); }
.auth-msg-ok { background: var(--green-wash); }
.auth-msg-ok svg { color: var(--green); }

/* ── the alternate action ───────────────────────────────────────────── */

.auth-alt {
  margin: 22px 0 0; padding-top: 18px;
  border-top: 1px solid var(--separator);
  text-align: center; font-size: 13.5px; color: var(--label-2);
}
.auth-alt a { color: var(--blue); font-weight: 600; text-decoration: none; }
.auth-alt a:hover { text-decoration: underline; }

.auth-choice { display: grid; gap: 10px; }
.auth-choice .btn { width: 100%; }

.auth-free {
  margin: 20px 0 0; padding-top: 18px;
  border-top: 1px solid var(--separator);
  text-align: center;
}
.auth-free p { margin: 0 0 10px; font-size: 13.5px; color: var(--label-2); }

.auth-note {
  margin: 18px auto 0; max-width: 420px; text-align: center;
  font-size: 12.5px; color: var(--label-2);
}

.auth-account { display: grid; gap: 14px; justify-items: center; }
.auth-email { font-size: 15px; font-weight: 600; word-break: break-all;
              text-align: center; }

/* ── panels ─────────────────────────────────────────────────────────── */

/* .js-gated, the same pattern index.html uses for .reveal: with scripting off
   all three panels stack and the page is degraded rather than blank. */
.js .auth-panel { display: none; }
.js .auth-panel.is-active { display: block; }

/* The touch floor, keyed on the POINTER as well as the width — the same
   condition the block above uses, so an iPad gets it at any width. Measured
   without it: Show was 26.1px and every text link about 18px. The links grow
   their hit box through padding, so the type stays the size it was, exactly
   how .foot-links a was solved. */
@media (max-width: 640px), (hover: none) and (pointer: coarse) {
  .auth-peek { min-height: 44px; padding: 4px 8px; }
  .auth-link, .auth-alt a { display: inline-block; padding: 13px 0; }
  .auth-row { margin-top: -4px; }
}

/* And the header's own links, keyed the same way and for the same reason.
   Above 900px there is no menu and .chrome-nav is the desktop row, so on an
   iPad in landscape these are 34px targets at a desktop width: the exact band
   that put five faults on one in August. Found by checkTapTargets the moment
   .chrome-menu-panel a went on its allowlist, as 7 controls at 1024x768.

   Padding, not a taller bar: .chrome-inner centres a 48px lockup beside them,
   so a 44px link fits inside the 77px bar and the type stays the size it was.
   Below 900px these already carry their own 44px floor inside the menu. */
@media (hover: none) and (pointer: coarse) {
  .chrome-nav a, .chrome-login {
    display: inline-flex; align-items: center; min-height: 44px;
  }
}

@media (max-width: 400px) {
  .auth-main { padding: 32px 16px 64px; }
  .auth-card { padding: 26px 20px 22px; }
}

/* ═══════════════════════ the question box ═══════════════════════
   Candidate C off the 14 September contact sheet, chosen by Vic from three
   injected into this page by chattry.js.

   TOKENS ONLY, so this introduces no colour. The accent is --blue, which is
   what every primary control on this site already wears. --green, --red and
   --orange are deliberately unused: they already mean paid, overdue and
   chart series in this product, and a bubble wearing one would be making a
   statement nobody intended.

   WHITE ON --blue IS 2.86:1 IN DARK. The token lightens to #6E9BD8 at
   night, and CLAUDE.md records that exact figure for .pro-pill, fixed on
   2 September with the same one line. Anything sitting ON blue takes --bg
   in dark instead, which measures 6.13:1. Every pair here was measured by
   chattry.js rather than eyeballed. */

.cc-launch, .cc-panel { font-family: var(--font); box-sizing: border-box; }
.cc-launch *, .cc-panel *, .cc-panel *::before { box-sizing: border-box; }

/* [hidden] LOSES TO display:flex, so it is restated. An element carrying
   the hidden attribute and a display rule is simply visible, which is how a
   panel ends up open on every page load with nothing in the JS to blame. */
.cc-panel[hidden], .cc-chips[hidden] { display: none !important; }

.cc-launch {
  position: fixed; right: 20px; bottom: 20px; z-index: 60;
  display: inline-flex; align-items: center; justify-content: center;
  width: 56px; height: 56px; padding: 0; overflow: hidden;
  border: 0; cursor: pointer; border-radius: 50%;
  background: var(--blue); box-shadow: var(--shadow);
  transition: transform .18s var(--ease);
}
.cc-launch:hover { transform: translateY(-1px); }
.cc-launch-m { width: 40px; height: 40px; }
.cc.is-open .cc-launch { display: none; }

.cc-panel {
  position: fixed; right: 20px; bottom: 20px; z-index: 61;
  width: 380px; max-width: calc(100vw - 40px);
  max-height: min(560px, calc(100vh - 40px));
  display: flex; flex-direction: column; overflow: hidden;
  background: var(--bg); border: 1px solid var(--separator);
  border-radius: var(--radius); box-shadow: var(--shadow);
}

.cc-head {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 14px; flex: none; background: var(--blue);
}
.cc-head-t { display: flex; flex-direction: column; min-width: 0; }
.cc-head-t strong { font-size: 14px; font-weight: 650; color: #fff; }
.cc-head-t span { font-size: 12px; color: rgba(255, 255, 255, .78); }
.cc-mark { width: 28px; height: 28px; border-radius: 8px; flex: none;
  background: rgba(255, 255, 255, .16); }
.cc-x {
  margin-left: auto; flex: none; width: 32px; height: 32px; border: 0;
  background: none; cursor: pointer; font-size: 22px; line-height: 1;
  border-radius: 8px; color: #fff; font-family: inherit;
}
.cc-x:hover { background: rgba(255, 255, 255, .16); }

.cc-body {
  flex: 1 1 auto; overflow-y: auto; padding: 12px 14px;
  display: flex; flex-direction: column; gap: 10px;
}
/* --label-2, not --label-3. These are sentences a visitor reads, and
   --label-3 measured 2.2:1. */
.cc-note { margin: 0; font-size: 11.5px; letter-spacing: .01em;
  color: var(--label-2); }

.cc-msg { max-width: 86%; }
.cc-msg p { margin: 0; font-size: 13.5px; line-height: 1.5; }
.cc-bot p {
  background: var(--surface); color: var(--label);
  padding: 9px 12px; border-radius: var(--radius-sm);
  border: 1px solid var(--separator);
}
.cc-you { align-self: flex-end; }
.cc-you p { background: var(--blue); color: #fff;
  padding: 9px 12px; border-radius: var(--radius-sm); }
.cc-thinking p { color: var(--label-2); }

.cc-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.cc-chip {
  font-size: 12px; padding: 6px 10px; cursor: pointer; border-radius: 999px;
  font-family: inherit; background: var(--surface); color: var(--blue);
  border: 1px solid var(--separator);
}
.cc-chip:hover { background: var(--surface-2); }

.cc-foot { flex: none; padding: 10px 14px 12px; margin: 0;
  border-top: 1px solid var(--separator); background: var(--surface); }
.cc-input { display: flex; align-items: center; gap: 8px; }
/* 16px, NOT 14. Below 16 mobile Safari zooms the viewport when a field takes
   focus and never zooms back. checkInputZoom() sweeps this. */
.cc-input input {
  flex: 1 1 auto; min-width: 0; font-family: inherit; font-size: 16px;
  padding: 9px 12px; background: var(--bg); color: var(--label);
  border: 1px solid var(--separator); border-radius: var(--radius-sm);
}
.cc-input input::placeholder { color: var(--label-3); }
.cc-input input:disabled { opacity: .6; }
.cc-send {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; border: 0; cursor: pointer;
  border-radius: var(--radius-sm); background: var(--blue); color: #fff;
}
.cc-send:disabled { opacity: .6; cursor: default; }
.cc-send svg { width: 18px; height: 18px; }
.cc-help { margin: 8px 0 0; font-size: 11.5px; text-align: center;
  color: var(--label-2); }

:root[data-theme="dark"] .cc-head-t strong,
:root[data-theme="dark"] .cc-x,
:root[data-theme="dark"] .cc-you p,
:root[data-theme="dark"] .cc-send { color: var(--bg); }
/* .78 measured 2.88:1 against the lighter night blue and .85 measured 3.46.
   Full --bg is 6.13:1, and 12px at normal weight still reads as a sub-line
   under a 14px 650. */
:root[data-theme="dark"] .cc-head-t span { color: var(--bg); opacity: 1; }

/* A THUMB RULE, KEYED ON THE POINTER AND NOT ON A WIDTH. An iPad in
   landscape is a coarse pointer at 1024px, and a max-width query would tidy
   the phone and leave the tablet short. */
@media (hover: none) and (pointer: coarse) {
  .cc-chip { min-height: 44px; }
  .cc-x, .cc-send { min-width: 44px; min-height: 44px; }
  .cc-input input { min-height: 44px; }
}
@media (max-width: 480px) {
  .cc-launch { right: 12px; bottom: 12px; }
  .cc-panel {
    right: 8px; left: 8px; bottom: 8px; width: auto; max-width: none;
    max-height: calc(100vh - 16px);
  }
}

/* ── How-to videos: how-to.html, and the landing page's #howto band ─────
   Candidate C off the 25 September sheet (screenshots/howto-try/): one
   player, the lesson list beside it, a Next button. The page is GENERATED by
   howto-build.js; these rules are the only hand-written half of it.

   THE PLAY CONTROL RIDES THE LENGTH PILL, bottom right, and never sits in
   the middle. Every thumbnail carries its title on the left half and Tess on
   the right, so a centred button covered "WHAT IT ACTUALLY" and "KNOW YOUR
   SPENDING" in the first capture. The whole thumbnail is still the button. */
.ht-top { padding: 64px 0 8px; }
.ht-top .sec-head { margin-bottom: 24px; }

/* The breadcrumb. The link carries its own vertical padding so the tap
   target clears 44px without the row looking tall; the negative margin
   takes that padding back out of the layout. */
.crumbs { margin: -12px 0 4px; font-size: 15px; }
.crumbs ol { display: flex; flex-wrap: wrap; align-items: center; margin: 0; padding: 0; list-style: none; }
.crumbs li { display: flex; align-items: center; color: var(--label); }
.crumbs li + li::before {
  content: "\203A";
  content: "\203A" / "";
  margin: 0 10px; color: var(--label); font-size: 18px; line-height: 1;
}
.crumbs a {
  display: inline-flex; align-items: center; min-height: 44px;
  color: var(--blue); font-weight: 600; text-decoration: none;
}
.crumbs a:hover { text-decoration: underline; text-underline-offset: 3px; }
.crumbs [aria-current="page"] { font-weight: 600; }
.ht-h {
  margin: 0 0 14px;
  font-size: clamp(28px, 3.4vw, 40px);
  font-weight: 700; letter-spacing: -0.024em; line-height: 1.12;
}
.ht-body { padding: 0 0 80px; }
.ht-layout {
  display: grid; grid-template-columns: minmax(0, 1fr) 360px;
  gap: 28px; align-items: start;
}
.ht-main { min-width: 0; scroll-margin-top: 88px; }

.ht-frame {
  position: relative; aspect-ratio: 16 / 9; overflow: hidden;
  border-radius: var(--radius); box-shadow: var(--shadow);
  background: var(--brand-ink);
  scroll-margin-top: 88px;
}
.ht-frame iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.ht-play {
  position: absolute; inset: 0; display: block; width: 100%; height: 100%;
  padding: 0; border: 0; margin: 0; background: none; cursor: pointer;
}
.ht-play img { display: block; width: 100%; height: 100%; object-fit: cover; }
.ht-play::before {
  content: ""; position: absolute; inset: 0;
  background: rgba(10, 16, 26, 0); transition: background .15s var(--ease);
}
.ht-play:hover::before { background: rgba(10, 16, 26, .18); }
.ht-play:focus-visible { outline: 3px solid var(--ring); outline-offset: -3px; }
.ht-len {
  position: absolute; right: 14px; bottom: 14px; pointer-events: none;
  display: flex; align-items: center; gap: 7px;
  padding: 8px 16px 8px 12px; border-radius: 999px;
  background: var(--blue); color: #fff;
  font-size: 15px; font-weight: 700;
  box-shadow: 0 4px 14px rgba(0, 0, 0, .35);
  transition: transform .15s var(--ease);
}
.ht-len::before {
  content: ""; width: 20px; height: 20px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23fff' d='M7 4.5v15l13-7.5z'/%3E%3C/svg%3E") center / contain no-repeat;
}
.ht-frame:hover .ht-len { transform: scale(1.06); }
/* Night's --blue is the light one, and white on it measured too faint. */
:root[data-theme="dark"] .ht-len { color: var(--bg); }
:root[data-theme="dark"] .ht-len::before { filter: invert(1) brightness(.12); }

.ht-now { margin-top: 18px; }
.ht-meta {
  display: block; margin: 0 0 6px;
  font-size: 12.5px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--blue);
}
.ht-now h2 { margin: 0 0 8px; font-size: 24px; letter-spacing: -.015em; line-height: 1.25; }
.ht-lead { margin: 0; font-size: 16px; line-height: 1.55; color: var(--label); }
.ht-next-row { margin: 16px 0 0; }
.ht-yt { margin: 18px 0 0; font-size: 13.5px; color: var(--label-2); }

.ht-side {
  padding: 6px 0 8px; overflow-y: auto;
  position: sticky; top: 88px; max-height: calc(100vh - 110px);
}
.ht-season {
  margin: 0; padding: 12px 16px 6px;
  font-size: 12px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--blue);
}
.ht-season span {
  display: block; margin-top: 2px;
  font-size: 12px; font-weight: 500; letter-spacing: 0; text-transform: none;
  color: var(--label-2);
}
.ht-list { list-style: none; margin: 0; padding: 0 8px 6px; }
.ht-item {
  display: grid; grid-template-columns: 120px minmax(0, 1fr); gap: 12px; align-items: center;
  width: 100%; padding: 8px; border: 0; border-radius: var(--radius-sm);
  background: none; color: inherit; font: inherit; text-align: left; cursor: pointer;
  scroll-margin-top: 88px;
}
.ht-item:hover { background: var(--surface-2); }
.ht-item:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--ring); }
.ht-item[aria-current="true"] { background: var(--surface-2); box-shadow: inset 3px 0 0 var(--blue); }
.ht-item img {
  display: block; width: 120px; height: auto; aspect-ratio: 16 / 9;
  object-fit: cover; border-radius: 6px;
}
.ht-item b { display: block; font-size: 14px; line-height: 1.3; color: var(--label); }
.ht-item b + span { display: block; margin-top: 3px; font-size: 12.5px; color: var(--label-2); }

@media (max-width: 960px) {
  .ht-layout { grid-template-columns: 1fr; }
  .ht-side { position: static; max-height: none; }
}
@media (max-width: 480px) {
  .ht-top { padding-top: 40px; }
  .ht-len { right: 10px; bottom: 10px; padding: 6px 12px 6px 9px; font-size: 13px; }
  .ht-len::before { width: 16px; height: 16px; }
  .ht-item { grid-template-columns: 104px minmax(0, 1fr); }
  .ht-item img { width: 104px; }
}
/* 250px is a 375pt iPhone with Larger Text on: a 104px thumbnail left the
   first lesson 8px wider than the list and the titles one word a line
   (v3.1.2). Below 300px the thumbnail goes ABOVE its title instead. */
@media (max-width: 300px) {
  .ht-item { grid-template-columns: minmax(0, 1fr); gap: 8px; }
  .ht-item img { width: 100%; }
}

/* "Start here": the install Short above the lessons (5 Oct 2026). A tall
   9:16 frame beside its words; pressing play opens the card out so the
   video plays at a size a phone can follow. Below 300px it stacks. */
.ht-start { padding: 0 0 32px; }
.ht-start-card {
  display: grid; grid-template-columns: 180px minmax(0, 1fr);
  gap: 28px; align-items: center; padding: 20px; max-width: 760px;
}
.ht-tall { aspect-ratio: 9 / 16; }
.ht-start-text { min-width: 0; }
.ht-start-text h2 { margin: 0 0 8px; font-size: 24px; letter-spacing: -.015em; line-height: 1.25; }
.ht-start-steps { margin: 12px 0 0; font-size: 15px; line-height: 1.55; color: var(--label-2); }
.ht-start-steps b { color: var(--label); white-space: nowrap; }
.ht-start-card.is-playing { grid-template-columns: minmax(0, 1fr); max-width: 400px; }
@media (max-width: 480px) {
  .ht-start-card { grid-template-columns: 112px minmax(0, 1fr); gap: 16px; padding: 14px; }
  .ht-start-text h2 { font-size: 19px; }
  .ht-start-card .ht-len { right: 6px; bottom: 6px; padding: 5px 9px 5px 7px; font-size: 12px; gap: 4px; }
  .ht-start-card .ht-len::before { width: 13px; height: 13px; }
}
/* Stacked below 340px: at 320 the words beside a 112px poster left 116px, and
   "chunkchunk.ca/app" is 135px of unbreakable bold (preview.js site-zoom). */
@media (max-width: 340px) {
  .ht-start-card { grid-template-columns: minmax(0, 1fr); }
  .ht-start-card .ht-tall { max-width: 180px; }
}

/* The landing page's band: three lessons and a way to the rest. */
.ht-teaser {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px;
}
.ht-card {
  display: flex; flex-direction: column; height: 100%;
  padding: 0; overflow: hidden; text-decoration: none; color: inherit;
  transition: transform .15s var(--ease);
}
.ht-card:hover { transform: translateY(-2px); }
.ht-card:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--ring); }
.ht-card img { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover; }
.ht-card-body { display: block; padding: 12px 16px 16px; }
.ht-card-body .ht-meta { margin-bottom: 4px; }
.ht-card-body b { display: block; font-size: 16px; line-height: 1.3; }
.ht-all { margin: 28px 0 0; }
@media (max-width: 860px) {
  .ht-teaser { grid-template-columns: 1fr; max-width: 520px; }
}

/* ── The book pages: ebook.html and coloring-book.html (books-build.js) ──
   Vic, 10 Oct 2026: Pinterest blocks chunkchunk.shop, so the books get pages
   here with their own Buy button. Every class is bk-, which Tailwind never
   generates and nothing else on this site uses. */
.bk-top { padding-top: 40px; }
.bk-grid {
  display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
  gap: 48px; align-items: start; margin-top: 16px;
}
.bk-cover img {
  display: block; width: 100%; height: auto; border-radius: var(--radius-sm);
  box-shadow: 0 2px 6px rgba(28, 42, 61, .12), 0 22px 48px rgba(28, 42, 61, .22);
}
.bk-h { margin: 4px 0 0; font-size: 44px; line-height: 1.05; letter-spacing: -0.02em; overflow-wrap: anywhere; }
.bk-sub { margin: 8px 0 0; font-size: 19px; color: var(--label-2); }
.bk-price { margin: 22px 0 0; font-size: 34px; font-weight: 800; color: var(--blue); white-space: nowrap; }
.bk-price span { font-size: 16px; font-weight: 600; color: var(--label-2); }
.bk-ship { margin: 6px 0 0; font-size: 15px; }
.bk-blurb { margin: 18px 0 0; font-size: 17px; line-height: 1.55; max-width: 60ch; }
.bk-actions { margin: 22px 0 0; }
.bk-btn { font-size: 17px; padding: 14px 24px; max-width: 100%; white-space: normal; text-align: center; }
.bk-msg { margin: 10px 0 0; font-size: 15px; color: var(--label); }
.bk-small { margin: 14px 0 0; font-size: 14px; line-height: 1.5; color: var(--label-2); max-width: 60ch; }
.bk-small b { color: var(--label); }
.bk-small a { color: var(--blue); }
.bk-spec { margin: 18px 0 0; padding-left: 20px; font-size: 15px; line-height: 1.6; }
.bk-free { padding: 0 0 72px; }
.bk-free-card {
  display: grid; grid-template-columns: minmax(0, 220px) minmax(0, 1fr); gap: 28px; align-items: center;
  padding: 24px;
}
.bk-free-card img { display: block; width: 100%; height: auto; border-radius: var(--radius-sm); border: 1px solid var(--separator); }
.bk-free-card h2 { margin: 4px 0 8px; font-size: 26px; line-height: 1.15; }
.bk-free-card p { margin: 0; }
.bk-free-actions { margin-top: 16px !important; }
.bk-free-actions .btn { white-space: normal; text-align: center; max-width: 100%; }
.bk-h2 { margin: 0 0 18px; font-size: 26px; }
.bk-h2 + .bk-list { margin-top: 0; }
.bk-peek {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(min(170px, 100%), 1fr));
  gap: 16px; margin-bottom: 44px;
}
.bk-peek img {
  display: block; width: 100%; height: auto; border-radius: var(--radius-sm);
  background: #fff; box-shadow: var(--shadow);
}
.bk-list { margin: 0; padding-left: 22px; font-size: 16px; line-height: 1.7; max-width: 70ch; }
.bk-other { padding: 64px 0 80px; }
.bk-other-card {
  display: flex; align-items: center; gap: 20px; max-width: 560px; padding: 16px;
  text-decoration: none; color: inherit; transition: transform .15s var(--ease);
}
.bk-other-card:hover { transform: translateY(-2px); }
.bk-other-card:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--ring); }
.bk-other-card img { width: 96px; height: auto; flex: none; border-radius: 6px; box-shadow: var(--shadow); }
.bk-other-card > span { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.bk-other-card b { font-size: 21px; }
.bk-other-card > span > span:last-child { color: var(--label-2); font-size: 15px; }
@media (max-width: 860px) {
  .bk-grid { grid-template-columns: minmax(0, 1fr); gap: 28px; }
  .bk-cover { max-width: 360px; }
  .bk-h { font-size: 36px; }
  .bk-free-card { grid-template-columns: minmax(0, 1fr); }
  .bk-free-card img { max-width: 240px; }
}
.bk-soon { padding: 0 0 72px; }
.bk-soon-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(240px, 100%), 1fr)); gap: 20px; max-width: 640px; }
.bk-soon-card { margin: 0; padding: 0; overflow: hidden; }
.bk-soon-card img { display: block; width: 100%; height: auto; }
.bk-soon-card figcaption { display: flex; flex-direction: column; gap: 2px; padding: 12px 16px 16px; }
.bk-soon-card b { font-size: 17px; line-height: 1.3; }
.bk-soon-card span { font-size: 14px; color: var(--label-2); }
/* At 250px the card's text had 54px beside a 96px cover and ran out of its box
   (preview.js site-zoom, 10 Oct 2026). The cover takes its own row when the
   text cannot have 150px, and a long word may break rather than spill. */
.bk-other-card { flex-wrap: wrap; }
.bk-other-card > span { flex: 1 1 150px; overflow-wrap: anywhere; }

/* The links page (links.html, generated by books-build.js; 11 Oct 2026): the bio-link page for Instagram and TikTok. */
.lk-top { padding-top: 36px; }
.lk-wrap { max-width: 600px; text-align: center; }
.lk-mark { display: block; width: 140px; height: auto; margin: 0 auto 8px; }
.lk-h { margin: 0; font-size: 40px; line-height: 1.1; letter-spacing: -0.02em; }
.lk-sub { margin: 6px 0 24px; color: var(--label-2); font-size: 18px; }
.lk-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; text-align: left; }
.lk-card { display: flex; align-items: center; gap: 16px; padding: 16px 18px; text-decoration: none; color: inherit; transition: transform .15s var(--ease); }
.lk-card:hover { transform: translateY(-2px); }
.lk-card:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--ring); }
.lk-emoji { flex: none; font-size: 32px; line-height: 1; width: 44px; text-align: center; }
.lk-card > span:last-child { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 150px; overflow-wrap: anywhere; }
.lk-card b { font-size: 19px; }
.lk-card > span:last-child > span { color: var(--label-2); font-size: 15px; }
/* Vic's Toolbox (14 Oct 2026): the disclosure above the list, the affiliate tag, the rough cost line. */
.tb-disclose { max-width: 560px; margin: 0 auto 18px; }
.lk-card .tb-aff { display: inline-block; margin-left: 8px; padding: 2px 8px; border-radius: 999px; background: var(--amber-wash); color: var(--amber); font-size: 12px; font-weight: 700; vertical-align: middle; }
.lk-card > span:last-child > span.tb-cost { color: var(--label); font-size: 14px; font-weight: 600; margin-top: 4px; }
.lk-follow-h { margin: 28px 0 8px; }
.lk-follow { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px 18px; margin: 0; }
.lk-follow a { font-weight: 700; color: var(--blue); text-decoration: none; }
.lk-follow a:hover { text-decoration: underline; }

/* ── The Christmas cards page, cards.html (13 Oct 2026). xcd- prefix: nothing Tailwind or the app owns. ── */
.xcd-h { margin: 4px 0 8px; font-size: 40px; line-height: 1.1; letter-spacing: -0.02em; }
.xcd-sub { margin: 0 0 24px; color: var(--label-2); font-size: 18px; max-width: 640px; }
.xcd-grid { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(min(250px, 100%), 1fr)); gap: 22px; }
.xcd-card { padding: 0; overflow: hidden; display: flex; flex-direction: column; }
.xcd-card img { display: block; width: 100%; height: auto; aspect-ratio: 3 / 4; object-fit: cover; }
.xcd-body { padding: 14px 16px 18px; display: flex; flex-direction: column; gap: 6px; flex: 1; }
.xcd-body h2 { margin: 0; font-size: 20px; line-height: 1.2; }
.xcd-body p { margin: 0; color: var(--label-2); font-size: 15px; }
.xcd-btns { display: flex; flex-wrap: wrap; gap: 8px; margin-top: auto !important; padding-top: 10px; }
.xcd-btns .btn { flex: 1 1 auto; min-width: 0; justify-content: center; text-align: center; }
.xcd-ask-card { text-align: center; max-width: 560px; margin: 0 auto; }
.xcd-ask-card h2 { margin: 0 0 6px; font-size: 26px; }
.xcd-ask-card p { margin: 0 0 12px; }
.xcd-treat { max-width: 600px; text-align: center; }
.xcd-treat .xcd-sub { margin-left: auto; margin-right: auto; }
.xcd-treat .xcd-btns { justify-content: center; }
.xcd-wp .xcd-card img { aspect-ratio: 9 / 16; }
