/* Method & Mark · motion layer
   One idea: the red pen. Working is written, then marked. Everything else stays still or
   settles quietly. Nothing here hides content unless motion.js has set .js-motion, which it
   never does under reduced motion, so no-JS and reduced-motion visitors get the plain page. */

:root {
  --ease-out: cubic-bezier(.2, .7, .2, 1);   /* settles, never bounces */
  --ease-pen: cubic-bezier(.45, .05, .35, 1); /* a pen stroke: quick start, slows to lift */
  --t-reveal: .6s;
  --t-write: .45s;
  --t-mark: .26s;
}

/* ---------- pages cross-fade instead of flashing white (Chrome 126+, Safari 18.2+) ---------- */
@view-transition { navigation: auto; }
.nav { view-transition-name: site-nav; }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: .22s; }
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none; }
}

/* ---------- header: a hairline shadow once the page moves under it ---------- */
.nav { transition: box-shadow .3s var(--ease-out), background-color .3s var(--ease-out); }
.nav.is-stuck {
  box-shadow: 0 1px 0 var(--rule), 0 8px 24px -18px rgb(28 26 23 / .35);
  background: rgb(245 241 234 / .94); /* opaque enough that the red banner does not tint it pink */
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
}

/* ---------- homepage nav: the section being read is underlined in red pen ---------- */
@media (min-width: 1024px) {
  .nav__links a { position: relative; }
  .nav__links a::after {
    content: ""; position: absolute; left: 0; right: 0; bottom: 10px; height: 1.5px; background: var(--mark);
    transform: scaleX(0); transform-origin: 0 50%; transition: transform .25s var(--ease-pen);
  }
  .nav__links a.is-current { color: var(--mark); }
  .nav__links a.is-current::after { transform: scaleX(1); }
}

/* ---------- the Headstart banner's arrow leans the way it points ---------- */
.holiday-banner__go span { display: inline-block; transition: transform .3s var(--ease-out); }
.holiday-banner:hover .holiday-banner__go span { transform: translate(2px, -2px); }

/* ---------- buttons: a press you can feel ---------- */
.btn { transition: background-color .22s, color .22s, border-color .22s, transform .12s var(--ease-out); }
.btn:active { transform: translateY(1px) scale(.985); }

/* ---------- FAQ opens to its height instead of snapping (Chrome 131+; others snap as now) ---------- */
@supports (interpolate-size: allow-keywords) {
  .faq { interpolate-size: allow-keywords; }
  .faq details::details-content {
    height: 0; overflow: clip;
    transition: height .32s var(--ease-out), content-visibility .32s allow-discrete;
  }
  .faq details[open]::details-content { height: auto; }
}
.faq .pm { transition: transform .32s var(--ease-out); }

/* ---------- notes: a red-pen reading line under the header (CSS scroll timeline) ---------- */
@supports (animation-timeline: scroll()) {
  .note::before {
    content: ""; position: fixed; z-index: 30; left: 0; right: 0; top: var(--nav-size, 60px);
    height: 2px; background: var(--mark); transform-origin: 0 50%;
    animation: read-line linear both; animation-timeline: scroll(root);
  }
  @keyframes read-line { from { transform: scaleX(0); } to { transform: scaleX(1); } }
}

/* ---------- photos: settle and lift slowly on hover ---------- */
.lesson-photos__frame img, .tutor__portrait img { transition: transform 1.2s var(--ease-out); }
@media (hover: hover) {
  .lesson-photos__item:hover img, .tutor__visual:hover .tutor__portrait img { transform: scale(1.03); }
}

/* ---------- programme cards: the worked card lifts off the graph paper ---------- */
.prog__img .script { transition: transform .45s var(--ease-out), box-shadow .45s var(--ease-out); }
.prog__img { transition: background-position .8s var(--ease-out); }
@media (hover: hover) {
  .prog:hover .prog__img .script { transform: translateY(-4px) rotate(-.4deg); box-shadow: 0 22px 34px -22px rgb(28 26 23 / .5); }
  .prog:hover .prog__img { background-position: 6px -6px; }
}

/* ---------- note cards lift a little, like a sheet picked off the pile ---------- */
.note-card { transition: border-color .22s, transform .35s var(--ease-out), box-shadow .35s var(--ease-out); }
@media (hover: hover) {
  .note-card:hover { transform: translateY(-3px); box-shadow: 0 18px 30px -24px rgb(28 26 23 / .45); }
}

