/* WAYWARD ROBOTS — house styles
   Palette: the lancenabers.com warm canvas (spruce/gold/cream)
   married to the Lighthouse Command Center cyan — the mascot's eye. */
:root {
  --ink: #13201C;
  --ink-soft: #3C4A46;
  --mute: #6E7B77;
  --paper: #FFFFFF;
  --cream: #FBFAF7;
  --cloud: #F4F6F3;
  --mist: #E9F2EE;
  --line: #E4E9E7;
  --spruce: #1E6E5A;
  --spruce-deep: #14523F;
  --gold: #CD944A;
  --gold-deep: #A86F2C;
  --cyan: #3ECFCF;        /* the mascot's eye */
  --teal: #0E7C7C;        /* command-center teal */
  --night: #0D1B22;       /* poster sky */
  --night-soft: #16323B;
  --sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --serif: "Fraunces", ui-serif, "New York", Georgia, serif;
  --r: 14px;
  --r-lg: 24px;
  --r-pill: 100px;
  --sh: 0 1px 2px rgba(19,32,28,.05), 0 10px 34px rgba(19,32,28,.08);
  --sh-lg: 0 2px 6px rgba(19,32,28,.06), 0 26px 70px rgba(19,32,28,.16);
  --t: .3s cubic-bezier(.4,0,.2,1);
  --wrap: 1140px;
  /* THE PAINTED REGISTER (2026-07-19) — the LANCE opening's pastels, spread
     across the whole product family per Lance's order. */
  --paint-mist: #AEC6D4;
  --paint-glass: #9CC5B8;
  --paint-gold: #E8D9B0;
  --paint-cream: #EFE6CF;
  --paint-paper: #FAF7F0;
}

/* the painted canvas — watercolor blooms on warm paper, pure CSS */
.painted-wash {
  background-color: var(--paint-paper);
  background-image:
    radial-gradient(52% 38% at 10% 8%,  rgba(174,198,212,0.32) 0%, transparent 70%),
    radial-gradient(46% 34% at 90% 14%, rgba(232,217,176,0.28) 0%, transparent 70%),
    radial-gradient(58% 42% at 80% 90%, rgba(156,197,184,0.26) 0%, transparent 70%),
    radial-gradient(44% 30% at 6% 94%,  rgba(239,230,207,0.36) 0%, transparent 70%);
}
* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0; font-family: var(--sans); color: var(--ink);
  background: var(--paint-paper); line-height: 1.6; -webkit-font-smoothing: antialiased;
}
img { max-width: 100%; height: auto; }
a { color: var(--teal); text-decoration: none; }
a:hover { color: var(--spruce-deep); }
.wrap { max-width: var(--wrap); margin: 0 auto; padding: 0 22px; }

h1, h2, h3 { font-family: var(--serif); font-weight: 600; line-height: 1.15; margin: 0 0 .5em; }
h1 { font-size: clamp(2rem, 5.4vw, 3.6rem); letter-spacing: -.01em; }
h2 { font-size: clamp(1.5rem, 3.4vw, 2.3rem); }
h3 { font-size: 1.22rem; }
.kicker {
  font: 700 .78rem/1 var(--sans); letter-spacing: .16em; text-transform: uppercase;
  color: var(--gold-deep); margin: 0 0 14px;
}
.lead { font-size: 1.13rem; color: var(--ink-soft); max-width: 46em; }

/* ---------- header ---------- */
.site-head {
  position: sticky; top: 0; z-index: 50;
  background: rgba(251,250,247,.88); backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}
