/* ============================================================
   App in a Day: page layout only.
   Additive to styles.css (generated from the Precise Impact AI
   design system's tokens, APP-662). Every colour, font, radius
   and shadow here is one of styles.css's --pi-* variables: this
   file sets layout and composition, and picks which token does
   which job, never a colour of its own.
   ============================================================ */

.wrap { max-width: 1120px; margin: 0 auto; padding-left: var(--pi-space-24); padding-right: var(--pi-space-24); }
@media (max-width: 560px) {
  .wrap { padding-left: var(--pi-space-16); padding-right: var(--pi-space-16); }
}

/* Nav: the white wordmark on the navy bar (styles.css's .nav). */
.nav { position: relative; }

/* Hero: white, navy type, one blue button. The page's one display line. */
.hero { margin: var(--pi-space-24) auto var(--pi-space-48); position: relative; }
.hero-grid { display: grid; grid-template-columns: 1.15fr .85fr; gap: var(--pi-space-48); align-items: center;
             padding: var(--pi-space-48) 0; position: relative; }
.hero h1 { font-size: clamp(var(--pi-h1-size), 6vw, var(--pi-display-size)); line-height: var(--pi-display-line);
           letter-spacing: var(--pi-display-tracking); margin-bottom: var(--pi-space-16); }
.hero .lede { font-size: 20px; max-width: 46ch; }
.hero-meta { color: var(--pi-text-secondary); }
/* The hero's "By 5pm" line (APP-799): the lede's measure, so it wraps with it. */
.hero-outcome { max-width: 46ch; font-weight: 600; }
/* The event date, as the first and loudest fact on the page. At the design
   system's small tag size it read as decoration, and a booking closing date in
   small print a week earlier was taken for the day itself. */
.hero-date { font-size: clamp(16px, 2.2vw, 24px); padding: var(--pi-space-8) var(--pi-space-24);
             border-radius: var(--pi-radius-pill); letter-spacing: .01em; margin-bottom: var(--pi-space-24); }
.hero-date b { font-weight: 700; white-space: nowrap; }
/* On a phone the chip cannot fit on one line, so the date gets a line of its
   own rather than wrapping wherever it falls and stranding the separator. */
@media (max-width: 560px) {
  .hero-date { border-radius: var(--pi-radius-card); }
  .hero-date-sep { display: none; }
  .hero-date b { display: block; }
}

/* The dark statement band ("The important bit"): styles.css's .dark, navy
   with white type. The brand keeps these rare and flat, so no texture. */
.section-texture { position: relative; overflow: hidden; }

.video-frame { aspect-ratio: 16/10; border-radius: var(--pi-radius-dialog); display: grid; place-items: center;
               position: relative; color: var(--pi-on-action); overflow: hidden; background: var(--pi-text); }
.video-frame .play { width: 72px; height: 72px; border-radius: 50%; background: var(--pi-surface);
                      color: var(--pi-action); display: grid; place-items: center; font-size: 26px; box-shadow: var(--pi-shadow-medium); }
.video-frame .video-label { position: absolute; bottom: var(--pi-space-12); left: var(--pi-space-16); right: var(--pi-space-16);
                             font-size: 13px; color: var(--pi-statement-muted); }
.video-frame .video-embed-note { position: absolute; top: var(--pi-space-12); left: var(--pi-space-16); }
.video-frame .tag-outline { border-color: var(--pi-statement-muted); color: var(--pi-on-action); }
/* The homepage hero's demo screenshots (APP-800): three stacked in one sized
   frame, so nothing shifts as they load. The first is never animated and is
   always underneath; the second and third fade in over it in turn and the
   third fades out to show the first again, about seven seconds each. */
.hero-slides { position: relative; aspect-ratio: 800 / 500; border-radius: var(--pi-radius-dialog); overflow: hidden;
               box-shadow: var(--pi-shadow-medium); background: var(--pi-surface-subtle); }
.hero-slide { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.hero-slide + .hero-slide { opacity: 0; }
/* Only for a visitor who has not asked for reduced motion; otherwise the first
   stays, by never animating rather than by an override that has to win. */
@media (prefers-reduced-motion: no-preference) {
  .hero-slides-rotate .hero-slide:nth-child(2) { animation: hero-slide-2 21s linear infinite; }
  .hero-slides-rotate .hero-slide:nth-child(3) { animation: hero-slide-3 21s linear infinite; }
}
@keyframes hero-slide-2 { 0%, 28% { opacity: 0; } 33%, 71% { opacity: 1; } 72%, 100% { opacity: 0; } }
@keyframes hero-slide-3 { 0%, 61% { opacity: 0; } 66%, 95% { opacity: 1; } 100% { opacity: 0; } }

/* "Is this you?" (APP-920): a checklist to agree with, not cards to click. It
   sits on the page like every other section, so its heading lines up with
   theirs; each picture carries a green tick and nothing has a box or a shadow,
   because a white card on a tinted panel reads as a link and these go nowhere. */
.you-section { padding-bottom: var(--pi-space-32); }
.you-list { list-style: none; margin: 0; padding: 0; max-width: none; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--pi-space-32); }
.you-item { margin: 0; }
.you-media { position: relative; }
.you-media .you-photo { margin: 0; }
.you-tick { position: absolute; left: var(--pi-space-12); bottom: calc(-1 * var(--pi-space-16)); width: 40px; height: 40px; border-radius: 50%;
            display: grid; place-items: center; background: var(--pi-success); color: var(--pi-on-action);
            box-shadow: 0 0 0 4px var(--pi-surface); }
