/* Kiteleo: the one-page site. Mural design system (wall, ink, bottle green, coral; Anybody).
   Decisions: ../findings-and-decisions.md */

/* ---------- the font: Anybody, served from the site itself (fonts/SOURCE.md). This page needs only the Latin file;
   the extended file loads only for letters such as macrons ---------- */
@font-face{font-family:"Anybody";font-style:normal;font-weight:100 900;font-stretch:50% 150%;font-display:swap;src:url(fonts/anybody-latin-ext.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:"Anybody";font-style:normal;font-weight:100 900;font-stretch:50% 150%;font-display:swap;src:url(fonts/anybody-latin.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}

/* ---------- tokens ---------- */
:root{
  /* Mural palette: four roles */
  --wall:oklch(95.5% .012 85);
  --ink:oklch(21% .02 40);
  --green:oklch(40% .085 160);
  --coral:oklch(73% .15 18);
  /* secondary text on each painted panel */
  --on-coral-2:oklch(28% .03 30);
  --on-ink-2:oklch(82% .015 85);
  /* surface roles; painted panels override these */
  --bg:var(--wall);
  --fg:var(--ink);
  --fg-2:oklch(40% .02 40);
  --line:oklch(21% .02 40 / .22);
  --shape:var(--coral);
  --btn:var(--coral);
  --btn-ink:var(--ink);
  /* owner decisions still open: shown, never hidden, until they are resolved */
  --todo-bg:oklch(90% .1 95);
  --todo-ink:oklch(30% .07 75);
  /* EDIT ME: how tall the hero is (100svh is a full screen), and how big the kite is within it (100% fills it) */
  --hero-height:90svh;
  --mascot-size:80%;
  /* EDIT ME: how tall the Pricing photo section is. 100svh is a full screen, 50svh half a screen. The owner
     chose a full screen (7 October); change only the number */
  --pricing-height:100svh;
  --wrap:1280px;
  --pad:clamp(16px,4vw,48px);
  --head:0px;
  --nav:64px;
  --ease:cubic-bezier(.16,1,.3,1);
  --font:"Anybody",system-ui,-apple-system,"Segoe UI",sans-serif;
}

/* ---------- base ---------- */
*{box-sizing:border-box}
/* keep anchors and keyboard focus clear of the header (WCAG 2.2 SC 2.4.11) */
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%;background:var(--bg);scroll-padding:calc(var(--head) + 2.5rem) 0 1rem}
body{margin:0;background:var(--bg);color:var(--fg);font:400 1.0625rem/1.6 var(--font)}
img,svg{max-width:100%;display:block}
a{color:inherit}
h1,h2,h3{margin:0;font-weight:800}
p{margin:0 0 1rem}
:focus-visible{outline:3px solid var(--fg);outline-offset:3px;border-radius:2px}
.wrap{max-width:var(--wrap);margin:0 auto;padding-inline:var(--pad)}
.skip{position:absolute;left:-999px;top:0;z-index:400;background:var(--fg);color:var(--bg);padding:.7rem 1rem}
.skip:focus{left:0}
.todo{background:var(--todo-bg);color:var(--todo-ink);border-radius:2px;padding:0 .3em;font-size:.9em;font-weight:600}
@media (min-width:1000px){
  html{scroll-padding:calc(var(--head) + 1rem) 0 1rem}
}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}*,*::before,*::after{transition-duration:0s!important;animation:none!important}}
/* ---------- controls ---------- */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:.6rem;min-height:52px;padding:.8rem 1.4rem;background:var(--btn);color:var(--btn-ink);font:800 1.02rem var(--font);font-stretch:112%;text-decoration:none;border:0;border-radius:2rem 2rem 2rem 0;cursor:pointer;transition:transform .15s var(--ease)}
/* a small kite in front of every button label */
.btn::before{content:"";flex:none;width:.5em;height:.7em;background:currentColor;clip-path:polygon(50% 0,100% 38%,50% 100%,0 38%)}
.btn:hover{transform:translateY(-2px)}
.btn:active{transform:none}