/* ---------- the trial-class dialog leaves the way it came, instead of vanishing ---------- */
@media (prefers-reduced-motion: no-preference) {
  @supports (transition-behavior: allow-discrete) {
    .enq { transition: opacity .2s var(--ease-out), transform .2s var(--ease-out), overlay .2s allow-discrete, display .2s allow-discrete; }
    .enq:not([open]) { opacity: 0; transform: translateY(8px); }
    .enq::backdrop { transition: opacity .2s var(--ease-out), overlay .2s allow-discrete, display .2s allow-discrete; }
    .enq:not([open])::backdrop { opacity: 0; }
  }

  /* the phone menu drops in, its rows a beat apart */
  .sheet:not([hidden]) { animation: sheet-in .24s var(--ease-out); }
  .sheet:not([hidden]) nav a, .sheet:not([hidden]) > .btn, .sheet:not([hidden]) .sheet__contact {
    animation: sheet-row .32s var(--ease-out) both;
  }
  .sheet nav a:nth-child(2) { animation-delay: 30ms; }
  .sheet nav a:nth-child(3) { animation-delay: 60ms; }
  .sheet nav a:nth-child(4) { animation-delay: 90ms; }
  .sheet nav a:nth-child(5) { animation-delay: 120ms; }
  .sheet > .btn, .sheet .sheet__contact { animation-delay: 150ms; }
  @keyframes sheet-in { from { opacity: 0; } }
  @keyframes sheet-row { from { opacity: 0; transform: translateY(-6px); } }
}

/* ======================================================================
   Everything below only runs with .js-motion (set by motion.js).
   ====================================================================== */