.you-tick svg { width: 22px; height: 22px; stroke: currentColor; fill: none; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.you-text { margin: var(--pi-space-24) 0 0; }

/* The three roads, Grow, Run and Invent (APP-636): the design system's own
   road tokens, the same three colours in the room, the handouts and the
   CHARM Design Tool. Each road sets --road and --road-tint, and everything
   below reads only those two. */
:root {
  --path-grow: var(--pi-grow);     --path-grow-tint: var(--pi-grow-bg);
  --path-run: var(--pi-run);       --path-run-tint: var(--pi-run-bg);
  --path-invent: var(--pi-invent); --path-invent-tint: var(--pi-invent-bg);
}
.path-grow   { --road: var(--path-grow);   --road-tint: var(--path-grow-tint); }
.path-run    { --road: var(--path-run);    --road-tint: var(--path-run-tint); }
.path-invent { --road: var(--path-invent); --road-tint: var(--path-invent-tint); }

/* The road tiles in "Grow. Run. Invent.": the tile takes the road's tint,
   the road's name is the heading rather than a small kicker, and the icon
   follows the icon set's style, a rounded stroke in the road colour over a
   fill in its tint. */
.road-card { background: var(--road-tint); border-color: transparent; border-top: 6px solid var(--road); }
.road-head { display: flex; align-items: baseline; gap: var(--pi-space-12); margin: 0 0 var(--pi-space-16); color: var(--road);
             font-family: var(--pi-font-display); }
.road-number { font-weight: 700; font-size: 1rem; letter-spacing: .04em; }
.road-name { font-weight: 700; font-size: 2rem; line-height: 1; }
.road-icon { width: 72px; height: 72px; margin-bottom: var(--pi-space-16); }
.road-icon svg { width: 100%; height: 100%; fill: none; stroke: var(--road); stroke-width: 3.5;
                 stroke-linecap: round; stroke-linejoin: round; }
.road-icon svg .fill { fill: color-mix(in srgb, var(--road) 22%, var(--pi-surface)); }

/* The coloured title bar across the top of every demo card (PathBar). It is
   the card's first subgrid row, so the rows below it still line up across
   the grid. White on each road colour clears 4.5:1. */
.example-card .path-bar { display: flex; align-items: baseline; flex-wrap: wrap; gap: 0 var(--pi-space-12);
                          margin: 0 0 var(--pi-space-16); padding: var(--pi-space-12) var(--pi-space-24);
                          background: var(--road); color: var(--pi-on-action); line-height: 1.3; }
.path-bar-road { font-family: var(--pi-font-display); font-weight: 700; font-size: 1.25rem; letter-spacing: .01em; }
.path-bar-business { font-weight: 600; font-size: .9375rem; }
/* The separators keep the text reading "Grow · Roofing firm" when copied or
   read aloud; the flex gap already spaces them visually. */
.path-bar-sep { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

/* Card icon badges */
/* The "Is this you?" cards' pictures (APP-883): illustrative, so decorative to a
   screen reader (alt=""); the card's words carry the meaning. Same frame as the
   example cards' screenshots, so the page's pictures look like one set. */
.you-photo { display: block; width: 100%; height: auto; aspect-ratio: 3 / 2; object-fit: cover;
             border-radius: var(--pi-radius-control); margin: 0 0 var(--pi-space-16); background: var(--pi-canvas); }
.card-icon { width: 44px; height: 44px; border-radius: 50%; background: var(--pi-surface-subtle);
             color: var(--pi-action); display: grid; place-items: center; margin-bottom: var(--pi-space-12); }
.card-icon svg { width: 22px; height: 22px; stroke: currentColor; fill: none; stroke-width: 2;
                  stroke-linecap: round; stroke-linejoin: round; }

/* Section rhythm. Longhand top/bottom only, deliberately not a padding
   shorthand, so this never clobbers the left/right padding that .dark or
   .panel already set when a section carries one of those classes too
   (a real bug: the shorthand was zeroing their horizontal padding). */
.section { padding-top: var(--pi-space-64); padding-bottom: var(--pi-space-64); }
.section-head { max-width: 62ch; margin-bottom: var(--pi-space-32); }
/* A landing page section's heading is a statement, set at the page title's
   size rather than the design system's smaller in-app section size. */
.section-head h2, .section > h2, .offer-grid h2, .cta-band h2, .dark.section h2 { font-size: var(--pi-h1-size); letter-spacing: var(--pi-h1-tracking); }

/* Three-up cards */
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--pi-space-16); }
.grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--pi-space-16); }

/* Authority chips */
.chip-row { display: flex; flex-wrap: wrap; gap: var(--pi-space-8); margin-top: var(--pi-space-16); }

/* Offer */
.offer-grid { display: grid; grid-template-columns: 1.1fr .9fr; gap: var(--pi-space-32); align-items: center; }
.pricebox { background: var(--pi-surface); border: 1px solid var(--pi-border); border-radius: var(--pi-radius-dialog);
            padding: var(--pi-space-32); box-shadow: var(--pi-shadow-medium); position: relative; overflow: hidden; }
.pricebox .price { font-family: var(--pi-font-display); font-size: 64px; font-weight: 600; color: var(--pi-text);
                    letter-spacing: -.03em; line-height: 1; }
/* The full price beside a cheaper tier (APP-515): crossed by a diagonal from bottom left to top right,
   not a text strikethrough. "to bottom right" puts the gradient's middle stripe on that diagonal, and em
   units scale the line with the text so it meets the corners at any size, phone included. */
.price-was { position: relative; display: inline-block; color: var(--pi-text-secondary); margin-right: .4em; }
.pricebox .price .price-was { font-size: .5em; }
.price-was::after { content: ""; position: absolute; inset: 0; pointer-events: none;
                    background: linear-gradient(to bottom right, transparent calc(50% - .06em), var(--pi-error) calc(50% - .06em),
                                                var(--pi-error) calc(50% + .06em), transparent calc(50% + .06em)); }
.price-note { display: block; font-family: var(--pi-font-body); font-size: 15px; font-weight: 400; letter-spacing: 0; color: var(--pi-text-secondary); }
.cta-note .price-note { display: inline; }
.cta-note .price-note::before { content: " \00b7  "; }
.pricebox ul { list-style: none; padding: 0; margin: var(--pi-space-16) 0; }
.pricebox li { padding: var(--pi-space-4) 0 var(--pi-space-4) var(--pi-space-24); position: relative; }
.pricebox li::before { content: "✓"; position: absolute; left: 0; color: var(--pi-action); font-weight: 700; }
.quote-line { font-family: var(--pi-font-display); font-weight: 500; font-size: 22px; color: var(--pi-text); }

/* Ticket-perforation divider inside the pricebox, between the feature list
   and the CTA. Punched "notches" match the panel colour sitting behind the
   card so they read as a real tear rather than a decoration on top. */
.ticket-tear { position: relative; height: 0; border-top: 2px dashed var(--pi-border); margin: var(--pi-space-24) 0; }
.ticket-tear::before, .ticket-tear::after {
  content: ""; position: absolute; top: 50%; transform: translateY(-50%);
  width: 24px; height: 24px; border-radius: 50%; background: var(--pi-surface-subtle);
}
.ticket-tear::before { left: calc(-1 * var(--pi-space-32) - 12px); }
.ticket-tear::after { right: calc(-1 * var(--pi-space-32) - 12px); }

/* FAQ */
/* The idea form as three steps (APP-919). Without the script (no .steps-on) the
   fieldsets are one plain form. With it, one step shows under a progress bar
   whose fill eases to each step, still for anyone who asks for less motion. */
.lead-form .form-step { border: 0; margin: 0; padding: 0; min-width: 0; }
.lead-form .form-step + .form-step { margin-top: var(--pi-space-16); }
.lead-form.steps-on .form-step + .form-step { margin-top: 0; }
.form-step-title { font-weight: 700; font-size: 18px; color: var(--pi-text); margin: 0 0 var(--pi-space-12); padding: 0; }
.lead-form:not(.steps-on) .form-step-title { font-size: 16px; }
.form-progress { margin: 0 0 var(--pi-space-24); }
.form-progress-label { margin: 0 0 var(--pi-space-8); font-size: 13px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--pi-text-secondary); }
.form-progress-track { height: 8px; border-radius: var(--pi-radius-pill); background: var(--pi-surface-subtle); overflow: hidden; }
.form-progress-fill { height: 100%; width: 33.34%; border-radius: inherit; background: linear-gradient(90deg, var(--pi-action), var(--pi-brand-cyan)); transition: width 0.35s ease; }
.lead-form.steps-on .contact-fields { grid-template-columns: minmax(0, 1fr); }
/* The last step ends on Send beside Back; without the script, Send stands alone, full width. */
.form-step-actions { display: flex; align-items: center; justify-content: space-between; gap: var(--pi-space-12); margin-top: var(--pi-space-16); }
.form-step-actions > [type="submit"] { flex: 1; }
.lead-form.steps-on .form-step-actions > [type="submit"] { flex: 0 1 auto; min-width: 10rem; }
.form-step-nav { display: flex; justify-content: space-between; gap: var(--pi-space-12); margin-top: var(--pi-space-16); }
.form-step-nav [data-step-next]:only-child { margin-left: auto; }
.form-step-nav [data-step-next] { min-width: 8rem; }
@media (prefers-reduced-motion: reduce) { .form-progress-fill { transition: none; } }

/* The idea form and the FAQ as blocks of their own (APP-918): at the foot of the
   page they ran together on plain white. The idea section takes the tinted band
   the pricing section uses; the FAQ a white card with a soft edge, so the two
   neighbours never share a background. */
.section-band { padding-left: var(--pi-space-32); padding-right: var(--pi-space-32); margin-top: var(--pi-space-32); }
.faq-band { background: var(--pi-surface); border: 1px solid var(--pi-border); border-radius: var(--pi-radius-dialog);
            box-shadow: var(--pi-shadow-small); padding-left: var(--pi-space-32); padding-right: var(--pi-space-32); margin-top: var(--pi-space-32); }