/* ---------- kite glyphs (symbols in the page's sprite) ---------- */
.g{display:inline-block;height:.74em;width:auto;overflow:visible}
/* styled on the symbol's own elements: selectors like ".g path" cannot reach inside <use> */
.gs{fill:none;stroke:currentColor;vector-effect:non-scaling-stroke}
.gi{fill:none;stroke:currentColor;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;vector-effect:non-scaling-stroke}
.gs{stroke-width:var(--gw,5);stroke-linecap:round;stroke-linejoin:round}
.btn .g{--gw:2;height:.9em}

/* ---------- header ---------- */
/* it floats over the page: clear at the very top, gone while the reader scrolls down, back (on wall, so it can be
   read over any section) when they scroll up (scroll.js; owner, 7 October). Without JavaScript it stays, on wall */
header.site{position:fixed;inset:0 0 auto;z-index:300;background:var(--bg);transition:transform .3s var(--ease),background-color .2s linear}
header.site[data-clear]{background:transparent}
header.site[data-hidden]:not(:focus-within){transform:translateY(-100%)}
.nav{display:flex;align-items:center;justify-content:space-between;gap:clamp(.6rem,2.5vw,1.2rem);min-height:var(--nav)}
/* the logo is the drawn wordmark, as an image: 30px tall is 104px wide, over the usage guide's 96px minimum */
.logo{display:inline-flex;align-items:center;min-height:44px}
.logo img{display:block;width:auto;height:30px}
/* the one link every screen has; phones show it alone (owner, 7 October) */
.nav-book{display:inline-block;padding:.6rem 0;white-space:nowrap;font-weight:500;text-decoration:underline;text-decoration-thickness:1.5px;text-underline-offset:8px}

/* ---------- footer ---------- */
footer.site{--bg:var(--ink);--fg:var(--wall);--fg-2:var(--on-ink-2);background:var(--bg);color:var(--fg);padding-block:2.5rem}
/* the logo on the left, the rights line opposite it on the right; they stack when there is no room side by side */
footer.site .wrap{display:flex;flex-wrap:wrap;align-items:end;justify-content:space-between;gap:1.2rem 2rem}
footer.site p{margin:0;color:var(--fg-2);font-size:1.15rem}
/* the reversed wordmark, large, on ink; it gives way before the rights line does */
footer.site .foot-mark{flex:0 1 36rem}
.foot-mark img{display:block;width:min(100%,36rem);height:auto}
/* ---------- hero: the mascot, a doodled kite flying on a plain grey sheet (mascot.js) ---------- */
/* off-white on grey, as the artwork is drawn (owner, 6 October); the page's colours start below it */
.drawing{--bg:oklch(84% .004 85);--fg:var(--ink);--fg-2:oklch(34% .02 40);--paper:oklch(94.5% .012 95);position:relative;background:var(--bg);color:var(--fg)}
.drawing{--edge:max(var(--pad),calc((100vw - var(--wrap)) / 2 + var(--pad)));display:grid;grid-template-columns:minmax(0,1fr)}
/* the open sheet the kite flies on; the headline is outside it, so the sheet's clip never cuts the words */
.drawing-stage{position:relative;grid-area:1/1;min-height:var(--hero-height);overflow:clip}

/* ---------- the kite: drawn in the page; mascot.js flies it. It may leave its own box, never the sheet ---------- */
/* it has the whole sheet, behind the words, so its size follows the sheet and not the words' rows */
.mascot{position:absolute;inset:0;z-index:0;width:var(--mascot-size);height:var(--mascot-size);margin:auto;overflow:visible;pointer-events:none}
.m-body,.m-eye,.m-bow path{fill:var(--paper);stroke:var(--ink);stroke-width:6;stroke-linejoin:round;stroke-linecap:round}
.m-line,.m-scribble{fill:none;stroke:var(--ink);stroke-width:5;stroke-linecap:round;stroke-linejoin:round}
.m-scribble{stroke-width:4}
.m-thin{stroke-width:3.5}
.m-bow path{stroke-width:4.5}
.m-pupil,.m-bow circle{fill:var(--ink)}

/* ---------- the words: the headline, one supporting line and the button, at the hero's foot ---------- */
/* They share the sheet's cell and sit at its foot, clear of the header; if they ever need more room than the sheet
   (very large text), the hero grows instead of the words being cut. */