.site-head .wrap { display: flex; align-items: center; gap: 26px; height: 64px; }
.brand { display: flex; align-items: center; gap: 10px; font-family: var(--serif); font-weight: 700; font-size: 1.08rem; color: var(--ink); }
.brand .eye {
  width: 26px; height: 26px; border-radius: 8px; flex: none;
  background: radial-gradient(circle at 50% 45%, var(--cyan) 0 26%, #0e2a2a 34% 100%);
  box-shadow: 0 0 12px rgba(62,207,207,.55);
}
.nav { margin-left: auto; display: flex; gap: 20px; align-items: center; }
.nav a { color: var(--ink-soft); font-weight: 600; font-size: .93rem; }
.nav a:hover { color: var(--spruce-deep); }
.nav a.cta {
  background: var(--spruce); color: #fff; padding: 9px 18px; border-radius: var(--r-pill);
  transition: background var(--t);
}
.nav a.cta:hover { background: var(--spruce-deep); }
.nav-toggle { display: none; }

/* ---------- hero (the poster) ---------- */
.hero {
  position: relative; background: var(--night); color: #fff; overflow: hidden;
}
.hero .poster {
  display: block; width: 100%; height: min(92vh, 860px); object-fit: cover; object-position: center 22%;
}
.hero .veil {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(13,27,34,.10) 0%, rgba(13,27,34,0) 30%, rgba(13,27,34,.78) 86%, rgba(13,27,34,.94) 100%);
  pointer-events: none;
}
.hero .hero-copy {
  position: absolute; left: 0; right: 0; bottom: 0; padding: 0 22px 46px; text-align: center;
}
.hero .wordmark {
  font-family: var(--serif); font-weight: 700; letter-spacing: .04em;
  font-size: clamp(2.2rem, 7vw, 4.6rem); margin: 0;
  color: #FBFAF7; text-shadow: 0 2px 30px rgba(0,0,0,.55);
}
.hero .wordmark .accent { color: var(--cyan); }
.hero .tagline {
  font-family: var(--serif); font-style: italic; font-size: clamp(1.05rem, 2.6vw, 1.5rem);
  color: #EBD9B8; margin: 8px 0 22px; text-shadow: 0 1px 18px rgba(0,0,0,.6);
}
/* The one shared message. Short on purpose — the hero copy is a bottom-anchored
   overlay, and every line added to it grows upward over the painting. */
.hero .hero-message {
  font-size: clamp(.92rem, 2vw, 1.05rem); font-weight: 600; letter-spacing: .01em;
  color: #CFE7E3; margin: -10px auto 22px; text-shadow: 0 1px 16px rgba(0,0,0,.7);
  /* Capped and centred (2026-08-15). At 1440 this ran nearly edge to edge as one
     thin ribbon across the painting — which is where a sentence stops being read
     and becomes decoration. It is now the line that tells a stranger what the
     product IS, so it gets a measure. Two comfortable lines beat one wide one. */
  max-width: 62ch;
}
.hero .hero-actions { display: flex; gap: 14px; justify-content: center; flex-wrap: wrap; }

/* The origin line — the company's own sentence, set as a quote, not body copy. */
.origin-line {
  margin: 0 0 22px; padding: 0 0 0 20px; border-left: 3px solid var(--gold);
  font-family: var(--serif); font-style: italic; font-size: clamp(1.1rem, 2.6vw, 1.5rem);
  line-height: 1.45; color: #EBD9B8; max-width: 62ch;
}
/* On a phone the decorative gramophone robot (#story .bot.small, right:6%) sits
   at the same height as this quote. Keep the words clear of the sprite — never
   lay copy across a character. */