/* Two panels in a row (APP-926): the testimonial band and the plain pricing
   panel after it touched, because only a band carries its own top margin. */
.panel + .panel { margin-top: var(--pi-space-32); }
@media (max-width: 560px) {
  .section-band, .faq-band { padding-left: var(--pi-space-16); padding-right: var(--pi-space-16); }
}
.faq details { border-top: 1px solid var(--pi-border); padding: var(--pi-space-16) 0; }
.faq details:last-of-type { border-bottom: 1px solid var(--pi-border); }
.faq summary { font-weight: 600; cursor: pointer; color: var(--pi-text); }
.faq summary::marker, .faq summary::-webkit-details-marker { color: var(--pi-action); }
.faq p { margin-top: var(--pi-space-8); }
/* The answers built from the event and venue (APP-578) list their facts, one per line. */
.faq details ul, .faq details ol { margin: var(--pi-space-8) 0 0; padding-left: var(--pi-space-24); }
.faq details li + li { margin-top: var(--pi-space-4); }
/* Two columns of questions (APP-564). Two containers rather than CSS columns, so
   opening one never moves the others from one column to the other. Each column
   is narrower than styles.css's 68ch cap on p, which is what used to end every
   answer two thirds of the way across a single full-width column. */
.faq-cols { display: grid; grid-template-columns: 1fr 1fr; column-gap: var(--pi-space-48); align-items: start; }
.faq-col details:last-of-type { border-bottom: 1px solid var(--pi-border); }
@media (max-width: 760px) {
  .faq-cols { grid-template-columns: 1fr; }
  /* Stacked, the first group's closing line and the second's opening line would meet as a double rule. */
  .faq-col:first-child details:last-of-type { border-bottom: 0; }
}

/* Success / holding pages */
.success-wrap { max-width: 640px; margin: var(--pi-space-64) auto; text-align: center; }
.success-wrap .video-frame { max-width: 460px; margin: var(--pi-space-24) auto; }

/* Build Brief form */
.form-card { max-width: 760px; margin: var(--pi-space-32) auto var(--pi-space-64); padding: var(--pi-space-32);
             border: 1px solid var(--pi-border); border-radius: var(--pi-radius-dialog); background: var(--pi-surface); }
.form-field { margin: var(--pi-space-24) 0; }
/* A radio or checkbox group is a fieldset with a legend (APP-180), so a screen
   reader announces the question with every option. Both come with a border,
   padding and a shrink-wrapped width of their own; these put them back to
   exactly what the div and span they replaced looked like. */
fieldset.form-field { border: 0; padding: 0; min-width: 0; }
.form-field > legend.q { padding: 0; }
.form-field > .q { display: block; font-family: var(--pi-font-display); font-weight: 600; font-size: 17px;
                    color: var(--pi-text); margin-bottom: var(--pi-space-8); }
.form-field .hint { font-size: 13px; color: var(--pi-text-secondary); margin: -4px 0 var(--pi-space-8); }
.choice-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--pi-space-8); }
.choice { display: flex; align-items: center; gap: var(--pi-space-8); padding: var(--pi-space-12); border: 1px solid var(--pi-control-border);
          border-radius: var(--pi-radius-control); cursor: pointer; background: var(--pi-surface); position: relative; margin-bottom: 0; }
.choice:hover { border-color: var(--pi-action); }
.choice:has(input:checked) { border-color: var(--pi-action); background: var(--pi-surface-subtle); }
.choice input { accent-color: var(--pi-action); }
.range-scale { display: flex; justify-content: space-between; font-size: 12px; color: var(--pi-text-secondary); margin-top: var(--pi-space-4); }
.conditional { margin-top: var(--pi-space-12); display: none; }
.conditional.is-visible { display: block; }

/* Checkout: what you are buying on the left, Stripe's form on the right.
   Stripe's embedded form sizes itself to its container, so it gets the wider
   column and a plain white card, and nothing here reaches inside its iframe. */
.checkout-grid { display: grid; grid-template-columns: .85fr 1.15fr; gap: var(--pi-space-48); align-items: start; }
.checkout-title { margin-bottom: var(--pi-space-12); }
.checkout-wordmark { display: block; width: 100%; max-width: 240px; height: auto; }
.checkout-summary { text-align: left; background: var(--pi-surface-subtle); border-radius: var(--pi-radius-card);
                     padding: var(--pi-space-24); margin: var(--pi-space-24) 0 0; }
.checkout-includes { margin: var(--pi-space-8) 0 var(--pi-space-16); padding-left: var(--pi-space-24); }
.checkout-includes li { padding: var(--pi-space-4) 0; }
.checkout-summary dl { display: grid; grid-template-columns: auto 1fr; gap: var(--pi-space-8) var(--pi-space-12); margin: 0;
                        padding-top: var(--pi-space-12); border-top: 1px solid var(--pi-border); font-variant-numeric: tabular-nums; }
.checkout-summary dt { color: var(--pi-text-secondary); }
.checkout-summary dd { margin: 0; font-weight: 600; text-align: right; }
.checkout-summary .checkout-total { color: var(--pi-text); font-weight: 700; font-size: 18px; }
.checkout-pay { padding: var(--pi-space-24); min-height: 420px; }
.checkout-closed { padding: var(--pi-space-24) 0; }
@media (max-width: 860px) {
  .checkout-grid { grid-template-columns: 1fr; gap: var(--pi-space-24); }
  .checkout-pay { padding: var(--pi-space-12); }
}
/* Once Stripe's embedded Checkout has mounted (APP-566), its frame paints the
   account's brand background edge to edge, so our padding and white card only
   framed a square block inside rounded white corners. The card steps back
   and clips to its own radius, and Stripe's background fills the rounded box.
   No colour is copied from Stripe, so a branding change there needs nothing
   here. Before the frame loads, and for a message shown instead of it, the
   card keeps its padding. */