.drawing-words{position:relative;z-index:1;grid-area:1/1;align-self:end;display:grid;grid-template-columns:minmax(0,1fr);justify-items:start;gap:1rem;padding:calc(var(--nav) + 1rem) var(--edge) 1.75rem}
/* The headline, in capitals, in Anybody, heavy and at its narrowest, so the letters are tall (owner, 7 October).
   EDIT ME: font-weight (100 to 900) and font-stretch (50% is narrowest and tallest, 150% widest); after changing
   either, or the words, change --fit too. --fit is how many times its own font size the line is long: the size is
   the room divided by it, so the line always fits (a smaller --fit is bigger letters, until the line no longer fits).
   Upright phones and tablets: one line running up the left edge of the screen, sized from the hero's height. */
.drawing-h{--fit:5.6;--sit:.225em;margin:0;font-size:calc((var(--hero-height) - var(--nav) - 2.75rem) / var(--fit));font-weight:800;font-stretch:50%;line-height:1;letter-spacing:0;white-space:nowrap;writing-mode:vertical-rl;transform:rotate(180deg)}
.drawing-sub{max-width:30ch;margin:0;color:var(--fg-2);font-weight:500}
/* wide screens, and any screen on its side: one line across the column at the foot of the sheet, sized from the
   column's width. --sit lowers it by the space under its letters, so the capitals stand on the wall below */
@media (min-width:1000px),(orientation:landscape){
  .drawing-words{padding-bottom:0}
  .drawing-h{--fit:5.6;order:1;margin-top:.75rem;font-size:calc((100vw - 2 * var(--edge)) / var(--fit));writing-mode:horizontal-tb;transform:translateY(var(--sit))}
}

/* ---------- booking: the coral panel ---------- */
.book{--bg:var(--coral);--fg:var(--ink);--fg-2:var(--on-coral-2);--line:oklch(21% .02 40 / .3);--shape:var(--green);--btn:var(--ink);--btn-ink:var(--wall);background:var(--bg);color:var(--fg);padding-block:clamp(5rem,10vw,9rem)}
.book-grid{display:grid;gap:2rem}
.book-label{display:flex;align-items:center;gap:.7rem;margin-bottom:1.2rem;font-size:1rem;font-weight:800;font-stretch:130%;letter-spacing:.03em;text-transform:uppercase}
.book-label::before{content:"";flex:none;width:1.2em;height:1.2em;border-radius:50%;background:var(--shape)}
.book h2{max-width:18ch;font-size:clamp(2.8rem,7vw,5.75rem);font-weight:900;font-stretch:85%;letter-spacing:-.02em;line-height:.92;text-transform:uppercase}
.book-sub{max-width:48ch;margin-top:1.1rem;color:var(--fg-2)}
.submit-status{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}
.form .btn:disabled{cursor:wait;opacity:.72}
.form{display:grid;max-width:720px}
.field{display:grid;gap:.25rem;margin-top:-1px;padding:1.1rem 1.3rem 1.2rem;background:var(--wall);border:1px solid var(--ink)}
.field:focus-within{position:relative;z-index:1;outline:3px solid var(--fg);outline-offset:3px}
.field label{font-size:1rem;font-weight:700;line-height:1.4;color:var(--fg-2)}
.field input,.field textarea{width:100%;min-height:44px;padding:.2rem 0;font:500 1.1875rem/1.5 var(--font);color:var(--fg);background:transparent;border:0}
.field input::placeholder,.field textarea::placeholder{color:oklch(45% .02 40);opacity:1}
.field input:focus,.field textarea:focus{outline:none}
.field textarea{min-height:130px;resize:vertical}
.field:has([aria-invalid="true"]){border-width:2px}
.err{margin:.2rem 0 0;font-size:.9rem;font-weight:600}
.err::before{content:"! "}
.form .btn{justify-self:start;margin-top:1.4rem}
.book-next{max-width:46ch;margin:1.4rem 0 0;color:var(--fg-2);font-size:.95rem}
.book-next+.book-next{margin-top:.4rem}
.book-next a{font-weight:700;text-underline-offset:3px}
.done{max-width:640px;padding:1.5rem;border:1px solid var(--fg)}
.done h3{margin-bottom:.6rem;font-size:1.5rem}
@media (min-width:1000px){.book-grid{grid-template-columns:minmax(0,1fr) minmax(0,1.2fr);align-items:start}}
/* ---------- the small kite beside the form: drawn in the page, as the mascot is, in the same ink and paper ---------- */
.book-kite{--paper:oklch(94.5% .012 95);display:block;width:clamp(110px,14vw,196px);height:auto;margin-top:clamp(1.25rem,4vw,3rem);overflow:visible}
.bk-body{fill:var(--paper);stroke:var(--ink);stroke-width:6;stroke-linejoin:round}
/* each tail is drawn twice, wide in ink and narrow in paper on top, so the ribbon has an outline and no seams */
.bk-ink rect{fill:var(--ink)}
.bk-paper rect{fill:var(--paper)}
.bk-line{fill:none;stroke:var(--ink);stroke-width:5;stroke-linecap:round}
/* It moves in place: the kite rocks a few degrees, and each strip of a tail swings a moment after the one above it, so
   a ripple runs down the tail. An SVG part turns about its own origin, which is where each strip hangs from.
   Reduced motion stops all of it (the rule at the top of this file). */