@media (prefers-reduced-motion: no-preference) {

  /* section content rises a short distance, once */
  .js-motion [data-reveal] {
    opacity: 0; transform: translateY(14px);
    transition: opacity var(--t-reveal) var(--ease-out), transform var(--t-reveal) var(--ease-out);
    transition-delay: calc(var(--i, 0) * 70ms);
  }
  .js-motion [data-reveal].is-in { opacity: 1; transform: none; }

  /* photos open from the bottom like a print sliding out of a sleeve */
  .js-motion [data-reveal="photo"] { opacity: 1; transform: none; clip-path: inset(100% 0 0 0); transition: clip-path 1s var(--ease-out); transition-delay: calc(var(--i, 0) * 90ms); }
  .js-motion [data-reveal="photo"] img { transform: scale(1.08); transition: transform 1.4s var(--ease-out); transition-delay: inherit; }
  .js-motion [data-reveal="photo"].is-in { clip-path: inset(0); }
  .js-motion [data-reveal="photo"].is-in img { transform: none; }

  /* rules draw across instead of appearing */
  .js-motion [data-reveal="rule"] { opacity: 1; transform: none; position: relative; }
  .js-motion [data-reveal="rule"]::before {
    content: ""; position: absolute; left: 0; right: 0; top: -1px; height: 1px; background: var(--paper);
    transform-origin: 100% 50%; transition: transform 1s var(--ease-pen); transition-delay: calc(var(--i, 0) * 90ms);
  }
  .js-motion [data-reveal="rule"].is-in::before { transform: scaleX(0); }

  /* the hero photo is the LCP image, so it is never hidden: it only settles from a slight zoom */
  .js-motion .hero__media .media img { animation: settle 1.6s var(--ease-out) both; }
  @keyframes settle { from { transform: scale(1.05); } }

  /* the worked card arrives a beat after the headline */
  .js-motion .hero .working { animation: card-in .7s var(--ease-out) .35s both; }
  @keyframes card-in { from { opacity: 0; transform: translateY(16px); } }
  .js-motion .hero .u path { transition-duration: .6s; transition-delay: .25s; }

  /* ---------- writing: lines are written left to right, then marked ---------- */
  .js-motion [data-write] .working__row > span:first-child,
  .js-motion [data-write] .script__row > span:first-child,
  .js-motion [data-write] .script__row > span:last-child:not(:first-child, .mk, :has(.mk)),
  .js-motion [data-write] .working__row > span:last-child:not(:first-child, .mk, :has(.mk)),
  .js-motion [data-write] .script__q,
  .js-motion [data-write] .working__q {
    clip-path: inset(-20px 100% -20px -24px); /* roomy, so a ring drawn round the answer is not cut */
    transition: clip-path var(--t-write) var(--ease-pen);
    transition-delay: var(--d, 0ms);
  }
  .js-motion [data-write] .mk {
    display: inline-block; opacity: 0; clip-path: inset(0 100% 0 0); transform: translateY(2px) rotate(-6deg);
    transition: opacity .1s, clip-path var(--t-mark) var(--ease-pen), transform var(--t-mark) var(--ease-out);
    transition-delay: var(--d, 0ms);
  }
  .js-motion [data-write].is-written .working__row > span:first-child,
  .js-motion [data-write].is-written .script__row > span:first-child,
  .js-motion [data-write].is-written .script__row > span:last-child:not(:first-child, .mk, :has(.mk)),
  .js-motion [data-write].is-written .working__row > span:last-child:not(:first-child, .mk, :has(.mk)),
  .js-motion [data-write].is-written .script__q,
  .js-motion [data-write].is-written .working__q { clip-path: inset(-20px -24px -20px -24px); }
  .js-motion [data-write].is-written .mk { opacity: 1; clip-path: inset(0 -6px 0 -2px); transform: none; }
  .js-motion [data-write] .script__note.mk { display: block; transform-origin: 100% 50%; }
  .js-motion [data-write].is-written .script__note.mk { transform: rotate(-2deg); }

  /* main.js draws rings on sight; inside a script the ring waits until its line is marked */
  .js-motion [data-write]:not(.is-written) .circled path { stroke-dashoffset: 1; transition: none; }

  /* a mark being corrected: the strike is drawn through, then the new mark is written */
  .js-motion [data-write] s.mk, .js-motion [data-write] s.was { text-decoration: none; position: relative; }
  .js-motion [data-write] s.mk::after, .js-motion [data-write] s.was::after {
    content: ""; position: absolute; left: -2px; right: -2px; top: 55%; height: 1.5px; background: var(--mark);
    transform: scaleX(0); transform-origin: 0 50%; transition: transform .22s var(--ease-pen);
    transition-delay: calc(var(--d, 0ms) + 380ms);
  }
  .js-motion [data-write].is-written s.mk::after, .js-motion [data-write].is-written s.was::after { transform: scaleX(1); }
  .js-motion [data-write] s.was::after { height: 2px; top: 52%; transition-duration: .3s; transition-delay: calc(var(--d, 0ms) + 420ms); }

  /* the timing bar runs down once its lines are written */
  .js-motion [data-write] .clock span { transform: scaleX(0); transform-origin: 0 50%; transition: transform .9s var(--ease-pen); transition-delay: var(--d, 0ms); }
  .js-motion [data-write].is-written .clock span { transform: none; }

  /* the classroom plan: five seats fill in order, each gets a script, then the tutor reaches all five */
  .js-motion .room .room__seat rect, .js-motion .room .room__n text, .js-motion .room .room__script rect, .js-motion .room .room__lbl {
    opacity: 0; transition: opacity .4s var(--ease-out); transition-delay: calc(var(--i, 0) * 110ms + 150ms);
  }
  .js-motion .room .room__script rect { transition-delay: calc(var(--i, 0) * 110ms + 700ms); }
  .js-motion .room .room__tutor { transform: scale(0); transform-box: fill-box; transform-origin: center; transition: transform .45s var(--ease-out) .1s; }
  .js-motion .room .room__reach { clip-path: inset(0 100% 0 0); transition: clip-path .9s var(--ease-pen) 1.3s; }
  .js-motion .room.is-in .room__seat rect, .js-motion .room.is-in .room__n text,
  .js-motion .room.is-in .room__script rect, .js-motion .room.is-in .room__lbl { opacity: 1; }
  .js-motion .room.is-in .room__tutor { transform: none; }
  .js-motion .room.is-in .room__reach { clip-path: inset(0); }

  /* the timeline: the red line is drawn from 2026 to 2028, and each year lands as the line reaches it */
  .js-motion .timeline::before { transform: scaleY(0); transition: transform 1.3s var(--ease-pen); }
  @media (min-width: 768px) { .js-motion .timeline::before { transform: scaleX(0); } }
  .js-motion .timeline.is-in::before { transform: none; }
  .js-motion .timeline__item::before { transform: scale(0); transition: transform .4s var(--ease-out); transition-delay: calc(var(--i, 0) * 520ms + 80ms); }
  .js-motion .timeline__item > * { opacity: 0; transform: translateY(10px); transition: opacity .55s var(--ease-out), transform .55s var(--ease-out); transition-delay: calc(var(--i, 0) * 520ms + 160ms); }
  .js-motion .timeline__item > .h3 { transition-delay: calc(var(--i, 0) * 520ms + 230ms); }
  .js-motion .timeline__item > p:last-child { transition-delay: calc(var(--i, 0) * 520ms + 300ms); }
  .js-motion .timeline.is-in .timeline__item::before { transform: none; }
  .js-motion .timeline.is-in .timeline__item > * { opacity: 1; transform: none; }

  /* the margin note in the hero counts its marks as they are written */
  .js-motion .hero .display[data-aside]::after { transition: opacity .3s; }
  .js-motion .hero .display[data-aside="method marks 0/3"]::after { opacity: 0; transition: none; }
}

@media print {
  .js-motion [data-reveal], .js-motion [data-reveal] img, .js-motion [data-write] *, .js-motion .room *, .js-motion .timeline *, .js-motion .timeline::before, .js-motion .timeline__item::before { opacity: 1 !important; transform: none !important; clip-path: none !important; }
}