@media (max-width: 760px) { .origin-line { margin-right: 80px; } }
.btn {
  display: inline-block; font-weight: 700; font-size: .97rem; border-radius: var(--r-pill);
  padding: 13px 28px; transition: transform var(--t), background var(--t), box-shadow var(--t);
}
.btn-gold { background: var(--gold); color: #211505; }
.btn-gold:hover { background: #E0A85C; color: #211505; transform: translateY(-1px); }
.btn-ghost { border: 1.5px solid rgba(251,250,247,.55); color: #FBFAF7; }
.btn-ghost:hover { border-color: var(--cyan); color: var(--cyan); }
.btn-spruce { background: var(--spruce); color: #fff; }
.btn-spruce:hover { background: var(--spruce-deep); color: #fff; transform: translateY(-1px); }

/* ---------- sections ---------- */
section { padding: 84px 0; position: relative; }
section.alt { background: var(--cloud); }
section.night { background: var(--night); color: #E8EFEA; }
section.night h2 { color: #FBFAF7; }
section.night .lead { color: #B9C8C2; }

/* ---------- world / product cards ---------- */
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(270px, 1fr)); gap: 22px; margin-top: 36px; }
.card {
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-lg);
  padding: 26px; box-shadow: var(--sh); transition: transform var(--t), box-shadow var(--t);
  display: flex; flex-direction: column; gap: 10px; position: relative; overflow: hidden;
}
.card:hover { transform: translateY(-4px); box-shadow: var(--sh-lg); }
.card .badge {
  align-self: flex-start; font: 700 .7rem/1 var(--sans); letter-spacing: .12em; text-transform: uppercase;
  padding: 6px 12px; border-radius: var(--r-pill);
}
.badge.live { background: var(--mist); color: var(--spruce-deep); }
.badge.soon { background: #F6EBDD; color: var(--gold-deep); }
.card img.thumb { border-radius: var(--r); aspect-ratio: 16/10; object-fit: cover; }
.card .push { margin-top: auto; }
.price { font-family: var(--serif); font-size: 1.7rem; color: var(--ink); }
.price small { font-family: var(--sans); font-size: .85rem; color: var(--mute); }

/* ---------- the scattered robots ---------- */
.bots { pointer-events: none; }
.bot {
  position: absolute; width: clamp(56px, 8vw, 110px); filter: drop-shadow(0 10px 18px rgba(19,32,28,.25));
  animation: bob 6s ease-in-out infinite; pointer-events: none; z-index: 0;
}
section > .wrap { position: relative; z-index: 1; }
.bot.small { width: clamp(42px, 5.5vw, 74px); }
.bot.flip { transform: scaleX(-1); }
@keyframes bob { 0%,100% { translate: 0 0; } 50% { translate: 0 -10px; } }
.bot:nth-child(2n) { animation-duration: 7.4s; animation-delay: 1.1s; }
.bot:nth-child(3n) { animation-duration: 8.6s; animation-delay: .6s; }
@media (prefers-reduced-motion: reduce) { .bot { animation: none; } }

/* NEVER LAY COPY ACROSS A CHARACTER.
   The decorative robots are absolutely positioned in the top corners of a
   section; `section > .wrap { z-index: 1 }` puts the words in FRONT of them, so
   on a narrow screen a heading runs straight over a robot's face instead of
   being pushed aside by it. Only sections that actually carry a robot pay the
   padding, so nothing else re-wraps for a decoration it doesn't have. */
/* THE ROBOTS ONLY APPEAR WHERE THERE IS GUTTER FOR THEM.
   `.bot` is absolutely positioned in a section's corners at `left: 2%` /
   `right: 4%`. Below ~1180px the `.wrap` fills the viewport, so those corners
   ARE the text column — and measured at glyph level (a Range, not the element
   box, which padding shrinks without moving) headings and body copy really were
   printed across Skip's face on the home page and across Barnacle on the store
   page. Padding the column from both sides to rescue a 40px trinket leaves
   ~186px of text on a phone, which trades a real thing for a decorative one.
   Above 1180px the wrap is centred with empty gutters, the robots sit in them,
   and nothing collides — verified at 1440px.
   The paintings that carry these pages on a small screen are the heroes and the
   story films, and those are always there. NEVER LAY COPY ACROSS A CHARACTER.

   WHY 1420px, and not a round number: it is arithmetic, not taste. The wrap is
   1140px, so each gutter is (vw − 1140) / 2. A bot sits at `left: 2%` of the
   viewport and is up to 110px wide, so it clears the text only when
   0.02·vw + 110 ≤ (vw − 1140) / 2  →  vw ≥ 1417px. Measured, not guessed: 1440
   is clear and 1280 collides. If this breakpoint is ever raised or lowered,
   re-run the glyph-level overlap check across widths — an element's box is not
   its text, and padding moves one without moving the other. */
@media (max-width: 1419px) { .bot { display: none; } }

/* ---------- footer ---------- */
.site-foot { background: var(--night); color: #B9C8C2; padding: 56px 0 40px; font-size: .92rem; }
.site-foot a { color: #DCE7E2; }
.site-foot a:hover { color: var(--cyan); }
.foot-grid { display: grid; grid-template-columns: 2fr 1fr 1fr 1fr; gap: 30px; }
.foot-grid h4 { color: #FBFAF7; font: 700 .8rem/1 var(--sans); letter-spacing: .14em; text-transform: uppercase; margin: 0 0 12px; }
.foot-grid ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.one-law {
  margin-top: 36px; padding-top: 22px; border-top: 1px solid rgba(255,255,255,.12);
  font-family: var(--serif); font-style: italic; color: #EBD9B8;
}
.fineprint { margin-top: 14px; font-size: .8rem; color: #7E9089; }

/* The transparency pledge — standing site order. It lives in the footer of EVERY
   page, not only the store, because it is the reason a careful clinician trusts
   this company. qa:one-voice fails if a page loses it. */
.pledge-line {
  margin-top: 18px; font-size: .86rem; color: #C4D3CD; max-width: 78ch; line-height: 1.6;
}
.pledge-line strong { color: #EBD9B8; }

/* ---------- store ---------- */
.store-hero { background: var(--night); color: #fff; padding: 70px 0 60px; text-align: center; }
.store-hero .tagline { color: #EBD9B8; font-family: var(--serif); font-style: italic; }
/* 🚪 The door notice — shown only while the store is shut (js/store.js DOOR_OPEN).
   Gold on night, reading as an announcement rather than an error: the doors are
   not broken, they are dated. Sized in ch so the line wraps sanely on a phone. */
#door-notice {
  display: inline-block; max-width: 58ch; margin: 0 auto 18px;
  padding: 12px 20px; border: 1px solid var(--paint-gold, #C89B3C); border-radius: 10px;
  background: rgba(200, 155, 60, .12); color: #F0DCB4;
  font-size: clamp(.95rem, 2vw, 1.05rem); line-height: 1.5;
}
#door-notice[hidden] { display: none; }
.founders {
  background: linear-gradient(120deg, #FDF6EA, #F6EBDD); border: 1px solid #EAD9BC;
  border-radius: var(--r-lg); padding: 22px 26px; margin: 30px 0; display: flex; gap: 16px; align-items: center;
}
.founders strong { color: var(--gold-deep); }

/* The phones-only store band (2026-08-18). Default is HIDDEN, and the
   max-width:720px block far below is the only place it is ever shown — so a
   desktop reader never meets two doors to the same room. */
.store-band { display: none; }

/* ---------- responsive ---------- */
@media (max-width: 860px) {
  .foot-grid { grid-template-columns: 1fr 1fr; }
  .nav { gap: 14px; }
  .nav a:not(.cta):not(.keep) { display: none; }
  .hero .poster { height: min(78vh, 640px); }
  section { padding: 60px 0; }
  .bot { width: 52px; opacity: .9; }
  .bot.small { width: 40px; }
}

/* ── THE FUNNEL BAND (2026-07-30) ──────────────────────────────────────────
   Lance's order: every page has a direction going to the store. Sits directly
   above the footer on all eight pages, identical everywhere — a visitor who
   reaches the bottom of any page finds the same door in the same place. */
.funnel-band {
  background: var(--night);
  background-image:
    radial-gradient(60% 60% at 12% 0%, rgba(62,207,207,.14) 0%, transparent 70%),
    radial-gradient(55% 55% at 92% 100%, rgba(205,148,74,.16) 0%, transparent 70%);
  color: #E6F2EE; padding: 66px 0 60px; text-align: center;
}
.funnel-band h2 { color: #FBFAF7; margin: 0 0 .35em; font-size: clamp(1.7rem, 4.6vw, 2.6rem); }
.funnel-band p { color: #C9DAD5; max-width: 60ch; margin: 0 auto 10px; }
.funnel-band strong { color: #EBD9B8; }
.funnel-band .band-cta { display: flex; gap: 14px; justify-content: center; flex-wrap: wrap; margin: 26px auto 0; }
.funnel-band .band-fine { font-size: .9rem; margin-top: 22px; color: #A8BEB9; }
.funnel-band .band-fine a { color: var(--cyan); }

/* ── THE TWO DOORS (2026-07-30) ────────────────────────────────────────────
   Lance's call: anyone may buy the worlds, but the whole site was written for
   therapists. Nobody reads copy addressed to someone else, so the first thing
   after the poster is a fork, and each side speaks only to its own reader. */
.doorway { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 26px; }
.door-card {
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-lg);
  padding: 32px 30px; box-shadow: var(--sh); display: flex; flex-direction: column;
  position: relative; overflow: hidden;
}
.door-card::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 5px;
}
.door-card.clinician::before { background: linear-gradient(90deg, var(--gold), var(--gold-deep)); }
.door-card.self::before      { background: linear-gradient(90deg, var(--cyan), var(--teal)); }
.door-kick {
  font-size: .72rem; letter-spacing: .18em; text-transform: uppercase; font-weight: 800;
  color: var(--mute);
}
.door-card h3 { margin: .5em 0 .35em; font-size: clamp(1.25rem, 2.6vw, 1.6rem); }
.door-card > p { color: var(--ink-soft); margin: 0 0 16px; }
.door-list { list-style: none; margin: 0 0 18px; padding: 0; display: grid; gap: 7px; color: var(--ink-soft); font-size: .95rem; }
.door-list li { padding-left: 22px; position: relative; }
.door-list li::before { content: "◆"; position: absolute; left: 2px; font-size: .72em; top: .3em; color: var(--gold); }
.door-card.self .door-list li::before { color: var(--teal); }
.door-price { margin: auto 0 18px; font-family: var(--serif); font-size: 1.5rem; color: var(--spruce-deep); }
.door-price strong { font-weight: 700; }
.door-price span { font-family: var(--sans); font-size: .82rem; font-weight: 500; color: var(--mute); display: block; }
.door-quiet { display: inline-block; margin-top: 12px; font-size: .9rem; font-weight: 600; }
.door-foot { text-align: center; margin-top: 30px; color: var(--mute); font-size: .95rem; }

/* ── THE LIGHTHOUSE HERO (2026-07-30) ──────────────────────────────────────
   The flagship page had no art at all — a text band where the product a
   clinician is being asked to pay for should be making its case. The painting
   carries the argument the copy then makes in words. */
.lh-hero { position: relative; overflow: hidden; background: var(--night); }
.lh-hero-art { width: 100%; display: block; object-fit: cover; max-height: 70vh; }
.lh-hero-veil {
  position: absolute; inset: 0;
  background: linear-gradient(100deg, rgba(9,22,28,.90) 0%, rgba(9,22,28,.72) 34%, rgba(9,22,28,.12) 62%, transparent 78%);
}
.lh-hero-copy { position: absolute; inset: 0; display: flex; align-items: center; }
.lh-hero-copy h1 { color: #FBFAF7; margin: .1em 0 .15em; }
.lh-hero-copy .tagline { color: var(--paint-gold); font-size: clamp(1.05rem, 2.4vw, 1.4rem); margin: 0; }
.lh-hero-sub { color: #C9DAD5; max-width: 34ch; margin: 14px 0 0; font-size: 1.02rem; line-height: 1.55; }
.lh-hero-cta { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 26px; }
/* ON A PHONE THE COPY COMES OUT FROM UNDER THE PAINTING.
   First attempt kept it absolutely positioned over a shortened image and the
   headline was clipped straight off the top — the copy is simply taller than a
   42vh painting, and an overlay cannot shrink to fit. Caught in a 390px
   screenshot, not in the CSS.
   So on narrow screens the hero stops being an overlay entirely: the painting
   is a band, the words sit beneath it on the same dark ground. Nothing to
   collide with, nothing to clip. (THE CROP LAW: never lay words across a
   painting that has no room for them.) */
@media (max-width: 760px) {
  .lh-hero-art { max-height: 34vh; object-fit: cover; object-position: 68% center; }
  .lh-hero-veil { display: none; }
  .lh-hero-copy {
    position: static; display: block; padding: 26px 0 32px;
    background: linear-gradient(180deg, #0B1E26 0%, var(--night) 100%);
  }
  .lh-hero-sub { max-width: none; }
  .lh-hero-cta .btn { width: 100%; text-align: center; }
}

/* The ghost CTA lands wherever the painting is brightest, so it carries its own
   dark ground rather than trusting the art underneath to stay dark. */
.lh-hero-cta .btn-ghost {
  background: rgba(9, 22, 28, .58);
  backdrop-filter: blur(6px);
  border: 1.5px solid rgba(235, 217, 184, .55);
  color: #FBFAF7;
}
.lh-hero-cta .btn-ghost:hover { background: rgba(9, 22, 28, .78); }

/* ── THE STORY FILMS (2026-07-30) ──────────────────────────────────────────
   Lance: "shout out why these products deserve their time." The three books
   are the answer, and until now none of them were on the site.

   A film is a poster <img> with a <video> laid exactly over it. The poster is
   what loads; the video arrives on scroll and fades in on top. See
   js/story-film.js for the behaviour and the reasoning. */
.filmstrip { display: grid; gap: 30px; margin-top: 34px; }
.filmstrip.two { grid-template-columns: repeat(auto-fit, minmax(330px, 1fr)); }
.filmstrip.three { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }

.film {
  position: relative; overflow: hidden; border-radius: var(--r-lg);
  background: var(--night); box-shadow: var(--sh-lg); isolation: isolate;
  /* <figure> carries a default margin of 16px 40px in every browser, which was
     eating 80px of width out of every card in a three-column strip. Grid gap
     already does the spacing. */
  margin: 0;
  display: flex; flex-direction: column;
}
.film-media { position: relative; aspect-ratio: 16 / 9; overflow: hidden; }
.film-media img, .film-video {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; display: block;
}
.film-video { opacity: 0; transition: opacity .7s ease; }
.film.film-ready .film-video { opacity: 1; }

/* The caption sits UNDER the painting, never across it. A face or a lit window
   is the whole point of the frame; words on top of it destroy both.
   (THE CROP LAW — the same rule that governs the app openings.) */
.film-words { padding: 20px 22px 22px; background: var(--night); color: #C9DAD5; }
.film-line {
  margin: 0; font-family: var(--serif); font-size: clamp(1.05rem, 2.1vw, 1.3rem);
  line-height: 1.35; color: #FBFAF7;
}
.film-note { margin: 9px 0 0; font-size: .89rem; line-height: 1.5; color: #A8BEB9; }
.film-src {
  display: block; margin-top: 11px; font-size: .74rem; letter-spacing: .13em;
  text-transform: uppercase; font-weight: 700; color: var(--paint-gold); opacity: .78;
}

/* A single wide film that carries one line — used where a page needs one
   moment rather than a strip. */
.film.solo .film-media { aspect-ratio: 21 / 9; }
@media (max-width: 700px) { .film.solo .film-media { aspect-ratio: 16 / 9; } }

/* The dark story band the films sit in. */
.story-band { background: var(--night); padding: 68px 0 62px; }
.story-band .kicker { color: var(--paint-gold); }
.story-band h2 { color: #FBFAF7; }
.story-band > .wrap > p { color: #C9DAD5; max-width: 64ch; }
.story-band .pull {
  margin: 30px 0 0; padding-left: 22px; border-left: 3px solid var(--gold);
  font-family: var(--serif); font-size: clamp(1.15rem, 2.6vw, 1.6rem);
  line-height: 1.35; color: #EBD9B8;
}
.story-band .pull cite { display: block; margin-top: 10px; font: 600 .8rem var(--sans);
  letter-spacing: .12em; text-transform: uppercase; color: #8FA8A2; font-style: normal; }
.story-more { margin-top: 30px; }

/* ── CHIP (2026-07-30) ─────────────────────────────────────────────────────
   Lance: the intern boy should be on the site more. He is the character the
   client actually spends the journey with, and the art here is the app's own
   character sheet — so the site shows exactly who they will meet. */
.chip-row { display: grid; grid-template-columns: minmax(180px, 300px) 1fr; gap: 40px; align-items: center; }
.chip-art { display: flex; justify-content: center; }
.chip-art img {
  width: 100%; max-width: 300px; height: auto;
  filter: drop-shadow(0 18px 34px rgba(19,32,28,.28));
}
.chip-copy h2 { margin: .1em 0 .3em; }
.chip-copy p { color: var(--ink-soft); }
.chip-quiet { font-style: italic; color: var(--mute); }
@media (max-width: 720px) {
  .chip-row { grid-template-columns: 1fr; gap: 22px; text-align: center; }
  .chip-art img { max-width: 210px; }
}


/* ── SEE IT (2026-07-31) ───────────────────────────────────────────────────
   The storefront asked for $49.99/month while showing a buyer nothing of the
   software. Screens go ABOVE the price, because "show me" comes before "how
   much". Scrolls on a phone rather than shrinking to illegibility. */
.seeit { margin: 0 0 46px; }
.seeit h2 { margin: 0 0 10px; }
.seeit-lead { color: var(--ink-soft, #3C4A46); max-width: 62ch; margin: 0 0 26px; }
.shots {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px;
}
.shot { margin: 0; }
.shot img {
  width: 100%; display: block; border-radius: 14px; border: 1px solid rgba(19,32,28,.12);
  box-shadow: 0 12px 34px rgba(19,32,28,.14); background: #fff;
  /* The set mixes 1600x1000 desktop captures with 820x1520 phone ones. Without a
     fixed ratio the grid tore itself apart around the tall ones. Cropping from
     the TOP keeps each screen's header and first rows — the part that identifies
     it — rather than centring on empty middle. */
  aspect-ratio: 16 / 10; object-fit: cover; object-position: top center;
}
.shot figcaption { margin-top: 9px; font-size: .84rem; line-height: 1.45; color: #6E7B77; }
@media (max-width: 900px) { .shots { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) {
  /* One up, full width — a screenshot two inches wide proves nothing. */
  .shots { grid-template-columns: 1fr; }
}

/* The store's three world cards were pure text and buttons — a bullet list for
   products whose whole pitch is that they are beautiful places. (2026-07-31) */
.app-shot {
  width: 100%; display: block; aspect-ratio: 16/9; object-fit: cover;
  border-radius: 12px; margin: 0 0 14px;
  box-shadow: 0 8px 24px rgba(19,32,28,.16);
}

/* The flagship page shows the flagship (2026-07-31). Two-up, because these are
   wide console captures and three across makes them unreadable. */
.lh-shots { padding: 74px 0; background: var(--cloud); }
.lh-shots .shots { grid-template-columns: repeat(2, 1fr); margin-top: 30px; }
@media (max-width: 760px) { .lh-shots .shots { grid-template-columns: 1fr; } }

/* ---------- "See it running" — the proof band (2026-08-15) ----------
   The home page sold a $49.99 workspace and showed a stranger no pixel of it.
   The store page had proof since 08-14; the page a stranger actually LANDS on
   had none. Prose is not proof.

   ⚠️ NAMED `.proof-shots`, NOT `.shots`. The first version of this reused
   `.shots`, which already exists at line ~451 and is what the Lighthouse page's
   gallery is built on — including two media queries that set its column count.
   Because this block sits LATER in the file, its unconditional
   `grid-template-columns` beat both of them at every width, so a change meant
   for the home page silently relaid out a different page's gallery. Nothing
   errored and nothing warned; the only way to see it was to notice the name was
   already taken. A class name is an interface, and reusing one is editing
   whatever else answers to it. [[unlayered-css-beats-a-utility]]

   Two columns on a laptop, one on a phone — a screenshot of a dense clinical
   screen shrunk into a three-up grid is legible to nobody, and an illegible
   screenshot argues against the product rather than for it. */
.proof-shots {
  display: grid; gap: 26px;
  grid-template-columns: repeat(auto-fit, minmax(min(420px, 100%), 1fr));
}
.proof-shots figure { margin: 0; }
.proof-shots img {
  display: block; width: 100%; height: auto;
  border-radius: 14px; border: 1px solid rgba(13, 27, 34, .12);
  box-shadow: 0 10px 34px rgba(13, 27, 34, .16);
  background: #F8FAFC;   /* so a slow image is a calm panel, never a black hole */
}
.proof-shots figcaption {
  margin-top: 10px; font-size: .93rem; line-height: 1.5;
  color: var(--ink-soft, #4A5A60);
}

/* ---------- the mobile menu (2026-08-15) ----------
   Paired with js/nav.js. See that file for what was wrong: the toggle class
   existed, was hidden unconditionally, and no button was ever built — so on a
   phone the header's six links simply were not there, and it looked deliberate.

   The toggle appears ONLY at the width where the links are hidden, so the two
   rules cannot disagree about when a menu is needed. */
@media (max-width: 720px) {
  .nav-toggle {
    display: flex; flex-direction: column; justify-content: center; gap: 5px;
    /* 44px: the tap target, not the icon. A 20px hamburger is a 20px target. */
    width: 44px; height: 44px; padding: 0 10px; margin-left: auto;
    background: none; border: 0; cursor: pointer;
  }
  .nav-toggle span {
    display: block; height: 2px; width: 100%; border-radius: 2px;
    background: var(--ink-soft, #4A5A60);
    transition: transform .18s ease, opacity .18s ease;
  }
  .nav-toggle.open span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
  .nav-toggle.open span:nth-child(2) { opacity: 0; }
  .nav-toggle.open span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

  /* ── THE STORE PILL LEAVES THE BAR ON PHONES (2026-08-18, Lance's call) ──
     It used to stay here at all times, and the rule behind that — "the money
     path is never behind a menu" — is still right and still enforced. What
     changed is WHERE the unmenued path lives: above the poster it read as an
     artifact floating over the painting. It is now `.store-band`, a full-width
     bar directly under the hero, in the reading path and not behind a tap.

     ⚠️ It is still ALSO given back inside the opened menu below, so a person
     who opens the hamburger looking for it finds it there too. What must never
     happen is the menu becoming the ONLY way. */
  .nav a.cta { display: none; }
  .nav.open a.cta { display: block; width: 100%; padding: 11px 2px; font-size: 1rem; }

  .nav { margin-left: auto; }

  /* The band itself: phones only. Hidden at every wider width, where the header
     pill is correct and stays. */
  .store-band {
    display: flex; flex-direction: column; gap: 2px;
    padding: 14px 20px; text-decoration: none;
    background: var(--spruce, #1E6E5A); color: #fff;
    border-bottom: 1px solid rgba(0, 0, 0, .18);
  }
  .store-band-label { font-weight: 800; font-size: 1.02rem; color: #fff; }
  /* ⚠️ MEASURED, and my first number was wrong. I wrote "4.6:1" from a ground I
     had GUESSED (#2E5A54) rather than read. `--spruce` is #1E6E5A. Computed
     against the real token: the label is 6.12:1 and this sub-line 5.15:1 —
     both clear AA at these sizes. A contrast claim must name the ground it was
     measured against, and I nearly shipped one that named a colour this site
     does not contain. [[a-contrast-fix-must-name-its-ground]] */
  .store-band-sub { font-size: .84rem; color: rgba(255, 255, 255, .88); }

  /* 🔴 THE PANEL OPENED OVER THE PAINTING, UNREADABLE (caught by opening the PNG).
     `.site-head .wrap` is `height: 64px` — a fixed height, not a minimum. So the
     expanded menu overflowed BELOW the header's painted background and the links
     rendered in dark ink directly on top of the poster: eight links present,
     eight links technically visible, none of them legible.

     The automated check said "closed=1, open=8" and was perfectly correct and
     completely useless — it counted what the DOM offered, not what a person
     could read. The screenshot took two seconds. [[a-check-that-passes-on-a-blank-screen]]

     The header must be allowed to GROW when it holds a panel. */
  .site-head .wrap { flex-wrap: wrap; height: auto; min-height: 64px; }
  .site-head:has(.nav.open) { background: var(--cream); }

  .nav.open {
    display: flex; flex-direction: column; align-items: flex-start;
    gap: 2px; width: 100%; order: 3;
    padding: 8px 0 12px; margin: 6px 0 0;
    border-top: 1px solid rgba(13, 27, 34, .10);
  }
  /* ⚠️ This has to beat `.nav a:not(.cta):not(.keep) { display: none }` above,
     which is what hides them in the first place. Same specificity would lose on
     source order alone, so the open panel names the parent as well. */
  .nav.open a:not(.cta):not(.keep) {
    display: block; width: 100%; padding: 11px 2px; font-size: 1rem;
  }
}