.bk-sway{animation:bk-sway 3.4s ease-in-out infinite alternate}
.bk-seg{animation:bk-ripple 1.3s ease-in-out infinite alternate}
.bk-seg .bk-seg{animation-delay:-.3s}
.bk-seg .bk-seg .bk-seg{animation-delay:-.6s}
.bk-seg .bk-seg .bk-seg .bk-seg{animation-delay:-.9s}
.bk-seg .bk-seg .bk-seg .bk-seg .bk-seg{animation-delay:-1.2s}
.bk-tail-2 .bk-seg{animation-duration:1.5s}
@keyframes bk-sway{from{transform:rotate(-2.5deg)}to{transform:rotate(2.5deg)}}
@keyframes bk-ripple{from{transform:rotate(-8deg)}to{transform:rotate(8deg)}}
@media (prefers-reduced-motion:reduce){.btn:hover{transform:none}}

/* ---------- section heads: label | statement ---------- */
.sec{padding-block:clamp(72px,11vw,150px)}
.sechead{display:grid;gap:1rem 2rem;margin-bottom:clamp(2.5rem,5vw,4.5rem)}
/* labels lead with a cut shape in the panel's shape colour */
.sh-label{display:flex;align-items:center;gap:.7rem;align-self:start;margin:0;font-size:.875rem;font-weight:800;font-stretch:130%;letter-spacing:.03em;text-transform:uppercase;text-wrap:balance}
.sh-label::before{content:"";flex:none;width:1.2em;height:1.2em;border-radius:50%;background:var(--shape)}
.sechead h2{max-width:18ch;font-size:clamp(min(2rem,10vw),4.6vw,3.9rem);line-height:.98;letter-spacing:-.02em}
.sh-sub{max-width:48ch;margin:1.1rem 0 0;color:var(--fg-2)}
@media (min-width:1000px){
  .sechead{grid-template-columns:minmax(0,1fr) minmax(0,1.9fr)}
}
.schools{padding-bottom:0}

