/* assets/css/site.css — public-facing website.
   Design tokens:
   Color   : the two blues from the Studylane logo — deep navy for
             structure and trust, bright cyan for anything the visitor
             should act on — over a cool off-white ground.
   Type    : Fraunces (display, characterful serif) for headlines,
             Inter (body/UI) for everything else.
   Signature: the "journey path" — a dashed route connecting numbered
             steps in the How It Works section, literal to the brief
             (this business's entire product is a multi-step journey
             from Chitwan to a university overseas).
*/

:root{
  /* ---- Studylane International brand ------------------------------
     Taken from the logo: a deep navy block and a bright cyan figure.
     Everything else on the page is a neutral, so these two carry the
     identity — navy for structure and trust, cyan for anything the
     visitor should act on.

     The --forest-* / --gold-* names below are the original green-theme
     tokens, kept as aliases because they're referenced from inline
     styles across the templates. New code should use --brand-*. */
  --brand-900:#0D4278;   /* deepest navy — footers, gradients */
  --brand-800:#0F4C8C;
  --brand-700:#12569E;   /* primary navy — logo block */
  --brand-600:#1B6FC4;   /* lifted navy for hovers */
  --brand-100:#DCEBF8;
  --brand-050:#EDF5FC;   /* tinted surface */
  --cyan-500:#29ACE3;    /* logo figure — accent + CTA */
  --cyan-600:#1E93C6;
  --cyan-050:#E6F5FC;

  --forest-900:var(--brand-900);
  --forest-700:var(--brand-700);
  --forest-600:var(--brand-600);
  --forest-050:var(--brand-050);
  --gold-500:var(--cyan-500);
  --gold-600:var(--cyan-600);

  --paper:#F6F9FC;
  --surface:#FFFFFF;
  --ink-900:#122234;
  --ink-600:#4B5C6E;   /* 7.2:1 on --paper */
  /* Was #9AA7A1, which measured about 2.6:1 against the page background —
     below the 4.5:1 minimum, and this token is used for post dates, form
     hints and disclaimers, i.e. small text that needs it most. Darkened
     to 4.6:1 while staying visibly quieter than --ink-600. */
  /* 4.99:1 on --paper. Was #69788A at 4.27:1 — under the 4.5 minimum,
     and this token carries post dates, form hints and disclaimers, i.e.
     small text where contrast matters most. */
  --ink-300:#5F6D80;
  --border:#DFE7F0;
  /* ==================================================================
     Design tokens — "Soft UI Evolution"
     ------------------------------------------------------------------
     Softer than flat, clearer than neumorphism. The elevation scale is
     the important part: each level is TWO layered shadows — a tight,
     nearly-opaque one for the contact edge and a wide, faint one for
     the ambient cast. A single shadow reads as a grey smudge; two read
     as an object sitting above a surface.

     Shadows are tinted with the brand navy rather than black, so depth
     belongs to the palette instead of muddying it.
     ================================================================== */
  --radius-sm:8px;
  --radius-md:12px;
  --radius-lg:18px;
  --radius-xl:24px;
  --radius-pill:999px;

  --elev-1:0 1px 2px rgba(13,66,120,.06), 0 1px 3px rgba(13,66,120,.04);
  --elev-2:0 2px 4px rgba(13,66,120,.05), 0 4px 12px rgba(13,66,120,.06);
  --elev-3:0 4px 8px rgba(13,66,120,.05), 0 12px 28px rgba(13,66,120,.09);
  --elev-4:0 8px 16px rgba(13,66,120,.06), 0 24px 48px rgba(13,66,120,.13);
  --elev-5:0 16px 32px rgba(13,66,120,.08), 0 40px 80px rgba(13,66,120,.18);

  --shadow-card:var(--elev-2);
  --shadow-lift:var(--elev-4);

  /* Motion: 150–300ms is the band that reads as responsive without
     feeling twitchy. One easing curve everywhere keeps the whole
     interface feeling like a single object. */
  --ease-out:cubic-bezier(.22,.61,.36,1);
  --ease-spring:cubic-bezier(.34,1.4,.64,1);
  --dur-fast:150ms;
  --dur-base:220ms;
  --dur-slow:320ms;

  /* Focus ring, used by every interactive element. */
  --ring:0 0 0 3px rgba(41,172,227,.45);
  --ring-offset:0 0 0 2px var(--surface);

  /* Fluid type. clamp() scales between the two ends smoothly instead
     of jumping at a breakpoint, so a 900px tablet gets a size that
     actually suits it rather than the phone's or the desktop's. */
  --step-hero:clamp(2rem, 1.2rem + 3.4vw, 3.25rem);
  --step-h1:clamp(1.75rem, 1.2rem + 2.4vw, 2.5rem);
  --step-h2:clamp(1.4rem, 1.1rem + 1.4vw, 1.95rem);
  --step-h3:clamp(1.1rem, 1rem + .5vw, 1.3rem);
  --step-body:clamp(.95rem, .92rem + .18vw, 1.03rem);
  --step-lede:clamp(1rem, .95rem + .5vw, 1.16rem);

  /* Section rhythm scales with the viewport too. */
  /* Vertical rhythm between sections. Tightened from
     clamp(52px, 6vw, 88px): at a 1280px viewport that was 76.8px top
     and bottom, so two plain sections in a row sat 153px apart and the
     page read as a series of separate pages rather than one. */
  --section-y:clamp(38px, 4vw, 60px);
}

*{box-sizing:border-box}
html{scroll-behavior:smooth}
body.site-body{
  margin:0;
  background:var(--paper);
  color:var(--ink-900);
  font-family:'Inter', system-ui, -apple-system, "Segoe UI", sans-serif;
  line-height:1.55;
  -webkit-font-smoothing:antialiased;
}
img{max-width:100%; display:block}
a{color:inherit}
.container{max-width:1160px; margin:0 auto; padding:0 24px}

h1,h2,h3,.font-display{
  font-family:'Fraunces', Georgia, serif;
  font-weight:600;
  color:var(--forest-900);
  line-height:1.15;
  margin:0;
}
.eyebrow{
  display:inline-block; font-size:12.5px; font-weight:700; letter-spacing:.08em;
  text-transform:uppercase; color:var(--forest-700); margin-bottom:10px;
}
.section{padding:72px 0}
.section-head{max-width:640px; margin:0 0 40px}
.section-head p{color:var(--ink-600); font-size:15.5px; margin-top:10px}

