/* 312 Muzik - shared */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
:root{--g:max(0px, calc((100vw - 1200px) / 2))}
body{margin:0;background:#fff;font-family:'Montserrat',Helvetica,Arial,sans-serif}
/* overflow:clip, NOT overflow:hidden. Both clip the strays, but `hidden` makes this
   element a SCROLL CONTAINER, and a scroll container is the thing position:sticky
   sticks to -- so every locked section would silently never stick. `clip` clips
   without creating one. The `hidden` line stays first as the fallback for engines
   that predate `clip`; they lose the pinning and still read fine. */
.page{position:relative;overflow:hidden;overflow:clip}

/* Locked blocks pin to the top of the viewport and let later blocks scroll over them.
   The engine does this by swapping the block to position:fixed and leaving a
   placeholder to hold its space; position:sticky is that same behaviour with NO
   JavaScript, which is the whole point: it is handled by the compositor, so it cannot
   lag a frame behind the scroll or land half-applied. The previous version recomputed
   a transform in a scroll handler on every event, which is what made the packages
   reveal stutter and could leave a section parked mid-flight. */
@media(min-width:768px){.sec[data-lock*="d"]{position:sticky;top:0}}
@media(max-width:767px){.sec[data-lock*="m"]{position:sticky;top:0}}
img{max-width:100%;border:0}
a{text-decoration:none;color:inherit}
button.asbtn{background:none;border:0;padding:0;margin:0;font:inherit;color:inherit;cursor:pointer;text-align:inherit}
.sec{position:relative;width:100%;height:var(--h);background-repeat:no-repeat;background-size:cover;pointer-events:none}
.sec>.bgm{position:absolute;inset:0;z-index:0;overflow:hidden;pointer-events:none}
/* bgScroll is PER BREAKPOINT and has three values, not two:
   'f' -> layer fixed to the viewport (rate 0)   -- .plx-f, applied by site.js
   'x' -> layer moves at HALF scroll speed (rate 0.5) -- transform + clip by site.js
   absent -> no parallax, the layer scrolls with its section (rate 1) -- this base rule.
   Treating 'x' as 'f' pinned the packages backgrounds to the viewport instead of
   drifting them, which is why that page disagreed with the original by 25% of
   pixels while the section sat only part-way up the screen. */
.sec>.bgm.plx-f{position:fixed;inset:auto;top:0;left:0;width:100vw;height:100vh}
/* THE DESIGN IS A 1200px CANVAS, SO BELOW 1200px IT MUST SCALE, NOT OVERFLOW.
   The engine already does exactly this (it is the same rule the 320 mobile canvas
   uses, just with a different design width), and the ratio is verifiable: the CTA
   sits at x=679 in canvas space, and at a 900px window the original paints it at
   679 * 900/1200 = 509. Without this the canvas stays 1200 wide inside a narrower
   window and .page quietly clips the overflow, so on any 768-1200px window the whole
   right-hand column -- including the button -- is cut off with no scrollbar to hint
   that anything is missing. Origin is top LEFT because an over-constrained
   `margin:0 auto` resolves to 0 rather than centring once the canvas is wider than
   its container, so the unscaled canvas already starts at x=0. */
@media(min-width:768px) and (max-width:1199px){
  .sec{height:calc(var(--h) * var(--ds, 1))}
  .cv{transform:scale(var(--ds, 1));transform-origin:top left}
}

.bgv{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block}
.cv{position:relative;top:0;width:1200px;height:100%;margin:0 auto;z-index:1;pointer-events:none}
.el{position:absolute;display:block;pointer-events:auto}
.el>.shape{width:100%;height:100%}
.ph{position:absolute;inset:0;display:block;background-repeat:no-repeat;background-size:cover;background-position:50% 50%;border-radius:inherit}
.vid{width:100%;height:100%;object-fit:cover;display:block;border-radius:inherit}
.ico{width:100%;height:100%;display:block}
.ico svg{width:100%;height:100%;display:block;fill:currentColor}
/* A TEXT BOX NEVER GROWS PAST THE ELEMENT THAT HOLDS IT.
   This is the engine's own rule, verbatim from showit.css 2.8.0:
     .se-t{background:transparent;border:0;height:100%;left:0;padding:0;
           position:absolute;top:0;width:100%}
   Every text node is pinned to its element's box with overflow visible, so copy
   that is too long for its box still PAINTS outside it and is still readable --
   but the box itself never grows, so it can never win a hit test against
   something underneath.

   Ours left the text in normal flow, where its height is whatever the copy needs.
   Measured on the home page: the closing line's box ran 180px tall inside a 31px
   element and covered the BOOK NOW button 94px below it, so the one call to
   action in the About section could not be clicked or hovered at all. Live is
   31px there and 0 controls are blocked; this build had exactly 1, and that was
   it. Same cause would hit any button sitting under any overlong line. */
.txt{position:absolute;top:0;left:0;width:100%;height:100%;
  background:transparent;border:0;margin:0;padding:0;font-weight:inherit}
.btn{display:flex;align-items:center;justify-content:center;width:100%;height:100%;cursor:pointer}
.btn span{display:block;width:100%}
.st{display:none}
.st.is-on{display:block}
/* state transitions, per the engine's stateTrIn */
/* The state layer spans the whole canvas, so it must never eat clicks meant for
   siblings sitting under it (the testimonial prev/next arrows live outside the
   states). Only its own children take pointer events. */
.sec[data-sttr] > .cv > .st{display:block;visibility:hidden;opacity:0;pointer-events:none;
  position:absolute;inset:0;
  /* visibility is in the transition on purpose: it is a discrete property, so
     without a duration it flips on frame one and the OUTGOING view vanishes
     before it has faded, which reads as a cut with a gap in it rather than a
     crossfade. Given a duration it holds until the fade is done. */
  transition:opacity var(--sttrd,.5s) ease,transform var(--sttrd,.5s) ease,
             visibility var(--sttrd,.5s)}
.sec[data-sttr] > .cv > .st.is-on{visibility:visible;opacity:1;transform:none}
.sec[data-sttr] > .cv > .st.is-on > *{pointer-events:auto}
.sec.is-mobnav.is-shown{pointer-events:auto}
.sec[data-sttr="slide"] > .cv > .st{transform:translateX(6%)}
@media(prefers-reduced-motion:reduce){.sec[data-sttr] > .cv > .st{transition:none}}
.gal{position:absolute;inset:0;overflow:hidden}
.gtrack{display:flex;height:100%;width:max-content;will-change:transform}
.gcell{display:block;height:100%;flex:0 0 auto;background-size:cover;background-position:center}
.gtrack.gstep{transition:transform .34s cubic-bezier(.4,0,.2,1);align-items:center}  /* .34s: live's slide runs 0.61s->0.93s */
.gtrack.gstep .gcell{transition:transform .6s cubic-bezier(.4,0,.2,1)}
.gtrack.gstep .gcell.is-sel{transform:none!important}
@keyframes gslide{from{transform:translateX(0)}to{transform:translateX(-50%)}}
@media(prefers-reduced-motion:reduce){.gtrack{animation:none!important}}
.si-embed{position:absolute;inset:0}
.only-m{display:none}
/* Entrance transitions are opacity ONLY (trIn is fadeIn everywhere on this site).
   These rules must NEVER declare transform: '.anim.is-in' is specificity (0,2,0)
   and outranks the per-element '.e-<sid>' rule (0,1,0) that carries the element's
   own rotation, so a 'transform:none' here silently un-rotates any animated element
   once it scrolls into view. That is what made both add-ons back arrows point RIGHT
   while the live site points them left, on both breakpoints. A geometry gate cannot
   see it, because rotating an icon does not change its box. */
.anim{opacity:0;transition:opacity var(--ad,.5s) ease var(--adl,0s)}
.anim.is-in{opacity:1}
@media(prefers-reduced-motion:reduce){.anim{opacity:1!important;transition:none}}
.is-menu{position:fixed;top:0;left:0;right:0;height:1px;z-index:1000;overflow:visible}
/* The engine emits a flow PLACEHOLDER (sb-fp) after a block it takes out of
   flow, so the page keeps that block's height. The menu is position:fixed and
   1px tall, so without its placeholder every section below sat 1px high and
   the whole page was 1px short of the original. */
.fp-menu{height:0}
@media(min-width:768px){.fp-menu{height:1px}}
/* FIX 4 -- THE MOBILE MENU FADES IN INSTEAD OF POPPING.
   A full-screen overlay appearing in one frame is the harshest cut on the site,
   because it replaces the entire viewport at once. Same display problem, same
   answer: it stays in the layout and is hidden by opacity + visibility, so both
   directions can be timed.

   It stays `pointer-events:none` while closed (inherited from .sec), so an
   always-present full-screen panel can never intercept a tap meant for the page
   underneath -- the one thing that would be worse than the pop. */
.sec.is-mobnav{display:block;position:fixed;inset:0;z-index:1100;height:100%;
  opacity:0;visibility:hidden;transform:translateY(-12px);
  transition:opacity .26s var(--ease),transform .26s var(--ease),visibility 0s linear .26s}
.sec.is-mobnav.is-shown{opacity:1;visibility:visible;transform:none;
  transition:opacity .26s var(--ease),transform .26s var(--ease),visibility 0s}
@media(prefers-reduced-motion:reduce){
  .sec.is-mobnav,.sec.is-mobnav.is-shown{transition:none;transform:none}}
.is-mobnav .cv{height:100%}
/* FIX 1 -- THE FAQ ANSWER COLLAPSES, IT DOES NOT VANISH.
   This was display:none <-> display:block. `display` is not animatable, so the
   panel appeared and disappeared in a single frame and the page below it snapped
   up. An animation could be made to run on the way IN (a newly displayed element
   can animate) but never on the way OUT, which is exactly the asymmetry you get:
   a fade opening and a hard cut closing.

   Height is animatable, so the panel is always in the layout and simply has no
   height when it is closed. Both directions now take the same 320ms.

   `visibility` is the third property and it carries the accessibility half: a
   collapsed panel must not be readable by a screen reader or reachable by Tab.
   It flips instantly, so it is delayed until the collapse FINISHES on the way out
   (`0s linear .32s`) and applied immediately on the way in -- otherwise the text
   would blink out before it had finished sliding away. */
.sec.is-answer{height:0;overflow:hidden;opacity:0;visibility:hidden;
  transition:height .32s var(--ease),opacity .2s var(--ease),visibility 0s linear .32s}
.sec.is-answer.is-shown{height:var(--h);opacity:1;visibility:visible;
  transition:height .32s var(--ease),opacity .26s var(--ease) .06s,visibility 0s}
/* the mobile canvas is scaled, so its height is the scaled one */
@media(max-width:767px){.sec.is-answer.is-shown{height:calc(var(--mh) * var(--ms))}}
@media(prefers-reduced-motion:reduce){
  .sec.is-answer,.sec.is-answer.is-shown{transition:none}}
/* form */
.se-tf{position:absolute;inset:0;width:100%;height:100%;background:transparent;border:0;outline:0;resize:none;overflow:hidden;padding:0;font:inherit;color:inherit;letter-spacing:inherit}
.se-tf::placeholder{color:inherit;opacity:.75}
.fm-status{position:absolute;left:0;right:0;top:100%;margin-top:8px;font-size:13px;font-family:'Montserrat',sans-serif}
@media(max-width:767px){
 /* --ms is a UNITLESS ratio, set by js (see site.js). It cannot be written in
    pure css: min(100vw,500px)/320 yields a LENGTH, and length x length is
    invalid, which silently voids every mobile height. The engine scales the 320
    canvas to the full client width with NO cap (measured: 585/320 at 600px,
    725/320 at 740px). 1 = unscaled 320 canvas, what a no-js browser gets. */
 :root{--ms:1}
 .only-d{display:none!important}
 .only-m{display:block}
 .sec{height:calc(var(--mh) * var(--ms))}
 .cv{position:absolute;top:0;left:0;right:0;width:320px;height:var(--mh);margin:0 auto;transform:scale(var(--ms));transform-origin:top center}
 .is-menu{height:1px}
 .is-mobnav .cv{height:var(--mh)}
}

/* A GALLERY ELEMENT MUST BE ITS OWN STACKING CONTEXT.

   Flickity's stylesheet puts `z-index: 1` on .flickity-viewport. On the live
   page that is harmless because the ENGINE gives every .sie-* element a
   transform, which makes each one a stacking context, so the viewport's
   z-index is scoped inside its own gallery element and never competes with
   anything outside it.

   These rebuilt .el elements carry no transform, so there was nothing between
   .flickity-viewport and .cv to trap it: the viewport's z-index:1 went up
   against .e-contact-cta_3 (z-index auto, i.e. 0) and won. The gallery painted
   OVER the "Plan your celebration" heading, which on the live page paints over
   the photos. The two overlap by 32px BY DESIGN -- geometry was identical the
   whole time, it was purely paint order.

   isolation:isolate rather than a transform: it creates the stacking context
   and nothing else. A transform would also work (it is what the engine
   happens to use) but it additionally establishes a containing block for
   fixed/absolute descendants and can force layer rasterisation. */
.el.ty-gallery{isolation:isolate}

/* ===========================================================================
   INTERACTION LAYER
   ---------------------------------------------------------------------------
   Everything below is about what happens when a visitor points at, taps, or
   tabs to something. It lives in shared.css because it is identical on both
   pages, and it sits AFTER the engine's own rules on purpose (see the
   specificity note on each block).
   =========================================================================== */

/* --- BUTTONS --------------------------------------------------------------
   DESIGNED, not inherited. The old site's hover took a primary button from brand
   blue to pure black, which on the black contact section makes the SUBMIT button
   disappear the moment you point at it. Copying that was the wrong instinct: a
   hover has to work on the background it actually sits on, and this site puts
   buttons on black, on white and on photographs.

   One system, two states, readable on all three:
     PRIMARY   (solid blue)   -> deeper blue. Stays a solid block, never vanishes.
     SECONDARY (outline)      -> fills with brand blue, label flips to white.
                                 An outline button filling in is the clearest
                                 "this is a button" signal there is, and because
                                 the fill is the BRAND colour it reads the same
                                 whether the outline was white (dark sections) or
                                 blue (light ones) -- no per-instance guessing.
   Both lift 2px with a soft shadow so the button feels like it comes forward,
   and the press puts it back down, so a click has a beginning and an end.

   180ms: long enough to read as motion, short enough that a fast pointer sweep
   does not leave a trail of half-lit buttons behind it. */
:root{--brand:#2C9BF6;--brand-deep:#1173c9;--ease:cubic-bezier(.4,0,.2,1)}

.btn{transition:background-color .18s var(--ease), border-color .18s var(--ease),
     color .18s var(--ease), transform .18s var(--ease), box-shadow .18s var(--ease)}
.btn span{transition:color .18s var(--ease)}

@media (hover:hover) and (pointer:fine){
  .st-primary.btn:hover{background-color:var(--brand-deep);background-image:none;
    transform:translateY(-2px);box-shadow:0 6px 18px rgba(0,0,0,.34)}
  /* --brand-deep, not --brand: one of these secondaries (CHECK YOUR DATE) already
     carries a brand-blue fill at rest, so filling it with the same blue was a
     hover you could not see. Both button kinds now settle on the same deeper
     blue, which means "hovered" looks identical everywhere on the site. */
  .st-secondary.btn:hover{background-color:var(--brand-deep);border-color:var(--brand-deep);
    background-image:none;transform:translateY(-2px);box-shadow:0 6px 18px rgba(0,0,0,.34)}
  .st-secondary.btn:hover span{color:#fff}
}
/* The press. Applied on the ELEMENT that receives the click (the <a>/<button>
   wrapper) as well as the button itself, because on this site the clickable node
   is sometimes the wrapper and sometimes the .btn. */
.btn:active,a:active .btn,button:active .btn{
  transform:translateY(0);box-shadow:0 2px 6px rgba(0,0,0,.3);transition-duration:.06s}

/* --- EVERY OTHER CLICKABLE THING ------------------------------------------
   Icons, social logos, footer links, the hamburger, the testimonial and add-on
   arrows. None of these had any hover at all: you could not tell the Instagram
   logo from the decorative photo beside it until you clicked. */
@media (hover:hover) and (pointer:fine){
  /* social logos + icon links: come forward and brighten */
  a.el.ty-graphic:hover .ph, a.el.ty-svg:hover .ph{
    transform:scale(1.09);filter:brightness(1.12)}
  /* The SVG's colour has to be set as `fill`, not as `color`. Every icon carries a
     per-element `.e-<sid> svg{fill:...}` rule (0,1,1) which beats `.ico{color}`
     inheriting through `fill:currentColor`, so setting colour alone did nothing
     visible -- the icon scaled a little and stayed the colour it was. */
  a.el.ty-icon:hover .ico svg{fill:var(--brand)}
  a.el.ty-icon:hover .ico{transform:scale(1.14)}
  a.el.ty-video:hover .vid{filter:brightness(1.08)}

  /* text links (footer nav, menu): the label lifts to brand blue and an
     underline grows out from the left rather than snapping on */
  a.el.ty-text:hover .txt{color:var(--brand)}
  /* NO position:relative here -- .txt is already absolute (it is pinned to its
     element box so an overlong line cannot cover the control beneath it), and
     absolute is already a containing block for this ::after. Setting relative
     would put the text back in normal flow and bring that bug straight back. */
  a.el.ty-text .txt::after{content:'';position:absolute;left:0;bottom:-2px;height:1px;
    width:100%;background:currentColor;transform:scaleX(0);transform-origin:left;
    transition:transform .22s var(--ease)}
  a.el.ty-text:hover .txt::after{transform:scaleX(1)}

  /* the hamburger and the FAQ +/x icons -- same fill-not-colour rule as above */
  .asbtn.ty-icon:hover .ico svg{fill:var(--brand)}
  .asbtn.ty-icon:hover .ico{transform:scale(1.18)}

  /* THE HOVER COLOUR HAS TO CONTRAST WITH WHAT IS BEHIND IT, and brand blue is
     the one colour that does not work everywhere on this site: the testimonial
     arrows are white on a brand-blue panel, so turning them brand blue makes
     them vanish -- the same failure as the black-on-black submit button. On that
     panel they go to deep navy instead. Everywhere else the panel is black or
     white and blue reads strongly against both.
     The rule is "a hover must be visible", not "a hover must be one colour". */
  .sec-testimonials .asbtn.ty-icon:hover .ico svg{fill:#0a2540}

  /* an FAQ row: the whole heading nudges toward the reader */
  .asbtn.ty-text:hover .txt{color:var(--brand)}
}
.ph,.ico,.vid{transition:transform .22s var(--ease), filter .22s var(--ease)}
.ico svg{transition:fill .18s var(--ease)}
.txt{transition:color .18s var(--ease)}
.asbtn:active .ico,a:active .ph,a:active .ico{transform:scale(.96);transition-duration:.06s}

/* Nothing above may move a millimetre for a visitor who asked for stillness. */
@media (prefers-reduced-motion:reduce){
  .btn,.btn span,.ph,.ico,.vid,.txt,a.el.ty-text .txt::after{transition:none}
  .st-primary.btn:hover,.st-secondary.btn:hover,.btn:active,a:active .btn,button:active .btn,
  a.el.ty-graphic:hover .ph,a.el.ty-svg:hover .ph,a.el.ty-icon:hover .ico,
  .asbtn.ty-icon:hover .ico,.asbtn:active .ico,a:active .ph,a:active .ico{transform:none}
  a.el.ty-text:hover .txt::after{transform:scaleX(1)}
}

/* --- A LINK HAS TO LOOK LIKE A LINK ---------------------------------------
   Measured at the hit point (elementFromPoint under the pointer, not the
   anchor's own computed style) on live AND on this build: the social icons and
   the footer nav links hand back `cursor: auto`. The arrow cursor over a real
   link is the same defect on both, inherited from the scrape.

   It happens because these anchors carry the engine's `.el` (position:absolute,
   display:block) and their only child is a `<span class="ph">` background
   image, so nothing in the chain ever asks for a pointer. The buttons escaped
   it only because `.btn` sets cursor:pointer for its own reasons.

   `cursor` is an inherited property, so setting it on the anchor is enough for
   every child -- with one exception carved out below, because a text cursor is
   correct inside a form field and would otherwise be overridden. */
a[href]{cursor:pointer}
a[href] .se-tf{cursor:auto}

/* --- KEYBOARD FOCUS -------------------------------------------------------
   Neither live nor this build had a single :focus rule. Tabbing through the
   page fell back to the browser's default ring, which the form fields then
   removed outright (`.se-tf{outline:0}`), so a keyboard visitor filling in the
   contact form had NO indication of where they were at all.

   :focus-visible, not :focus, so a mouse click never paints a ring -- the
   indicator appears for keyboard and other non-pointer input only, and mouse
   users see no change whatsoever.

   Two rings rather than one: this site puts controls on black, on white, on
   brand blue and on photographs, and no single colour is visible on all four.
   The blue ring carries the brand and the white halo guarantees contrast
   against whatever sits behind it. */
a[href]:focus-visible,
button:focus-visible,
[tabindex]:focus-visible,
.se-tf:focus-visible{
  outline:3px solid #2C9BF6;
  outline-offset:2px;
  box-shadow:0 0 0 6px rgba(250,250,250,.55);
  position:relative;z-index:5;   /* over neighbouring canvas elements, never clipped by them */
}
/* A text field is different: focus there is always worth showing, pointer or
   not, because the caret alone is easy to lose on these dark panels. */
.se-tf:focus{outline:2px solid rgba(44,155,246,.9);outline-offset:1px}

/* --- CONTROLS WITH NOWHERE TO GO ------------------------------------------
   18 `<button>` elements across the two pages carry no href, no handler and no
   data-* action: the 3 "let's go" buttons under the package-card photos, the 15
   on the accessories cards, and the current-page items in the nav. They are
   Kindle & Co template residue that the client never wired, and they are dead
   on the live site in exactly the same way.

   Marking them aria-hidden + tabindex="-1" in the markup takes them out of the
   tab order and out of the screen-reader tree; this rule stops them swallowing
   a click that would otherwise be a no-op. Nothing about how they LOOK changes,
   so the card hover still reveals the "let's go" label exactly as designed.
   Giving them a destination is a content decision, not a code one. */
.el[aria-hidden="true"]{pointer-events:none}

/* The gallery widget makes its viewport focusable so the arrow keys can page it,
   which is a real feature -- and then removes the focus ring with
   `.flickity-enabled:focus{outline:none}` from the stylesheet it injects at
   runtime. That selector is (0,2,0), exactly the same weight as the
   `[tabindex]:focus-visible` rule above, and it is injected later, so it wins the
   tie. One more class settles it. Without this, tabbing into the gallery moves
   focus somewhere invisible and the keyboard user is lost. */
.el .flickity-enabled:focus-visible{
  outline:3px solid #2C9BF6;outline-offset:2px;
  box-shadow:0 0 0 6px rgba(250,250,250,.55)}

/* A MARQUEE THAT CANNOT BE STOPPED IS A NUISANCE, and WCAG 2.2.2 asks for a way
   to pause anything that moves for more than five seconds. The intro strip runs a
   45s loop forever, so you cannot look at the photo your eye just caught. Pausing
   while the pointer is on it (or while focus is inside it) is the standard answer
   and costs nothing at rest.
   hover:hover again, or a tap on a phone would latch the pause and stop the strip
   for good. Visitors who ask for reduced motion have it stopped outright, in the
   .gtrack rule further up. */
@media (hover:hover){
  .gal:hover .gtrack{animation-play-state:paused}
}
.gal:focus-within .gtrack{animation-play-state:paused}

/* --- THE FAQ TOGGLE --------------------------------------------------------
   The + and the x are the SAME glyph: an X, with the + being that X turned 45
   degrees. The engine keeps them as two separate elements in two separate
   states, so opening a question used to swap one for the other in a single
   frame -- a hard cut, no motion at all.

   The rotation is applied to the INNER .ico rather than to the button, because
   the button already carries its own base rotation (315deg for the + on desktop,
   45deg on the phone) and overwriting that is exactly how the add-on arrows once
   ended up pointing the wrong way. Turning the .ico composes with whatever the
   button is already doing, so neither breakpoint needs to be special-cased for
   the hover.

   Only the CLOSE icon can share one keyframe: it rests at 0 on both breakpoints,
   so starting it 45 degrees back always looks like a +. The + itself rests at a
   different angle per breakpoint, so its keyframe turns the other way on the
   phone -- otherwise it would start on an x and end on an x. */
@keyframes faq-becomes-x    {from{transform:rotate(-45deg)} to{transform:rotate(0)}}
@keyframes faq-becomes-plus {from{transform:rotate(45deg)}  to{transform:rotate(0)}}
@keyframes faq-becomes-plus-m{from{transform:rotate(-45deg)}to{transform:rotate(0)}}

/* No fill-mode on purpose: the animation ends exactly where the icon rests
   anyway, and a `both`/`forwards` fill would pin the transform afterwards and
   make the hover turn below do nothing. */
.has-toggled .st.is-on .faq-x .ico{animation:faq-becomes-x .34s var(--ease)}
@media(min-width:768px){
  .has-toggled .st.is-on .faq-plus .ico{animation:faq-becomes-plus .34s var(--ease)}
}
@media(max-width:767px){
  .has-toggled .st.is-on .faq-plus .ico{animation:faq-becomes-plus-m .34s var(--ease)}
}

/* Hover: a quarter turn. Both glyphs have four-fold symmetry, so 90 degrees
   lands the icon back on the shape it started as -- it spins and settles as the
   same mark, which reads as alive without ever implying it means something else.
   Specificity has to beat the generic `.asbtn.ty-icon:hover .ico` scale rule
   above (0,4,0), or that rule's scale-only transform would cancel the turn. */
@media (hover:hover) and (pointer:fine){
  .faq-plus.asbtn.ty-icon:hover .ico,
  .faq-x.asbtn.ty-icon:hover .ico{transform:rotate(90deg) scale(1.12)}
}
.faq-plus .ico,.faq-x .ico{transition:transform .3s var(--ease)}
.faq-plus.asbtn:active .ico,.faq-x.asbtn:active .ico{
  transform:rotate(90deg) scale(.94);transition-duration:.08s}


@media (prefers-reduced-motion:reduce){
  .has-toggled .st.is-on .faq-x .ico,.has-toggled .st.is-on .faq-plus .ico{animation:none}
  .faq-plus .ico,.faq-x .ico{transition:none}
  .faq-plus.asbtn.ty-icon:hover .ico,.faq-x.asbtn.ty-icon:hover .ico,
  .faq-plus.asbtn:active .ico,.faq-x.asbtn:active .ico{transform:none}
}

/* FIX 3 -- THE DESKTOP NAV BAR SLIDES IN.
   The menu block declares two states and emits only one div: state 0 is the bare
   hamburger (which lives outside the states and is always there), state 1 is the
   nav bar. Toggling it was `.st{display:none}` -> `.st.is-on{display:block}`, so a
   full-width bar and its links appeared in a single frame.

   Same reasoning as the FAQ answer: display cannot be transitioned, so the bar is
   always present and instead has no opacity and no height offset when closed.
   It drops from -8px, which is the direction it comes from, and visibility is
   delayed out so the links are not stripped from the keyboard and screen reader
   before the bar has finished leaving. */
.sec-menu > .cv > .st{display:block;visibility:hidden;opacity:0;pointer-events:none;
  transform:translateY(-8px);
  transition:opacity .26s var(--ease),transform .26s var(--ease),visibility 0s linear .26s}
.sec-menu > .cv > .st.is-on{visibility:visible;opacity:1;transform:none;
  transition:opacity .26s var(--ease),transform .26s var(--ease),visibility 0s}
.sec-menu > .cv > .st.is-on > *{pointer-events:auto}
@media(prefers-reduced-motion:reduce){
  .sec-menu > .cv > .st,.sec-menu > .cv > .st.is-on{transition:none;transform:none}}

/* ---- DESIGN-BUILD EXTRA: the brand colour behind selected text. ---- */
::selection{background:var(--brand);color:#fff}