/* ---------- the examples: the panels (plain wall, so each example's own colours lead) ---------- */
.stack{border-top:1px solid var(--line)}
.panel{display:grid;background:var(--wall);border-bottom:1px solid var(--line)}
.panel-text{display:flex;flex-direction:column;gap:1.3rem;padding:clamp(28px,4vw,56px) var(--pad)}
.tag{align-self:flex-start;margin:0;padding:.2rem .6rem;border:2px solid var(--ink);border-radius:99px;color:var(--fg-2);font-size:.875rem;font-weight:800;font-stretch:130%;letter-spacing:.03em;text-transform:uppercase}
.panel-name{margin:0}
.panel h3{max-width:20ch;font-size:clamp(min(1.8rem,9vw),3.2vw,2.8rem);line-height:1;letter-spacing:-.015em}
.because{max-width:40ch;margin:-.4rem 0 0;color:var(--fg-2)}
@media (min-width:1000px){
  .panel{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
  /* the text lines up with the page's column; 15px allows for a scrollbar */
  /* and starts below where the header returns, so the header never covers a panel's tag */
  .panel-text{padding-top:calc(var(--nav) + 1rem);padding-left:max(var(--pad),calc((100vw - 15px - var(--wrap)) / 2 + var(--pad)));padding-right:clamp(24px,4vw,64px)}
  /* each school fills the screen and the next one slides over it, but only while every panel fits below the header:
     schools.js measures them and sets data-stick. Otherwise, and without JavaScript, the panels simply follow on */
  .stack[data-stick] .panel{position:sticky;top:var(--head);min-height:calc(100vh - var(--head))}
}

/* ---------- the examples: each panel's picture. Every one is a pair of screenshots on a plain ground ---------- */
/* the extra room at the bottom keeps the art label clear of the picture */
.panel-art{position:relative;display:grid;place-items:center;min-height:440px;padding:clamp(24px,4vw,56px) clamp(24px,4vw,56px) 4.5rem;overflow:hidden}
/* Give the preview more room without narrowing the reading column; the phone sits alongside only on wide screens. */
.panel[data-featured] .panel-art{grid-template-columns:minmax(0,1fr);gap:clamp(12px,2vw,28px);padding-inline:clamp(24px,2vw,40px)}
.panel-plain{background:oklch(90% .014 85)}
.art-label{position:absolute;left:1rem;bottom:1rem;margin:0;padding:.25rem .5rem;background:var(--wall);color:var(--fg-2);font-size:.875rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase}
/* the frame every example shares: a browser, flat on its ground. What sits inside is a screenshot or the concept's own layout */
.browser{position:relative;z-index:1;width:min(100%,440px);overflow:hidden;border-radius:8px;background:var(--s-bg);color:var(--s-ink);font:500 .85rem/1.45 var(--s-font);box-shadow:12px 14px 0 oklch(21% .02 40 / .85)}
@media (min-width:1000px){.panel[data-featured] .browser{width:100%;max-width:580px}}
:where(.browser) p{margin:0}
:where(.browser) :is(ul,ol){margin:0;padding:0;list-style:none}
/* the browser itself is neutral, in the visitor's own system font */
.b-top{display:flex;align-items:center;gap:.7rem;padding:.55rem .8rem;background:oklch(90% .01 85);color:oklch(30% .01 85);font:600 .75rem system-ui,sans-serif}
.b-dots{display:inline-flex;gap:4px}
.b-dots i{width:8px;height:8px;border:1.5px solid currentColor;border-radius:50%}
/* a real screenshot fills the browser; the address bar shows where it lives */
.b-shot{--s-bg:var(--wall);--s-ink:var(--ink);--s-font:system-ui,sans-serif}
:is(.b-shot,.phone) img{width:100%;height:auto}
/* the phone beside it: a screenshot, or the concept's own small layout */
.phone{position:relative;z-index:1;width:100%;max-width:150px;overflow:hidden;border:6px solid var(--ink);border-radius:24px;background:var(--wall);box-shadow:8px 10px 0 oklch(21% .02 40 / .75)}
@media (min-width:1400px){.panel[data-featured] .panel-art{grid-template-columns:minmax(0,1fr) minmax(112px,150px)}}
@media (max-width:999px){.panel[data-featured] .phone{justify-self:end;width:min(38%,160px);min-width:132px}}
.design-choices{margin-top:auto;padding-top:1.1rem;border-top:3px solid var(--ink)}
.design-choices h4{margin:0 0 .5rem;color:var(--fg-2);font-size:.875rem;font-weight:800;letter-spacing:.03em;text-transform:uppercase}
.design-choices p{margin:.45rem 0 0;color:var(--fg-2)}
.design-choices strong{color:var(--fg);font-weight:800}
@media (min-width:1000px){.panel-art{min-height:auto}}

/* enlarged text: a word too long for a phone (a school name, a headline) breaks rather than pushing the page sideways.
   It is the last resort: the markers beside the text (numbers, half-discs, beads, badges, the plus) keep their normal
   size, min(Xrem, Ypx), and the big type's smallest size is capped by the screen width, min(Xrem, Yvw), with Y equal
   to X on a 320px screen, so nothing changes at normal text size */
body{overflow-wrap:anywhere}

/* content that follows a section head lines up with the statement column on large screens */
@media (min-width:1000px){.offer{margin-left:calc((100% - 2rem) / 2.9 + 2rem)}}
/* ---------- reviews: Appy's Tangible impact rhythm, using Kiteleo's own type and palette ---------- */
.reviews{--bg:var(--ink);--fg:var(--wall);--fg-2:var(--on-ink-2);--line:oklch(95.5% .012 85 / .24);--review-top:var(--nav,var(--head));--edge:max(var(--pad),calc((100vw - var(--wrap)) / 2 + var(--pad)));background:var(--bg);color:var(--fg)}
.reviews-sticky{display:grid;gap:clamp(2rem,4vw,4rem);padding-block:clamp(3rem,6vw,6rem)}
.reviews .sechead{width:100%;margin-bottom:0}
/* the cards start on the page's own column (--edge), under the section label, and never at the screen's edge */
.reviews-window{min-width:0;padding-inline:var(--edge)}
.reviews-track{display:grid;gap:1.5rem}
/* each review is a speech bubble on one of the page's own grounds: the button's cut corner, at card size */
.review-card{display:flex;flex-direction:column;gap:clamp(1.5rem,3vw,2.5rem);min-width:0;margin:0;padding:clamp(1.5rem,3vw,3rem);border-radius:clamp(1.5rem,3vw,2.5rem) clamp(1.5rem,3vw,2.5rem) clamp(1.5rem,3vw,2.5rem) 0;background:var(--bg);color:var(--fg)}
.review-card:nth-child(3n+1){--bg:var(--wall);--fg:var(--ink);--fg-2:oklch(40% .02 40);--mark:var(--coral)}
.review-card:nth-child(3n+2){--bg:var(--coral);--fg:var(--ink);--fg-2:var(--on-coral-2);--mark:var(--ink)}
.review-card:nth-child(3n){--bg:var(--green);--fg:var(--wall);--fg-2:var(--on-ink-2);--mark:var(--coral)}
/* the same pill as the examples' "Concept" tag */
.review-status{align-self:flex-start;margin:0;padding:.2rem .6rem;border:2px solid currentColor;border-radius:99px;font-size:.875rem;font-weight:800;font-stretch:130%;letter-spacing:.03em;text-transform:uppercase}
/* the words lead, set as the headings are */
.review-quote{margin:0;max-width:22ch;font-size:clamp(min(1.6rem,8vw),3.2vw,3.25rem);font-weight:800;line-height:1.02;letter-spacing:-.02em;text-wrap:balance}
.review-quote::before{content:"\201c";display:block;height:.42em;margin-bottom:.12em;color:var(--mark);font-size:3em;line-height:.8}
.review-quote p{margin:0}
/* who said it, at the foot, behind a small kite as the buttons have */
.review-author{display:flex;align-items:baseline;gap:.7rem;margin-top:auto}
.review-author::before{content:"";flex:none;width:.6em;height:.84em;background:var(--mark);clip-path:polygon(50% 0,100% 38%,50% 100%,0 38%)}
.review-name{margin:0;font-weight:800}
.review-role{margin:.1rem 0 0;color:var(--fg-2);font-size:.92rem}
/* Native scroll animation only when supported, motion is welcome and reviews.js confirms the content fits.
   The default stack remains complete on phones, short screens, larger text and without JavaScript. */
@supports (animation-timeline:--reviews){
  @media (min-width:1000px) and (min-height:700px) and (prefers-reduced-motion:no-preference){
    .reviews[data-motion]{height:calc(100svh + 140vw);view-timeline:--reviews block;view-timeline-inset:var(--review-top) 0}
    .reviews[data-motion] .reviews-sticky{position:sticky;top:var(--review-top);height:calc(100svh - var(--review-top));padding-block:2.5rem;gap:2rem;grid-template-rows:auto minmax(0,1fr)}
    .reviews[data-motion] .reviews-window{overflow:clip;min-height:0}
    .reviews[data-motion] .reviews-track{display:flex;gap:2rem;width:max-content;max-width:none;height:100%;margin:0;animation:reviews-travel 1ms linear both;animation-timeline:--reviews;animation-range:contain}
    .reviews[data-motion] .review-card{flex:none;width:min(58vw,54rem);min-height:26rem}
  }
}
@keyframes reviews-travel{from{transform:translateX(0)}to{transform:translateX(calc(-100% + 100vw - 2 * var(--edge)))}}

/* ---------- the type band: a continuous loop with no ground of its own: the Pricing photograph below reaches up
   behind it (owner, 7 October), so the band is lifted over that section. If --band-pad or --band-size change, change
   the same two clamps on .pricing-track ---------- */
.band{--fg:var(--wall);--band-pad:clamp(28px,5vw,64px);--band-size:clamp(2.8rem,9vw,7rem);position:relative;z-index:1;color:var(--fg);overflow:clip;padding-block:var(--band-pad)}
.band-track{display:flex;width:max-content;font-size:var(--band-size);font-weight:900;font-stretch:150%;letter-spacing:-.015em;line-height:1;text-transform:uppercase;white-space:nowrap}
.band-group{display:flex;flex-shrink:0;align-items:center;justify-content:space-around;gap:.35em;min-width:100vw;padding-right:.35em}
.band-icon{color:var(--coral)}
/* It moves by CSS alone; with reduced motion the words stay still (the rule at the top of this file). */
.band-track{animation:band-drift 24s linear infinite}
@keyframes band-drift{to{transform:translateX(-50%)}}
/* the pause control: a tick box and its label, as one pill in the band's corner. It works by CSS alone. With reduced
   motion nothing moves, so there is nothing to pause and it is not shown */
.band-pause:checked~.band-track{animation-play-state:paused}
.band-pause,.band-pause+label{position:absolute;right:max(var(--pad),calc((100vw - var(--wrap)) / 2 + var(--pad)));bottom:.5rem}
.band-pause{z-index:3;width:1.1rem;height:1.1rem;margin:calc((44px - 1.1rem) / 2) .9rem;accent-color:var(--green);cursor:pointer}
.band-pause+label{z-index:2;display:flex;align-items:center;min-height:44px;padding:0 2.9rem 0 1.1rem;border-radius:99px;background:var(--wall);color:var(--ink);font-size:.875rem;font-weight:700;cursor:pointer}
.band-pause:focus-visible{outline:none}
.band-pause:focus-visible+label{outline:3px solid var(--fg);outline-offset:3px}
@media (prefers-reduced-motion:reduce){.band-pause,.band-pause+label{display:none}}


/* ---------- pricing: Appy's section 5 photo-and-text treatment, with Kiteleo's own image ---------- */
.pricing{--bg:var(--ink);--fg:var(--wall);--line:oklch(95.5% .012 85 / .3);--shape:var(--coral);position:relative;isolation:isolate;padding:0;background:var(--bg);color:var(--fg)}
/* the track is the section's own box, so the photo can never pass the section's end */
/* It starts above the section, by the band's height (its two paddings and its one line of lettering, the same two clamps as on .band
   above), so the one photograph runs behind the band and the pricing words alike */
.pricing-track{position:absolute;inset:calc(-2 * clamp(28px,5vw,64px) - clamp(2.8rem,9vw,7rem)) 0 0;z-index:-1;pointer-events:none}
.pricing-photo{height:100%;overflow:clip}
.pricing-photo img{width:100%;height:100%;object-fit:cover;object-position:center}
/* A uniform scrim keeps even the brightest sky behind the text dark enough to read. */
.pricing-track::after{content:"";position:absolute;inset:0;background:oklch(21% .02 40 / .68)}
/* the sentence, then the offer's three parts close under it, as one group. Its height is --pricing-height, set at the
   top of this file for the owner to change; it grows only if the words need more */
.pricing-copy{display:grid;align-content:center;gap:clamp(2rem,5svh,3.5rem);min-height:var(--pricing-height);padding-block:clamp(4rem,10svh,7rem)}
.pricing .sechead{margin:0}
.pricing .sh-label::before{height:.6em;border-radius:99px 99px 0 0}
.offer{display:grid;margin-block:0;padding:0;list-style:none}
.offer li{display:flex;align-items:baseline;justify-content:space-between;gap:1rem;padding:.7rem 0;border-top:1px solid var(--line)}
.offer span{font-size:.875rem;font-weight:800;font-stretch:130%;letter-spacing:.03em;text-transform:uppercase}
.offer strong{font-size:clamp(min(1.4rem,7vw),3.4vw,3rem);font-weight:800;line-height:1;letter-spacing:-.02em}
@media (min-width:760px){
  .offer{grid-template-columns:repeat(3,minmax(0,1fr));gap:0 clamp(1rem,3vw,2rem)}
  .offer li{display:grid;justify-content:start;gap:.5rem;padding:1.2rem 0 0}
}
/* the shade that darkens the section as the booking section covers it; clear until then */
.pricing::after{content:"";position:absolute;inset:0;z-index:2;background:var(--ink);opacity:0;pointer-events:none}
/* the booking section slides over the pricing section, so it has to paint above it */
.book{position:relative}
/* Motion, native CSS: the section holds at the top of the screen while the booking section slides over it.
   scroll.js marks it data-cover and measures how far it is taller than the screen (--pin, nothing unless the text is
   enlarged), so it would hold from its foot and cut no words off. Without JavaScript, or with reduced motion, the
   section simply scrolls on. */
@media (prefers-reduced-motion:no-preference){
  .pricing[data-cover]{position:sticky;top:calc(-1 * var(--pin,0px))}
}
/* darker and darker as less of it shows: the shade follows the booking section's way up the screen, starting
   where it meets the foot of the held section */
@supports (animation-timeline:--book){
  @media (prefers-reduced-motion:no-preference){
    main{timeline-scope:--book}
    .book{view-timeline:--book block}
    .pricing[data-cover]::after{animation:pricing-dim 1ms linear both;animation-timeline:--book;animation-range:entry calc(100% - var(--pricing-height)) entry 100%}
    /* the words go up with the booking section, at its pace, while the photo stays behind (owner, 7 October) */
    .pricing[data-cover] .pricing-copy{animation:pricing-rise 1ms linear both;animation-timeline:--book;animation-range:entry calc(100% - var(--pricing-height)) entry 100%}
  }
}
@keyframes pricing-dim{to{opacity:.85}}
@keyframes pricing-rise{to{transform:translateY(calc(-1 * var(--pricing-height)))}}


/* ---------- header links ---------- */
/* wide screens only: phones and tablets show just the logo and "Apply Now" (owner, 7 October) */
.nav-links{display:none;margin-left:auto}
.nav-links ul{display:flex;flex-wrap:wrap;gap:0 clamp(.6rem,3vw,1.3rem);margin:0;padding:0;list-style:none}
.nav-links a{display:block;padding:.6rem 0;font-size:.95rem;font-weight:500;text-decoration:none}
.nav-links a:hover{text-decoration:underline;text-underline-offset:6px}
@media (min-width:1000px){.nav-links{display:block}}

/* ---------- the kite string: one still line, drawn by string.js ---------- */
main{position:relative}
.sg{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;z-index:1}
.sg use{fill:none;stroke-width:2px;stroke-linecap:round;stroke-linejoin:round}
/* the content sits above the string and the section colours below it, so the string passes behind text and buttons.
   Only .wrap is lifted: a position rule on .panel would undo the panels' sticking */
.wrap{position:relative;z-index:1}

/* ---------- part 4: ready to launch ---------- */
/* the icon sprite takes no room; a class rather than a style attribute, so the security policy can refuse inline styles */
.sprite{position:absolute}
/* the not-found and thank-you pages: the logo, a line or two and the way back */
body.plain{padding-bottom:0}
.plain-main{display:grid;align-content:center;justify-items:start;gap:1.4rem;min-height:100svh;padding-block:3rem}
.plain-main h1{max-width:16ch;font-size:clamp(min(2.4rem,12vw),6vw,5rem);font-weight:900;font-stretch:85%;letter-spacing:-.02em;line-height:.92;text-transform:uppercase}
.plain-note{max-width:48ch;margin:0;color:var(--fg-2)}
/* the booking form's spam trap: off screen and out of the tab order, so only bots fill it in (Netlify drops those) */
.hp{position:absolute;left:-10000px}
.form-err{margin-top:1rem}

/* the privacy page: headed paragraphs at reading width */
.privacy h2{margin-top:1rem;font-size:1.3rem}
.privacy p{max-width:62ch;margin:0}