/* ---------------- Buttons ---------------- */
.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:8px;
  padding:13px 26px; border-radius:999px; font-weight:600; font-size:14.5px;
  text-decoration:none; border:1.5px solid transparent; cursor:pointer;
  min-height:44px;               /* WCAG target size */
  transition:background-color .18s ease, border-color .18s ease, color .18s ease, transform .18s ease;
}
.btn:active{transform:translateY(1px)}
button, summary, [role="button"], label{cursor:pointer}
input, select, textarea{cursor:auto}
.btn-primary{background:var(--forest-700); color:#fff}
.btn-primary:hover{background:var(--forest-900)}
/* Ink on the cyan CTA is deliberately darker than --brand-900, which
   measured 3.92:1 against #29ACE3 — below AA. #06263F gives 5.97:1 on
   the same background. This is the site's primary call to action, so
   it's the last place to accept borderline contrast. */
.btn-gold{background:var(--gold-500); color:#06263F}
.btn-gold:hover{background:var(--gold-600)}
.btn-outline{border-color:var(--forest-700); color:var(--forest-700); background:transparent}
.btn-outline-light{border-color:rgba(255,255,255,.6); color:#fff}
.btn-outline-light:hover{background:rgba(255,255,255,.12)}

/* ---------------- Navbar ---------------- */
.site-header{position:sticky; top:0; z-index:50; background:rgba(246,249,252,.92); backdrop-filter:blur(6px); border-bottom:1px solid var(--border)}

/* The header is a strict single line.
   nowrap on every level stops the nav dropping onto a second row when
   the link list gets long; the switch to the hamburger happens at
   1080px (below), which is before the content can run out of room —
   so there is no width at which the bar wraps. */
.navbar{display:flex; align-items:center; justify-content:space-between; gap:18px; padding:12px 0; flex-wrap:nowrap}
.navbar .logo{display:flex; align-items:center; gap:10px; text-decoration:none; flex-shrink:0}
.navbar .logo img{height:42px; width:auto; max-width:200px}
.navbar .logo .brand-name{font-family:'Fraunces',serif; font-weight:700; font-size:18px; color:var(--brand-900); white-space:nowrap}

.nav-links{
  display:flex; align-items:center; gap:2px; list-style:none; margin:0; padding:0;
  flex-wrap:nowrap; min-width:0;
}
.nav-links > li{position:relative; flex-shrink:0}
.nav-links > li > a{
  display:flex; align-items:center; gap:3px; white-space:nowrap;
  padding:10px 11px; text-decoration:none; font-size:14px; font-weight:600;
  color:var(--ink-900); border-radius:8px; transition:background-color .18s ease, color .18s ease;
}
.nav-cta{flex-shrink:0}

/* Between the collapse point and 1320px the bar is tight but still one
   line — shave the spacing rather than let anything wrap. */
@media (min-width:1081px) and (max-width:1320px){
  .nav-links > li > a{padding:10px 8px; font-size:13.2px}
  .nav-links .caret{display:none}
  .navbar{gap:10px}
  .navbar .logo img{height:36px}
  .nav-phone{padding:9px 8px; font-size:12.5px}
  .nav-cta .btn{padding:11px 16px; font-size:13.5px}
}

/* ------------------------------------------------------------------
   More menu items than the bar comfortably fits
   ------------------------------------------------------------------
   navbar.php counts the top-level items and adds .navbar--dense past
   eight, because the count is knowable in PHP and not in CSS. The row
   then tightens instead of spilling: at nine or more items the old
   spacing pushed the row past the container, and from about six extra
   items it dragged the whole page into a horizontal scroll.

   Applied only above the collapse point — below that the drawer takes
   over and none of this matters.
   ------------------------------------------------------------------ */
@media (min-width:1081px){
  .navbar--dense{gap:8px}
  .navbar--dense .nav-links{gap:0}
  .navbar--dense .nav-links > li > a{padding:9px 7px; font-size:13px}
  .navbar--dense .nav-links .caret{display:none}
  .navbar--dense .navbar .logo img,
  .navbar--dense .logo img{height:34px}
  .navbar--dense .nav-cta .btn{padding:10px 14px; font-size:13px}

  /* A floor under the tightening. Past a certain number of links no
     amount of shaving fits them, and the row would start overlapping
     the button. Allowing the list to shrink lets the flex layout take
     the space back from the widest items first. */
  .navbar--dense .nav-links{min-width:0; flex-shrink:1}
  .navbar--dense .nav-links > li{min-width:0}
}

/* Last-resort guard, at every width: keep an over-full bar from
   dragging the whole page into a sideways scroll.
   overflow-x:clip rather than hidden — hidden would make this a scroll
   container on both axes and cut off the dropdowns, which open
   downwards out of the bar. clip leaves the vertical axis visible. */
@media (min-width:1081px){
  .navbar{min-width:0}
  .nav-links{overflow-x:clip; overflow-y:visible}
}
.nav-links > li > a:hover{background:var(--brand-050); color:var(--brand-700)}
.nav-links > li > a.is-active{color:var(--brand-700)}
.nav-links > li > a.is-active::after{
  content:''; position:absolute; left:13px; right:13px; bottom:2px; height:2px;
  background:var(--cyan-500); border-radius:2px;
}
.nav-links .caret{display:inline-flex; opacity:.55; transition:transform .18s ease}
.nav-links > li:hover .caret{transform:rotate(180deg)}
.nav-phone{
  display:inline-flex; align-items:center; gap:7px; text-decoration:none;
  font-size:13.5px; font-weight:700; color:var(--brand-700); padding:9px 12px; border-radius:8px;
}
.nav-phone:hover{background:var(--brand-050)}
.dd-flag{display:inline-flex; margin-right:9px; vertical-align:middle}
.dropdown a{display:flex; align-items:center}
.dropdown{
  position:absolute; top:100%; left:0; background:var(--surface); border:1px solid var(--border);
  border-radius:var(--radius-md); box-shadow:var(--shadow-card); min-width:190px; padding:8px;
  opacity:0; visibility:hidden; transform:translateY(6px); transition:.15s ease;
}
.nav-links > li:hover .dropdown{opacity:1; visibility:visible; transform:translateY(0)}
.dropdown a{display:block; padding:9px 12px; font-size:13.5px; text-decoration:none; color:var(--ink-900); border-radius:6px}
.dropdown a:hover{background:var(--forest-050); color:var(--forest-700)}
.nav-cta{display:flex; align-items:center; gap:10px}
.nav-toggle{
  display:none; background:none; border:0; cursor:pointer; color:var(--forest-900);
  width:44px; height:44px; align-items:center; justify-content:center; border-radius:10px;
}
.nav-toggle:hover{background:var(--forest-050)}

/* ------------------------------------------------------------------
   Hamburger -> X
   ------------------------------------------------------------------
   Three bars morph into a close icon, keyed off aria-expanded rather
   than a separate JS-toggled class — the button already carries that
   attribute (see initNav in site.js), so the icon animation costs no
   extra state. The transition is already covered by the sitewide
   reduced-motion rule that forces all transition-durations to .01ms.
   ------------------------------------------------------------------ */
.nav-toggle-bars{position:relative; width:21px; height:15px; display:block; flex:none}
.nav-toggle-bars span{
  position:absolute; left:0; width:100%; height:2px; border-radius:2px;
  background:currentColor;
  transition:transform .32s var(--ease-spring), opacity .2s var(--ease-out), top .32s var(--ease-out);
}
.nav-toggle-bars span:nth-child(1){top:0}
.nav-toggle-bars span:nth-child(2){top:6.5px}
.nav-toggle-bars span:nth-child(3){top:13px}
.nav-toggle[aria-expanded="true"] .nav-toggle-bars span:nth-child(1){top:6.5px; transform:rotate(45deg)}
.nav-toggle[aria-expanded="true"] .nav-toggle-bars span:nth-child(2){opacity:0; transform:scaleX(0)}
.nav-toggle[aria-expanded="true"] .nav-toggle-bars span:nth-child(3){top:6.5px; transform:rotate(-45deg)}

/* ---------------- Hero ---------------- */
.hero{
  background:linear-gradient(180deg, var(--forest-900) 0%, var(--forest-700) 100%);
  /* Trimmed from 88/100. The hero still gets more room than a normal
     section — it should — but at 100px bottom against a 51px section
     rhythm it was the one gap on the page that read as a mistake. */
  color:#fff; padding:72px 0 78px; position:relative; overflow:hidden;
}
.hero .container{position:relative; z-index:2}
.hero-grid{display:grid; grid-template-columns:1.1fr .9fr; gap:48px; align-items:center}
.hero h1{color:#fff; font-size:44px; margin-bottom:18px}
.hero p.lede{font-size:17px; color:rgba(255,255,255,.85); max-width:480px; margin-bottom:30px}
.hero-actions{display:flex; gap:14px; flex-wrap:wrap}
.hero-stats{display:flex; gap:32px; margin-top:44px; flex-wrap:wrap}
.hero-stats .stat-num{font-family:'Fraunces',serif; font-size:30px; font-weight:700; color:var(--gold-500)}
.hero-stats .stat-label{font-size:12.5px; color:rgba(255,255,255,.7); text-transform:uppercase; letter-spacing:.05em}
.hero-visual{
  background:rgba(255,255,255,.06); border:1px solid rgba(255,255,255,.14);
  border-radius:var(--radius-lg); padding:28px; backdrop-filter:blur(4px);
}
.hero-visual .route{display:flex; flex-direction:column; gap:0}
.route-node{display:flex; align-items:center; gap:14px; position:relative; padding:14px 0}
.route-node:not(:last-child)::after{
  content:''; position:absolute; left:15px; top:44px; bottom:-10px; width:2px;
  background:repeating-linear-gradient(180deg, rgba(255,255,255,.5) 0 6px, transparent 6px 12px);
}
.route-dot{width:32px; height:32px; border-radius:50%; background:var(--gold-500); color:var(--forest-900);
  display:flex; align-items:center; justify-content:center; font-weight:700; font-size:14px; flex-shrink:0; z-index:1}
.route-node .route-label{font-weight:600; font-size:14.5px}
.route-node .route-sub{font-size:12.5px; color:rgba(255,255,255,.65)}

/* ---------------- Journey / How it works (signature element) ---------------- */
.journey{background:var(--surface)}

/* ==================================================================
   Journey path -- wave layout
   ------------------------------------------------------------------
   The four steps alternate above and below the row's centre line,
   connected by one smooth curve rather than the straight dashed rule
   this replaces. A step resting ABOVE the line arrives by dropping
   into place from further up; a step resting BELOW it arrives by
   rising from further down -- the entrance direction always matches
   where the step actually lives, never a single shared direction for
   all four. The resting offset (--up / --down) is unconditional, so a
   reduced-motion or JS-disabled visitor still sees the wave -- only
   the entrance motion is skipped, never the layout itself.

   Everything here is scoped to .journey-step and its own children;
   nothing in this block reaches outside the How It Works section.
   ================================================================== */
.journey-path{
  display:grid; grid-template-columns:repeat(4,1fr); gap:0;
  position:relative; margin-top:64px; padding-bottom:24px;
}
.journey-curve{
  position:absolute; top:0; left:0; width:100%; height:70px;
  z-index:0; overflow:visible; pointer-events:none;
}
.journey-curve path{
  fill:none; stroke:var(--border); stroke-width:2; stroke-dasharray:10 10; stroke-linecap:round;
}
.journey-step{position:relative; z-index:1; text-align:center; padding:0 16px}
/* Resting position -- permanent, independent of the reveal system. */
.journey-step--up{transform:translateY(-20px)}
.journey-step--down{transform:translateY(20px)}

/* Hover feedback lives on the circle and heading only -- never on
   .journey-step itself, which already carries the wave's resting
   translateY(--up/--down). Touching transform at that level would mean
   composing two translateY() values again, same as the entrance
   animation had to; scoping the hover one level down sidesteps it
   entirely and keeps this simple. */
.journey-step .step-num{
  width:56px; height:56px; border-radius:50%; background:var(--forest-700); color:#fff;
  display:flex; align-items:center; justify-content:center; font-family:'Fraunces',serif; font-size:20px;
  font-weight:700; margin:0 auto 18px; box-shadow:0 6px 16px rgba(15,110,81,.25);
  transition:transform .4s var(--ease-spring), box-shadow .35s var(--ease-out), background .35s var(--ease-out);
}
/* The diagonal gradient echoes the curve connecting the four steps --
   same two colours, so the circle reads as "a point on that line"
   rather than an unrelated badge. The ring is a soft halo, not a hard
   outline, so it doesn't compete with the wave's own spacing. */
.journey-step:hover .step-num{
  transform:scale(1.12);
  background:linear-gradient(135deg, var(--cyan-500), var(--forest-700));
  box-shadow:0 10px 24px rgba(41,172,227,.35), 0 0 0 6px var(--forest-050);
}
.journey-step h3{font-size:16.5px; margin-bottom:8px; transition:color .3s var(--ease-out)}
.journey-step:hover h3{color:var(--forest-700)}
.journey-step p{font-size:13.5px; color:var(--ink-600); margin:0}

/* Entrance -- additive on top of the resting transform above, so each
   step lands exactly on its point of the wave rather than at a shared
   baseline. Specificity here (class + class + attribute) is chosen to
   beat the sitewide generic [data-reveal] rule on purpose -- these two
   steps need their own transform math, not the generic translateY(24px). */
.reveal-ready .journey-step--up[data-reveal]{
  opacity:0; transform:translateY(-20px) translateY(-40px);
  transition:opacity .5s var(--ease-out), transform .5s var(--ease-out);
}
.reveal-ready .journey-step--up[data-reveal].is-visible{opacity:1; transform:translateY(-20px)}

.reveal-ready .journey-step--down[data-reveal]{
  opacity:0; transform:translateY(20px) translateY(40px);
  transition:opacity .5s var(--ease-out), transform .5s var(--ease-out);
}
.reveal-ready .journey-step--down[data-reveal].is-visible{opacity:1; transform:translateY(20px)}

/* ---------------- Cards / grids ---------------- */
.grid{display:grid; gap:22px}
.grid-4{grid-template-columns:repeat(4,1fr)}
.grid-3{grid-template-columns:repeat(3,1fr)}
.grid-2{grid-template-columns:repeat(2,1fr)}

.dest-card{
  background:var(--surface); border:1px solid var(--border); border-radius:var(--radius-lg);
  overflow:hidden; text-decoration:none; color:var(--ink-900); transition:.18s ease; box-shadow:var(--shadow-card);
}
.dest-card:hover{transform:translateY(-4px); box-shadow:0 10px 26px rgba(11,79,59,.13)}
.dest-card .flag{font-size:38px; padding:26px 24px 0}
.dest-card .body{padding:16px 24px 24px}
.dest-card h3{font-size:18px; margin-bottom:6px}
.dest-card p{font-size:13.5px; color:var(--ink-600); margin:0 0 14px}
.dest-card .cta{font-size:13px; font-weight:700; color:var(--forest-700)}

/* ==================================================================
   Service cards -- signature hover
   ------------------------------------------------------------------
   Deliberately its own effect, not the shared lift every other card
   type uses: a cyan-to-forest accent bar draws in across the top on
   hover, and the icon itself "activates" -- inverting to a solid
   filled colour with a small spring-eased scale and tilt, rather than
   sitting still while just the card around it lifts. The same
   .service-card markup renders on the homepage and on /services, so
   this one block covers both.

   overflow:hidden is load-bearing, not decorative: without it the
   accent bar's square corners poke out past the card's own rounded
   ones. :focus-within is included alongside :hover so a keyboard user
   tabbing to the "More detail" summary on /services gets the same
   feedback a mouse user gets.
   ================================================================== */
.service-card{
  position:relative; overflow:hidden;
  background:var(--surface); border:1px solid var(--border); border-radius:var(--radius-lg); padding:26px;
}
.service-card::before{
  content:''; position:absolute; top:0; left:0; right:0; height:3px;
  background:linear-gradient(90deg, var(--cyan-500), var(--forest-700));
  transform:scaleX(0); transform-origin:left;
  transition:transform .45s var(--ease-out);
}
.service-card:hover::before, .service-card:focus-within::before{transform:scaleX(1)}

.service-card .icon{
  width:44px; height:44px; border-radius:12px; background:var(--forest-050); color:var(--forest-700);
  display:flex; align-items:center; justify-content:center; margin-bottom:16px; flex-shrink:0;
  transition:transform .4s var(--ease-spring), background-color .3s var(--ease-out), color .3s var(--ease-out);
}
.service-card:hover .icon, .service-card:focus-within .icon{
  background:var(--forest-700); color:#fff;
  transform:scale(1.1) rotate(-6deg);
}

/* Fallback when an admin typed something that isn't a known icon name. */
.cms-icon-literal{font-size:20px; line-height:1}
.service-card h3{font-size:15.5px; margin-bottom:6px; transition:color .3s var(--ease-out)}
.service-card p{font-size:13px; color:var(--ink-600); margin:0}
.service-card:hover h3, .service-card:focus-within h3{color:var(--forest-700)}

.service-card:hover, .service-card:focus-within{
  transform:translateY(-6px);
  box-shadow:var(--elev-4);
  border-color:var(--cyan-500);
}

.test-card{background:var(--forest-050); border-radius:var(--radius-md); padding:24px; text-align:center}
.test-card .badge{font-family:'Fraunces',serif; font-size:22px; font-weight:700; color:var(--forest-900); margin-bottom:8px}
.test-card p{font-size:13px; color:var(--ink-600); margin:0}

/* Small cover image above the test's name.
   ------------------------------------------------------------------
   A landscape rectangle rather than a circle, because this is the same
   `image` field the single test-prep page runs full-width as a banner
   — the bundled artwork is 600x380. Cropping a banner into a circle
   throws most of it away and reads as a mistake.

   object-fit:cover fills the frame whatever gets uploaded later; the
   demo art is abstract texture with no subject to lose, and a real
   photo centre-crops acceptably at this size.

   Deliberately modest — it introduces the card, it isn't the subject
   of it, so the name underneath stays what you read first. Rendered
   only when that test actually has an image; the cards are grid items
   so a mix of some-with and some-without still tops out level, the
   badge simply starts higher on the ones without. */
.test-thumb{
  display:block;
  width:88px; height:56px;
  margin:0 auto 14px;
  border-radius:10px;
  overflow:hidden;
  background:var(--surface);
  box-shadow:0 0 0 1px var(--border), var(--elev-1);
  transition:box-shadow var(--dur-base) var(--ease-out),
             transform var(--dur-base) var(--ease-out);
}
.test-thumb img{
  width:100%; height:100%; display:block;
  object-fit:cover;
}
.test-card:hover .test-thumb{
  box-shadow:0 0 0 1px var(--cyan-500), var(--elev-2);
  transform:translateY(-2px);
}

/* ---------------- About / stats band ---------------- */
.about-band{background:var(--forest-050)}
.about-grid{display:grid; grid-template-columns:1fr 1fr; gap:56px; align-items:center}
.about-grid p{color:var(--ink-600); font-size:15px}
.stat-row{display:flex; gap:36px; margin-top:24px}
.stat-row .num{font-family:'Fraunces',serif; font-size:34px; font-weight:700; color:var(--forest-700)}
.stat-row .label{font-size:12.5px; color:var(--ink-600); text-transform:uppercase; letter-spacing:.04em}

/* ---------------- Testimonials ---------------- */
.testimonial-card{background:var(--surface); border:1px solid var(--border); border-radius:var(--radius-lg); padding:26px}
.testimonial-card .quote{font-size:14.5px; color:var(--ink-900); margin-bottom:16px}
.testimonial-card .who{font-size:13px; font-weight:700; color:var(--forest-900)}
.testimonial-card .where{font-size:12px; color:var(--ink-600)}

/* ---------------- CTA band ---------------- */
.cta-band{
  background:linear-gradient(120deg, var(--forest-900), var(--forest-700));
  color:#fff; border-radius:var(--radius-lg); padding:48px; text-align:center;
}
.cta-band h2{color:#fff}
.cta-band p{color:rgba(255,255,255,.82); margin:10px 0 26px}
.cta-actions{display:flex; gap:14px; justify-content:center; flex-wrap:wrap}

/* ---------------- Local SEO / Chitwan block ---------------- */
.local-block{display:grid; grid-template-columns:1fr 1fr; gap:44px; align-items:start}
.local-tags{display:flex; flex-wrap:wrap; gap:8px; margin-top:16px}
.local-tags span{background:var(--forest-050); color:var(--forest-700); font-size:12.5px; font-weight:600; padding:6px 12px; border-radius:999px}

/* ---------------- Footer ---------------- */
.site-footer{background:var(--forest-900); color:rgba(255,255,255,.82); padding:60px 0 24px; margin-top:40px}
.footer-grid{display:grid; grid-template-columns:1.4fr 1fr 1fr 1.2fr; gap:40px}
.footer-grid h4{color:#fff; font-size:13.5px; text-transform:uppercase; letter-spacing:.05em; margin-bottom:16px}
.footer-grid ul{list-style:none; margin:0; padding:0}
.footer-grid li{margin-bottom:9px; font-size:13.5px}
.footer-grid a{text-decoration:none; color:rgba(255,255,255,.82)}
.footer-grid a:hover{color:#fff}
.footer-brand p{font-size:13.5px; color:rgba(255,255,255,.68); max-width:280px}
.social-row{display:flex; gap:10px; margin-top:16px}
.social-row a{
  width:34px; height:34px; border-radius:50%; background:rgba(255,255,255,.1);
  display:flex; align-items:center; justify-content:center; font-size:14px;
}
.footer-bottom{border-top:1px solid rgba(255,255,255,.12); margin-top:40px; padding-top:20px; font-size:12.5px; color:rgba(255,255,255,.55); display:flex; justify-content:space-between; flex-wrap:wrap; gap:8px}

/* ---------------- Forms (public site, e.g. Contact page) ---------------- */
.site-form label{display:block; font-size:13px; font-weight:600; margin:14px 0 5px; color:var(--ink-900)}
.site-form label:first-child{margin-top:0}
.site-form input, .site-form select, .site-form textarea{
  width:100%; padding:11px 13px; border:1px solid var(--border); border-radius:10px;
  font-size:14px; font-family:inherit; background:var(--surface);
}
.site-form .hint{font-size:12px; color:var(--ink-600); margin-top:10px}

/* ---------------- Floating contact buttons ---------------- */
.floating-contact{position:fixed; right:20px; bottom:20px; display:flex; flex-direction:column; gap:12px; z-index:60}
.floating-contact a{
  width:52px; height:52px; border-radius:50%; display:flex; align-items:center; justify-content:center;
  color:#fff; text-decoration:none; box-shadow:0 6px 18px rgba(0,0,0,.22);
  transition:transform .18s ease, box-shadow .18s ease;
}
.floating-contact a:hover{transform:translateY(-2px); box-shadow:0 10px 24px rgba(0,0,0,.28)}
.fc-whatsapp{background:#25D366}
.fc-phone{background:var(--forest-700)}

.fc-messenger{background:#0084FF}

/* ---------------- Accessibility ---------------- */
.skip-link{
  position:absolute; left:-9999px; top:0; z-index:100;
  background:var(--forest-900); color:#fff; padding:12px 20px; border-radius:0 0 8px 0;
  text-decoration:none; font-weight:600; font-size:14px;
}
.skip-link:focus{left:0}
:focus-visible{outline:3px solid var(--gold-500); outline-offset:2px}

/* ---------------- Page banner (interior pages) ---------------- */
.page-banner{
  background:linear-gradient(140deg, var(--forest-900), var(--forest-700));
  color:#fff; padding:56px 0 60px;
}
.page-banner h1{color:#fff; font-size:36px; margin-bottom:12px}
.page-banner p{color:rgba(255,255,255,.84); font-size:16px; max-width:640px; margin:0}
.breadcrumbs-bar{font-size:13px; color:rgba(255,255,255,.7); margin-bottom:14px}
.breadcrumbs-bar a{color:rgba(255,255,255,.9); text-decoration:none}
.breadcrumbs-bar a:hover{text-decoration:underline}
.breadcrumbs-bar .sep{margin:0 7px; opacity:.6}

/* ---------------- Long-form article/page content ---------------- */
.prose{font-size:16px; color:var(--ink-900); line-height:1.75; max-width:72ch}
.prose > *:first-child{margin-top:0}
.prose h2{font-size:25px; margin:36px 0 12px}
.prose h3{font-size:20px; margin:30px 0 10px}
.prose p{margin:0 0 18px}
.prose ul,.prose ol{margin:0 0 18px; padding-left:24px}
.prose li{margin-bottom:8px}
.prose a{color:var(--forest-700); font-weight:600}
.prose img{border-radius:var(--radius-md); margin:24px 0; height:auto}
.prose blockquote{
  margin:24px 0; padding:4px 0 4px 22px; border-left:4px solid var(--gold-500);
  color:var(--ink-600); font-size:17px;
}
.prose table{width:100%; border-collapse:collapse; margin:24px 0; font-size:14.5px}
.prose th,.prose td{border:1px solid var(--border); padding:10px 12px; text-align:left}
.prose th{background:var(--forest-050)}
.prose code{background:var(--forest-050); padding:2px 6px; border-radius:4px; font-size:14px}
.prose hr{border:0; border-top:1px solid var(--border); margin:32px 0}

/* ---------------- Blog ---------------- */
.post-card{
  background:var(--surface); border:1px solid var(--border); border-radius:var(--radius-lg);
  overflow:hidden; display:flex; flex-direction:column; text-decoration:none; color:inherit;
  transition:.18s ease; box-shadow:var(--shadow-card);
}
.post-card:hover{transform:translateY(-4px); box-shadow:0 10px 26px rgba(11,79,59,.13)}
.post-card .thumb{aspect-ratio:16/9; background:var(--forest-050); overflow:hidden}
.post-card .thumb img{width:100%; height:100%; object-fit:cover}
.post-card .thumb.placeholder{display:flex; align-items:center; justify-content:center; font-size:34px; color:var(--forest-700); opacity:.35}
.post-card .body{padding:20px 22px 24px; display:flex; flex-direction:column; flex:1}
.post-card h3{font-size:17.5px; margin-bottom:8px; line-height:1.3}
.post-card p{font-size:13.5px; color:var(--ink-600); margin:0 0 14px; flex:1}
.post-meta{font-size:12px; color:var(--ink-300); display:flex; gap:10px; flex-wrap:wrap; align-items:center}
.tag-pill{
  display:inline-block; background:var(--forest-050); color:var(--forest-700);
  font-size:11.5px; font-weight:700; padding:4px 11px; border-radius:999px;
  text-decoration:none; letter-spacing:.02em;
}
a.tag-pill:hover{background:var(--forest-700); color:#fff}

.article-header{max-width:72ch; margin:0 auto}
.article-hero{border-radius:var(--radius-lg); overflow:hidden; margin:0 0 36px; max-height:460px}
.article-hero img{width:100%; height:100%; object-fit:cover}

.sidebar-card{
  background:var(--surface); border:1px solid var(--border);
  border-radius:var(--radius-md); padding:22px; margin-bottom:18px;
}
.sidebar-card h3{
  font-size:13px; margin-bottom:14px;
  text-transform:uppercase; letter-spacing:.06em; color:var(--brand-700);
  padding-bottom:11px; border-bottom:1px solid var(--border);
}
.sidebar-card ul{list-style:none; margin:0; padding:0}
.sidebar-card li{margin-bottom:2px; font-size:14px}

/* Full-width rows with a hover fill — a link list reads better as
   tappable rows than as bare text, and it gives a 40px+ tap target
   without needing a separate mobile rule. */
.sidebar-card li > a{
  display:flex; align-items:center; justify-content:space-between; gap:10px;
  padding:9px 10px; margin:0 -10px; border-radius:8px;
  color:var(--ink-900); text-decoration:none;
  transition:background-color .16s ease, color .16s ease;
}
.sidebar-card li > a:hover{background:var(--brand-050); color:var(--brand-700)}
.sidebar-card li > a[aria-current="page"]{
  background:var(--brand-050); color:var(--brand-700); font-weight:600;
}
.sidebar-card a{color:var(--ink-900); text-decoration:none}
.sidebar-card a:hover{color:var(--brand-700)}
.sidebar-card .count{
  font-size:11.5px; color:var(--ink-300); background:var(--paper);
  padding:2px 8px; border-radius:999px; flex-shrink:0;
}

.content-with-sidebar{display:grid; grid-template-columns:minmax(0,1fr) 320px; gap:48px; align-items:start}

/* The sidebar follows you down a long article instead of scrolling out
   of view and leaving a column of whitespace. The top offset clears the
   sticky header; max-height plus its own scroll stops a tall sidebar
   from becoming unreachable on a short viewport. */
@media (min-width: 901px){
  .content-with-sidebar > aside{
    position:sticky; top:96px;
    max-height:calc(100vh - 120px); overflow-y:auto;
    scrollbar-width:thin;
  }
  .content-with-sidebar > aside::-webkit-scrollbar{width:5px}
  .content-with-sidebar > aside::-webkit-scrollbar-thumb{background:var(--border); border-radius:3px}
}

/* ---------------- FAQ accordion ---------------- */
.faq-item{background:var(--surface); border:1px solid var(--border); border-radius:var(--radius-md); margin-bottom:12px; overflow:hidden}
.faq-item summary{
  padding:18px 22px; cursor:pointer; font-weight:600; font-size:15.5px; color:var(--forest-900);
  list-style:none; display:flex; justify-content:space-between; align-items:center; gap:16px;
}
.faq-item summary::-webkit-details-marker{display:none}
.faq-item summary::after{content:'+'; font-size:22px; color:var(--forest-700); font-weight:400; flex-shrink:0}
.faq-item[open] summary::after{content:'−'}
.faq-item summary:hover{background:var(--forest-050)}
.faq-item .faq-answer{padding:0 22px 20px; font-size:14.5px; color:var(--ink-600); line-height:1.7}

/* ---------------- Pagination ---------------- */
.pager{display:flex; gap:8px; justify-content:center; margin-top:44px; flex-wrap:wrap}
.pager a, .pager span{
  min-width:40px; height:40px; padding:0 12px; border-radius:10px; border:1px solid var(--border);
  background:var(--surface); display:inline-flex; align-items:center; justify-content:center;
  font-size:14px; font-weight:600; text-decoration:none; color:var(--ink-900);
}
.pager a:hover{border-color:var(--forest-700); color:var(--forest-700)}
.pager .current{background:var(--forest-700); border-color:var(--forest-700); color:#fff}

/* ---------------- Alerts & empty states ---------------- */
.alert{padding:14px 18px; border-radius:10px; font-size:14px; margin-bottom:20px}
.alert-success{background:var(--forest-050); color:var(--forest-900); border:1px solid #C6E3D6}
.alert-error{background:#FDECEA; color:#A93226; border:1px solid #F5C6C0}
.empty-note{text-align:center; color:var(--ink-600); font-size:15px; padding:48px 20px}

/* ------------------------------------------------------------------
   Centred popup notice
   ------------------------------------------------------------------ */
.notice-popup{
  position:fixed; inset:0; z-index:110;
  display:flex; align-items:center; justify-content:center; padding:24px;
  background:rgba(6,24,44,.62); backdrop-filter:blur(3px);
  opacity:0; transition:opacity .3s ease;
}
/* A class rule with display:flex outranks the HTML hidden attribute,
   so hidden has to be re-asserted — the same trap the cookie banner
   fell into. */
.notice-popup[hidden]{display:none !important}
.notice-popup.is-open{opacity:1}

.np-panel{
  position:relative; width:min(460px, 100%);
  background:var(--surface); border-radius:20px; overflow:hidden;
  box-shadow:0 30px 80px rgba(6,24,44,.4);
  transform:translateY(16px) scale(.97);
  transition:transform .35s var(--ease-out);
}
.notice-popup.is-open .np-panel{transform:none}

.np-close{
  position:absolute; top:12px; right:12px; z-index:2;
  width:34px; height:34px; border-radius:50%; border:0; cursor:pointer;
  background:rgba(255,255,255,.9); color:var(--ink-900);
  display:flex; align-items:center; justify-content:center;
  box-shadow:0 2px 8px rgba(6,24,44,.18);
}
.np-close:hover{background:#fff; color:var(--brand-700)}

.np-media{aspect-ratio:16/9; overflow:hidden; background:var(--brand-050)}
.np-media img{width:100%; height:100%; object-fit:cover; display:block}

.np-body{padding:28px 28px 26px; text-align:center}
.np-title{font-size:22px; margin:0 0 10px; line-height:1.25}
.np-message{font-size:14.5px; color:var(--ink-600); line-height:1.7; margin:0 0 22px}
.np-actions{display:flex; flex-direction:column; gap:10px; align-items:center}
.np-actions .btn{width:100%; justify-content:center}
.np-dismiss{
  background:none; border:0; cursor:pointer; padding:6px 10px;
  font-size:13px; font-weight:600; color:var(--ink-600); font-family:inherit;
}
.np-dismiss:hover{color:var(--ink-900); text-decoration:underline}

.sr-only{
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0;
}

@media (max-width: 480px){
  .np-body{padding:24px 20px 22px}
  .np-title{font-size:19px}
}

/* ---------------- Cookie notice ---------------- */
.cookie-notice{
  position:fixed; left:16px; bottom:16px; right:16px; max-width:560px; z-index:70;
  background:var(--surface); border:1px solid var(--border); border-radius:var(--radius-md);
  box-shadow:var(--shadow-lift); padding:18px 20px;
  display:flex; gap:16px; align-items:center; flex-wrap:wrap;
  transform:translateY(0); opacity:1;
  transition:transform .35s var(--ease-out), opacity .3s ease;
}
/* A class rule with `display:flex` beats the HTML `hidden` attribute,
   which is why the banner used to ignore both its initial hidden state
   and the "Got it" button. `hidden` has to be re-asserted explicitly. */
.cookie-notice[hidden]{display:none !important}
.cookie-notice.is-leaving{transform:translateY(20px); opacity:0}
.cookie-notice p{margin:0; font-size:13.5px; color:var(--ink-600); flex:1; min-width:220px}
.cookie-notice a{color:var(--forest-700); font-weight:600}

/* ---------------- Filter bar (universities, courses, blog) ---------------- */
.public-filters{
  display:flex; gap:12px; flex-wrap:wrap; align-items:center;
  background:var(--surface); border:1px solid var(--border); border-radius:var(--radius-md);
  padding:16px 18px; margin-bottom:32px;
}
.public-filters input, .public-filters select{
  padding:10px 13px; border:1px solid var(--border); border-radius:10px;
  font-size:14px; font-family:inherit; background:var(--surface);
}
.public-filters input[type=search], .public-filters input[type=text]{flex:1; min-width:200px}

/* ==================================================================
   Scroll-reveal animation
   ------------------------------------------------------------------
   Elements marked [data-reveal] start slightly low and transparent,
   and an IntersectionObserver adds .is-visible as they enter view.

   Two deliberate choices:
   - The starting state is applied by JS (via .reveal-ready on <html>),
     not by this stylesheet alone. If JavaScript is off or fails, the
     content is simply visible — never permanently invisible.
   - Only transform and opacity are animated. Both are compositor
     properties, so this doesn't trigger layout on scroll.
   ================================================================== */
.reveal-ready [data-reveal]{
  opacity:0;
  transform:translateY(22px);
  transition:opacity .6s var(--ease-out), transform .6s var(--ease-out);
  will-change:opacity, transform;
}
.reveal-ready [data-reveal="left"]{transform:translateX(-26px)}
.reveal-ready [data-reveal="right"]{transform:translateX(26px)}
.reveal-ready [data-reveal="scale"]{transform:scale(.96)}

.reveal-ready [data-reveal].is-visible{
  opacity:1;
  transform:none;
  will-change:auto;
}

/* Children stagger in sequence rather than all at once. Same 0.6s
   duration as a single [data-reveal] above, for one consistent feel
   sitewide. The actual per-child delay is set inline by JS (see
   initReveal in site.js), not by nth-child here — a fixed CSS list
   tops out at some number and silently stops staggering every child
   past it, which is exactly what happened before: six was enough for
   a 4-across destination row but not for the 14-item Services grid or
   any grid an admin grows over time. JS reads the real child count
   instead, so the wave holds together at 4 items or 40. */
.reveal-ready [data-reveal-group] > *{
  opacity:0; transform:translateY(20px);
  transition:opacity .6s var(--ease-out), transform .6s var(--ease-out);
}
.reveal-ready [data-reveal-group].is-visible > *{opacity:1; transform:none}

/* Counters animate from 0 to their real value on first view. */
.stat-num, .stat-row .num{font-variant-numeric:tabular-nums}

/* ---------------- Announcement bar ---------------- */
.announcement-bar{
  background:linear-gradient(90deg, var(--brand-900), var(--brand-700) 55%, var(--cyan-600));
  color:#fff; font-size:13.5px; position:relative; z-index:60;
}
.announcement-bar .container{
  display:flex; align-items:center; justify-content:center; gap:18px;
  padding:9px 24px; flex-wrap:wrap; text-align:center;
}
.announcement-bar a{color:#fff; font-weight:600; text-decoration:underline; text-underline-offset:3px}
.announcement-bar .ab-sep{opacity:.45}
.announcement-bar .ab-close{
  position:absolute; right:12px; top:50%; transform:translateY(-50%);
  background:none; border:0; color:rgba(255,255,255,.75); cursor:pointer;
  width:32px; height:32px; display:flex; align-items:center; justify-content:center; border-radius:6px;
}
.announcement-bar .ab-close:hover{background:rgba(255,255,255,.14); color:#fff}
.announcement-bar[hidden]{display:none !important}

/* ---------------- Header scroll behaviour ---------------- */
.site-header{
  transition:box-shadow .28s ease, background-color .28s ease, padding .28s ease;
}
.site-header.is-stuck{
  box-shadow:0 4px 24px rgba(13,66,120,.12);
  background:rgba(255,255,255,.96);
}
.site-header.is-stuck .navbar{padding:9px 0}
.site-header.is-stuck .navbar .logo img{height:32px}
.navbar .logo img{transition:height .28s var(--ease-out)}

/* Reading-progress line along the bottom of the sticky header. */
.scroll-progress{
  position:absolute; left:0; bottom:-1px; height:3px; width:0;
  background:linear-gradient(90deg, var(--brand-700), var(--cyan-500));
  transition:width .1s linear; border-radius:0 3px 3px 0;
}

/* ---------------- Flags ---------------- */
.flag-svg{
  display:block; border-radius:3px;
  box-shadow:0 1px 3px rgba(13,66,120,.22);
}
.dest-card .flag{
  padding:24px 24px 0; display:flex; align-items:center; gap:12px; font-size:inherit;
}
.dest-card .flag .flag-svg{width:52px; height:auto}
.page-banner .flag-svg{display:inline-block; vertical-align:middle; margin-right:12px}

/* ---------------- Premium polish ---------------- */
.dest-card, .post-card, .service-card, .testimonial-card{
  transition:transform .25s var(--ease-out), box-shadow .25s var(--ease-out), border-color .25s ease;
}
.testimonial-card:hover{
  transform:translateY(-3px); box-shadow:var(--shadow-lift); border-color:var(--brand-100);
}
.dest-card:hover, .post-card:hover{box-shadow:var(--shadow-lift)}

/* Subtle depth behind the hero without a background image. */
.hero{
  background:
    radial-gradient(1100px 460px at 88% -10%, rgba(41,172,227,.34), transparent 60%),
    radial-gradient(760px 420px at 6% 108%, rgba(41,172,227,.16), transparent 62%),
    linear-gradient(160deg, var(--brand-900) 0%, var(--brand-700) 55%, var(--brand-800) 100%);
}

/* ==================================================================
   Hero themes -- Admin -> Settings -> Theme -> Homepage hero style
   ------------------------------------------------------------------
   Two ready-made looks an admin can switch to for a season or a
   specific event -- a festival, an admissions deadline, an education
   fair -- and switch back out of once it passes. Only the background
   glow and an optional badge change; layout, copy and every other
   section are untouched. Compound selectors (.hero.hero--festive) so
   these reliably beat the plain .hero background above regardless of
   source order, rather than relying on a specificity tie.
   ================================================================== */
.hero-badge{
  display:inline-flex; align-items:center;
  padding:7px 16px; border-radius:999px; margin-bottom:16px;
  font-size:12.5px; font-weight:700; letter-spacing:.02em;
}

/* Festive -- warm gold layered over the standard navy. Dashain, Tihar,
   New Year, or any warm-season promotion. */
.hero.hero--festive{
  background:
    radial-gradient(900px 420px at 85% -8%, rgba(245,180,60,.30), transparent 62%),
    radial-gradient(700px 380px at 8% 105%, rgba(245,180,60,.16), transparent 60%),
    radial-gradient(1100px 460px at 88% -10%, rgba(41,172,227,.18), transparent 60%),
    linear-gradient(160deg, var(--brand-900) 0%, var(--brand-700) 55%, var(--brand-800) 100%);
}
.hero--festive .hero-badge{
  background:linear-gradient(90deg, #F5B43C, #E8963C); color:#3F2508;
}

/* Spotlight -- brighter and busier on purpose, for a single dated
   event rather than a season: an application deadline, an education
   fair, a scholarship drive. The badge pulses gently to read as
   time-limited without being frantic about it. */
.hero.hero--spotlight{
  background:
    radial-gradient(1000px 480px at 50% -20%, rgba(41,172,227,.48), transparent 65%),
    radial-gradient(700px 380px at 92% 100%, rgba(41,172,227,.22), transparent 60%),
    linear-gradient(160deg, var(--brand-900) 0%, var(--brand-700) 55%, var(--brand-800) 100%);
}
.hero--spotlight .hero-badge{
  background:var(--cyan-500); color:#04243D;
  animation:hero-badge-pulse 2.2s ease-in-out infinite;
}
@keyframes hero-badge-pulse{
  0%,100%{box-shadow:0 0 0 0 rgba(41,172,227,.5)}
  50%{box-shadow:0 0 0 8px rgba(41,172,227,0)}
}
@media (prefers-reduced-motion: reduce){
  .hero--spotlight .hero-badge{animation:none}
}

.hero::after{
  content:''; position:absolute; inset:0; pointer-events:none;
  background-image:
    linear-gradient(rgba(255,255,255,.045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.045) 1px, transparent 1px);
  background-size:64px 64px;
  mask-image:linear-gradient(180deg, rgba(0,0,0,.7), transparent 72%);
  -webkit-mask-image:linear-gradient(180deg, rgba(0,0,0,.7), transparent 72%);
}
.page-banner{
  background:
    radial-gradient(760px 320px at 92% -30%, rgba(41,172,227,.32), transparent 62%),
    linear-gradient(140deg, var(--brand-900), var(--brand-700));
}
.cta-band{
  background:
    radial-gradient(620px 300px at 15% 0%, rgba(41,172,227,.34), transparent 62%),
    linear-gradient(120deg, var(--brand-900), var(--brand-700));
}

/* Trust strip under the hero */
.trust-strip{background:var(--surface); border-bottom:1px solid var(--border); padding:22px 0}
.trust-strip .container{display:flex; gap:34px; align-items:center; justify-content:center; flex-wrap:wrap}
.trust-item{display:flex; align-items:center; gap:10px; font-size:13.5px; font-weight:600; color:var(--ink-600)}
.trust-item svg{color:var(--cyan-600); flex-shrink:0}

/* ==================================================================
   Trust strip <-> brand rail, alternating
   ------------------------------------------------------------------
   Two panels cross-fade in the same slot. They are stacked rather than
   sequential: the strip is a grid with one cell, both panels occupy it,
   and the taller one sets the height. That way the page below does not
   jump by a few pixels every time the panels swap, which it would if
   they were laid out one after another and toggled.

   Without brand logos the .has-alt class is never added, the second
   panel is never rendered, and this whole block does nothing — the
   trust lines behave exactly as they did before.
   ================================================================== */
.trust-strip.has-alt{display:grid; grid-template-columns:100%; align-items:center}
.trust-strip.has-alt > .strip-panel{
  grid-area:1 / 1;
  opacity:0; visibility:hidden;
  transition:opacity .5s var(--ease-out), visibility 0s linear .5s;
}
.trust-strip.has-alt > .strip-panel.is-active{
  opacity:1; visibility:visible;
  transition:opacity .5s var(--ease-out), visibility 0s;
}

/* Both panels on with switching turned off: show them one under the
   other rather than picking a winner. Without .has-alt there is no
   stacking grid and no hiding rule, so this only needs the spacing. */
.trust-strip.is-stacked > .strip-panel + .strip-panel{margin-top:16px}

/* The brand rail runs continuously, right to left, and does not stop
   for hover or focus the way the destination and story rails do. Those
   pause so a card can be read or clicked; these are logos with nothing
   to read, and the request here was for constant movement. */
.brand-rail:hover .marquee-track,
.brand-rail:focus-within .marquee-track{animation-play-state:running}

/* The brand panel is a full-width rail, so it opts out of the centred
   flex row the trust lines use. */
.strip-brands{width:100%}
.brand-rail{padding:0}
.brand-rail .marquee-track{gap:clamp(30px, 5vw, 58px); align-items:center}

/* A fixed cell per logo, so a wide wordmark and a square mark get the
   same footprint and the row reads as evenly spaced.
   The 10vw floor is what keeps one loop cycle wider than the rail on a
   large monitor: the cells grow with the viewport, so the cycle grows
   with it too rather than running short and letting a gap through. */
.brand-item{
  flex:none; display:flex; align-items:center; justify-content:center;
  min-width:max(140px, 10vw);
  text-decoration:none;
}
.brand-logo{display:block; height:34px}
.brand-logo img{
  height:100%; width:auto; display:block;
  /* Logos arrive in every colour and weight. Greyscale plus reduced
     opacity settles them into one quiet row, and full colour on hover
     rewards the look without making the resting state noisy. */
  filter:grayscale(1); opacity:.62;
  transition:filter var(--dur-base) var(--ease-out), opacity var(--dur-base) var(--ease-out);
}
.brand-item:hover .brand-logo img,
.brand-item:focus-visible .brand-logo img{filter:none; opacity:1}

@media (max-width:640px){
  .brand-logo{height:28px}
  .brand-rail .marquee-track{gap:26px}
}

/* Reduced motion: stop rotating, but show both panels rather than one.
   The switching is what that preference objects to, not the logos —
   holding on panel one would hide the brand rail from those visitors
   entirely, which turns a motion preference into missing content. Laid
   out one under the other, nothing moves and nothing is lost. */
@media (prefers-reduced-motion: reduce){
  .trust-strip.has-alt{display:block}
  .trust-strip.has-alt > .strip-panel{
    opacity:1 !important; visibility:visible !important; transition:none !important;
  }
  .trust-strip.has-alt > .strip-panel + .strip-panel{margin-top:16px}
}

/* Parent-company line */
.parent-company{
  display:inline-flex; align-items:center; gap:7px;
  font-size:12.5px; color:rgba(255,255,255,.72); margin-top:14px;
}
.parent-company a{color:#fff; font-weight:600; text-decoration:none; border-bottom:1px solid rgba(255,255,255,.35)}
.parent-company a:hover{border-bottom-color:#fff}

/* ==================================================================
   Marquee — the continuously scrolling rails
   ------------------------------------------------------------------
   The track holds the item list twice, and the animation moves it by
   exactly -50%. At that point the second copy sits precisely where the
   first started, so the reset is invisible and the loop is seamless.
   Duplicating in markup (rather than cloning in JS) means the rail is
   already full on first paint, with no empty gap while JS boots.
   ================================================================== */
.marquee{
  position:relative; overflow:hidden; padding:6px 0;
  /* Fade the ends so items enter and leave rather than being sliced
     off at a hard edge. */
  mask-image:linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
  -webkit-mask-image:linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
}
.marquee-track{
  display:flex; gap:22px; width:max-content;
  animation:marquee-left var(--marquee-speed, 46s) linear infinite;
}
.marquee--reverse .marquee-track{animation-name:marquee-right}

@keyframes marquee-left{
  from{transform:translateX(0)}
  to{transform:translateX(-50%)}
}
@keyframes marquee-right{
  from{transform:translateX(-50%)}
  to{transform:translateX(0)}
}

/* Pause when someone is trying to read or click an item. */
.marquee:hover .marquee-track,
.marquee:focus-within .marquee-track{animation-play-state:paused}

/* ------------------------------------------------------------------
   Destination postcards — a single tall rail
   ------------------------------------------------------------------
   Portrait 3:4 cards rather than the earlier squat landscape pair.
   One row of taller cards reads as a deliberate gallery; two rows of
   small ones read as filler. The artwork gets room to be seen, and the
   detail panel slides up over it on hover.
   ------------------------------------------------------------------ */
/* The rail is bounded by the container, not full-bleed. That's what
   guarantees a cycle is wider than the visible area, so a card and its
   duplicate can never be on screen at the same time. */
.dest-rail{margin:0 auto}
.dest-rail .marquee-track{gap:24px}
.dest-rail.is-static .marquee-track{
  animation:none; width:100%; justify-content:center; flex-wrap:wrap;
}

.dest-tile{
  position:relative; flex:0 0 auto; width:280px; aspect-ratio:3/4;
  border-radius:20px; overflow:hidden; text-decoration:none; isolation:isolate;
  box-shadow:0 8px 24px rgba(13,66,120,.16); background:var(--brand-900);
  transition:transform .4s var(--ease-out), box-shadow .4s var(--ease-out);
}
.dest-tile:hover, .dest-tile:focus-visible{
  transform:translateY(-8px);
  box-shadow:0 24px 50px rgba(13,66,120,.32);
}
.dest-tile img{
  position:absolute; inset:0; width:100%; height:100%; object-fit:cover;
  transition:transform .8s var(--ease-out);
}
.dest-tile:hover img{transform:scale(1.08)}

/* Photo-less fallback: a branded gradient rather than a broken frame. */
.dest-tile .tile-fallback{
  position:absolute; inset:0;
  background:
    radial-gradient(420px 260px at 78% 6%, rgba(41,172,227,.5), transparent 66%),
    linear-gradient(155deg, var(--brand-900), var(--brand-700));
}
.dest-tile .tile-veil{
  position:absolute; inset:0;
  background:linear-gradient(180deg, rgba(6,28,52,0) 32%, rgba(6,28,52,.62) 62%, rgba(5,22,42,.94) 100%);
}

/* Flag badge, top-RIGHT, on a frosted chip so it stays legible over any
   artwork. `left:auto` is explicit because the shorthand-free rule
   previously set both left and right, and left won — which is why the
   badge sat in the wrong corner. */
.dest-tile .tile-flag{
  position:absolute; top:14px; right:14px; left:auto; z-index:3;
  background:rgba(255,255,255,.18); backdrop-filter:blur(8px); -webkit-backdrop-filter:blur(8px);
  border:1px solid rgba(255,255,255,.34);
  padding:6px; border-radius:10px; display:flex; line-height:0;
  box-shadow:0 4px 14px rgba(4,20,40,.28);
  transition:transform .28s var(--ease-out);
}
.dest-tile:hover .tile-flag{transform:scale(1.08)}
.dest-tile .tile-flag .flag-svg{width:32px; height:auto}

/* Small flag prefixing the country name. */
.dest-tile .tile-body h3{
  display:flex; align-items:center; gap:9px;
}
.dest-tile .tile-name-flag{display:inline-flex; line-height:0; flex-shrink:0}
.dest-tile .tile-name-flag .flag-svg{
  width:24px; height:auto;
  border:1px solid rgba(255,255,255,.5);
  box-shadow:0 2px 6px rgba(4,20,40,.4);
}

.dest-tile .tile-body{
  position:absolute; left:0; right:0; bottom:0; z-index:2;
  padding:20px 20px 22px; color:#fff;
}
.dest-tile h3{color:#fff; font-size:22px; margin:0; line-height:1.15; letter-spacing:-.01em}
.dest-tile .tile-sub{
  font-size:12.5px; color:rgba(255,255,255,.8); margin-top:7px;
  display:flex; align-items:center; gap:7px;
}

/* The blurb is revealed on hover so the resting card stays clean. */
.dest-tile .tile-reveal{
  max-height:0; opacity:0; overflow:hidden;
  transition:max-height .45s var(--ease-out), opacity .3s ease, margin-top .45s var(--ease-out);
  margin-top:0;
}
.dest-tile:hover .tile-reveal,
.dest-tile:focus-visible .tile-reveal{max-height:120px; opacity:1; margin-top:10px}
.dest-tile .tile-reveal p{
  font-size:12.8px; line-height:1.6; color:rgba(255,255,255,.86); margin:0 0 12px;
}
.dest-tile .tile-cta{
  display:inline-flex; align-items:center; gap:6px;
  font-size:12.5px; font-weight:700; color:var(--cyan-500);
}

/* Touch devices have no hover, so the panel is always open there. */
@media (hover: none){
  .dest-tile .tile-reveal{max-height:120px; opacity:1; margin-top:10px}
  .dest-tile .tile-reveal p{-webkit-line-clamp:2; display:-webkit-box; -webkit-box-orient:vertical; overflow:hidden}
}

/* ------------------------------------------------------------------
   Success stories — cinematic poster cards
   ------------------------------------------------------------------
   Deliberately a different object from the destination postcards, so
   the two rails don't read as the same component twice. Destinations
   are bottom-weighted with a hover-reveal; these are centre-weighted
   posters: the play control and the student's name sit in the middle
   of the frame, the way a film poster or a video thumbnail does.
   ------------------------------------------------------------------ */
.story-rail .marquee-track{gap:24px}
.story-rail .story-tile{flex:0 0 auto; width:300px}

.story-tile{
  position:relative; aspect-ratio:4/5; isolation:isolate;
  border-radius:20px; overflow:hidden; border:0; padding:0;
  background:var(--brand-900); color:#fff; font:inherit; text-align:center;
  cursor:pointer; display:block; text-decoration:none;
  box-shadow:0 8px 24px rgba(13,66,120,.16);
  transition:transform .4s var(--ease-out), box-shadow .4s var(--ease-out);
}
.story-tile:hover, .story-tile:focus-visible{
  transform:translateY(-8px);
  box-shadow:0 24px 50px rgba(13,66,120,.32);
}

.story-thumb{position:absolute; inset:0; overflow:hidden}
.story-thumb img{
  width:100%; height:100%; object-fit:cover;
  transition:transform .8s var(--ease-out), filter .4s ease;
}
.story-tile:hover .story-thumb img{transform:scale(1.07)}
.story-thumb .thumb-fallback{
  position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
  background:linear-gradient(155deg, var(--brand-900), var(--brand-700));
  color:rgba(255,255,255,.45);
}
/* Two-stop veil: dark enough in the centre for the title to hold, and
   dark at the base so the badges stay readable over any artwork. */
.story-thumb::after{
  content:''; position:absolute; inset:0;
  background:
    radial-gradient(120% 78% at 50% 42%, rgba(5,22,42,.72), rgba(5,22,42,.30) 62%, rgba(5,22,42,.62) 100%),
    linear-gradient(180deg, rgba(5,22,42,.34) 0%, rgba(5,22,42,0) 34%, rgba(5,22,42,.86) 100%);
  transition:opacity .4s ease;
}
.story-tile:hover .story-thumb::after{opacity:.92}

/* Centre stack: play control, name, course */
.story-centre{
  position:absolute; left:0; right:0; top:50%; transform:translateY(-52%);
  z-index:2; padding:0 22px;
  display:flex; flex-direction:column; align-items:center; gap:13px;
}
.play-badge{
  width:60px; height:60px; border-radius:50%; flex-shrink:0;
  background:rgba(255,255,255,.14); backdrop-filter:blur(10px);
  border:1.5px solid rgba(255,255,255,.55); color:#fff;
  display:flex; align-items:center; justify-content:center;
  transition:transform .3s var(--ease-out), background-color .25s ease, border-color .25s ease;
}
.play-badge svg{margin-left:3px}
.story-tile:hover .play-badge, .story-tile:focus-visible .play-badge{
  transform:scale(1.14); background:var(--cyan-500); border-color:var(--cyan-500);
}
/* A gentle pulse marks the card as playable without being a distraction. */
.story-tile .play-badge::before{
  content:''; position:absolute; width:60px; height:60px; border-radius:50%;
  border:1.5px solid rgba(255,255,255,.5); animation:play-pulse 2.6s ease-out infinite;
}
@keyframes play-pulse{
  0%{transform:scale(1); opacity:.7}
  70%{transform:scale(1.55); opacity:0}
  100%{transform:scale(1.55); opacity:0}
}

.story-title{
  font-family:'Fraunces', Georgia, serif; font-weight:600;
  font-size:19px; line-height:1.25; color:#fff; margin:0;
  text-shadow:0 2px 14px rgba(0,0,0,.45);
}
.story-course{
  font-size:12.5px; color:rgba(255,255,255,.86); line-height:1.55;
  text-shadow:0 1px 10px rgba(0,0,0,.4);
}

/* Base strip: outcome badges */
.story-foot{
  position:absolute; left:0; right:0; bottom:0; z-index:2; padding:16px 18px 18px;
  display:flex; gap:6px; flex-wrap:wrap; justify-content:center;
}
.story-foot span{
  background:rgba(255,255,255,.16); backdrop-filter:blur(8px);
  border:1px solid rgba(255,255,255,.26); color:#fff;
  font-size:10.5px; font-weight:700; letter-spacing:.02em;
  padding:5px 10px; border-radius:999px; white-space:nowrap;
}
.story-foot span.is-result{background:var(--cyan-500); border-color:var(--cyan-500); color:#06263F}

@media (hover: none){
  .story-tile .play-badge::before{animation:none}
}

/* ---------------- Video lightbox ---------------- */
.video-modal{
  position:fixed; inset:0; z-index:120; display:flex; align-items:center; justify-content:center;
  background:rgba(6,24,44,.88); padding:24px; opacity:0; transition:opacity .25s ease;
}
.video-modal[hidden]{display:none !important}
.video-modal.is-open{opacity:1}
.video-modal .vm-inner{width:min(960px, 100%); position:relative}
.video-modal .vm-frame{
  position:relative; aspect-ratio:16/9; background:#000;
  border-radius:var(--radius-md); overflow:hidden; box-shadow:0 30px 70px rgba(0,0,0,.5);
}
.video-modal iframe{position:absolute; inset:0; width:100%; height:100%; border:0}
.video-modal .vm-placeholder{
  position:absolute; inset:0; display:flex; flex-direction:column;
  align-items:center; justify-content:center; text-align:center; gap:10px;
  padding:32px; color:#fff;
  background:
    radial-gradient(520px 260px at 50% 0%, rgba(41,172,227,.28), transparent 68%),
    linear-gradient(155deg, var(--brand-900), var(--brand-700));
}
.video-modal .vm-placeholder[hidden]{display:none !important}
.video-modal .vm-placeholder svg{color:var(--cyan-500); opacity:.9}
.video-modal .vm-placeholder h3{color:#fff; font-size:19px; margin:0}
.video-modal .vm-placeholder p{font-size:14px; color:rgba(255,255,255,.82); margin:0; max-width:440px; line-height:1.65}
.video-modal .vm-placeholder strong{color:#fff}
.video-modal .vm-placeholder .vm-formats{font-size:12.5px; color:rgba(255,255,255,.6)}
.video-modal .vm-close{
  position:absolute; top:-46px; right:0;
  background:rgba(255,255,255,.14); border:0; color:#fff; cursor:pointer;
  width:38px; height:38px; border-radius:50%; display:flex; align-items:center; justify-content:center;
}
.video-modal .vm-close:hover{background:rgba(255,255,255,.28)}
.video-modal .vm-caption{color:#fff; margin-top:14px; font-size:14px; text-align:center}
.video-modal .vm-caption strong{display:block; font-size:16px; margin-bottom:2px}

/* ==================================================================
   Hero: floating composition
   ------------------------------------------------------------------
   Deliberately a different object from the About composition, so the
   two don't read as the same widget twice. About is two overlapping
   photo cards with a badge; this is a single portrait card with
   destination chips orbiting it and a glass status card.

   Everything sits on the dark hero gradient, so the floating elements
   are frosted glass rather than solid white — solid cards would punch
   holes in the gradient.
   ================================================================== */
.hero-stage{
  position:relative;
  min-height:560px;
  display:flex; align-items:center; justify-content:center;
}

/* Glow behind the card */
.hs-glow{
  position:absolute; z-index:0; width:440px; height:440px; border-radius:50%;
  background:radial-gradient(circle, rgba(41,172,227,.42), rgba(41,172,227,0) 68%);
  animation:hs-pulse 9s ease-in-out infinite;
  pointer-events:none;
}

/* Orbit ring — decorative, and the chips sit on its edge */
.hs-orbit{
  position:absolute; z-index:1; width:440px; height:440px; border-radius:50%;
  border:1.5px dashed rgba(255,255,255,.22);
  animation:hs-rotate 44s linear infinite;
  pointer-events:none;
}
.hs-orbit::after{
  content:''; position:absolute; top:-5px; left:50%; margin-left:-5px;
  width:10px; height:10px; border-radius:50%; background:var(--cyan-500);
  box-shadow:0 0 14px 3px rgba(41,172,227,.7);
}

/* The student card -- sized to match the About page's .av-card (340px
   / 78% cap), which is this site's existing "big hero photo" scale. */
.hs-card{
  position:relative; z-index:3;
  width:min(340px, 74%); aspect-ratio:10/13;
  border-radius:26px; overflow:hidden;
  box-shadow:0 30px 70px rgba(4,20,40,.5);
  border:1px solid rgba(255,255,255,.22);
  animation:hs-float-main 8s ease-in-out infinite;
  will-change:transform;
}
.hs-card img{width:100%; height:100%; object-fit:cover; display:block}

/* Destination chips positioned around the card. Each drifts on its own
   timing, so they never line up into a single pulse. */
.hs-chip{
  position:absolute; z-index:4;
  display:flex; align-items:center; gap:9px;
  padding:9px 14px 9px 10px; border-radius:999px;
  background:rgba(255,255,255,.14);
  border:1px solid rgba(255,255,255,.3);
  backdrop-filter:blur(12px); -webkit-backdrop-filter:blur(12px);
  color:#fff; font-size:12.5px; font-weight:600; white-space:nowrap;
  box-shadow:0 10px 26px rgba(4,20,40,.3);
  will-change:transform;
}
/* Slightly larger, with a light edge and shadow — a small flag on a
   translucent chip over a dark gradient otherwise reads as a smudge. */
.hs-chip .flag-svg{
  width:30px; height:auto; flex-shrink:0;
  border:1px solid rgba(255,255,255,.55);
  box-shadow:0 2px 8px rgba(4,20,40,.45);
}

.hs-chip--1{top:6%;  left:-2%;  animation:hs-float-a 7s  ease-in-out infinite}
.hs-chip--2{top:26%; right:-4%; animation:hs-float-b 9s  ease-in-out infinite}
.hs-chip--3{bottom:26%; left:-6%; animation:hs-float-b 11s ease-in-out infinite reverse}
.hs-chip--4{bottom:8%; right:-2%; animation:hs-float-a 10s ease-in-out infinite reverse}

/* Glass status card */
.hs-status{
  position:absolute; z-index:5; bottom:2%; left:50%;
  transform:translateX(-50%);
  display:flex; align-items:center; gap:12px;
  padding:13px 18px; border-radius:16px;
  background:rgba(255,255,255,.96);
  box-shadow:0 20px 44px rgba(4,20,40,.36);
  animation:hs-float-status 12s ease-in-out infinite;
  will-change:transform;
}
.hs-status .hs-tick{
  width:36px; height:36px; border-radius:50%; flex-shrink:0;
  background:#5FE0B0; color:#06263F;
  display:flex; align-items:center; justify-content:center;
}
.hs-status .hs-line1{font-size:13.5px; font-weight:700; color:var(--brand-900); line-height:1.2}
.hs-status .hs-line2{font-size:11.5px; color:var(--ink-600); margin-top:2px}

@keyframes hs-float-main{
  0%,100%{transform:translate3d(0,0,0) rotate(0deg)}
  50%    {transform:translate3d(0,-16px,0) rotate(.7deg)}
}
@keyframes hs-float-a{
  0%,100%{transform:translate3d(0,0,0)}
  50%    {transform:translate3d(8px,-13px,0)}
}
@keyframes hs-float-b{
  0%,100%{transform:translate3d(0,0,0)}
  50%    {transform:translate3d(-9px,-15px,0)}
}
/* The status card is horizontally centred with a translate, so its
   keyframes have to carry that offset through or it jumps left. */
@keyframes hs-float-status{
  0%,100%{transform:translate3d(-50%,0,0)}
  50%    {transform:translate3d(-50%,-11px,0)}
}
@keyframes hs-pulse{
  0%,100%{transform:scale(1); opacity:.85}
  50%    {transform:scale(1.12); opacity:1}
}
@keyframes hs-rotate{
  from{transform:rotate(0deg)} to{transform:rotate(360deg)}
}

/* ==================================================================
   Hero -- Photo
   ------------------------------------------------------------------
   A full-width background photo behind the hero text, in place of
   the portrait card + orbiting flag chips. Animated with a slow,
   deliberately large zoom (scale 1 -> 1.14 over 22s) rather than a
   subtle one -- at this size and duration it reads as cinematic
   rather than as motion for its own sake.

   transform:scale() on a dedicated <img>, not an animated
   background-size -- the former is compositor-friendly and stays
   smooth; the latter forces layout recalculation on every frame.

   The scrim is a left-to-right gradient, not a flat overlay: darkest
   under the text column on the left (up to ~55% width, comfortably
   past .hero-grid--photo's 640px cap), lighter toward the right where
   the photo itself is the point. Contrast was checked by hand against
   a worst-case pure-white photo underneath -- 10:1 in the text zone,
   only dropping below AA well outside where any text sits.
   ================================================================== */
.hero-photo-frame{position:absolute; inset:0; z-index:0; overflow:hidden}
.hero-photo-img{
  width:100%; height:100%; object-fit:cover; display:block;
  transform:scale(1);
  animation:hero-photo-zoom 22s ease-in-out infinite alternate;
}
.hero-photo-scrim{
  position:absolute; inset:0;
  background:linear-gradient(90deg, rgba(6,20,38,.92) 0%, rgba(6,20,38,.8) 55%, rgba(6,20,38,.45) 100%);
}
@keyframes hero-photo-zoom{
  from{transform:scale(1)}
  to{transform:scale(1.14)}
}
@media (prefers-reduced-motion: reduce){
  .hero-photo-img{animation:none}
}

/* Text left, cut-out figure right. */
.hero-grid--photo{grid-template-columns:1.05fr .95fr; align-items:center}

/* ------------------------------------------------------------------
   The cut-out figure and its circle
   ------------------------------------------------------------------
   --orb is the circle's diameter; --rise is how much room the image
   gets above it. The wrapper is exactly those two added together and
   clips, which is the whole trick: its bottom edge coincides with the
   bottom of the circle, so an image taller than the circle is cut off
   level with the base of the disc instead of hanging below it, while
   the top --rise pixels stay free for the head and shoulders to break
   out above the rim.

   Both values are clamped rather than fixed so the composition scales
   with the viewport instead of needing a breakpoint per size.
   ------------------------------------------------------------------ */
.hero-figure{
  --orb:clamp(230px, 26vw, 360px);
  --rise:clamp(56px, 7vw, 104px);
  /* How far the image is pushed past the bottom of the circle. That
     overhang is masked away, which is the point: a cut-out PNG usually
     ends in a hard straight edge at the waist or knees, and this buries
     that edge below the disc instead of leaving it hanging in mid-air. */
  --sink:clamp(28px, 4vw, 60px);

  position:relative;
  height:calc(var(--orb) + var(--rise));
  overflow:hidden;
}

/* Glass, not a solid disc — the background photo reads straight through
   it, only blurred and lifted a little.

   The ring matters more than it looks: the figure's lower body is cut
   along this circle's edge, and with a fully transparent fill the ring
   is the only thing explaining that cut. Without it the body would just
   appear to stop for no visible reason.

   box-sizing is border-box globally, so the 1px ring sits inside --orb
   and the circle stays exactly the diameter the cut-out mask is
   calculated against. */
.hero-orb{
  position:absolute; bottom:0; left:50%;
  width:var(--orb); height:var(--orb);
  margin-left:calc(var(--orb) / -2);
  border-radius:50%;
  background:
    radial-gradient(circle at 32% 26%, rgba(255,255,255,.20), transparent 62%),
    rgba(255,255,255,.08);
  border:1px solid rgba(255,255,255,.30);
  backdrop-filter:blur(7px) saturate(115%);
  -webkit-backdrop-filter:blur(7px) saturate(115%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.28),
    0 24px 60px -22px rgba(4,20,40,.5);
}

/* ------------------------------------------------------------------
   The mask: everything above the circle's centre, plus the disc.
   ------------------------------------------------------------------
   Two mask layers, which the browser composites as a union. Above the
   circle's midpoint the first layer is fully opaque, so head and
   shoulders show at their true width — free to be wider than the disc
   and to rise above it. Below that midpoint only the disc is opaque,
   so the body narrows along the circle's curve and is gone by the time
   it reaches the base. Nothing is cut off in a straight line, which is
   what a single overflow:hidden box would have done.

   The mask sits on this wrapper, not the image, because its geometry
   is expressed against the circle. The wrapper fills .hero-figure, and
   the circle is centred in both, so "50%" lines them up whatever the
   uploaded image turns out to be.
   ------------------------------------------------------------------ */
.hero-cutout-wrap{
  position:absolute; inset:0; z-index:1;
  display:block;

  --mask-rect:linear-gradient(#000, #000);
  --mask-disc:radial-gradient(
      circle calc(var(--orb) / 2) at 50% calc(var(--rise) + var(--orb) / 2),
      #000 99%, transparent 100%);

  -webkit-mask-image:var(--mask-rect), var(--mask-disc);
          mask-image:var(--mask-rect), var(--mask-disc);
  -webkit-mask-size:100% calc(var(--rise) + var(--orb) / 2), 100% 100%;
          mask-size:100% calc(var(--rise) + var(--orb) / 2), 100% 100%;
  -webkit-mask-position:left top, left top;
          mask-position:left top, left top;
  -webkit-mask-repeat:no-repeat, no-repeat;
          mask-repeat:no-repeat, no-repeat;
}

.hero-cutout{
  position:absolute; left:0; right:0;
  /* Pushed below the disc by --sink; the height grows by the same
     amount so the top edge stays put and the rise above the circle is
     unaffected by how much is buried at the bottom. */
  bottom:calc(var(--sink) * -1);
  height:calc(100% + var(--sink));
  width:100%;

  /* contain + a bottom anchor rather than width:auto. An SVG without an
     intrinsic aspect ratio stretches to its container under width:auto,
     and the bundled fallback illustration is exactly that; contain
     derives the ratio from the rendered content instead, so a portrait
     PNG, a square one and the fallback all sit correctly without the
     rule needing to know which it got. */
  object-fit:contain;
  object-position:center bottom;

  display:block;
  filter:drop-shadow(0 18px 30px rgba(4,20,40,.45));
}

@media (max-width: 1080px){
  /* Stacked: the figure goes under the text, still centred on its
     circle, just smaller so it doesn't push the buttons off-screen. */
  .hero-grid--photo{grid-template-columns:1fr}
  .hero-figure{--orb:clamp(190px, 44vw, 260px); --rise:clamp(40px, 9vw, 72px); margin-top:26px}
}

@media (max-width: 900px){
  /* On a narrow screen the whole viewport is roughly the text column
     anyway, so the gradient needs to stay dark all the way across —
     the lighter right-hand zone above only makes sense with room for
     the photo to breathe beside the text. */
  .hero-photo-scrim{background:rgba(6,20,38,.82)}
}

/* ==================================================================
   Hero stage -- Festive
   ------------------------------------------------------------------
   The same big hero photo as Standard, gold-framed, with the occasion
   medal overlapping its top-left corner -- same top:8%; left:0
   positioning as the About page's .av-badge over .av-card, reused
   deliberately rather than inventing new offsets I have no way to
   check against a live render this session. Sparks drift around the
   frame; destination stamps sit below it.

   The medal's text sits on a FLAT gold (#F5B43C), not a gradient -- a
   soft highlight is layered in via a separate radial that fades out
   before it reaches the text, so the 7.6:1 contrast measured against
   the flat colour holds regardless of where the highlight falls.
   ================================================================== */
.hero-stage--festive{flex-direction:column; gap:26px}

.hsf-glow{
  position:absolute; z-index:0; width:440px; height:440px; border-radius:50%;
  background:radial-gradient(circle, rgba(245,180,60,.34), rgba(245,180,60,0) 68%);
  animation:hs-pulse 9s ease-in-out infinite;
  pointer-events:none;
}

.hsf-sparks{position:absolute; inset:0; z-index:1; pointer-events:none}
.hsf-sparks i{
  position:absolute; width:6px; height:6px; border-radius:50%;
  background:#F5B43C; opacity:.8; font-style:normal;
  animation:hsf-drift 6s ease-in-out infinite;
}
.hsf-sparks i:nth-child(1){top:10%; left:16%; animation-delay:0s}
.hsf-sparks i:nth-child(2){top:20%; left:80%; animation-delay:.8s; background:var(--cyan-500)}
.hsf-sparks i:nth-child(3){top:48%; left:6%;  animation-delay:1.6s}
.hsf-sparks i:nth-child(4){top:64%; left:88%; animation-delay:2.4s; background:var(--cyan-500)}
.hsf-sparks i:nth-child(5){top:80%; left:26%; animation-delay:3.2s}
.hsf-sparks i:nth-child(6){top:6%;  left:50%; animation-delay:4s;   background:var(--cyan-500)}
@keyframes hsf-drift{
  0%,100%{transform:translate3d(0,0,0); opacity:.5}
  50%{transform:translate3d(0,-14px,0); opacity:1}
}

/* The photo, framed in gold rather than the plain white-ish edge the
   Standard card uses -- the frame colour is the one thing that ties
   the photo back to the medal and stamps around it. */
.hsf-card{
  position:relative; z-index:2;
  width:min(340px, 74%); aspect-ratio:10/13;
  border-radius:26px; overflow:hidden;
  box-shadow:0 30px 70px rgba(4,20,40,.5);
  border:3px solid #F5B43C;
  animation:hs-float-main 8s ease-in-out infinite;
  will-change:transform;
}
.hsf-card img{width:100%; height:100%; object-fit:cover; display:block}

/* Overlapping badge, positioned exactly like .av-badge on the About
   page, at a fraction of its size since it's an accent here rather
   than the sole focal point. */
.hsf-medal{
  position:absolute; z-index:4; top:8%; left:-6%;
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:6px;
  width:132px; height:132px; border-radius:50%;
  background:radial-gradient(circle at 30% 22%, rgba(255,255,255,.24), rgba(255,255,255,0) 42%), #F5B43C;
  box-shadow:0 20px 40px rgba(201,122,31,.4), inset 0 0 0 4px rgba(255,255,255,.16);
  padding:14px; text-align:center;
  animation:hsf-float 7s ease-in-out infinite;
}
.hsf-medal-icon{color:#3F2508; opacity:.85}
.hsf-medal-text{
  font-family:'Fraunces',serif; font-size:12.5px; font-weight:700; line-height:1.2;
  color:#3F2508;
  display:-webkit-box; -webkit-line-clamp:3; -webkit-box-orient:vertical; overflow:hidden;
}
@keyframes hsf-float{
  0%,100%{transform:translate3d(0,0,0)}
  50%{transform:translate3d(0,-10px,0)}
}

.hsf-stamps{position:relative; z-index:2; display:flex; flex-wrap:wrap; justify-content:center; gap:10px; max-width:340px}
.hsf-stamp{
  display:inline-flex; align-items:center; gap:7px;
  padding:8px 13px 8px 9px; border-radius:999px;
  background:rgba(255,255,255,.1); border:1px dashed rgba(255,255,255,.35);
  color:#fff; font-size:12.5px; font-weight:600;
  backdrop-filter:blur(6px); -webkit-backdrop-filter:blur(6px);
}
.hsf-stamp .flag-svg{width:20px; height:auto; border-radius:3px; flex-shrink:0}

/* ==================================================================
   Hero stage -- Spotlight
   ------------------------------------------------------------------
   The same big hero photo as Standard, with the urgent panel tucked
   into its bottom edge -- both sit in normal flow (the panel pulled
   up by a fixed negative margin, not absolute-positioned at a
   computed corner), which is deliberately the more robust choice
   given this couldn't be checked against a live render this session.
   The panel still carries its own headline and call to action, so the
   "act now" framing reaches something clickable, not just a badge.
   ================================================================== */
.hero-stage--spotlight{flex-direction:column}

.hss-glow{
  position:absolute; z-index:0; width:440px; height:440px; border-radius:50%;
  background:radial-gradient(circle, rgba(41,172,227,.4), rgba(41,172,227,0) 68%);
  animation:hs-pulse 9s ease-in-out infinite;
  pointer-events:none;
}

.hss-card{
  position:relative; z-index:1;
  width:min(340px, 74%); aspect-ratio:10/13;
  border-radius:26px; overflow:hidden;
  box-shadow:0 30px 70px rgba(4,20,40,.5);
  border:1px solid rgba(255,255,255,.22);
  animation:hs-float-main 8s ease-in-out infinite;
  will-change:transform;
}
.hss-card img{width:100%; height:100%; object-fit:cover; display:block}

.hss-panel{
  position:relative; z-index:2;
  width:min(320px, 88%);
  margin-top:-40px;
  padding:26px 24px;
  border-radius:20px;
  background:linear-gradient(165deg, rgba(13,32,58,.92), rgba(13,32,58,.86));
  border:1px solid rgba(255,255,255,.16);
  backdrop-filter:blur(10px); -webkit-backdrop-filter:blur(10px);
  box-shadow:0 24px 50px rgba(4,20,40,.5);
  text-align:center;
}
.hss-live{
  display:inline-flex; align-items:center; gap:8px;
  padding:6px 14px; border-radius:999px;
  background:rgba(41,172,227,.16); border:1px solid rgba(41,172,227,.4);
  color:#BFE7FA; font-size:11.5px; font-weight:700; letter-spacing:.08em; text-transform:uppercase;
  margin-bottom:16px;
}
.hss-dot{
  width:7px; height:7px; border-radius:50%; background:var(--cyan-500);
  box-shadow:0 0 0 0 rgba(41,172,227,.6);
  animation:hero-badge-pulse 2.2s ease-in-out infinite;
}
.hss-headline{
  font-family:'Fraunces',serif; font-size:23px; font-weight:700; line-height:1.28;
  color:#fff; margin:0 0 20px;
}
.hss-flags{display:flex; justify-content:center; flex-wrap:wrap; gap:9px; margin-bottom:24px}
.hss-flag{
  display:flex; padding:5px; border-radius:8px;
  background:rgba(255,255,255,.08); border:1px solid rgba(255,255,255,.14);
}
.hss-flag .flag-svg{width:24px; height:auto; display:block}
.hss-cta{width:100%; justify-content:center}

@media (prefers-reduced-motion: reduce){
  .hsf-sparks i, .hsf-medal, .hsf-glow, .hsf-card,
  .hss-dot, .hss-glow, .hss-card{animation:none}
}

@media (max-width: 1080px){
  .hero-stage{min-height:500px; margin-top:30px}
  .hs-glow, .hs-orbit{width:370px; height:370px}
  .hs-card, .hsf-card, .hss-card{width:min(260px, 62%)}
  .hs-chip{font-size:11.5px; padding:8px 12px 8px 9px}
  .hs-chip .flag-svg{width:26px}

  .hsf-glow, .hss-glow{width:340px; height:340px}
  .hsf-medal{width:104px; height:104px; padding:10px; top:6%; left:-8%}
  .hsf-medal-text{font-size:10.5px}
  .hss-panel{margin-top:-32px; padding:22px 20px}
}
@media (max-width: 560px){
  .hero-stage{min-height:420px}
  .hs-orbit{display:none}
  .hs-chip--2, .hs-chip--3{display:none}
  .hs-chip--1{left:-1%}
  .hs-chip--4{right:-1%}
  .hs-status{padding:11px 14px}
  .hs-card, .hsf-card, .hss-card{width:min(220px, 58%)}

  /* Sparks are the first thing to go on a small phone -- purely
     decorative, and six drifting dots add visual noise at this size
     without adding anything the medal, photo and stamps don't already
     say. */
  .hsf-sparks{display:none}
  .hsf-medal{width:88px; height:88px; padding:8px; gap:3px; left:-10%}
  .hsf-medal-icon svg{width:16px; height:16px}
  .hsf-medal-text{font-size:9px; -webkit-line-clamp:2}
  .hss-panel{margin-top:-26px; padding:18px 16px}
  .hss-headline{font-size:18px}
}

/* ==================================================================
   About: floating image composition
   ------------------------------------------------------------------
   A layered stack — a tall primary card, a smaller secondary card
   overlapping its lower-left, an experience badge on the upper-left,
   and decorative shapes behind everything.

   The motion is built from three independent drifts running at
   different durations (7s / 9s / 11s). Because those don't divide into
   one another, the layers never resynchronise into a single visible
   pulse — the composition keeps breathing rather than bobbing in time.

   Only transform is animated, so none of this touches layout while it
   runs.
   ================================================================== */
.about-visual{
  position:relative;
  min-height:560px;
  display:flex; align-items:center; justify-content:center;
  perspective:1200px;
}

/* Decorative shapes sit furthest back */
.av-blob{
  position:absolute; border-radius:50%; pointer-events:none; z-index:0;
  filter:blur(2px);
}
.av-blob--one{
  width:280px; height:280px; top:-10px; right:6%;
  background:radial-gradient(circle at 35% 30%, rgba(41,172,227,.42), rgba(41,172,227,0) 68%);
  animation:av-drift-slow 11s ease-in-out infinite;
}
.av-blob--two{
  width:220px; height:220px; bottom:8%; left:2%;
  background:radial-gradient(circle at 60% 40%, rgba(18,86,158,.30), rgba(18,86,158,0) 70%);
  animation:av-drift-slow 9s ease-in-out infinite reverse;
}
.av-dots{
  position:absolute; z-index:0; width:132px; height:132px;
  right:2%; bottom:12%;
  background-image:radial-gradient(var(--brand-600) 1.6px, transparent 1.6px);
  background-size:16px 16px; opacity:.28;
  animation:av-drift-slow 13s ease-in-out infinite;
}
.av-ring{
  position:absolute; z-index:0; width:96px; height:96px; left:6%; top:12%;
  border:2px dashed var(--cyan-500); border-radius:50%; opacity:.4;
  animation:av-spin 26s linear infinite;
}

/* Primary card */
.av-card{
  position:relative; z-index:2;
  width:min(340px, 78%); aspect-ratio:5/6;
  border-radius:26px; overflow:hidden;
  box-shadow:0 28px 60px rgba(13,66,120,.30);
  animation:av-float-a 7s ease-in-out infinite;
  will-change:transform;
}
.av-card img{width:100%; height:100%; object-fit:cover; display:block}

/* Secondary card, overlapping the primary's lower-left */
.av-card--sub{
  position:absolute; z-index:3;
  left:2%; bottom:6%;
  width:min(210px, 46%); aspect-ratio:4/3;
  border-radius:18px; overflow:hidden;
  border:5px solid var(--surface);
  box-shadow:0 18px 40px rgba(13,66,120,.26);
  animation:av-float-b 9s ease-in-out infinite;
  will-change:transform;
}

/* Experience badge */
.av-badge{
  position:absolute; z-index:4; top:8%; left:0;
  background:var(--surface); border-radius:16px;
  padding:16px 20px; text-align:center; min-width:132px;
  box-shadow:0 16px 38px rgba(13,66,120,.22);
  border:1px solid var(--brand-100);
  animation:av-float-c 11s ease-in-out infinite;
  will-change:transform;
}
.av-badge .av-num{
  font-family:'Fraunces', Georgia, serif; font-size:34px; font-weight:700;
  color:var(--brand-700); line-height:1;
}
.av-badge .av-label{
  font-size:11px; text-transform:uppercase; letter-spacing:.06em;
  color:var(--ink-600); font-weight:700; margin-top:5px;
}

/* Floating chip on the right edge */
.av-chip{
  position:absolute; z-index:4; right:0; top:38%;
  background:var(--brand-700); color:#fff;
  border-radius:14px; padding:12px 16px;
  display:flex; align-items:center; gap:10px;
  font-size:12.5px; font-weight:600; white-space:nowrap;
  box-shadow:0 16px 34px rgba(13,66,120,.32);
  animation:av-float-b 8s ease-in-out infinite reverse;
}
.av-chip svg{color:var(--cyan-500); flex-shrink:0}

@keyframes av-float-a{
  0%,100%{transform:translate3d(0,0,0) rotate(0deg)}
  50%    {transform:translate3d(0,-18px,0) rotate(-.6deg)}
}
@keyframes av-float-b{
  0%,100%{transform:translate3d(0,0,0)}
  50%    {transform:translate3d(6px,-14px,0)}
}
@keyframes av-float-c{
  0%,100%{transform:translate3d(0,0,0)}
  50%    {transform:translate3d(-7px,-11px,0)}
}
@keyframes av-drift-slow{
  0%,100%{transform:translate3d(0,0,0) scale(1)}
  50%    {transform:translate3d(14px,-16px,0) scale(1.05)}
}
@keyframes av-spin{
  from{transform:rotate(0deg)} to{transform:rotate(360deg)}
}

/* Mouse parallax — the JS writes --px/--py, and each layer moves by a
   different multiple so the stack gains depth as the pointer moves. */
@media (hover: hover) and (pointer: fine){
  .about-visual .av-card  {transform:translate3d(calc(var(--px,0) * 8px),  calc(var(--py,0) * 8px),  0)}
  .about-visual .av-card--sub{transform:translate3d(calc(var(--px,0) * 18px), calc(var(--py,0) * 18px), 0)}
  .about-visual .av-badge {transform:translate3d(calc(var(--px,0) * 26px), calc(var(--py,0) * 26px), 0)}
  .about-visual .av-chip  {transform:translate3d(calc(var(--px,0) * 22px), calc(var(--py,0) * 22px), 0)}

  /* While the pointer is over the composition, the parallax transform
     takes over and the idle float pauses — running both would fight
     over the same property. */
  .about-visual.is-tracking .av-card,
  .about-visual.is-tracking .av-card--sub,
  .about-visual.is-tracking .av-badge,
  .about-visual.is-tracking .av-chip{
    animation-play-state:paused;
    transition:transform .35s var(--ease-out);
  }
  .about-visual:not(.is-tracking) .av-card,
  .about-visual:not(.is-tracking) .av-card--sub,
  .about-visual:not(.is-tracking) .av-badge,
  .about-visual:not(.is-tracking) .av-chip{transform:none}
}

@media (max-width: 900px){
  .about-visual{min-height:440px; margin-top:36px}
  .av-card{width:min(280px, 70%)}
  .av-card--sub{width:min(170px, 44%); left:0}
  .av-badge{padding:13px 16px; min-width:114px}
  .av-badge .av-num{font-size:28px}
  .av-chip{font-size:11.5px; padding:10px 13px}
}
@media (max-width: 560px){
  .about-visual{min-height:380px}
  .av-chip{display:none}
  .av-dots{display:none}
}

/* ---------------- Mission / vision / values ---------------- */
.value-card{
  background:var(--surface); border:1px solid var(--border);
  border-radius:var(--radius-lg); padding:30px 26px; position:relative;
  transition:transform .28s var(--ease-out), box-shadow .28s var(--ease-out), border-color .28s ease;
}
.value-card:hover{transform:translateY(-5px); box-shadow:var(--shadow-lift); border-color:var(--brand-100)}
.value-card .vc-icon{
  width:52px; height:52px; border-radius:15px; margin-bottom:18px;
  background:linear-gradient(145deg, var(--brand-700), var(--cyan-500));
  color:#fff; display:flex; align-items:center; justify-content:center;
  box-shadow:0 8px 20px rgba(18,86,158,.28);
}
.value-card h3{font-size:18px; margin-bottom:10px}
.value-card p{font-size:14px; color:var(--ink-600); line-height:1.75; margin:0}
.value-card .vc-num{
  position:absolute; top:22px; right:24px;
  font-family:'Fraunces', Georgia, serif; font-size:40px; font-weight:700;
  color:var(--brand-050); line-height:1; pointer-events:none;
}

/* ---------------- Team ---------------- */
.team-card{
  background:var(--surface); border:1px solid var(--border); border-radius:var(--radius-lg);
  padding:30px 26px; text-align:center;
  transition:transform .25s var(--ease-out), box-shadow .25s var(--ease-out), border-color .25s ease;
}
.team-card:hover{transform:translateY(-4px); box-shadow:var(--shadow-lift); border-color:var(--brand-100)}

.team-photo{
  width:120px; height:120px; margin:0 auto 18px; border-radius:50%;
  overflow:hidden; position:relative;
  background:linear-gradient(145deg, var(--brand-700), var(--cyan-500));
  display:flex; align-items:center; justify-content:center;
  box-shadow:0 6px 20px rgba(13,66,120,.22);
}
.team-photo img{width:100%; height:100%; object-fit:cover}
.team-initials{
  font-family:'Fraunces', Georgia, serif; font-size:38px; font-weight:700;
  color:#fff; letter-spacing:.02em;
}

.team-name{font-size:18px; margin:0 0 4px}
.team-role{font-size:13px; font-weight:600; color:var(--brand-700); margin:0 0 12px}
.team-tags{display:flex; gap:6px; flex-wrap:wrap; justify-content:center; margin-bottom:14px}
.team-tags span{
  background:var(--brand-050); color:var(--brand-700);
  font-size:11px; font-weight:700; padding:4px 10px; border-radius:999px;
}
.team-bio{font-size:13.5px; color:var(--ink-600); line-height:1.7; margin:0 0 16px}

.team-meta{display:grid; gap:9px; margin:0 0 16px; text-align:left}
.team-meta dt{
  font-size:10.5px; text-transform:uppercase; letter-spacing:.05em;
  color:var(--ink-300); font-weight:700;
}
.team-meta dd{margin:2px 0 0; font-size:13px; color:var(--ink-600)}

.team-contact{display:flex; gap:9px; justify-content:center; padding-top:14px; border-top:1px solid var(--border)}
.team-contact a{
  width:36px; height:36px; border-radius:50%; display:flex; align-items:center; justify-content:center;
  background:var(--brand-050); color:var(--brand-700); text-decoration:none;
  font-size:13px; font-weight:700; transition:background-color .2s ease, color .2s ease;
}
.team-contact a:hover{background:var(--brand-700); color:#fff}

.team-card--compact{padding:24px 20px}
.team-card--compact .team-photo{width:104px; height:104px; margin-bottom:14px}
.team-card--compact .team-initials{font-size:32px}
.team-card--compact .team-name{font-size:16px}

/* ---------------- Google reviews ---------------- */
.reviews-band{background:var(--surface); border-top:1px solid var(--border); border-bottom:1px solid var(--border)}
.review-summary{
  display:flex; align-items:center; gap:26px; flex-wrap:wrap; justify-content:center;
  background:linear-gradient(140deg, var(--brand-050), #fff);
  border:1px solid var(--brand-100); border-radius:var(--radius-lg);
  padding:26px 32px; margin:0 auto 38px; max-width:760px;
}
.review-score{text-align:center}
.review-score .score{
  font-family:'Fraunces',serif; font-size:46px; font-weight:700;
  color:var(--brand-900); line-height:1;
}
.review-score .count{font-size:12.5px; color:var(--ink-600); margin-top:6px}
.stars{display:inline-flex; gap:3px; margin-top:7px; color:#F5A623}
.stars svg{fill:currentColor; stroke:none}
.review-summary .g-logo{display:flex; align-items:center; gap:9px; font-size:14px; font-weight:600; color:var(--ink-900)}
.review-divider{width:1px; align-self:stretch; background:var(--brand-100)}

.review-card{
  background:var(--surface); border:1px solid var(--border); border-radius:var(--radius-lg);
  padding:24px; display:flex; flex-direction:column; gap:12px;
  transition:transform .25s var(--ease-out), box-shadow .25s var(--ease-out);
}
.review-card:hover{transform:translateY(-3px); box-shadow:var(--shadow-lift)}
.review-card .rc-head{display:flex; align-items:center; gap:12px}
.review-card .rc-avatar{
  width:44px; height:44px; border-radius:50%; object-fit:cover; flex-shrink:0;
  background:var(--brand-050); color:var(--brand-700);
  display:flex; align-items:center; justify-content:center; font-weight:700; font-size:16px;
}
.review-card .rc-name{font-weight:700; font-size:14.5px}
.review-card .rc-sub{font-size:12px; color:var(--ink-600)}
.review-card .rc-text{font-size:14px; color:var(--ink-600); line-height:1.7; margin:0}


/* ==================================================================
   Modern refinements
   ------------------------------------------------------------------
   Applies the token scale above to the components. Everything here is
   a refinement of what already existed — no new components — so the
   layout is unchanged and only the finish moves.
   ================================================================== */

/* ---- Fluid type ---- */
.hero h1{font-size:var(--step-hero); letter-spacing:-.02em}
.page-banner h1{font-size:var(--step-h1); letter-spacing:-.015em}
.section-head h2, .prose h2{font-size:var(--step-h2); letter-spacing:-.01em}
.prose h3{font-size:var(--step-h3)}
.hero p.lede, .page-banner p{font-size:var(--step-lede)}
body.site-body{font-size:var(--step-body)}

/* Optical tightening: display faces look loose at large sizes and
   cramped at small ones, so headings tighten as they grow. */
h1, h2{text-wrap:balance}
p.lede, .section-head p{text-wrap:pretty}

.section{padding:var(--section-y) 0}

/* Two plain sections in a row would otherwise stack a full bottom
   padding on top of a full top padding, making that gap twice the size
   of the one before it. Most sections carry an inline padding-top:0 to
   avoid this, but a few were missed — Destinations and Services sat in
   153px of space while their neighbours sat in 77px. Handling it here
   means it holds for any section added later without remembering the
   inline style. */
.section + .section{padding-top:0}

/* Sections with a background of their own are the exception: that top
   padding is the inside of the coloured band, not a gap between two
   things. Removing it would print the heading hard against the band's
   top edge. Two classes, so this wins over the rule above. */
.section.journey,
.section.about-band,
.section.reviews-band{padding-top:var(--section-y)}

/* ---- Buttons ---- */
.btn{
  transition:background-color var(--dur-base) var(--ease-out),
             border-color var(--dur-base) var(--ease-out),
             color var(--dur-base) var(--ease-out),
             transform var(--dur-fast) var(--ease-out),
             box-shadow var(--dur-base) var(--ease-out);
  position:relative;
}
.btn-primary{box-shadow:var(--elev-2)}
.btn-primary:hover{box-shadow:var(--elev-3); transform:translateY(-1px)}
.btn-primary:active{transform:translateY(0); box-shadow:var(--elev-1)}
.btn-gold{box-shadow:0 2px 4px rgba(41,172,227,.2), 0 8px 20px rgba(41,172,227,.28)}
.btn-gold:hover{box-shadow:0 4px 8px rgba(41,172,227,.24), 0 14px 30px rgba(41,172,227,.34); transform:translateY(-1px)}
.btn-gold:active{transform:translateY(0)}
.btn-outline:hover{background:var(--brand-050); transform:translateY(-1px)}
.btn:focus-visible{outline:none; box-shadow:var(--ring)}

/* ---- Cards: one elevation language ---- */
.service-card, .testimonial-card, .post-card, .dest-card,
.sidebar-card, .review-card, .team-card, .value-card{
  box-shadow:var(--elev-1);
  transition:transform var(--dur-slow) var(--ease-out),
             box-shadow var(--dur-slow) var(--ease-out),
             border-color var(--dur-base) var(--ease-out);
}
.testimonial-card:hover, .post-card:hover,
.dest-card:hover, .review-card:hover, .team-card:hover, .value-card:hover{
  box-shadow:var(--elev-3);
  border-color:var(--brand-100);
}
.dest-tile{box-shadow:var(--elev-3)}
.dest-tile:hover{box-shadow:var(--elev-5)}
.story-tile{box-shadow:var(--elev-3)}
.story-tile:hover, .story-tile:focus-visible{box-shadow:var(--elev-5)}

/* Radii nudged up a step — larger corners read as more current, and
   they pair with the softer shadows. */
.service-card, .testimonial-card, .review-card, .value-card, .team-card{border-radius:var(--radius-lg)}
.post-card, .dest-card{border-radius:var(--radius-xl)}
.sidebar-card{border-radius:var(--radius-lg)}

/* ---- Forms ---- */
.site-form input, .site-form select, .site-form textarea,
.public-filters input, .public-filters select{
  border-radius:var(--radius-sm);
  transition:border-color var(--dur-base) var(--ease-out),
             box-shadow var(--dur-base) var(--ease-out),
             background-color var(--dur-base) var(--ease-out);
}
.site-form input:hover, .site-form select:hover, .site-form textarea:hover{border-color:var(--brand-100)}
.site-form input:focus, .site-form select:focus, .site-form textarea:focus,
.public-filters input:focus, .public-filters select:focus{
  outline:none;
  border-color:var(--cyan-500);
  box-shadow:var(--ring);
  background:var(--surface);
}
.site-form label{font-size:13.5px; letter-spacing:.005em}

/* Invalid only after the visitor has actually typed something —
   colouring an untouched required field red is scolding, not helping. */
.site-form input:not(:placeholder-shown):invalid{border-color:#E5A0A0}

/* ---- Focus visible, everywhere ---- */
a:focus-visible, button:focus-visible,
summary:focus-visible, [tabindex]:focus-visible{
  outline:none;
  box-shadow:var(--ring-offset), var(--ring);
  border-radius:var(--radius-sm);
}

/* ---- Links in prose ---- */
.prose a{
  text-decoration:underline;
  text-decoration-color:rgba(41,172,227,.45);
  text-underline-offset:3px;
  text-decoration-thickness:1.5px;
  transition:text-decoration-color var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out);
}
.prose a:hover{text-decoration-color:var(--cyan-500); color:var(--brand-900)}

/* ---- Nav polish ---- */
.dropdown{
  border-radius:var(--radius-md);
  box-shadow:var(--elev-4);
  transition:opacity var(--dur-fast) var(--ease-out),
             visibility var(--dur-fast),
             transform var(--dur-base) var(--ease-spring);
}
.nav-links > li > a{transition:background-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out)}

/* ---- Tag pills ---- */
.tag-pill{transition:background-color var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out), transform var(--dur-fast) var(--ease-out)}
a.tag-pill:hover{transform:translateY(-1px)}

/* ---- Section heads ---- */
.eyebrow{
  display:inline-flex; align-items:center; gap:8px;
  font-size:12px; letter-spacing:.1em;
}
/* A short rule before the eyebrow anchors it to the section rather
   than leaving it floating above the heading. */
.section-head .eyebrow::before{
  content:''; width:22px; height:2px; border-radius:2px;
  background:var(--cyan-500); flex-shrink:0;
}
.hero .eyebrow::before, .page-banner .eyebrow::before{background:rgba(255,255,255,.6)}

/* ---- Footer ---- */
.site-footer{
  background:
    radial-gradient(900px 400px at 12% -30%, rgba(41,172,227,.16), transparent 62%),
    var(--brand-900);
}
.footer-grid a{transition:color var(--dur-fast) var(--ease-out), padding-left var(--dur-fast) var(--ease-out)}
.footer-grid li > a:hover{padding-left:4px}
.social-row a{transition:background-color var(--dur-base) var(--ease-out), transform var(--dur-fast) var(--ease-out)}
.social-row a:hover{background:var(--cyan-500); transform:translateY(-2px)}

/* ---- Selection ---- */
::selection{background:var(--cyan-500); color:#06263F}

/* ---- Scrollbar (desktop) ---- */
@media (min-width: 901px){
  html{scrollbar-color:var(--brand-100) transparent; scrollbar-width:thin}
  ::-webkit-scrollbar{width:11px}
  ::-webkit-scrollbar-track{background:transparent}
  ::-webkit-scrollbar-thumb{background:var(--brand-100); border-radius:99px; border:3px solid var(--paper)}
  ::-webkit-scrollbar-thumb:hover{background:var(--brand-600)}
}

/* ---------------- Responsive ---------------- */
@media (max-width: 900px){
  .hero-grid,.about-grid,.local-block{grid-template-columns:1fr}
  .grid-4{grid-template-columns:repeat(2,1fr)}
  .grid-3{grid-template-columns:repeat(2,1fr)}
  .footer-grid{grid-template-columns:1fr 1fr}
  /* Below the collapse point the wave becomes a plain stack -- a
     left-to-right curve has no meaning in a single column, and forcing
     it would either flatten to nothing or read as random jitter.
     Specificity here matches the base .journey-step--up/--down rules
     on purpose, so this reliably wins the cascade rather than losing a
     specificity tie to them despite being the later, narrower-viewport
     rule. */
  .journey-path{grid-template-columns:1fr; gap:28px; margin-top:36px; padding-bottom:0}
  .journey-curve{display:none}
  .journey-step--up, .journey-step--down{transform:none}
  .reveal-ready .journey-step--up[data-reveal],
  .reveal-ready .journey-step--down[data-reveal]{
    opacity:0; transform:translateY(24px);
    transition:opacity .5s var(--ease-out), transform .5s var(--ease-out);
  }
  .reveal-ready .journey-step--up[data-reveal].is-visible,
  .reveal-ready .journey-step--down[data-reveal].is-visible{opacity:1; transform:none}
  .content-with-sidebar{grid-template-columns:1fr; gap:32px}
  .announcement-bar .container{padding-right:44px; font-size:12.5px}
  .page-banner h1{font-size:28px}
  .hero h1{font-size:32px}
  /* Adjacent taps need clear separation on a phone. */
  .hero-actions, .cta-actions{gap:12px}
  .nav-links > li > a{min-height:48px; display:flex; align-items:center}

  /* Mobile navigation styles live in the 1080px block below. */
}
@media (max-width: 560px){
  .grid-4,.grid-3,.grid-2{grid-template-columns:1fr}
  .footer-grid{grid-template-columns:1fr}
  .cta-band{padding:32px 20px}
  /* .section padding is deliberately not set here. It used to be a flat
     48px, which overrode --section-y and made small screens roomier
     than the tightened desktop rhythm rather than tighter. The token's
     own 38px floor covers this width. */
  .floating-contact{right:14px; bottom:14px}
  .floating-contact a{width:46px; height:46px; font-size:19px}
  .cookie-notice{left:10px; right:10px; bottom:10px; padding:14px 16px}
}

/* ------------------------------------------------------------------
   Navigation collapse point — 1080px, not the 900px used for the rest
   of the layout.

   The nav has nine links plus a phone number and a CTA. Somewhere
   around 1100px that stops fitting beside the logo, and the old 900px
   breakpoint let it wrap onto a second row in the gap between. Moving
   the collapse up means the desktop bar is always exactly one line.
   ------------------------------------------------------------------ */
/* The phone number is deliberately absent from the desktop bar. It was
   competing with the "Free Consultation" button for the same job while
   taking space the nine nav links needed, and the number is already in
   the announcement bar, the footer and the floating call button. On
   mobile it stays as an icon-only tap target inside the drawer header,
   where tapping to call is the fastest possible action. */
@media (min-width: 1081px){
  .nav-phone{display:none}
}

@media (max-width: 1080px){
  .nav-toggle{display:flex}

  /* ----------------------------------------------------------------
     The drawer lives inside <header>, and two header properties were
     breaking it:

     1. backdrop-filter creates a CONTAINING BLOCK for position:fixed
        descendants. The drawer was therefore positioned against the
        header box rather than the viewport, so top:0/bottom:0 gave it
        the header's height (104px) instead of the screen's. Dropping
        the blur on mobile hands the drawer back to the viewport — and
        the blur was never doing much on a phone anyway.

     2. z-index:50 traps the drawer in the header's stacking context,
        so the floating call buttons (60), cookie notice (70) and popup
        notice (110) all painted over it. The header is lifted above
        them only while the drawer is open.
     ---------------------------------------------------------------- */
  .site-header{backdrop-filter:none; -webkit-backdrop-filter:none; background:var(--paper)}
  body.nav-open .site-header{z-index:130}

  /* The floating call/WhatsApp buttons would otherwise sit on top of
     the drawer panel. */
  body.nav-open .floating-contact{opacity:0; pointer-events:none}
  .floating-contact{transition:opacity .2s ease}

  /* Stop the page behind the drawer from scrolling. */
  body.nav-open{overflow:hidden}

  /* ----------------------------------------------------------------
     Mobile navigation: a drawer that slides in from the right.
     ----------------------------------------------------------------
     It's a fixed panel translated off-screen rather than display:none,
     because display can't be animated — the panel has to remain in the
     layout for the transform to have something to move. visibility is
     what keeps it out of the tab order while closed, and it's delayed
     until the slide-out finishes so focus doesn't vanish mid-animation.
     ---------------------------------------------------------------- */
  .nav-links{
    display:flex; position:fixed; top:0; right:0; bottom:0; left:auto;
    width:min(320px, 86vw); z-index:80;
    flex-direction:column; align-items:stretch; gap:0;
    background:var(--surface);
    padding:0 20px 28px; margin:0;
    box-shadow:-12px 0 40px rgba(13,66,120,.22);
    overflow-y:auto; -webkit-overflow-scrolling:touch;
    transform:translateX(100%);
    visibility:hidden;
    transition:transform .32s var(--ease-out), visibility 0s linear .32s;
  }
  /* Open state is driven from a class on <body> as well as on the list
     itself. Either alone is enough; both are listed so the drawer still
     opens if one of the two class toggles ever fails. */
  .nav-links.open,
  body.nav-open .nav-links{
    transform:translateX(0);
    visibility:visible;
    transition:transform .32s var(--ease-out), visibility 0s;
  }

  /* Dimmed backdrop; tapping it closes the drawer. */
  .nav-backdrop{
    position:fixed; inset:0; z-index:70;
    background:rgba(6,24,44,.5); backdrop-filter:blur(2px);
    opacity:0; visibility:hidden;
    transition:opacity .32s ease, visibility 0s linear .32s;
  }
  .nav-backdrop.show{opacity:1; visibility:visible; transition:opacity .32s ease, visibility 0s}

  /* ------------------------------------------------------------------
     Drawer header: sticky, not absolutely positioned.
     ------------------------------------------------------------------
     The close button used to be position:absolute inside a li with no
     real height (its only child was taken out of flow) — a normal-flow
     child of .nav-links, which is also the scrolling element. So the
     button scrolled away with the list on any drawer taller than the
     screen, taking the "Menu" label (then a ::before on .nav-links
     itself) with it.

     A sticky flex row fixes both: it has real height, stays pinned to
     the top of its own scrollport as the list scrolls underneath it,
     and the label now lives in real markup rather than generated
     content the accessibility tree may not expose consistently.
     ------------------------------------------------------------------ */
  .nav-drawer-head{
    position:sticky; top:0; z-index:5;
    display:flex; align-items:center; justify-content:space-between;
    /* Bleeds to the drawer's true edges, then restores the same inset
       with its own padding -- .nav-links keeps its side padding for
       every other row, so this is the one row that has to override it. */
    margin:0 -20px; padding:16px 20px;
    background:var(--surface);
    border-bottom:1px solid var(--border);
  }
  .nav-drawer-label{
    font-size:11px; font-weight:700; letter-spacing:.1em;
    text-transform:uppercase; color:var(--ink-300);
  }
  .nav-close{
    display:flex; flex:none;
    width:40px; height:40px; border-radius:50%; border:0; cursor:pointer;
    background:var(--brand-050); color:var(--brand-700);
    align-items:center; justify-content:center;
  }
  .nav-close:hover{background:var(--brand-100)}

  .nav-links > li{flex-shrink:0}
  .nav-links > li > a{
    padding:14px 6px; border-bottom:1px solid var(--border); border-radius:0;
    min-height:48px; font-size:15.5px; justify-content:space-between;
  }
  .nav-links > li > a.is-active::after{display:none}
  .nav-links > li > a.is-active{color:var(--brand-700); font-weight:700}
  .nav-links .caret{display:inline-flex; opacity:.6}

  .dropdown{
    position:static; opacity:1; visibility:visible; transform:none;
    box-shadow:none; border:0; border-radius:0; padding:0 0 8px 14px;
    display:none; min-width:0; background:transparent;
  }
  .nav-links > li.open .dropdown{display:block}
  .nav-links > li.open .caret{transform:rotate(180deg)}
  .dropdown a{padding:11px 10px; font-size:14px; min-height:44px}

  /* Call + book actions sit at the foot of the drawer, where a thumb
     naturally rests. */
  .nav-drawer-actions{
    display:flex; flex-direction:column; gap:10px;
    margin-top:22px; padding-top:20px; border-top:1px solid var(--border);
  }
  .nav-drawer-actions .btn{width:100%; justify-content:center}
  .nav-drawer-actions .nav-phone{
    display:inline-flex; justify-content:center; width:100%;
    padding:12px; border:1.5px solid var(--brand-700); border-radius:999px;
  }
  .nav-drawer-actions .nav-phone span{display:inline}

  /* The header's own CTA is duplicated into the drawer, so hide the
     header copy to keep the collapsed bar to logo + menu button. */
  .nav-cta > .btn{display:none}
}

@media (min-width: 1081px){
  /* .nav-drawer-head as a whole, not just .nav-close inside it --
     .nav-drawer-label is a real span now (it used to be a ::before
     scoped entirely inside the mobile media query, so it never had
     this problem). Without this it renders as visible "Menu" text
     sitting in the desktop nav bar. */
  .nav-drawer-head, .nav-backdrop, .nav-drawer-actions{display:none}
}

@media (prefers-reduced-motion: reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation-duration:.01ms !important; transition-duration:.01ms !important}
  /* Reveal animations are decorative. For someone who has asked the
     system for less motion, show the content outright rather than
     fading it in very fast — a 0.01ms fade is still a flash. */
  .reveal-ready [data-reveal],
  .reveal-ready [data-reveal-group] > *{opacity:1 !important; transform:none !important}
  /* The generic rule above zeroes every [data-reveal] transform, which
     would flatten the journey wave for reduced-motion visitors -- that
     throws away real layout information (which step is above the line,
     which is below), not just motion. The restoration lives in its own
     media rule below rather than here, because it also has to lose to
     the mobile flat-stack override when both conditions are true at
     once (reduced motion AND a narrow screen) -- the wave has no
     narrow-screen equivalent, so mobile always wins there regardless
     of motion preference. */
  .hero::after{display:none}

  /* A continuously moving rail is exactly what "reduce motion" is
     about. Stop it and let the row scroll by hand instead — the
     content stays reachable, it just doesn't move on its own. */
  .marquee-track{animation:none !important; width:auto}
  .marquee{overflow-x:auto; mask-image:none; -webkit-mask-image:none}

  /* The brand and destination rails are the deliberate exceptions: the
     site owner asked for both to scroll at all times. Scoped to these
     two so every other moving thing on the site still stops for this
     preference.

     They need their whole setup restored, not just the animation — the
     duplicate half of the track and the max-content width are what make
     the loop seamless, and the rules above strip both. Kept slow on
     purpose; the speed is what makes constant motion tolerable here. */
  .brand-rail .marquee-track,
  .dest-rail .marquee-track{
    animation:marquee-left var(--marquee-speed, 90s) linear infinite !important;
    width:max-content !important;
  }
  .brand-rail, .dest-rail{overflow:hidden}
  .brand-rail .marquee-track > [aria-hidden="true"],
  .dest-rail .marquee-track > [aria-hidden="true"]{display:flex !important}

  /* A static row has one copy and nothing to loop, so it must not be
     handed an animation that would slide it away to nothing. */
  .dest-rail.is-static .marquee-track{animation:none !important; width:auto !important}

  /* The floating composition is decorative motion by definition. The
     layout, overlaps and depth all survive without it — only the drift
     stops. */
  .av-card, .av-card--sub, .av-badge, .av-chip,
  .av-blob--one, .av-blob--two, .av-dots, .av-ring,
  .hs-card, .hs-chip, .hs-glow, .hs-orbit{
    animation:none !important; transform:none !important;
  }
  /* The status card keeps its centring transform — removing it would
     shunt the card off to the left, which isn't "reduced motion", it's
     a broken layout. */
  .hs-status{animation:none !important; transform:translateX(-50%) !important}
  .story-tile .play-badge::before{animation:none !important}
}

/* Restores the journey wave's resting offset for reduced-motion
   visitors at desktop widths only -- see the comment above, inside
   the reduced-motion block, for why this can't just live there. */
@media (prefers-reduced-motion: reduce) and (min-width: 901px){
  .journey-step--up[data-reveal]{transform:translateY(-20px) !important}
  .journey-step--down[data-reveal]{transform:translateY(20px) !important}
}

@media (max-width: 640px){
  /* .dest-tile is deliberately absent here. It used to carry
     width:220px; height:160px, and that height beat the tile's own
     aspect-ratio — a portrait card came out 268x160 landscape, with the
     text block filling 118 of those 160px and almost no picture left.
     Sizing now comes from the max-width:900px block below, which sets
     width and lets the 4/5 ratio derive the height. */
  .story-rail .story-tile{width:250px}
  .review-summary{padding:22px 20px; gap:18px}
  .review-divider{display:none}
  .video-modal{padding:16px}
  .video-modal .vm-close{top:-42px}
}

/* ==================================================================
   Mobile: rails become swipeable carousels
   ------------------------------------------------------------------
   An auto-scrolling marquee is wrong on a phone. Only ~1.3 cards fit
   on a 375px screen, so content slides past before it can be read,
   and there's no way to hold it still — hover-to-pause doesn't exist
   on touch.

   Below 900px the same markup becomes a native horizontal scroller
   with scroll-snap: swipe to move, it stays where you put it, and the
   next card peeks in from the right so the affordance is obvious.
   No JavaScript — the browser's own scrolling does the work, which
   also means it inherits momentum and accessibility for free.
   ================================================================== */
@media (max-width: 900px){
  .marquee{
    overflow-x:auto; overflow-y:hidden;
    scroll-snap-type:x mandatory;
    -webkit-overflow-scrolling:touch;
    scroll-padding-left:16px;
    /* Full-bleed so cards can run to the screen edge */
    margin-left:calc(50% - 50vw); margin-right:calc(50% - 50vw);
    padding:4px 0 14px;
    mask-image:none; -webkit-mask-image:none;
    scrollbar-width:none;
  }
  .marquee::-webkit-scrollbar{display:none}

  .marquee-track{
    animation:none !important;
    width:max-content;
    padding:0 16px;
    gap:14px;
  }

  /* The duplicate copy exists only to make the infinite loop seamless.
     With swiping there is no loop, so the repeat is just a second set
     of the same cards to scroll past. */
  .marquee-track > [aria-hidden="true"]{display:none}

  /* The brand and destination rails keep scrolling here too, rather
     than becoming swipe carousels like the story rail. Turning them
     into manual scrollers on a phone meant most visitors never saw
     them move at all. They keep the whole loop: animation, duplicate
     half and clipped overflow. */
  .brand-rail, .dest-rail{
    overflow:hidden;
    scroll-snap-type:none;
    padding:0;
  }
  .brand-rail{margin-left:0; margin-right:0}
  /* The destination rail stays full-bleed so tiles run to the screen
     edge — it is the width that makes the row feel like it continues,
     rather than stopping inside a boxed container. */
  .dest-rail{margin-left:calc(50% - 50vw); margin-right:calc(50% - 50vw); padding:2px 0 6px}

  .brand-rail .marquee-track,
  .dest-rail .marquee-track{
    animation:marquee-left var(--marquee-speed, 90s) linear infinite !important;
    padding:0;
  }
  .brand-rail .marquee-track > [aria-hidden="true"],
  .dest-rail .marquee-track > [aria-hidden="true"]{display:flex}
  .dest-rail.is-static .marquee-track{animation:none !important}

  .dest-tile, .story-rail .story-tile{
    scroll-snap-align:start;
    /* Card + a peek of the next one, which is what tells a visitor
       the row scrolls at all. */
    width:min(268px, 76vw);
  }
  .dest-tile{aspect-ratio:4/5}

  /* Swipe hint under each rail */
  .marquee + .container .btn,
  .marquee ~ .container .btn{margin-top:2px}
}


/* ---- Hero: give the composition room to breathe ---- */
@media (max-width: 900px){
  .hero{padding:60px 0 70px}
  .hero-stage{min-height:360px; margin-top:26px}
  .hs-glow, .hs-orbit{width:290px; height:290px}
  .hs-card, .hsf-card, .hss-card{width:min(216px, 54%)}
  .hs-chip{font-size:11px; padding:7px 11px 7px 8px; gap:7px}
  .hs-chip .flag-svg{width:22px}
  /* Two chips rather than four — four around a 216px card is clutter,
     and the destinations have their own section directly below. */
  .hs-chip--2, .hs-chip--3{display:none}
  .hs-chip--1{top:2%; left:-1%}
  .hs-chip--4{bottom:16%; right:-1%}
  .hs-status{padding:11px 14px; gap:10px}
  .hs-status .hs-line1{font-size:12.5px}
  .hs-status .hs-line2{font-size:11px}

  .hero-stage--festive, .hero-stage--spotlight{margin-top:26px}
  .hsf-glow, .hss-glow{width:250px; height:250px}
  .hsf-stamps{gap:8px}
  .hss-headline{font-size:21px}
  .hss-panel{margin-top:-30px; padding:24px 20px}
}

/* ---- Trust strip: 2x2 instead of a 186px-tall stack ---- */
@media (max-width: 900px){
  .trust-strip{padding:16px 0}
  .trust-strip .container{
    display:grid; grid-template-columns:1fr 1fr; gap:12px 14px;
    justify-content:stretch;
  }
  .trust-item{font-size:12.5px; gap:8px; align-items:flex-start; line-height:1.35}
  .trust-item svg{margin-top:1px}
}

/* ---- Reviews ---- */
@media (max-width: 900px){
  .review-summary{flex-direction:column; gap:16px; padding:22px 18px; text-align:center}
  .review-score .score{font-size:38px}
}

/* ---- Section heads centre better on narrow screens ---- */
@media (max-width: 640px){
  .section-head{margin-bottom:26px}
  .section-head p{font-size:14.5px}
  .cta-band{padding:30px 18px}
  .cta-band h2{font-size:var(--step-h2)}
  .cta-actions .btn{width:100%; justify-content:center}
  .hero-actions .btn{width:100%; justify-content:center}
  .prose{font-size:15.5px}
  .page-banner{padding:36px 0 40px}
}

/* ==================================================================
   Mobile drawer: staggered reveal
   ------------------------------------------------------------------
   Items fade up in sequence as the panel arrives, so the eye is led
   down the list instead of meeting all nine links at once. Delays are
   small and cumulative — the whole sequence finishes in ~320ms, which
   is inside the panel's own slide.
   ================================================================== */
@media (max-width: 1080px){
  .nav-links > li,
  .nav-drawer-actions{
    opacity:0; transform:translateX(14px);
    transition:opacity .3s var(--ease-out), transform .3s var(--ease-out);
  }
  body.nav-open .nav-links > li,
  .nav-links.open > li,
  body.nav-open .nav-drawer-actions,
  .nav-links.open .nav-drawer-actions{opacity:1; transform:none}

  .nav-links.open > li:nth-child(1),  body.nav-open .nav-links > li:nth-child(1) {transition-delay:60ms}
  .nav-links.open > li:nth-child(2),  body.nav-open .nav-links > li:nth-child(2) {transition-delay:95ms}
  .nav-links.open > li:nth-child(3),  body.nav-open .nav-links > li:nth-child(3) {transition-delay:130ms}
  .nav-links.open > li:nth-child(4),  body.nav-open .nav-links > li:nth-child(4) {transition-delay:165ms}
  .nav-links.open > li:nth-child(5),  body.nav-open .nav-links > li:nth-child(5) {transition-delay:195ms}
  .nav-links.open > li:nth-child(6),  body.nav-open .nav-links > li:nth-child(6) {transition-delay:220ms}
  .nav-links.open > li:nth-child(7),  body.nav-open .nav-links > li:nth-child(7) {transition-delay:245ms}
  .nav-links.open > li:nth-child(8),  body.nav-open .nav-links > li:nth-child(8) {transition-delay:270ms}
  .nav-links.open > li:nth-child(9),  body.nav-open .nav-links > li:nth-child(9) {transition-delay:290ms}
  .nav-links.open > li:nth-child(n+10), body.nav-open .nav-links > li:nth-child(n+10){transition-delay:310ms}

  /* The close button is the first thing to appear — you should always
     know how to get out before you've finished reading the menu. */
  .nav-drawer-head{opacity:1 !important; transform:none !important; transition-delay:0ms !important}

  .nav-close{
    box-shadow:var(--elev-1);
    transition:background-color var(--dur-base) var(--ease-out),
               transform var(--dur-base) var(--ease-spring);
  }
  .nav-close:hover, .nav-close:focus-visible{transform:rotate(90deg)}

  /* Submenus slide open rather than snapping. */
  .dropdown{
    overflow:hidden;
    max-height:0; padding-top:0; padding-bottom:0;
    transition:max-height .3s var(--ease-out), opacity .25s var(--ease-out);
    opacity:0; display:block;
  }
  .nav-links > li.open .dropdown{max-height:520px; opacity:1; padding-bottom:8px}
  .dropdown a{
    border-left:2px solid var(--border); margin-left:2px;
    transition:border-color var(--dur-fast) ease, background-color var(--dur-fast) ease;
  }
  .dropdown a:hover{border-left-color:var(--cyan-500)}

}

@media (prefers-reduced-motion: reduce){
  .nav-links > li, .nav-drawer-actions{opacity:1 !important; transform:none !important; transition:none !important}
  .dropdown{transition:none}
}

/* ==================================================================
   Public sidebar (blog / test prep) on mobile
   ------------------------------------------------------------------
   It stacks below the content, where a tall column of link rows is a
   lot of scrolling before the footer. Tightened, and the promo card
   keeps its emphasis.
   ================================================================== */
@media (max-width: 900px){
  .content-with-sidebar > aside{display:grid; gap:14px}
  .sidebar-card{margin-bottom:0; padding:18px}
  .sidebar-card h3{margin-bottom:10px}
  .sidebar-card li{font-size:14.5px}
  .sidebar-card li > a{padding:11px 10px}
}


/* ==================================================================
   Maintenance bypass banner
   ------------------------------------------------------------------
   Shown on the public site only to staff who are getting through
   while maintenance mode is on. It sits above the sticky header in
   normal flow, so it is unmissable on load and then gets out of the
   way as you scroll — the point is to stop someone reviewing a page,
   forgetting the switch, and leaving visitors on the holding page.
   ================================================================== */
.maint-banner{
  display:flex; align-items:center; gap:10px; flex-wrap:wrap;
  padding:9px 20px;
  background:#3F2D08; color:#FFE9B8;
  font-size:13.5px; line-height:1.4;
}
.maint-banner strong{color:#FFF6E2}
.maint-banner a{
  margin-left:auto; color:#FFF6E2;
  text-decoration:underline; text-underline-offset:3px;
  white-space:nowrap; font-weight:600;
}
.maint-banner a:hover{color:#fff}
.maint-dot{
  width:8px; height:8px; border-radius:50%; flex:none;
  background:#F5B43C; box-shadow:0 0 0 0 rgba(245,180,60,.6);
  animation:maint-pulse 2s ease-out infinite;
}
@keyframes maint-pulse{
  70%{box-shadow:0 0 0 7px rgba(245,180,60,0)}
  100%{box-shadow:0 0 0 0 rgba(245,180,60,0)}
}
@media (prefers-reduced-motion: reduce){ .maint-dot{animation:none} }
@media (max-width:640px){
  .maint-banner{padding:9px 16px; font-size:12.5px; gap:8px}
  .maint-banner a{margin-left:0}
}