.checkout-pay:has(#checkout iframe) { padding: 0; min-height: 0; background: transparent; overflow: hidden; }
.checkout-pay:has(#checkout iframe) iframe { display: block; }
/* Stripe's form picks its layout from the frame's width, and none of its
   spacing can be set from here (APP-620). Measured on UAT: from 420px to at
   least 600px it centres a white card of a fixed 410px, so the background beside
   it is simply the width left over (about 90px a side in the 589px column at
   1280, 155px stacked at 768). At 400px and below it switches to its compact
   layout, the white running edge to edge, which is what a phone gets. 440px
   leaves an even 15px each side, lines Stripe's heading up with its
   card, and stays 40px clear of the compact switch. The payment card sits at
   the right edge of the grid beside the summary, and centred once stacked.
   Only the payment form is narrowed: the waiting list and "not open" cards
   keep the whole column. */
.checkout-pay:has(#checkout) { width: 100%; max-width: 440px; justify-self: end; }
@media (max-width: 860px) {
  .checkout-pay:has(#checkout) { justify-self: center; }
}

.footer-band { padding: var(--pi-space-32) 0; text-align: center; }
.footer-band .small { display: block; }
.footer-band .footer-links { display: block; margin-top: var(--pi-space-8); }
.footer-band .footer-links a { color: var(--pi-text-secondary); }
.footer-band .footer-links a:hover { color: var(--pi-action); }
/* The "Next event" callout (APP-464): a .panel sized to its content and
   centred, whose chip, title and details wrap onto lines of their own on a
   phone rather than squeezing into one. */
.footer-band .footer-next { display: inline-flex; flex-wrap: wrap; align-items: center;
  justify-content: center; gap: var(--pi-space-8) var(--pi-space-12); margin: 0 0 var(--pi-space-16); }

/* Privacy and terms: long-form text, so headings need their own rhythm rather
   than a fresh .section's padding around every one. The text runs the full
   width of .wrap like every other page (APP-463): a 74ch column stopped two
   thirds of the way across, and the design system's own p (68ch) and ul/ol
   (66ch) caps then ended paragraphs and lists at two more widths inside it. */
.legal, .legal p, .legal ul, .legal ol { max-width: none; }
.legal h2 { margin-top: var(--pi-space-48); }
.legal h2:first-of-type { margin-top: 0; }

@media (max-width: 860px) {
  .hero-grid, .offer-grid, .grid-3, .grid-2, .choice-grid { grid-template-columns: 1fr; }
  .hero { margin-top: var(--pi-space-16); }
  .hero-grid { padding: var(--pi-space-16) 0 0; gap: var(--pi-space-32); }
  .you-list { grid-template-columns: 1fr; gap: var(--pi-space-32); }
}

/* The design system's `.nav` rule (flex, space-between) already puts the logo
   and CTA at the outer edges; its `.nav a` rule (15px, left margin) is meant
   for text links, so stop it shrinking the CTA and indenting the brand. */
.nav .nav-brand { margin-left: 0; }
.nav .btn { margin-left: 0; font-size: 16px; white-space: nowrap; }
.nav .btn-primary, .nav .btn-primary:hover { color: var(--pi-on-action); }
.nav-brand img { display: block; height: 32px; width: auto; }
@media (max-width: 360px) {
  .nav .btn { font-size: 13px; padding: var(--pi-space-8) var(--pi-space-12); }
}

/* ============================================================
   LAUNCH CHECKLIST MARKER
   class="tbc" wraps any fact or policy still to be confirmed
   (dates, refund/transfer terms, a reply time…). It is meant to
   stand out: the design system's warning pair, with a dashed
   error-red underline. Search the HTML for tbc, resolve each one,
   remove the span, then delete these two rules.
   ============================================================ */
.tbc { background: var(--pi-warning-bg); color: var(--pi-warning); border-bottom: 2px dashed var(--pi-error);
       border-radius: var(--pi-radius-tag); padding: 0 3px; cursor: help; }
.dark .tbc { background: var(--pi-warning-bg); color: var(--pi-warning); }

/* Secondary "not ready to book" link under a primary CTA */
.cta-secondary { display: inline-block; font-size: 15px; font-weight: 600; margin-top: var(--pi-space-12); }
/* Quieter still: the way out of the price box, deliberately weaker than the
   button above it. Italic and unweighted so it reads as an aside rather than a
   second thing to choose between. */
/* The answer to "what if I don't build anything usable?" at the point of decision
   (APP-808), in the same words as the FAQ's answer. */
.pricebox-reassure { font-size: 14px; line-height: 1.5; color: var(--pi-text-secondary); text-align: center; margin: var(--pi-space-16) 0 0; }
.cta-quiet { text-align: center; font-size: 14px; font-style: italic; margin: var(--pi-space-12) 0 0; }
.cta-quiet a { color: var(--pi-text-secondary); text-decoration: underline; }
.cta-quiet a:hover { color: var(--pi-action); }
.cta-note { display: block; margin-top: var(--pi-space-8); }
.dark .cta-note { color: var(--pi-statement-muted); }

/* Example demo cards: label and title above the screenshot, on the homepage
   grid and "More examples" alike. CSS subgrid keeps every screenshot in a
   row starting at the same height: each card spans the grid's own row
   tracks (one per label/title/image/body/button), so a two line title
   makes room in every card sharing that row, not just its own, and the
   image below it lines up regardless. Fallback if subgrid ever misbehaves:
   min-height: 2lh on .example-card .card-title, reserving two lines for
   every title instead of letting the grid measure it.
   The grid's own row-gap would otherwise land between every one of those
   internal rows as well as between rows of cards, so it is zeroed here and
   replaced with margin-bottom on the card itself (the gap this grid actually
   wants, between one row of cards and the next); examples-grid's matching
   negative margin stops that same margin adding a stray gap under the last
   row of cards. */
.examples-grid { row-gap: 0; margin-bottom: calc(var(--pi-space-16) * -1); }
.example-card { display: grid; grid-template-rows: subgrid; grid-row: span 4; margin-bottom: var(--pi-space-16);
                padding: 0; overflow: hidden; text-decoration: none; color: inherit;
                transition: box-shadow .15s, transform .15s; }
.example-card.has-body { grid-row: span 5; }
.example-card:hover { color: inherit; box-shadow: var(--pi-shadow-medium); transform: translateY(-2px); }
.example-card .card-title { padding: 0 var(--pi-space-24); align-self: end; }
.example-card img { display: block; width: calc(100% - var(--pi-space-24) * 2); height: auto; margin: 0 var(--pi-space-24);
                    aspect-ratio: 8 / 5; object-fit: cover; object-position: top left; border-radius: var(--pi-radius-control);
                    border: 1px solid var(--pi-border); background: var(--pi-canvas); }
.example-card .card-body { padding: var(--pi-space-16) var(--pi-space-24) 0; margin: 0; }
/* The button is a styled span, not a nested <a> or <button>: the whole card
   is already the link, and either would be invalid HTML inside it and break
   keyboard and screen reader behaviour. */
.example-card .example-link { justify-self: start; margin: var(--pi-space-16) var(--pi-space-24) var(--pi-space-24); }
.path-example { font-weight: 600; font-style: normal; }

/* Example detail pages */
.back-link { display: inline-block; margin-top: var(--pi-space-24); font-size: 14px; font-weight: 600; text-decoration: none; }
.example-head { padding-top: var(--pi-space-24); max-width: 70ch; }
.example-head h1 { font-size: clamp(var(--pi-h1-size), 5vw, 52px); line-height: var(--pi-display-line); letter-spacing: var(--pi-h1-tracking); }
/* The frame around a demo: our chrome, in our brand. The demo inside the
   iframe keeps its own made-up business's look. */
.demo-frame { background: var(--pi-surface); border: 1px solid var(--pi-border); border-radius: var(--pi-radius-dialog);
              box-shadow: var(--pi-shadow-medium); overflow: hidden; margin: var(--pi-space-32) 0 var(--pi-space-48); }
.demo-bar { display: flex; align-items: center; gap: var(--pi-space-12); padding: var(--pi-space-8) var(--pi-space-16);
            background: var(--pi-canvas); border-bottom: 1px solid var(--pi-border); font-size: 13px; color: var(--pi-text-secondary); }
.demo-dots { display: flex; gap: 6px; }
.demo-dots span { width: 10px; height: 10px; border-radius: 50%; background: var(--pi-disabled-border); }
.demo-bar b { margin-left: auto; font-weight: 600; color: var(--pi-violet); text-transform: uppercase; letter-spacing: var(--pi-eyebrow-tracking); font-size: var(--pi-eyebrow-size); }
.demo-frame iframe { display: block; width: 100%; height: 620px; border: 0; }
.story-label { font-family: var(--pi-font-display); font-weight: 600; font-size: var(--pi-h3-size); color: var(--pi-text); margin: 0 0 var(--pi-space-8); }

.check-list { list-style: none; padding: 0; margin: var(--pi-space-24) 0 0; max-width: none;
              display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--pi-space-12) var(--pi-space-32); }
.check-list li { position: relative; padding-left: var(--pi-space-24); margin: 0; }
.check-list li::before { content: "→"; position: absolute; left: 0; color: var(--pi-action); font-weight: 700; }
.dark .check-list li::before { color: var(--pi-brand-cyan); }

.cta-band { text-align: center; border-radius: var(--pi-radius-dialog); padding: var(--pi-space-48) var(--pi-space-32); margin: var(--pi-space-48) 0; }
.cta-band p { margin-left: auto; margin-right: auto; }
.cta-band .btn { margin-top: var(--pi-space-16); }

/* Host */
/* "Why Precise Impact" as one block (APP-921): the testimonials and the host on
   one tinted band, each a white card on it, so the section reads as "who we are
   and what people say" rather than three boxes and a loose bio on white. */
.why-band .testimonial { position: relative; padding-top: var(--pi-space-48); }
.why-band .testimonial::before { content: "\201C"; position: absolute; top: var(--pi-space-8); left: var(--pi-space-24);
                                 font-family: var(--pi-font-display); font-size: 64px; line-height: 1; color: var(--pi-action); }
.why-band .host.card { padding: var(--pi-space-32); }
@media (max-width: 560px) { .why-band .host.card { padding: var(--pi-space-24) var(--pi-space-16); } }
.host { display: grid; grid-template-columns: 168px 1fr; gap: var(--pi-space-32); align-items: center; margin-top: var(--pi-space-48); }
/* The testimonial cards (APP-770): each person's own photo, given with their
   permission, in a circle like the host photo, beside their name at the foot of
   the card, so the three name rows line up whatever the quote's length. */
.testimonial { display: flex; flex-direction: column; }
.testimonial-who { display: flex; align-items: center; gap: var(--pi-space-12); margin-top: auto; padding-top: var(--pi-space-12); }
.testimonial-who .card-title { font-size: 16px; margin: 0; }
.testimonial-photo { flex: none; width: 56px; height: 56px; border-radius: 50%; object-fit: cover; background: var(--pi-surface-subtle); }
.host-photo { display: block; width: 168px; height: 168px; border-radius: 50%; object-fit: cover; background: var(--pi-surface-subtle);
              border: 4px solid var(--pi-surface); box-shadow: var(--pi-shadow-medium); }

/* "Send us your idea" */
.lead-grid { display: grid; grid-template-columns: .9fr 1.1fr; gap: var(--pi-space-48); align-items: start; }
.lead-steps { margin: var(--pi-space-12) 0 0; padding-left: var(--pi-space-24); }
.lead-steps li { padding: var(--pi-space-4) 0; }
.lead-form .field { max-width: none; }
.lead-form textarea.input { resize: vertical; }

/* Form validation, shown when the server rejects a submission. The forms post
   to the page they live on, so these appear with the answers still in place,
   with or without JavaScript. The design system's error pair: a failed form
   is a real error, never the action blue. */
.form-error { background: var(--pi-error-bg); color: var(--pi-error);
              border-left: 4px solid var(--pi-error); border-radius: var(--pi-radius-control);
              padding: var(--pi-space-12) var(--pi-space-16); margin: 0 0 var(--pi-space-16); font-size: 14px; }
.form-error p { margin: 0 0 var(--pi-space-8); }
.form-error > :last-child { margin-bottom: 0; }
.form-error ul { margin: 0; padding-left: var(--pi-space-24); }
.form-error a { color: inherit; }
.field-error { display: block; margin-top: var(--pi-space-8); font-size: 13px; color: var(--pi-error); }
.dark .form-error, .dark .field-error { color: var(--pi-on-action); }
.dark .form-error { background: transparent; border-left-color: var(--pi-on-action); }

/* Honeypot: a field only a bot fills in. Kept out of sight and out of the tab
   order rather than display:none, which some bots detect and skip. */
/* "Email me these results" under a demo */
.demo-email { margin: var(--pi-space-24) 0 var(--pi-space-48); }
.demo-email-fields .contact-fields { grid-template-columns: repeat(3, 1fr); }
.demo-email-fields .contact-fields .field-full-name { grid-column: auto; }
@media (max-width: 960px) {
  .demo-email-fields .contact-fields { grid-template-columns: 1fr 1fr; }
  .demo-email-fields .contact-fields .field-full-name { grid-column: 1 / -1; }
}

/* Full name, email and mobile number on every public form (APP-501, one
   name box since APP-653, src/components/ContactFields.astro): the name across
   the row, then email and mobile side by side, one to a row on a phone. */
.contact-fields { display: grid; grid-template-columns: 1fr 1fr; column-gap: var(--pi-space-16); }
.contact-fields .field { max-width: none; }
.contact-fields .field-full-name { grid-column: 1 / -1; }
@media (max-width: 560px) { .contact-fields, .demo-email-fields .contact-fields { grid-template-columns: 1fr; } }
.honeypot { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

@media (max-width: 860px) {
  .lead-grid, .check-list { grid-template-columns: 1fr; }
  .lead-grid { gap: var(--pi-space-24); }
  .host { grid-template-columns: 1fr; gap: var(--pi-space-16); }
  .host-photo { width: 128px; height: 128px; }
  .cta-band { padding: var(--pi-space-32) var(--pi-space-16); }
  .demo-frame iframe { height: 900px; }
}

/* "Behind the curtain" around a demo (src/components/CrmCurtain.astro): the
   frame is our chrome, so on the site's own pages it takes the brand's tokens
   through the component's --cc-* variables. Set on body, which beats the
   component's own :root defaults; the Brightside demo, which never loads this
   file, keeps them. */
body {
  --cc-surface: var(--pi-surface);
  --cc-top: var(--pi-text);
  --cc-head: var(--pi-text);
  --cc-body: var(--pi-text);
  --cc-soft: var(--pi-text-secondary);
  --cc-divider: var(--pi-border);
  --cc-tag: var(--pi-surface-subtle);
  --cc-tag-text: var(--pi-action);
  --cc-new: var(--pi-violet-bg);
  --cc-new-text: var(--pi-violet);
  --cc-ok: var(--pi-success);
  --cc-alert: var(--pi-error);
  --cc-illustrative: var(--pi-violet);
  --cc-illustrative-bg: var(--pi-violet-bg);
  --cc-skipped-bg: var(--pi-neutral-bg);
  --cc-note: var(--pi-canvas);
  --cc-shadow: var(--pi-shadow-medium);
  --cc-font: var(--pi-font-body);
  --cc-mono: var(--pi-font-mono);
  --cc-focus: var(--pi-focus);
  --cc-toggle-accent: var(--pi-brand-cyan);
}
.cc-crm { border: 1px solid var(--pi-border); }

.btn-sm { padding: var(--pi-space-8) var(--pi-space-16); font-size: 14px; }

/* ============================================================
   TRACKING ADMIN AND THE CONSENT BANNER (APP-71)
   The banner overlays rather than reserving space, so it cannot cause a
   layout shift on load: it is fixed, off the normal document flow, and
   hidden by default until the client script decides a choice is needed.
   ============================================================ */
.chip { display: inline-block; padding: 2px 10px; border-radius: var(--pi-radius-pill); font-size: 12px;
        font-weight: 600; }
/* color-text, not text-soft: text-soft on neutral-200 measures 4.40:1, just under
   the 4.5:1 AA needs, and APP-147 puts these chips inside tab labels. */
.chip-off { background: var(--pi-border); color: var(--pi-text); }
.chip-test { background: var(--pi-surface-subtle); color: var(--pi-warning); }
.chip-live { background: var(--pi-surface-subtle); color: var(--pi-text); }

/* ============================================================
   TRACKING TABS AND CARD DOCUMENTATION (APP-147)
   The tablist starts hidden and is revealed by the inline script on
   /admin/tracking, so with JavaScript off there are no tabs and every panel
   stacks, each under its own heading. Once the script has run, the headings
   are redundant (the tab names the panel) and are hidden.
   ============================================================ */

/* The homepage's phone booking bar (APP-806). Phones only; under the cookie
   banner's z-index, and the page script hides it while the banner is up. It
   slides out of the way rather than vanishing, and never shows on desktop. */
.book-bar { display: none; }
@media (max-width: 560px) {
  .book-bar { display: flex; position: fixed; left: 0; right: 0; bottom: 0; z-index: 800;
              align-items: center; justify-content: space-between; gap: var(--pi-space-12);
              padding: var(--pi-space-8) var(--pi-space-16) calc(var(--pi-space-8) + env(safe-area-inset-bottom, 0px));
              background: var(--pi-surface); border-top: 1px solid var(--pi-border); box-shadow: var(--pi-shadow-medium);
              transform: translateY(110%); visibility: hidden;
              transition: transform .2s ease, visibility 0s linear .2s; }
  .book-bar.is-shown { transform: none; visibility: visible; transition: transform .2s ease; }
  .book-bar-btn { flex: 0 0 auto; }
  .book-bar-price { font-weight: 600; text-align: right; }
}
@media (max-width: 560px) and (prefers-reduced-motion: reduce) {
  .book-bar, .book-bar.is-shown { transition: none; }
}

.consent-banner { position: fixed; left: 0; right: 0; bottom: 0; z-index: 900; background: var(--pi-surface);
                  box-shadow: var(--pi-shadow-medium); border-top: 1px solid var(--pi-border); }
.consent-banner-inner { max-width: 1100px; margin: 0 auto; padding: var(--pi-space-16) var(--pi-space-24);
                        display: flex; flex-wrap: wrap; gap: var(--pi-space-16); align-items: center;
                        justify-content: space-between; }
.consent-banner-text { margin: 0; font-size: 14px; max-width: 60ch; }
.consent-banner-text a { color: var(--pi-action); }
.consent-banner-actions { display: flex; flex-wrap: wrap; gap: var(--pi-space-8); }

.consent-dialog { position: fixed; inset: 0; z-index: 950; display: flex; align-items: center;
                  justify-content: center; padding: var(--pi-space-16); }
/* [hidden] is set and cleared by the client script; without this override the
   flex display above beats the browser's default [hidden]{display:none} (an
   author rule always wins over a user agent one), leaving the closed dialog
   invisible but still catching clicks meant for the page under it. */
.consent-dialog[hidden] { display: none; }
.consent-dialog-backdrop { position: absolute; inset: 0; background: color-mix(in srgb, var(--pi-text) 50%, transparent); z-index: 0; }
.consent-dialog-panel { position: relative; z-index: 1; background: var(--pi-surface); border-radius: var(--pi-radius-dialog);
                        box-shadow: var(--pi-shadow-overlay); padding: var(--pi-space-24); max-width: 480px; width: 100%;
                        max-height: calc(100vh - var(--pi-space-32)); overflow-y: auto; }
.consent-dialog-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--pi-space-8); }
.consent-dialog-head h2 { margin: 0; font-size: 18px; }
.consent-dialog-close { background: none; border: 0; font-size: 22px; line-height: 1; cursor: pointer;
                        color: var(--pi-text-secondary); padding: var(--pi-space-8); }
.consent-dialog-close:hover { color: var(--pi-text); }
.consent-dialog-intro { font-size: 13px; color: var(--pi-text-secondary); margin: 0 0 var(--pi-space-16); }
.consent-dialog-intro a { color: var(--pi-action); }
.consent-category { border-top: 1px solid var(--pi-border); padding: var(--pi-space-12) 0; }
.consent-category-head { display: flex; align-items: center; justify-content: space-between; font-weight: 600;
                         font-size: 14px; }
.consent-category-desc { margin: var(--pi-space-8) 0 0; font-size: 13px; color: var(--pi-text-secondary); }
.consent-dialog-actions { display: flex; flex-wrap: wrap; gap: var(--pi-space-8); margin-top: var(--pi-space-16);
                          border-top: 1px solid var(--pi-border); padding-top: var(--pi-space-16); }

/* The permanent "Cookie settings" line at the foot of every page (APP-208). */
.consent-foot { text-align: center; padding: 0 var(--pi-space-16) var(--pi-space-32); }
.consent-foot-link { background: none; border: 0; padding: 0; font: inherit; font-size: 13px;
                     color: var(--pi-text-secondary); text-decoration: underline; cursor: pointer; }
.consent-foot-link:hover { color: var(--pi-action); }

@media (max-width: 640px) {
  .consent-banner-inner { flex-direction: column; align-items: stretch; }
  .consent-banner-actions { justify-content: stretch; }
  .consent-banner-actions .btn { flex: 1; }
}

/* Accessibility (APP-180) ----------------------------------------------- */

/* Jumps past the nav to <main>. Kept off-screen rather than display:none so it
   is still the first stop for the Tab key, and only slid into view on focus.
   Above the consent banner (900) and dialogue (950): it must never be hidden. */
.skip-link { position: absolute; left: var(--pi-space-12); top: var(--pi-space-12); z-index: 1000;
             transform: translateY(-200%); background: var(--pi-surface); color: var(--pi-action);
             font-weight: 600; text-decoration: none; padding: var(--pi-space-8) var(--pi-space-16);
             border-radius: var(--pi-radius-card); box-shadow: var(--pi-shadow-medium); }
.skip-link:focus { transform: none; }

/* Pages whose only heading is their title use an h1 (one per page) but were
   designed as a section heading. It takes the size a landing page section
   heading has (.section-head h2 above), the design system's h1 token. */
.h2-size { font-size: var(--pi-h1-size); letter-spacing: var(--pi-h1-tracking); }

/* The reverse: an h2 that looks like an h3, for the sub-headings on a page
   where the h1 is the only heading above them (an h3 straight after an h1
   skips a level). Repeats styles.css's h3. */
.h3-size { font-size: var(--pi-h3-size); color: var(--pi-text); font-weight: var(--pi-h3-weight); line-height: var(--pi-h3-line); }

/* The only motion on the site that is not a colour change: a card lifting on
   hover. Anyone who has asked their system for less motion keeps the shadow. */
@media (prefers-reduced-motion: reduce) {
  .example-card { transition: none; }
  .example-card:hover { transform: none; }
}

/* "Where is this event?" on the sales page (APP-510, src/components/VenuePanel.astro).
   One box with a pin line (APP-553). The title row runs the full width, with
   Visit website level with the title on the right (APP-555); below it the
   details and, when there is one, a square photo, half each. No photo, the
   details take the full width. Below 760px of panel everything stacks in
   source order, title, button, photo, details. */
.venue-panel-box { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--pi-space-24) var(--pi-space-32);
                   background: var(--pi-surface); border: 1px solid var(--pi-border);
                   border-radius: var(--pi-radius-dialog); padding: var(--pi-space-32); }
.venue-panel-box.has-photo { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
                             grid-template-areas: "head head" "details media"; }
.venue-panel-box.has-photo .venue-panel-head { grid-area: head; }
.venue-panel-box.has-photo .venue-panel-media { grid-area: media; }
.venue-panel-box.has-photo .venue-panel-details { grid-area: details; }
.venue-panel-head { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: var(--pi-space-12) var(--pi-space-16); }
.venue-panel-title { min-width: 0; flex: 1 1 auto; }
.venue-panel-title h2 { margin: 0; }
.venue-panel-title .card-kicker { margin-top: 0; }
.venue-panel-website { display: inline-flex; align-items: center; gap: var(--pi-space-8); flex-shrink: 0; }
.venue-panel-icon { flex-shrink: 0; color: var(--pi-action); }
.venue-panel-subhead { font-family: var(--pi-font-display); font-size: var(--pi-h3-size); font-weight: 600; color: var(--pi-text); margin: var(--pi-space-24) 0 0; }
.venue-panel-directions li { display: flex; gap: var(--pi-space-12); align-items: flex-start; }
.venue-panel-directions .venue-panel-icon { margin-top: 2px; }
.venue-panel-media { min-width: 0; }
.venue-panel-photo { display: block; width: 100%; height: auto; aspect-ratio: 1 / 1; object-fit: cover;
                     border-radius: var(--pi-radius-card); background: var(--pi-surface-subtle); }
.venue-panel-town { margin-top: 0; font-weight: 600; }
.venue-panel-address { margin-top: var(--pi-space-8); }
.venue-panel-links { display: flex; flex-wrap: wrap; gap: var(--pi-space-12); align-items: center; margin-top: var(--pi-space-16); }
.venue-panel-list { list-style: none; padding: 0; margin: var(--pi-space-16) 0 0; }
.venue-panel-list li { padding: var(--pi-space-4) 0; }
.venue-panel-ticks { columns: 2 16rem; column-gap: var(--pi-space-32); }
.venue-panel-ticks li { padding-left: var(--pi-space-24); position: relative; break-inside: avoid; }
.venue-panel-ticks li::before { content: "\2713"; position: absolute; left: 0; color: var(--pi-action); font-weight: 700; }
.venue-panel { container-type: inline-size; }
/* On the panel's own width rather than the window's, so the admin preview
   column (APP-536) stacks exactly as a phone does. */
@container (max-width: 760px) {
  .venue-panel-box, .venue-panel-box.has-photo { grid-template-columns: minmax(0, 1fr); grid-template-areas: "head" "media" "details";
                                                 padding: var(--pi-space-16); }
  .venue-panel-head { flex-direction: column; align-items: flex-start; }
  .venue-panel-photo { aspect-ratio: 4 / 3; max-height: 260px; }
}

.chip-strong { font-weight: 700; }

/* Text for screen readers only (APP-553: "opens in a new tab" on the venue website button). */
.visually-hidden { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
                   clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }

/* "Want one of these on your own website?" under the three internal tools'
   demos (APP-634): the box and the done screen's questions are the shared
   demo engine's (public/demos/demo.js, aidInterest), which styles them from a
   demo's --accent colours. Here those are the site's action blue, and the box keeps
   a readable shape before that script has run. */
.demo-email { --accent: var(--pi-action); --accent-soft: var(--pi-surface-subtle); --accent-ink: var(--pi-text); }
.demo-email .aid-interest { margin: var(--pi-space-12) 0; padding: var(--pi-space-12); border: 1.5px solid var(--pi-action); border-radius: var(--pi-radius-card); background: var(--pi-surface-subtle); }
.demo-email .aid-interest-title { margin: 0 0 var(--pi-space-8); font-weight: 700; }
.demo-email .aid-interest-tick { display: flex; gap: var(--pi-space-8); align-items: flex-start; cursor: pointer; }
.demo-email .aid-interest-tick input { width: 20px; height: 20px; margin: 0; flex: none; accent-color: var(--pi-action); }

/* On a phone the header keeps the same 16px gutter as the page below it. */
@media (max-width: 560px) {
  .nav { padding-left: var(--pi-space-16); padding-right: var(--pi-space-16); }
}

/* The examples page (APP-693, laid out again in APP-767). The title row holds
   the big Reset filters button; the three road cards are the path filter and
   the main control; the count is display type; the two dropdowns sit in one
   compact row that wraps. Everything is a link or a GET form, so it works with
   no JavaScript. */
.btn-lg { min-height: 56px; padding: 14px 28px; font-size: 1.125rem; }

.examples-title { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between;
                  gap: var(--pi-space-16) var(--pi-space-32); margin-bottom: var(--pi-space-16); }
.examples-heading { flex: 1 1 32ch; max-width: 62ch; }
.examples-heading h1 { font-size: var(--pi-h1-size); letter-spacing: var(--pi-h1-tracking); }
.reset-slot { flex: none; }
.examples-intro { max-width: 62ch; margin: 0 0 var(--pi-space-32); }
@media (max-width: 640px) {
  .reset-slot { flex: 1 1 100%; }
  .reset-slot .btn { display: flex; width: 100%; }
}

/* A road card as the filter: the whole card is one link. It lifts on hover,
   the chosen one is filled in its road colour with a tick, the others dim, and
   the cue at the foot says what a click does. */
.road-pick { display: flex; flex-direction: column; color: inherit; text-decoration: none; cursor: pointer; position: relative;
             transition: transform .15s, box-shadow .15s, opacity .15s, background .15s; }
.road-pick:hover { transform: translateY(-3px); box-shadow: var(--pi-shadow-medium); opacity: 1; }
.road-pick .road-like { margin: var(--pi-space-12) 0 var(--pi-space-16); font-style: italic; }
.road-cue { display: inline-flex; align-items: center; align-self: flex-start; gap: var(--pi-space-4); margin: auto 0 0; padding: 8px 16px;
            border: 2px solid var(--road); border-radius: var(--pi-radius-control); color: var(--road); background: var(--pi-surface);
            font-weight: 700; font-size: .9375rem; line-height: 1.3; }
.road-pick:hover .road-cue { background: var(--road); color: var(--pi-surface); }
.road-tick { margin-left: auto; align-self: center; display: inline-grid; place-items: center; width: 32px; height: 32px;
             border-radius: 50%; background: var(--pi-surface); color: var(--road); font-size: 1.125rem; font-weight: 700; }
.road-pick.is-selected { background: var(--road); border-top-color: var(--road); color: var(--pi-surface); }
.road-pick.is-selected .road-head, .road-pick.is-selected .card-title, .road-pick.is-selected .card-body,
.road-pick.is-selected .road-like { color: var(--pi-surface); }
.road-pick.is-selected .road-icon svg { stroke: var(--pi-surface); }
.road-pick.is-selected .road-icon svg .fill { fill: color-mix(in srgb, var(--pi-surface) 25%, transparent); }
.road-pick.is-selected .road-cue { background: var(--pi-surface); border-color: var(--pi-surface); color: var(--road); }
[data-has-selection] .road-pick:not(.is-selected) { opacity: .5; }
[data-has-selection] .road-pick:not(.is-selected):hover, [data-has-selection] .road-pick:not(.is-selected):focus-visible { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .road-pick { transition: none; } .road-pick:hover { transform: none; } }

/* The count is the loudest thing under the cards. */
.filter-count { margin: var(--pi-space-32) 0 var(--pi-space-24); font-family: var(--pi-font-display); font-weight: 500;
                font-size: clamp(1.75rem, 5.5vw, 3.5rem); line-height: 1.4; letter-spacing: -.01em; }
.filter-count:focus { outline: none; }
.filter-count .count-num { font-weight: 700; color: var(--pi-action); }

.example-trim { margin-bottom: var(--pi-space-32); padding: var(--pi-space-24); border: 1px solid var(--pi-border);
                border-radius: var(--pi-radius-card); background: var(--pi-surface); }
.trim-line { margin: 0 0 var(--pi-space-16); font-weight: 600; }
.trim-row { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--pi-space-16); }
.trim-field { flex: 1 1 220px; min-width: 0; }
.trim-field label { display: block; margin-bottom: var(--pi-space-4); font-size: .875rem; font-weight: 700; color: var(--pi-text-secondary); }
.trim-field select { width: 100%; min-height: 56px; padding: 12px 44px 12px 16px; border: 1px solid var(--pi-control-border);
                     border-radius: var(--pi-radius-control); background-color: var(--pi-surface); color: var(--pi-text);
                     font: inherit; font-size: 1.0625rem; cursor: pointer; appearance: none;
                     background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, transparent 50%, currentColor 50%);
                     background-position: calc(100% - 22px) 50%, calc(100% - 16px) 50%; background-size: 6px 6px; background-repeat: no-repeat; }
.trim-field select:hover { border-color: var(--pi-action); }
.trim-field select option:disabled { color: var(--pi-disabled-text); }
.trim-reset { flex: none; }
/* The Apply button is only for a browser with no script: the script marks the page. */
[data-examples-js] .trim-apply { display: none; }
@media (max-width: 640px) {
  .example-trim { padding: var(--pi-space-16); }
  .trim-row .btn { flex: 1 1 100%; }
}
/* The picture pickers (APP-768, src/components/FilterPicker.astro). Drawn by the
   server and hidden until the script marks the page (data-pickers), which also
   hides the plain select they stand in for. Open, a panel anchored under the
   button; under 600px the same panel is a bottom sheet with rows of 56px or more.
   The select stays in the form, hidden, as what is submitted and what the
   filter script reads. */
.picker { display: none; position: relative; }
[data-pickers] .picker { display: block; }
[data-pickers] .trim-field select { display: none; }
.picker-button { display: flex; align-items: center; gap: var(--pi-space-12); width: 100%; min-height: 56px; padding: 6px 16px 6px 8px;
                 border: 1px solid var(--pi-control-border); border-radius: var(--pi-radius-control); background: var(--pi-surface);
                 color: var(--pi-text); font: inherit; font-size: 1.0625rem; text-align: left; cursor: pointer; }
.picker-button:hover, .picker.is-open .picker-button { border-color: var(--pi-action); }
.picker-text { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.picker-chevron { flex: none; width: 8px; height: 8px; margin: 0 4px 3px 0; border: solid currentColor; border-width: 0 2px 2px 0;
                  transform: rotate(45deg); transition: transform .15s; }
.picker.is-open .picker-chevron { transform: rotate(-135deg) translate(-2px, -2px); }
.picker-pic { flex: none; display: grid; place-items: center; width: 40px; height: 40px; border-radius: var(--pi-radius-control);
              overflow: hidden; background: var(--pi-surface-subtle); color: var(--pi-action); }
.picker-pic img { display: block; width: 100%; height: 100%; object-fit: cover; }
.picker-pic svg { width: 26px; height: 26px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.picker-pic.pic-any { color: var(--pi-text-secondary); }
.picker-panel { position: absolute; z-index: 30; top: calc(100% + 6px); left: 0; width: max(100%, 360px); max-width: calc(100vw - 32px);
                display: flex; flex-direction: column; max-height: min(70vh, 560px); background: var(--pi-surface);
                border: 1px solid var(--pi-border); border-radius: var(--pi-radius-card); box-shadow: var(--pi-shadow-overlay);
                visibility: hidden; opacity: 0; transform: translateY(-4px); transition: opacity .15s, transform .15s, visibility 0s .15s; }
.picker.is-open .picker-panel { visibility: visible; opacity: 1; transform: none; transition: opacity .15s, transform .15s; }
.picker-list { flex: 1 1 auto; margin: 0; padding: 6px; list-style: none; overflow-y: auto; outline: none; }
.picker-option { display: flex; align-items: center; gap: var(--pi-space-16); min-height: 64px; padding: 6px 12px 6px 6px; border-radius: var(--pi-radius-control);
                 cursor: pointer; }
.picker-option .picker-pic { width: 52px; height: 52px; }
.picker-option .picker-pic svg { width: 30px; height: 30px; }
.picker-option.is-active { background: var(--pi-surface-subtle); }
.picker-list:focus-visible { outline: 2px solid var(--pi-action); outline-offset: -2px; border-radius: var(--pi-radius-card); }
.picker-option[aria-selected="true"] { box-shadow: inset 3px 0 0 var(--pi-action); font-weight: 700; }
.picker-option-name { flex: 1 1 auto; min-width: 0; font-size: 1.0625rem; }
.picker-option-count { flex: none; font-size: .875rem; font-weight: 600; color: var(--pi-text-secondary); }
.picker-option[aria-disabled="true"] { cursor: not-allowed; color: var(--pi-disabled-text); }
.picker-option[aria-disabled="true"] .picker-option-count { color: var(--pi-disabled-text); }
.picker-option[aria-disabled="true"] .picker-pic { opacity: .45; filter: grayscale(1); }
.picker-note { margin: 0; padding: 4px 16px 8px; font-size: .8125rem; color: var(--pi-text-secondary); }
.picker-foot, .picker-backdrop, .picker-sheet-head { display: none; }
.picker-foot { gap: var(--pi-space-12); padding: var(--pi-space-12) var(--pi-space-16) var(--pi-space-16); border-top: 1px solid var(--pi-border); }
.picker-foot .btn { flex: 1 1 0; min-height: 56px; }
@media (max-width: 599px) {
  .picker-backdrop { display: block; position: fixed; z-index: 90; inset: 0; background: #14243D66; visibility: hidden; opacity: 0;
                     transition: opacity .25s, visibility 0s .25s; }
  .picker.is-open .picker-backdrop { visibility: visible; opacity: 1; transition: opacity .25s; }
  .picker-panel { position: fixed; z-index: 100; top: auto; left: 0; right: 0; bottom: 0; width: auto; max-width: none; max-height: 85vh;
                  max-height: 85dvh; border-radius: var(--pi-radius-dialog) var(--pi-radius-dialog) 0 0; border-width: 1px 0 0;
                  transform: translateY(100%); transition: transform .28s cubic-bezier(.3, .7, .2, 1), visibility 0s .28s; }
  .picker.is-open .picker-panel { transform: none; transition: transform .28s cubic-bezier(.3, .7, .2, 1); }
  .picker-sheet-head { display: flex; flex-direction: column; align-items: center; gap: var(--pi-space-8); padding: 10px 16px 8px; touch-action: none;
                       cursor: grab; }
  .picker-grab { width: 44px; height: 5px; border-radius: var(--pi-radius-pill); background: var(--pi-border); }
  .picker-sheet-title { font-family: var(--pi-font-display); font-weight: 700; font-size: 1.125rem; }
  .picker-option { min-height: 64px; }
  .picker-foot { display: flex; padding-bottom: max(var(--pi-space-16), env(safe-area-inset-bottom)); }
  body.picker-lock { overflow: hidden; }
}
@media (prefers-reduced-motion: reduce) {
  .picker-panel, .picker.is-open .picker-panel, .picker-backdrop, .picker.is-open .picker-backdrop, .picker-chevron { transition: none; }
}
/* The count rolls like an odometer when the filters change without a reload
   (src/scripts/examples-filter.ts): the old number leaves upwards, the new one
   arrives from below (or the other way when it falls). Each number is a window
   one line tall over a two-cell column that slides one line. Reduced motion
   swaps at once, in the script, and the transition is removed here as well. */
.count-num { display: inline-block; height: 1.4em; line-height: 1.4; overflow: hidden; vertical-align: bottom;
             font-variant-numeric: tabular-nums; }
.count-roll { display: flex; flex-direction: column; transition: transform .42s cubic-bezier(.3, .7, .2, 1); }
.count-roll > span { display: block; height: 1.4em; }
.count-roll.go { transform: translateY(-1.4em); }
.count-roll.down { transform: translateY(-1.4em); }
.count-roll.down.go { transform: none; }
@media (prefers-reduced-motion: reduce) { .count-roll { transition: none; } }
.filter-empty { padding: var(--pi-space-24); border: 1px dashed var(--pi-border); border-radius: var(--pi-radius-control); text-align: center; }
.examples-more { display: flex; justify-content: center; max-width: none; margin: var(--pi-space-48) 0 0; }
/* The design system caps every <p> at 68ch, which pulled this button left of the
   grid's centre; the row is full width so it centres under the six (APP-769). */
.examples-more-btn { min-height: 64px; padding: 18px 40px; font-size: 1.25rem; }
@media (max-width: 600px) { .examples-more-btn { width: 100%; justify-content: center; padding: 16px 20px; font-size: 1.125rem; } }
