/* LOGO SIZE, 29 Jul 2026. These two content:url() swaps used to point at
   IWS_logo_white_trimmed.png (80 KB, 2858x1147) and IWS_logo_color_trimmed.png
   (78 KB, 2857x1147), rendered at 120x48. content:url() OVERRIDES the img src, so the
   browser downloaded the small file from src AND the huge file from here, and displayed
   the huge one. 158 KB for a 120px mark. Now pointed at the already-trimmed 5.5 KB and
   6.9 KB versions the src attributes were already using. Do not re-point these at the
   originals: they are 24x the displayed size. */
/* ==========================================================================
   IWS site-wide design language. Loaded on EVERY page.
   Source of truth: IWS_DESIGN.md v1.0.
   Serif display type (Cormorant Garamond) and orange #FF9600 are RETIRED.

   READ THIS BEFORE EDITING THE HEADER RULES BELOW.
   WPCode snippet 37040 ("IWS Header", 142k chars) fights everything here.
   The three rules that matter, measured from the served page 25 Jul:

     .site-header .thim-ekits-menu__nav-link::after,
     .site-header .js_hover::after { content:none!important; display:none!important; }
                                                     -> specificity (0,2,2)
     body.iws-transparent-hero .site-header:not(.iws-solid)
       .navbar-main-menu > li:hover > .thim-ekits-menu__nav-link
                                     { color:#7BA7FF!important; }  -> (0,6,2)
     .site-header .navbar-main-menu > li:hover > .thim-ekits-menu__nav-link
                                     { color:#0067E0!important; }  -> (0,4,2)

   The first one is why two earlier attempts at a gradient underline rendered
   nothing: the background was being set on a pseudo-element that had been
   deleted. Beating a colour is not enough, the ::after has to be resurrected
   with content AND display, at higher specificity.

   The theme's JS also rewrites each label into
     <a class="thim-ekits-menu__nav-link"><span class="js_hover"><span>P</span>...
   so a colour set only on the <a> is overpainted by the spans. Every colour
   rule here therefore targets the anchor, .js_hover, and .js_hover span.
   ========================================================================== */

:root{
  /* ---- TYPE TOKENS, added 28 Jul 2026 ------------------------------------
     Before this, font-family was hardcoded in 136 declarations across five
     files in FIFTEEN different spellings of two typefaces. Conflicts were
     settled with !important, and on 28 Jul that produced a real bug: the nav
     label rendered in Sora, then the theme's letter-split wrapper rendered the
     same label in Inter, so the nav changed typeface mid-load and shifted.
     One definition per face makes that class of bug impossible.

     Values are the dominant spellings already in use (72 and 27 occurrences),
     so tokenising resolves to exactly what shipped before. NOTE: the @font-face
     rules in iws-fonts.css must NEVER use these tokens - they declare the
     family names themselves, and a var() there breaks font loading outright. */
  /* 'Sora Fallback' (iws-fonts.css, Task F fix 2, 30 Jul 2026) is a size-adjusted local
     stand-in, not a download: it occupies the same width Sora will once the woff2 lands,
     so the font-display:swap moment does not reflow the nav. Inter needed no such fix
     (measured 99.45%, see iws-fonts.css) so --iws-font-body is untouched. */
  --iws-font-display:'Sora','Sora Fallback',ui-sans-serif,system-ui,sans-serif;
  --iws-font-body:'Inter',ui-sans-serif,system-ui,sans-serif;

  --iws-royal:#0A1776;
  --iws-sky:#0067E0;
  --iws-ink:#1C1917;
  --iws-amber:#D97706;
  --iws-navy:#070D2E;
  --iws-peri:#CFE0FF;
  --iws-ease:cubic-bezier(.22,.61,.36,1);
  /* The CTA gradient, quoted once and reused so the nav underline and the
     announcement bar can never drift from the button. */
  --iws-grad:linear-gradient(90deg,#0A1776 0%,#0067E0 100%);
  /* The same ramp lifted for dark backgrounds. #0A1776 on a dark photograph is
     effectively invisible (about 1.4:1), so the transparent header and the hero
     use this instead. Same blue family, still reads as one gradient. */
  --iws-grad-light:linear-gradient(90deg,#7BA7FF 0%,#CFE0FF 100%);
  --iws-bar-h:42px;
}

/* ---- Typography: Sora for structure, Inter for reading ------------------ */
/* body-prefixed to outrank the legacy footer snippet, which injects the retired
   serif with !important AFTER this sheet loads. Same importance, higher
   specificity, so this wins regardless of order. */
body h1,body h2,body h3,body h4,body h5,body h6,
body .elementor-widget-heading .elementor-heading-title{
  font-family:var(--iws-font-display)!important;
}
/* Retired gold eyebrow labels: Sky per IWS_DESIGN.md (gold is not an IWS colour). */
body .iws-prog .ey{color:var(--iws-sky)!important;}
body,p,li,figcaption,blockquote,input,textarea,select,label{
  font-family:var(--iws-font-body);
}

/* ==========================================================================
   ANNOUNCEMENT BAR
   Fixed above the header, which is itself position:fixed at top:0 z-index:9999.
   The bar takes 10000 and pushes the header down by its own height; body gets
   the same padding so static content is not hidden underneath. The hero
   subtracts the bar from its 100svh in iws-home.css so the accreditation band
   still sits below the fold.
   ========================================================================== */
.iwsbar{
  position:fixed;top:0;left:0;right:0;z-index:10000;
  display:flex;align-items:center;justify-content:center;
  height:var(--iws-bar-h);
  background:var(--iws-grad);
  color:#fff;text-decoration:none;
  font-family:var(--iws-font-display);
  overflow:hidden;
}
/* The bar is a <div> since 27 Jul (two destinations, see functions.php), so the
   link states belong on its two anchors, not on the bar itself. */
.iwsbar a{color:#fff;text-decoration:none;}
.iwsbar a:hover,.iwsbar a:focus-visible{color:#fff;text-decoration:none;}
.iwsbar a:focus-visible{outline:2px solid #fff;outline-offset:-4px;}
.iwsbar__inner{
  display:flex;align-items:center;justify-content:center;gap:18px;
  width:100%;max-width:1180px;padding:0 24px;
}
/* The stage is a fixed-height window; messages stack inside it and only one is
   opaque at a time, so the bar never changes height as the text swaps.
   flex:1 1 auto is load-bearing, not cosmetic. Every child is absolutely
   positioned, so the stage has no content to size itself from: at 0 1 auto it
   computed to zero width, the messages' max-width:100% resolved to 0, and
   overflow:hidden rendered them as nothing at all. It has to be told to grow. */
.iwsbar__stage{
  position:relative;display:block;flex:1 1 auto;
  height:var(--iws-bar-h);min-width:0;
}
.iwsbar__msg{
  position:absolute;left:50%;top:50%;
  transform:translate(-50%,-50%) translateY(8px);
  width:max-content;max-width:100%;
  opacity:0;visibility:hidden;
  font-size:13px;font-weight:600;letter-spacing:.005em;line-height:1.2;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  transition:opacity .45s var(--iws-ease),transform .45s var(--iws-ease);
}
.iwsbar__msg.is-on{opacity:1;visibility:visible;transform:translate(-50%,-50%) translateY(0);}
.iwsbar__cta{
  flex:0 0 auto;display:inline-flex;align-items:center;gap:7px;
  font-size:13px;font-weight:700;
  padding-left:18px;border-left:1px solid rgba(255,255,255,.28);
}
/* The divider in "IWS Families | Log In". Dimmed so it reads as a separator
   rather than a third word competing with the two labels either side. */
.iwsbar__sep{opacity:.45;font-weight:400;}
.iwsbar__arw{transition:transform .22s var(--iws-ease);}
.iwsbar__cta:hover .iwsbar__arw{transform:translateX(4px);}

/* Everything below the fixed bar moves down by exactly its height. */
body{padding-top:var(--iws-bar-h);}
html body #masthead.site-header{top:var(--iws-bar-h)!important;}

@media (max-width:900px){
  :root{--iws-bar-h:40px;}
  /* 27 Jul: the CTA now STAYS on mobile. It used to be hidden because it was a
     second route to /contact-us/, which the whole bar already linked to, so it
     cost width and added nothing. It is now the families login, a destination
     with no other entry point in the header, and a parent hunting for it on a
     phone is exactly who needs it. Trimmed rather than dropped: the label loses
     its arrow and tightens up so the message still has room beside it. */
  .iwsbar__cta{padding-left:12px;gap:5px;font-size:12px;}
  .iwsbar__cta .iwsbar__arw{display:none;}
  .iwsbar__inner{padding:0 12px;gap:12px;}
  .iwsbar__msg{font-size:12px;}
}
@media (max-width:420px){
  /* Below this the two cannot coexist without both truncating. The login wins
     here, because the messages are ambient and it is not. */
  .iwsbar__stage{display:none;}
  .iwsbar__inner{justify-content:center;}
  .iwsbar__cta{padding-left:0;border-left:0;}
}
@media (prefers-reduced-motion:reduce){
  .iwsbar__msg{transition:none;}
}

/* ==========================================================================
   NAVIGATION
   Gradient underline, and a label colour that never changes on hover.
   ========================================================================== */

/* --- 1. Resurrect the pseudo-element 37040 deleted ----------------------- */
/* (0,4,5) against its (0,2,2). content and display must BOTH be restored;
   setting only the background is exactly the bug this replaces. Top level
   only: the > li > child combinator keeps it off dropdown items. */
html body .site-header .navbar-main-menu > li > a.thim-ekits-menu__nav-link.thim-ekits-menu__nav-link::after{
  content:""!important;
  display:block!important;
  position:absolute;
  left:0;right:0;
  /* top, NOT bottom. Both were tried and measured from rendered pixels:
       bottom:26px  -> 28px above the label, read as a strikethrough
       bottom:-6px  -> 89-91 on the four items that carry a dropdown chevron,
                       but 102-104 on "For Schools", which has none, despite
                       identical CSS and identical getComputedStyle values
       top:100%     -> correct on all five
     Offsetting from the containing block's TOP edge resolves consistently;
     offsetting from its bottom did not. Do not "tidy" this back to bottom.
     Note also that .js_hover, the span wrapping the label characters, carries
     overflow:hidden for the theme's own animation, so the rule cannot live on
     that span: it gets clipped away entirely. The anchor is overflow:visible. */
  top:calc(100% + 2px);
  height:3px;border-radius:3px;
  background:var(--iws-grad-light)!important;
  transform:scaleX(0);
  transform-origin:left center;
  transition:transform .28s var(--iws-ease);
  pointer-events:none;
  opacity:1;
}
html body .site-header .navbar-main-menu > li > a.thim-ekits-menu__nav-link.thim-ekits-menu__nav-link{
  position:relative!important;
}
/* Reveal on hover, on keyboard focus, and on the current page. */
html body .site-header .navbar-main-menu > li:hover > a.thim-ekits-menu__nav-link.thim-ekits-menu__nav-link::after,
html body .site-header .navbar-main-menu > li > a.thim-ekits-menu__nav-link.thim-ekits-menu__nav-link:focus-visible::after,
html body .site-header .navbar-main-menu > li.current-menu-item > a.thim-ekits-menu__nav-link.thim-ekits-menu__nav-link::after,
html body .site-header .navbar-main-menu > li.current-menu-parent > a.thim-ekits-menu__nav-link.thim-ekits-menu__nav-link::after,
html body .site-header .navbar-main-menu > li.current-menu-ancestor > a.thim-ekits-menu__nav-link.thim-ekits-menu__nav-link::after{
  transform:scaleX(1);
}
/* On the white header the exact CTA gradient is used, because Royal has the
   contrast there that it lacks over a photograph. */
html body .site-header.iws-solid .navbar-main-menu > li > a.thim-ekits-menu__nav-link.thim-ekits-menu__nav-link::after,
html body:not(.iws-transparent-hero) .site-header .navbar-main-menu > li > a.thim-ekits-menu__nav-link.thim-ekits-menu__nav-link::after{
  background:var(--iws-grad)!important;
}

/* --- 2. Label colour never changes on hover ----------------------------- */
/* Transparent header over the hero photograph: white, and it stays white.
   (0,6,4) beats 37040's (0,6,2) hover rule. .js_hover and its per-character
   spans are covered because the theme's JS wraps the label after load. */
html body.iws-transparent-hero .site-header:not(.iws-solid) .navbar-main-menu > li > a.thim-ekits-menu__nav-link.thim-ekits-menu__nav-link,
html body.iws-transparent-hero .site-header:not(.iws-solid) .navbar-main-menu > li:hover > a.thim-ekits-menu__nav-link.thim-ekits-menu__nav-link,
html body.iws-transparent-hero .site-header:not(.iws-solid) .navbar-main-menu > li.current-menu-item > a.thim-ekits-menu__nav-link.thim-ekits-menu__nav-link,
html body.iws-transparent-hero .site-header:not(.iws-solid) .navbar-main-menu > li.current-menu-parent > a.thim-ekits-menu__nav-link.thim-ekits-menu__nav-link,
html body.iws-transparent-hero .site-header:not(.iws-solid) .navbar-main-menu > li.current-menu-ancestor > a.thim-ekits-menu__nav-link.thim-ekits-menu__nav-link,
html body.iws-transparent-hero .site-header:not(.iws-solid) .navbar-main-menu > li > a.thim-ekits-menu__nav-link.thim-ekits-menu__nav-link .js_hover,
html body.iws-transparent-hero .site-header:not(.iws-solid) .navbar-main-menu > li:hover > a.thim-ekits-menu__nav-link.thim-ekits-menu__nav-link .js_hover,
html body.iws-transparent-hero .site-header:not(.iws-solid) .navbar-main-menu > li > a.thim-ekits-menu__nav-link.thim-ekits-menu__nav-link .js_hover span,
html body.iws-transparent-hero .site-header:not(.iws-solid) .navbar-main-menu > li:hover > a.thim-ekits-menu__nav-link.thim-ekits-menu__nav-link .js_hover span{
  color:#fff!important;
}
/* The dropdown chevron follows the label rather than turning blue. */
html body.iws-transparent-hero .site-header:not(.iws-solid) .navbar-main-menu > li > .thim-ekits-menu__icon.thim-ekits-menu__icon,
html body.iws-transparent-hero .site-header:not(.iws-solid) .navbar-main-menu > li:hover > .thim-ekits-menu__icon.thim-ekits-menu__icon,
html body.iws-transparent-hero .site-header:not(.iws-solid) .navbar-main-menu > li > .thim-ekits-menu__icon.thim-ekits-menu__icon:before,
html body.iws-transparent-hero .site-header:not(.iws-solid) .navbar-main-menu > li:hover > .thim-ekits-menu__icon.thim-ekits-menu__icon:before{
  color:#fff!important;border-color:#fff!important;
}
/* Solid white header: Royal, and it stays Royal. */
html body .site-header.iws-solid .navbar-main-menu > li > a.thim-ekits-menu__nav-link.thim-ekits-menu__nav-link,
html body .site-header.iws-solid .navbar-main-menu > li:hover > a.thim-ekits-menu__nav-link.thim-ekits-menu__nav-link,
html body .site-header.iws-solid .navbar-main-menu > li > a.thim-ekits-menu__nav-link.thim-ekits-menu__nav-link .js_hover,
html body .site-header.iws-solid .navbar-main-menu > li:hover > a.thim-ekits-menu__nav-link.thim-ekits-menu__nav-link .js_hover,
html body .site-header.iws-solid .navbar-main-menu > li > a.thim-ekits-menu__nav-link.thim-ekits-menu__nav-link .js_hover span,
html body .site-header.iws-solid .navbar-main-menu > li:hover > a.thim-ekits-menu__nav-link.thim-ekits-menu__nav-link .js_hover span,
html body:not(.iws-transparent-hero) .site-header .navbar-main-menu > li > a.thim-ekits-menu__nav-link.thim-ekits-menu__nav-link,
html body:not(.iws-transparent-hero) .site-header .navbar-main-menu > li:hover > a.thim-ekits-menu__nav-link.thim-ekits-menu__nav-link,
html body:not(.iws-transparent-hero) .site-header .navbar-main-menu > li > a.thim-ekits-menu__nav-link.thim-ekits-menu__nav-link .js_hover span,
html body:not(.iws-transparent-hero) .site-header .navbar-main-menu > li:hover > a.thim-ekits-menu__nav-link.thim-ekits-menu__nav-link .js_hover span{
  color:var(--iws-royal)!important;
}
html body .site-header.iws-solid .navbar-main-menu > li:hover > .thim-ekits-menu__icon.thim-ekits-menu__icon,
html body .site-header.iws-solid .navbar-main-menu > li:hover > .thim-ekits-menu__icon.thim-ekits-menu__icon:before,
html body:not(.iws-transparent-hero) .site-header .navbar-main-menu > li:hover > .thim-ekits-menu__icon.thim-ekits-menu__icon,
html body:not(.iws-transparent-hero) .site-header .navbar-main-menu > li:hover > .thim-ekits-menu__icon.thim-ekits-menu__icon:before{
  color:var(--iws-royal)!important;border-color:var(--iws-royal)!important;
}

/* --- 2b. THE MOBILE DRAWER IS WHITE, SO THE LABELS CANNOT BE ------------- */
/* Regression caught 25 Jul after snippet 37040 was retired. The rules above
   lock the label to white while the header is transparent over the hero. On a
   phone the menu is not a transparent bar, it is a white fixed drawer
   (.width-navigation, background #fff, z-index 1002) and the header still is
   not .iws-solid at scroll top, so every item rendered white on white: present,
   correctly sized at 280x45, and completely invisible. 37040 used to carry its
   own mobile-menu colours, which is why this only appeared once it was off.

   #masthead#masthead is needed because a media query adds no specificity and
   the white rules above are (0,6,4) with !important. */
@media (max-width:900px){
  html body #masthead#masthead .navbar-main-menu > li > a.thim-ekits-menu__nav-link,
  html body #masthead#masthead .navbar-main-menu > li:hover > a.thim-ekits-menu__nav-link,
  html body #masthead#masthead .navbar-main-menu > li > a.thim-ekits-menu__nav-link .js_hover,
  html body #masthead#masthead .navbar-main-menu > li > a.thim-ekits-menu__nav-link .js_hover span,
  html body #masthead#masthead .navbar-main-menu .thim-ekits-menu__dropdown a{
    color:var(--iws-royal)!important;
  }
  html body #masthead#masthead .navbar-main-menu > li > .thim-ekits-menu__icon,
  html body #masthead#masthead .navbar-main-menu > li > .thim-ekits-menu__icon:before{
    color:var(--iws-royal)!important;border-color:var(--iws-royal)!important;
  }
  /* The sweep-in underline belongs to the desktop bar; in a stacked drawer it
     reads as a stray rule under every row. */
  html body #masthead#masthead .navbar-main-menu > li > a.thim-ekits-menu__nav-link::after{
    display:none!important;
  }
  /* Comfortable rows and a clear divider, since there is no hover affordance. */
  html body #masthead#masthead .navbar-main-menu > li > a.thim-ekits-menu__nav-link{
    min-height:48px;display:flex!important;align-items:center;
  }
  html body #masthead#masthead .navbar-main-menu > li{
    border-bottom:1px solid rgba(10,23,118,.10);
  }
}

/* --- 3. Slightly larger nav type ---------------------------------------- */
/* 16px -> 17px. Deliberately small: at 18px the five top-level items start to
   crowd the CTA between 1024 and 1180px. */
html body .site-header .navbar-main-menu > li > a.thim-ekits-menu__nav-link.thim-ekits-menu__nav-link,
html body .site-header .navbar-main-menu > li > a.thim-ekits-menu__nav-link.thim-ekits-menu__nav-link .js_hover,
html body .site-header .navbar-main-menu > li > a.thim-ekits-menu__nav-link.thim-ekits-menu__nav-link .js_hover span{
  font-size:17px!important;
  letter-spacing:.002em!important;
}
@media (max-width:1180px) and (min-width:901px){
  html body .site-header .navbar-main-menu > li > a.thim-ekits-menu__nav-link.thim-ekits-menu__nav-link,
  html body .site-header .navbar-main-menu > li > a.thim-ekits-menu__nav-link.thim-ekits-menu__nav-link .js_hover,
  html body .site-header .navbar-main-menu > li > a.thim-ekits-menu__nav-link.thim-ekits-menu__nav-link .js_hover span{
    font-size:15.5px!important;
  }
}

@media (prefers-reduced-motion:reduce){
  html body .site-header .navbar-main-menu > li > a.thim-ekits-menu__nav-link.thim-ekits-menu__nav-link::after{transition:none;}
}


/* ---- Logo -----------------------------------------------------------------
   Snippet 37040 forces artwork through content:url(...) !important and adds a
   37px margin that pushes the logo off the container edge. Both are matched at
   higher specificity. Trimmed artwork has no baked padding, so the mark sits
   on the same left edge as the hero copy. */
html body .site-header .phys-logo.phys-logo img,
html body .site-header .width-logo.width-logo img,
html body .phys-logo.phys-logo img,
html body .width-logo.width-logo img{
  content:url('/wp-content/uploads/2026/07/iws-logo-white-trimmed.png')!important;
  filter:none!important;
  height:clamp(46px,4.4vw,60px)!important;
  width:auto!important;max-width:none!important;
  object-fit:contain;
}
/* Solid header state and any non-hero page take the colour mark. */
html body .site-header.iws-solid .phys-logo.phys-logo img,
html body .site-header.iws-solid .width-logo.width-logo img,
html body:not(.iws-transparent-hero) .site-header .phys-logo.phys-logo img,
html body:not(.iws-transparent-hero) .site-header .width-logo.width-logo img{
  content:url('/wp-content/uploads/2026/07/iws-logo-navy-trimmed.png')!important;
}
/* Align the mark to the container edge so header and hero share one column.
   The doubled ID is deliberate. 37040 carries
     #masthead .width-logo.sm-logo{margin-left:37px!important}   -> (1,1,2)
   inside a min-width:1025px query, so an ID is required to beat it. But an ID
   here also outranks any plain-class rule in a MEDIA query, because media
   queries contribute nothing to specificity. That is what silently broke the
   phone header: the desktop rule kept winning below 900px. Every rule in this
   pair therefore uses #masthead#masthead, so desktop and phone sit at equal
   specificity and source order decides, which is what was intended. */
html body #masthead#masthead .width-logo.sm-logo,
html body #masthead#masthead .width-logo.width-logo,
html body .site-header .width-logo.width-logo,
html body .site-header .phys-logo.phys-logo{
  margin-left:0!important;padding-left:0!important;
}
/* THE alignment fix. The header's container is .navigation.container with
   max-width:none and 20px padding, while the hero is 1180px centred, so the
   two could never share a left edge. Both now use one geometry. */
html body #masthead#masthead .navigation.container,
html body #masthead#masthead .container,
html body .site-header .navigation.container,
html body .site-header .container{
  max-width:1180px!important;
  margin-left:auto!important;margin-right:auto!important;
  padding-left:24px!important;padding-right:24px!important;
}
/* and nothing between the container edge and the mark */
html body #masthead#masthead .width-logo.width-logo,
html body #masthead#masthead .width-logo.sm-logo{
  margin:0!important;padding:0!important;max-width:none!important;
}

/* ---- Phone header ---------------------------------------------------------
   The menu toggle is the leftmost element on a phone, which pushed the mark
   about 28px off the copy column. The real class is .mobile-menu-container,
   confirmed from the served markup on 25 Jul; it had previously been guessed.
   Absolutely positioning it frees the mark to sit on the container edge. */
@media (max-width:900px){
  html body #masthead#masthead .navigation.container{
    position:relative;
    padding-left:20px!important;padding-right:20px!important;
  }
  /* The toggle moves to the RIGHT on phones. It was the leftmost element,
     which forced the mark about 28px inboard and made it impossible for the
     logo and the hero headline to share a left edge. Logo left, menu right is
     also the pattern people expect on a phone. */
  html body #masthead#masthead .mobile-menu-container{
    position:absolute!important;right:20px!important;left:auto!important;
    top:50%!important;transform:translateY(-50%)!important;
    margin:0!important;z-index:3;
    width:30px;height:30px;
    display:flex!important;flex-direction:column;justify-content:center;gap:5px;
  }
  /* Now the mark can sit on the container edge, level with the hero copy. */
  html body #masthead#masthead .width-logo.width-logo,
  html body #masthead#masthead .width-logo.sm-logo{
    margin-left:0!important;
  }
  html body #masthead#masthead .phys-logo.phys-logo img,
  html body #masthead#masthead .width-logo.width-logo img{
    height:clamp(40px,10.5vw,48px)!important;
  }
}


/* ==========================================================================
   MARKER HIGHLIGHT  (.hl)
   --------------------------------------------------------------------------
   Ported verbatim from the courses site
   (Courses Site WordPress/iws-courses-theme/assets/css/home.css) at Burak's
   request, 25 Jul 2026: "use the highlight system we have in the courses
   website". It REPLACES the gradient underline that used to sit under every
   section heading. That underline is the navigation's device and the
   navigation's alone; repeating it on headings made one signal mean two things.

   Spec: IWS_DESIGN.md section 4.3b. A solid Royal-to-Sky block with WHITE text,
   never a pale tint behind coloured text, because a tint reads as faint shading
   rather than a deliberate object. White on Royal measures about 15:1.

   The block sweeps in from the left when the heading is scrolled to. The sweep
   is decoration only: before it arrives the phrase is already Royal Blue on
   white and carries the emphasis on its own, which is what keeps this safe
   under prefers-reduced-motion and safe if the JavaScript never runs.
   ========================================================================== */
.hl{
  color:#fff;
  background-image:linear-gradient(90deg,var(--iws-royal,#0A1776) 0%,var(--iws-sky,#0067E0) 100%);
  background-repeat:no-repeat;
  background-position:0 0;
  background-size:0% 100%;
  padding:.04em .26em .1em;
  border-radius:.2em;
  transition:background-size .8s cubic-bezier(.22,.61,.36,1),color .5s ease .12s;
  -webkit-box-decoration-break:clone;box-decoration-break:clone;
}
.hl:not(.is-in){color:var(--iws-royal,#0A1776);}
.hl.is-in{background-size:100% 100%;color:#fff;}

/* A headline carrying a marker needs room: section 4.3b requires at least 1.2
   line height, otherwise the block fouls the descenders on the line above. */
h1:has(.hl),h2:has(.hl),h3:has(.hl){line-height:1.3;}

/* The block hangs left by its own side padding so the GLYPHS land on the text
   column, not the block's outer edge. Aligning the edge pushes the words inward
   and the marked line reads as indented against the line above (4.3b). Only for
   left-aligned headings; a centred block is centred on its own text already. */
.hl--own{display:block;width:fit-content;margin-left:-.26em;}

/* On dark ground the block inverts: periwinkle ground, Royal Blue text. */
.on-dark .hl,.iws-dark .hl,.iwshero .hl{
  background-image:linear-gradient(90deg,var(--iws-peri,#CFE0FF) 0%,#EAF1FF 100%);
}
.on-dark .hl:not(.is-in),.iws-dark .hl:not(.is-in),.iwshero .hl:not(.is-in){color:#fff;}
.on-dark .hl.is-in,.iws-dark .hl.is-in,.iwshero .hl.is-in{color:var(--iws-royal,#0A1776);}

/* ⚠️ A MARKED PHRASE MUST NEVER BREAK ACROSS TWO LINES (4.3b), AND BELOW ABOUT
   640px every centred section heading wraps, so an inline marker does exactly
   that. 4.3b's own remedy is the one applied here: "Where a headline runs to
   more than one line, the marked phrase starts its own line."

   Centred, not hung left, because these headings are centred; a LEFT-aligned
   heading uses .hl--own above, which hangs by its own padding so the glyphs
   land on the text column.

   Added 1 Aug 2026. It replaces the wrong fix from 31 Jul, which was to shorten
   each marked phrase until it fitted. That stopped the wrapping and left two
   markers sitting in the MIDDLE of their heading, which Burak ruled out flatly:
   "never highlight just the middle of a sentence." Fix the line, not the mark. */
@media (max-width:640px){
  h1 .hl, h2 .hl{display:block;width:fit-content;margin-inline:auto;}
  /* ...but `margin-inline:auto` CENTRES the block, which is right only where the
     heading itself is centred. The info pages (/term-dates/, /computer-requirements/,
     /welcome/) set their headings to text-align:start, so measured at 360px on
     1 Aug 2026 every one of the five markers on /term-dates/ sat 57 to 103px
     INSIDE its own heading's text column, while the unmarked words all began at
     39px. That is failure mode 3 in IWS_DESIGN.md 4.3b, "align the block's text,
     not the block's edge", reintroduced by the fix for the wrapping.
     A left-aligned heading hangs its block left by its own padding instead. The
     one centred band inside the component, .ip-end, opts back in below. */
  .iws-ip h1 .hl, .iws-ip h2 .hl{margin-left:-.26em;margin-right:auto;}
  .iws-ip .ip-end h2 .hl{margin-left:auto;margin-right:auto;}
}

@media (prefers-reduced-motion:reduce){
  .hl{transition:none;background-size:100% 100%;color:#fff;}
  .on-dark .hl,.iws-dark .hl,.iwshero .hl{color:var(--iws-royal,#0A1776);}
}


/* ==========================================================================
   VIDEO LIGHTBOX  (.iwsvid)
   --------------------------------------------------------------------------
   Every YouTube link on the site opens here rather than swapping a small
   iframe into the card it was clicked from (Burak, 25 Jul 2026). A 240px-wide
   player inside a carousel card is not a way to watch a student tell you why
   they chose the school.

   Sizing note. aspect-ratio plus max-height does NOT preserve the ratio: with a
   specified width the height is derived, then clamped, and the width is never
   recomputed, so the frame ends up letterboxed inside itself. The width is
   therefore clamped by all three constraints at once with min(), including the
   width that a full-height frame would need. That keeps the ratio exact at
   every viewport with no JavaScript measuring anything.
   ========================================================================== */
.iwsvid{
  position:fixed;inset:0;z-index:100000;
  display:flex;align-items:center;justify-content:center;
  padding:clamp(16px,4vw,56px);
  opacity:0;visibility:hidden;
  transition:opacity .26s ease,visibility 0s linear .26s;
}
.iwsvid.is-open{opacity:1;visibility:visible;transition:opacity .26s ease,visibility 0s;}
.iwsvid__scrim{
  position:absolute;inset:0;
  background:rgba(4,8,28,.88);
  backdrop-filter:blur(10px) saturate(.85);
  -webkit-backdrop-filter:blur(10px) saturate(.85);
}
.iwsvid__frame{
  position:relative;z-index:1;
  aspect-ratio:16/9;
  width:min(1140px,100%,calc(82vh * 16 / 9));
  border-radius:14px;overflow:hidden;
  background:#000;
  box-shadow:0 40px 120px rgba(0,0,0,.6);
  transform:scale(.955) translateY(12px);opacity:0;
  transition:transform .4s cubic-bezier(.22,.61,.36,1),opacity .3s ease;
}
.iwsvid.is-open .iwsvid__frame{transform:none;opacity:1;}
/* Shorts are 9:16. Sized off the viewport height first, because on a phone the
   height is what runs out. */
.iwsvid--portrait .iwsvid__frame{
  aspect-ratio:9/16;
  width:min(420px,100%,calc(84vh * 9 / 16));
}
.iwsvid__frame iframe{position:absolute;inset:0;width:100%;height:100%;border:0;display:block;}

.iwsvid__close{
  position:absolute;z-index:2;
  top:clamp(12px,2.4vw,26px);right:clamp(12px,2.4vw,26px);
  width:46px;height:46px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  border:1px solid rgba(255,255,255,.28);
  background:rgba(255,255,255,.1);
  color:#fff;cursor:pointer;
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
  transition:background .2s ease,border-color .2s ease,transform .2s ease;
}
.iwsvid__close:hover{background:rgba(255,255,255,.2);border-color:rgba(255,255,255,.5);transform:scale(1.06);}
.iwsvid__close:focus-visible{outline:2px solid var(--iws-peri,#CFE0FF);outline-offset:3px;}
.iwsvid__close svg{width:19px;height:19px;stroke:currentColor;stroke-width:2.4;fill:none;stroke-linecap:round;}

.iwsvid__cap{
  position:absolute;left:0;right:0;bottom:calc(-1 * clamp(30px,4vw,44px));
  text-align:center;color:#fff;
  font-family:var(--iws-font-body);
  font-size:14px;line-height:1.4;opacity:.82;
}
@media (max-width:640px){.iwsvid__cap{display:none;}}

/* Body lock. The padding compensates for the scrollbar the lock removes,
   otherwise the whole page jumps left the moment the video opens. */
html.iwsvid-lock,html.iwsvid-lock body{overflow:hidden;}

@media (prefers-reduced-motion:reduce){
  .iwsvid,.iwsvid__frame{transition:none;}
  .iwsvid__frame{transform:none;}
}


/* ==========================================================================
   MARKER HIGHLIGHT vs ELEMENTOR LAZY-LOAD — do not simplify these selectors
   --------------------------------------------------------------------------
   Elementor injects this, at (0,5,0) and !important:

     .e-con.e-parent:nth-of-type(n+4):not(.e-lazyloaded):not(.e-no-lazyload) *
       { background-image: none !important }

   The trailing " *" strips background-image off every descendant of the fourth
   top-level container onward until its own JavaScript marks it .e-lazyloaded.
   The marker highlight IS a background-image (a Royal-to-Sky gradient whose
   background-size animates from 0% to 100%), so measured on staging 25 Jul
   2026 the block on the Three Pathways heading computed to background-image:
   none and the phrase rendered as plain Royal text with no block at all.

   This is a SITE-WIDE hazard, not a homepage one: any marked heading in the
   fourth section or later of any page loses its block the same way, so the
   override lives here rather than in iws-home.css.

   The selectors carry six repeated classes plus html and body to reach (0,6,2),
   which beats (0,5,0) honestly rather than by escalating importance. The
   optimisation exists to defer heavy photographs; it saves nothing on a
   gradient and only costs correctness.
   ========================================================================== */
/* :not(.hl--amber) added 26 Jul. This selector is .hl repeated six times to
   brute-force specificity past the legacy header snippet, and with !important
   it beat the amber variant at (0,2,0) no matter what. Excluding the variant
   here is cleaner than escalating: one hack, not two. */
html body .hl.hl.hl.hl.hl.hl:not(.hl--amber){
  background-image:linear-gradient(90deg,var(--iws-royal,#0A1776) 0%,var(--iws-sky,#0067E0) 100%)!important;
}
html body .on-dark .hl.hl.hl.hl.hl.hl,
html body .iws-dark .hl.hl.hl.hl.hl.hl,
html body .iwshero .hl.hl.hl.hl.hl.hl{
  background-image:linear-gradient(90deg,var(--iws-peri,#CFE0FF) 0%,#EAF1FF 100%)!important;
}


/* ==========================================================================
   THE EMPHASIS WORD  (.em)
   IWS_DESIGN.md 4.3. The quieter of the two emphasis devices: colour only, no
   block. Sky Blue on light grounds, Periwinkle on dark.

   This is what most headings get. The marker block (.hl above) is reserved for
   the handful of headings carrying a real promise, because 4.3b caps it at one
   per view and warns that competing highlights cancel each other out. Putting
   the same loud device on fifteen headings is the mistake the gradient rule was
   removed for; repeating it in a different colour would not be an improvement.
   ========================================================================== */
.em{color:var(--iws-sky,#0067E0);}
.on-dark .em,.iws-dark .em,.iwshero .em{color:var(--iws-peri,#CFE0FF);}


/* ==========================================================================
   BENTO  (.iwsb)
   Vanilla MagicBento: cursor spotlight, border glow, tilt, magnetism, ripple.
   Amber #D97706 at low alpha. IWS_DESIGN.md 3.4 calls amber "a whisper, never
   a statement", so it lights an edge and never fills anything.
   ========================================================================== */
[data-bento]{position:relative;}

.iwsb{
  --glow-x:50%;--glow-y:50%;--glow-intensity:0;--glow-radius:320px;
  --tilt-x:0deg;--tilt-y:0deg;--mag-x:0px;--mag-y:0px;--lift:0px;
  /* Lift is its own translate rather than being folded into the magnetism with
     calc(). calc(0px + -14px) was dropped as invalid, which silently killed the
     WHOLE transform declaration: no lift, no tilt, no magnetism, computed
     identity matrix, and nothing in the console to say so. Separate functions
     compose the same way and cannot fail on a sign. */
  transform:
    translate3d(var(--mag-x),var(--mag-y),0)
    translateY(var(--lift))
    rotateX(var(--tilt-x)) rotateY(var(--tilt-y));
  transform-style:preserve-3d;
  transition:transform .28s cubic-bezier(.22,.61,.36,1),box-shadow .3s ease,border-color .3s ease;
  will-change:transform;
}
.iwsb:hover{--lift:-6px;}

/* Border glow. The two masks cancel everything but the padding ring, so the
   gradient paints the border only and never washes over the card's contents. */
.iwsb::after{
  content:"";position:absolute;inset:0;padding:1.5px;
  border-radius:inherit;pointer-events:none;z-index:2;
  background:radial-gradient(var(--glow-radius) circle at var(--glow-x) var(--glow-y),
    rgba(var(--glow-color,217,119,6),calc(var(--glow-intensity) * .95)) 0%,
    rgba(var(--glow-color,217,119,6),calc(var(--glow-intensity) * .45)) 32%,
    transparent 62%);
  -webkit-mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);
  -webkit-mask-composite:xor;
  mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);
  mask-composite:exclude;
  transition:opacity .3s ease;
}

.iwsb__spot{
  position:absolute;width:640px;height:640px;border-radius:50%;
  pointer-events:none;z-index:0;opacity:0;
  transform:translate(-50%,-50%);
  transition:opacity .3s ease;
  background:radial-gradient(circle,
    rgba(var(--glow-color,217,119,6),.10) 0%,
    rgba(var(--glow-color,217,119,6),.055) 18%,
    rgba(var(--glow-color,217,119,6),.025) 34%,
    transparent 68%);
}

.iwsb__ripple{
  position:absolute;border-radius:50%;pointer-events:none;z-index:3;
  transform:scale(0);opacity:.85;
  background:radial-gradient(circle,
    rgba(var(--glow-color,217,119,6),.32) 0%,
    rgba(var(--glow-color,217,119,6),.16) 30%,
    transparent 68%);
  transition:transform .8s cubic-bezier(.22,.61,.36,1),opacity .8s ease;
}
.iwsb__ripple.is-out{transform:scale(1);opacity:0;}

@media (prefers-reduced-motion:reduce){
  .iwsb{transform:none;transition:none;}
  .iwsb::after,.iwsb__spot,.iwsb__ripple{display:none;}
}


/* ==========================================================================
   ACCESSIBILITY FIXES, 25 Jul 2026
   From a measured audit of the homepage. Two of the three were introduced the
   same day, when amber was added at Burak's request.

   AMBER SPLITS INTO TWO TOKENS.
   IWS_DESIGN.md 3.4 requires WCAG AA: 4.5:1 for body text, 3:1 for large text.
   Measured, #D97706 gives:
       on #FFFFFF  3.19:1      on #F8FAFC  3.04:1
   That is fine for a rule, a ring or a border, which are non-text and need 3:1.
   It FAILS for text. The chapter numerals, the scrollytelling step numbers and
   the white-on-amber crown badge were all below the line.

   So:
     --iws-amber      #D97706  objects only: rules, rings, borders, fills
     --iws-amber-ink  #B45309  text on light grounds, measured 5.02:1 / 4.80:1
   and the crown badge keeps its amber fill but takes Royal Blue text (4.72:1)
   rather than white (3.19:1), which needs no new colour at all.

   #B45309 is a darker step of the same amber and is FLAGGED for Mustafa under
   section 12. It is not a free choice: the palette's own AA rule forces it the
   moment amber carries a letter.
   ========================================================================== */
:root{
  --iws-amber:#D97706;
  --iws-amber-ink:#B45309;
}

/* Skip link. (Rewritten 27 Jul 2026.)
   This block used to style our OWN `.iws-skip`, added in the belief that the
   site had no skip link. It has one -- the parent theme ships `a.skip-link` to
   `#primary-content`, and that target genuinely exists -- so every page was
   carrying two, and ours was the broken one (its `#content` target was never
   created). Ours is gone from functions.php; the theme's is styled here, which
   is the only part the theme actually got wrong: it was unstyled, so it either
   sat visible in the layout or vanished with no focus affordance.
   `.iws-skip` is kept in the selector list purely so the footer-underline
   :not() chains below keep working unchanged if it ever returns. */
.skip-link{
  position:absolute;left:8px;top:-60px;z-index:100001;
  padding:12px 20px;border-radius:0 0 10px 10px;
  background:var(--iws-royal,#0A1776);color:#fff;
  font-family:var(--iws-font-display);
  font-size:14px;font-weight:600;text-decoration:none;
  transition:top .18s ease;
}
.skip-link:focus,.skip-link:focus-visible{top:0;color:#fff;}


/* ---- Footer links: the same underline the navigation uses -----------------
   Burak: "make the footer buttons get underlined like the nav bar when hovered
   over with mouse". Same gradient, same 2px offset, same grow-from-left. It is
   drawn on ::after, so it needs the anchor to be a positioned inline-block;
   footer anchors are inline by default and an inline box cannot carry it. */
/* ---- Footer links: the same underline the navigation uses -----------------
   Burak, 26 Jul: "make the footer buttons get underlined like the nav bar when
   hovered over with mouse". Same gradient, same 2px offset, same grow-from-
   left. It lives here rather than in iws-home.css because the footer is on
   every page.

   The footer is NOT a <footer> element and has no .site-footer class: it is
   div.iws-ft inside div.thim-ekit__footer, an Elementor template. A selector
   written against the obvious names matches nothing at all, silently. */
.iws-ft a:not(.iws-skip):not([class*="btn"]):not([class*="button"]):not([class*="logo"]),
.thim-ekit__footer a:not(.iws-skip):not([class*="btn"]):not([class*="button"]):not([class*="logo"]){
  position:relative;text-decoration:none;
}
/* inline-block only where the anchor is genuinely a text link; forcing it on
   an anchor wrapping an icon or an image changes that element's box. */
.iws-ft li > a,.iws-ft p > a,.thim-ekit__footer li > a{display:inline-block;}
/* Burak, 26 Jul: "the social media icons at the footer get underlined as well
   dont underline them". Those six anchors sit in div.socs, carry NO class at
   all, and hold an icon with zero text, so they pass every :not() above and
   draw a 38px bar under the glyph. The footer logo escapes only because it
   matches [class*="logo"].

   :not(.socs a) is added to ALL FOUR selectors below, not just the resting
   one. Adding it to the resting rule alone takes that rule to (0,6,3) while
   the hover rule stays (0,6,2): the class counts tie and the resting rule
   wins on element count, which would kill the underline on every ordinary
   footer link. Both rules move together or neither does. */
.iws-ft a:not(.iws-skip):not([class*="btn"]):not([class*="button"]):not([class*="logo"]):not(.socs a)::after,
.thim-ekit__footer a:not(.iws-skip):not([class*="btn"]):not([class*="button"]):not([class*="logo"]):not(.socs a)::after{
  content:"";position:absolute;left:0;top:calc(100% + 2px);
  width:100%;height:2px;border-radius:2px;pointer-events:none;
  background:linear-gradient(90deg,var(--iws-sky,#0067E0),var(--iws-peri,#CFE0FF));
  transform:scaleX(0);transform-origin:left center;
  transition:transform .28s var(--iws-ease,cubic-bezier(.22,.61,.36,1));
}
/* The hover rule has to carry the SAME :not() chain. Each :not(.class) adds a
   class to the specificity, so the resting rule above is (0,5,1) and a plain
   `.iws-ft a:hover::after` is (0,2,1): it loses, the underline never grows, and
   nothing about that is visible in the markup. Measured, not guessed. */
.iws-ft a:not(.iws-skip):not([class*="btn"]):not([class*="button"]):not([class*="logo"]):not(.socs a):hover::after,
.iws-ft a:not(.iws-skip):not([class*="btn"]):not([class*="button"]):not([class*="logo"]):not(.socs a):focus-visible::after,
.thim-ekit__footer a:not(.iws-skip):not([class*="btn"]):not([class*="button"]):not([class*="logo"]):not(.socs a):hover::after,
.thim-ekit__footer a:not(.iws-skip):not([class*="btn"]):not([class*="button"]):not([class*="logo"]):not(.socs a):focus-visible::after{
  transform:scaleX(1);
}


/* ==========================================================================
   MOBILE HEADER, DRAWER AND STICKY CALL TO ACTION
   Everything below 1200px, which is where the theme swaps the navigation for
   the burger (measured: burger present at 1024, gone at 1200).

   THREE FAULTS, ALL FOUND BY MEASUREMENT ON 26 Jul, all visible in Burak's
   screenshots as one confusing icon:

   1. The burger and the header WhatsApp button occupied THE SAME PIXELS.
      Burger 325-355 x 66-96, WhatsApp 319-355 x 63-99. The burger's three
      white bars were drawn straight over the WhatsApp glyph, which is the
      struck-through logo in the screenshots, and elementsFromPoint confirmed
      the WhatsApp button could never be tapped at all.
   2. The dropdowns are a DESKTOP MEGA-MENU leaking into the drawer:
      `position:fixed; opacity:0`, 305 x 798px, sitting invisibly over the
      whole drawer from y=149 down. Every menu item below the first was under
      an invisible sheet.
   3. Tapping a parent item navigated instead of opening anything. Programmes
      and For Schools carry real hrefs, and the caret next to them
      (.thim-ekits-menu__icon, 40x36) had no behaviour bound to it.
   ========================================================================== */
@media (max-width:1199px){

  /* ---- 1. the header keeps the logo and the burger, nothing else ----------
     The two call-to-action buttons move to the sticky bar at the bottom of the
     screen (Burak, 26 Jul), which is where a thumb actually is, and that frees
     the corner so the burger can have a real 44px target. */
  .mfhcta{
    position:fixed;left:0;right:0;bottom:0;top:auto;
    z-index:60;
    display:flex;gap:10px;align-items:center;
    margin:0;padding:10px 14px calc(10px + env(safe-area-inset-bottom,0px));
    background-image:linear-gradient(180deg,rgba(255,255,255,.86) 0%,#FFFFFF 42%);
    border-top:1px solid rgba(10,23,118,.10);
    box-shadow:0 -10px 30px -18px rgba(10,23,118,.55);
    -webkit-backdrop-filter:saturate(1.6) blur(10px);backdrop-filter:saturate(1.6) blur(10px);
    /* Hidden until the reader is past the hero: the hero has its own buttons,
       and a bar over them on first paint is just a nag. iws-global.js adds
       .is-up. */
    transform:translateY(115%);
    transition:transform .34s cubic-bezier(.22,.61,.36,1);
    pointer-events:none;
  }
  .mfhcta.is-up{transform:translateY(0);pointer-events:auto;}
  /* A WPCode inline snippet sizes these two with !important at four
     breakpoints, at (0,4,1): `body .mfhcta a.mf-enq.mf-enq{height:36px
     !important}` and so on down to 34px at 380px wide. A plain `.mfhcta
     .mf-enq` is (0,2,0) and loses on importance before specificity is even
     considered. Same selector shape, same importance, so this wins. Measured
     from the served page, not guessed. */
  html body .mfhcta a.mf-enq.mf-enq.mf-enq,
  html body .mfhcta a.mf-wa.mf-wa.mf-wa{
    height:52px!important;border-radius:14px!important;
    display:inline-flex!important;align-items:center;justify-content:center;gap:9px;
    font-family:var(--iws-font-display);
    font-size:16px!important;font-weight:600;text-decoration:none;
    padding:0 18px!important;
  }
  html body .mfhcta a.mf-enq.mf-enq.mf-enq{
    flex:1 1 auto;color:#FFFFFF!important;
    background-image:linear-gradient(120deg,var(--iws-royal,#0A1776) 0%,var(--iws-sky,#0067E0) 100%)!important;
    box-shadow:0 10px 24px -12px rgba(10,23,118,.7);
  }
  html body .mfhcta a.mf-wa.mf-wa.mf-wa{
    flex:0 0 62px;width:62px!important;padding:0!important;color:#FFFFFF!important;
    background-image:linear-gradient(140deg,#25D366 0%,#12A150 100%)!important;
    box-shadow:0 10px 24px -12px rgba(18,161,80,.75);
  }
  html body .mfhcta a.mf-wa.mf-wa.mf-wa svg{width:26px!important;height:26px!important;fill:currentColor;}

  /* A real tap target. 30x30 was under the 44px floor and it was sharing those
     30px with another control. */
  /* Same story as the buttons: the theme sizes this at 30x30 from a rule that
     out-specifies a bare class. (0,5,1) here, and !important because the
     theme's is too. */
  html body #masthead .mobile-menu-container.mobile-menu-container,
  html body .mobile-menu-container.mobile-menu-container{
    width:44px!important;height:44px!important;right:14px!important;
    display:flex;flex-direction:column;justify-content:center;align-items:center;gap:6px;
    z-index:9;
  }
  html body .mobile-menu-container.mobile-menu-container span{
    position:static!important;width:24px!important;height:2px!important;
    left:auto!important;top:auto!important;margin:0!important;border-radius:2px;
    transition:transform .3s cubic-bezier(.22,.61,.36,1),opacity .2s ease;
  }
  /* An X while the drawer is open, so the control says what it will do. */
  body.mobile-menu-open .mobile-menu-container span:nth-child(1){transform:translateY(8px) rotate(45deg);}
  body.mobile-menu-open .mobile-menu-container span:nth-child(2){opacity:0;}
  body.mobile-menu-open .mobile-menu-container span:nth-child(3){transform:translateY(-8px) rotate(-45deg);}

  /* ---- 2 and 3. the drawer submenus become an accordion ------------------ */
  .width-navigation .thim-ekits-menu__dropdown,
  .width-navigation .navbar-nav ul.sub-menu{
    position:static!important;
    opacity:1!important;visibility:visible!important;
    transform:none!important;
    width:auto!important;min-width:0!important;left:auto!important;top:auto!important;
    box-shadow:none!important;background:transparent!important;
    padding:0!important;margin:0!important;
    /* height:auto matters as much as max-height. The desktop mega-menu sets a
       height of its own, so max-height alone left the open panel padded out to
       the full 520px with a slab of white under six links. */
    height:auto!important;min-height:0!important;
    max-height:0;overflow:hidden;
    transition:max-height .34s cubic-bezier(.22,.61,.36,1);
  }
  .width-navigation .navbar-nav > li.is-open > .thim-ekits-menu__dropdown,
  .width-navigation .navbar-nav > li.is-open > ul.sub-menu{
    max-height:520px;
  }
  .width-navigation .navbar-nav > li.menu-item-has-children{position:relative;}
  .width-navigation .navbar-nav ul li a{
    display:block;padding:12px 16px 12px 30px;
    font-size:15px;line-height:1.35;color:#334155;
  }
  .width-navigation .navbar-nav ul li a:hover{color:var(--iws-sky,#0067E0);}

  /* The caret. It was an empty span with no glyph and nothing bound to it, so
     drawn here rather than left to a font that never arrives. */
  .width-navigation .thim-ekits-menu__icon{
    position:absolute;top:0;right:0;
    width:52px;height:52px;z-index:2;cursor:pointer;
    display:flex;align-items:center;justify-content:center;
  }
  .width-navigation .thim-ekits-menu__icon::before{
    content:"";width:9px;height:9px;
    border-right:2px solid var(--iws-royal,#0A1776);
    border-bottom:2px solid var(--iws-royal,#0A1776);
    transform:translateY(-3px) rotate(45deg);
    transition:transform .3s cubic-bezier(.22,.61,.36,1);
  }
  .width-navigation .navbar-nav > li.is-open > .thim-ekits-menu__icon::before{
    transform:translateY(1px) rotate(-135deg);
  }

  /* Room for the sticky bar at the foot of every page, or it covers the last
     thing on it. */
  body{padding-bottom:76px;}
}

@media (prefers-reduced-motion:reduce){
  .mfhcta,.mobile-menu-container span,
  .width-navigation .thim-ekits-menu__dropdown,
  .width-navigation .thim-ekits-menu__icon::before{transition:none;}
}


/* ==========================================================================
   THE EMPHASIS WORD ON A DARK GROUND
   .em is Sky Blue, which is right on a white section and wrong on a dark one:
   measured, #0067E0 on Royal #0A1776 is 2.87:1, below the 4.5:1 floor and
   visibly dim. It only became a problem on 26 Jul, when the closing CTA's
   marker was demoted to the emphasis word to stay inside the six-marker cap.
   Periwinkle on the same ground is 11.28:1, and it is the established
   dark-system pairing.
   ========================================================================== */
.iws-dark .em,.hp-cta .em,.iwsstu .em,
[class*="dark"] .em{color:var(--iws-peri,#CFE0FF)!important;}


/* ==========================================================================
   PHONE REPAIRS found by walking the homepage 700px at a time, 26 Jul
   ========================================================================== */
@media (max-width:1199px){
  /* Footer links were 27px tall against the 44px floor: eleven of them in the
     footer alone, and they are the last thing a parent reaches for. Padding,
     not font size, so nothing reflows. */
  .iws-ft li > a,.thim-ekit__footer li > a,.iws-ft p > a{
    padding-top:9px;padding-bottom:9px;min-height:44px;
    display:inline-flex;align-items:center;
  }
}
@media (max-width:600px){
  /* MATT VICKERY at 36px needs 275px in a 260px box, white-space:nowrap and
     overflow:visible, so it ran straight out of its card. Measured on the
     served page. */
  .iws-fac-card-name{font-size:clamp(19px,5.4vw,27px)!important;white-space:normal!important;}
}


/* ---- Marker highlight, amber variant  (.hl.hl--amber) --------------------
   Burak, 26 Jul: "make the text white and the highlight orange gradient, let
   see how it comes out". A trial on the week-section heading.

   The gradient runs #B45309 to #7C2D12 rather than opening on the brighter
   #D97706, and that is forced by IWS_DESIGN.md 3.5, not a preference: white on
   #D97706 measures 3.19:1 and fails the 4.5:1 bar, while #B45309 measures
   5.02:1 and passes. Every stop in a gradient carries the text, so the
   LIGHTEST stop sets the limit. A brighter orange and white type cannot both
   be true.

   It inherits the sweep, the padding, the radius and the box-decoration-break
   from .hl, so only the fill changes. */
.hl.hl--amber{
  background-image:linear-gradient(90deg,var(--iws-amber-ink,#B45309) 0%,#7C2D12 100%);
}
/* On a dark section the base .hl flips to periwinkle with dark text; the amber
   variant would lose its contrast there, so it flips to the same light block
   rather than staying orange. */
.on-dark .hl.hl--amber,.iws-dark .hl.hl--amber,.iwshero .hl.hl--amber{
  background-image:linear-gradient(90deg,var(--iws-peri,#CFE0FF) 0%,#EAF1FF 100%);
}


/* ==========================================================================
   MOBILE SCROLL AND CHROME  (26 Jul 2026)

   1. THE SCROLL LOCK. Burak on iPhone: "it doesnt allow me to scroll past the
      hero section on mobile". Headless Chrome scrolls the page fine, and that
      is not a contradiction: the theme sets `body{overflow-x:hidden}`
      (style.css, phys-core), which the browser PROPAGATES to the viewport, and
      that exact pattern is a long-standing iOS Safari touch-scroll breaker
      that desktop Chrome does not reproduce.

      `overflow-x: clip` does the same job of stopping sideways drift WITHOUT
      creating a scroll container, so the viewport keeps its native touch
      handling. Ruled out first, by measurement, so nobody re-treads it: the
      lightbox lock class .iwsvid-lock was NOT on <html>, and the legacy
      `body:is(:has(.iws-ss-hero),:has(.iws-st-hero))` rule does not match the
      homepage at all. */
html body{overflow-x:clip;}

/* 2. The theme's blue circular back-to-top. Burak: "get rid of the blue
      background arrow on mobile view". On a phone it sits on top of the sticky
      Enquire and WhatsApp bar, and a phone already has a fast way back up. */
@media (max-width:900px){
  html body #back-to-top,
  html body .btn-back-to-top{display:none!important;}
}


/* ==========================================================================
   HEADER CALL-TO-ACTION PAIR, DESKTOP  (27 Jul 2026)

   Burak: "fix the cta buttons as well so they are on brand, the ones on the
   nav bar". The MOBILE pair was already correct (see the max-width:1199px
   block above: Sora, Royal to Sky gradient, white text). Desktop was still the
   agency's: Inter at 600, a transparent fill and a 1px white border. Three
   separate rule breaks in one small component.

     1. Inter on a button. 3.4 is explicit that Sora carries buttons; Inter is
        body copy only.
     2. A transparent fill with a white hairline. That reads only while the
        header is transparent over the dark hero. The same button on a white
        header (every inner page, and this page once scrolled) is white on
        white with a white outline.
     3. Burak's standing rule, 25 Jul: never a flat fill on a CTA background.
        Transparent is not a gradient either.

   Fixed by giving desktop the treatment mobile already had, so the component
   is one thing at both sizes rather than two designs sharing a class name. A
   filled gradient is also what makes point 2 go away by construction: it
   carries its own ground, so it is legible on a transparent header and a white
   one without needing a per-state rule.

   Geometry is deliberately unchanged (44px tall, 8px radius, the measured
   desktop values) so the header does not reflow.

   SPECIFICITY, measured rather than guessed. Two legacy inline rules set
   `background:none!important` on this button:
       body .mfhcta a.mf-enq.mf-enq                                   (0,3,2)
       body.iws-transparent-hero .site-header:not(.iws-solid)
         .mfhcta a.mf-enq.mf-enq                                      (0,6,2)
   The obvious `html body .mfhcta a.mf-enq.mf-enq.mf-enq` is only (0,4,3), and
   class count is compared before element count, so it LOST and the button kept
   font and radius while silently dropping the gradient. The class is therefore
   repeated to seven, giving (0,7,3), which clears the (0,6,2) rule on the axis
   that actually decides it. Same brute-force shape already used for `.hl` in
   this file; ugly, and cheaper than unpicking a 142k snippet.

   `background:none` is the SHORTHAND, so it resets background-image. Setting
   background-image at higher specificity is enough to win the property back.
   ========================================================================== */
@media (min-width:1200px){

  /* The wrapper's own layout. Lived in the retired iws-header-cta.css until
     28 Jul 2026; without it the two buttons stack instead of sitting in a row. */
  html body .mfhcta{display:flex;align-items:center;gap:12px;}

  html body .mfhcta a.mf-enq.mf-enq.mf-enq,
  html body .mfhcta a.mf-wa.mf-wa.mf-wa{
    font-family:var(--iws-font-display)!important;
    font-weight:600!important;
    border:0!important;
    border-radius:8px!important;
    display:inline-flex!important;align-items:center;justify-content:center;
    text-decoration:none;
    transition:transform .22s var(--iws-ease),box-shadow .22s var(--iws-ease),
               background-position .22s var(--iws-ease);
  }
  html body .mfhcta a.mf-enq.mf-enq.mf-enq{
    height:52px!important;padding:0 30px!important;font-size:15.5px!important;
    letter-spacing:.02em!important;white-space:nowrap!important;
    color:#FFFFFF!important;
    background-color:transparent!important;
    background-image:linear-gradient(120deg,var(--iws-royal,#0A1776) 0%,var(--iws-sky,#0067E0) 100%)!important;
    background-size:150% 100%!important;background-position:0% 0!important;
    box-shadow:0 8px 20px -10px rgba(10,23,118,.65)!important;  /* M2: !important, else an inline box-shadow:none wins */
  }
  html body .mfhcta a.mf-wa.mf-wa.mf-wa{
    height:52px!important;width:52px!important;padding:0!important;
    color:#FFFFFF!important;
    /* WhatsApp's own green, kept because it identifies the platform rather
       than the brand, exactly as the mobile bar already does. Gradient, not a
       flat fill, so the no-solid-CTA rule holds here too. */
    background-image:linear-gradient(140deg,#25D366 0%,#12A150 100%)!important;
    box-shadow:0 8px 20px -10px rgba(18,161,80,.7)!important;
  }
  html body .mfhcta a.mf-wa.mf-wa.mf-wa svg{width:24px!important;height:24px!important;display:block;fill:currentColor;}
  html body .mfhcta a.mf-enq.mf-enq.mf-enq:hover{
    background-position:100% 0!important;transform:translateY(-1px);
    box-shadow:0 12px 26px -10px rgba(10,23,118,.8)!important;
  }
  html body .mfhcta a.mf-wa.mf-wa.mf-wa:hover{
    transform:translateY(-1px)!important;
    box-shadow:0 12px 26px -10px rgba(18,161,80,.85)!important;
  }
}


/* ==========================================================================
   KEYBOARD ACCESS: THE MAIN NAV, AND FOCUS VISIBILITY SITE-WIDE  (27 Jul 2026)

   Two separate defects, both found by the site audit, both in inherited code,
   both of which made the site unusable without a mouse. Fixed together because
   fixing either alone still leaves a keyboard user stuck.

   1. THE DROPDOWNS WERE UNREACHABLE.
      thim-elementor-kit ships
        .thim-ekits-menu__dropdown{opacity:0;pointer-events:none;visibility:hidden}
      and restores it on :hover ONLY. `visibility:hidden` removes descendants
      from the tab order outright, so 19 sub-menu links across Programmes (5),
      About (6), How It Works (4) and Admissions (4) could not be reached at all.
      The plugin's alternative open state, .thim-ekits-menu__is-hover, is toggled
      by a click listener on a <span> with no tabindex and no role, so it is not
      keyboard-operable either.
      An existing :focus-within rule in iws-legacy.css sets `transform` only, so
      it looked like this was already handled and it was not. Restoring the three
      properties that actually gate reachability is the fix, and !important is
      required because the base declarations ship from the plugin.

   2. THE FOCUS RING WAS BEING DELETED SITE-WIDE.
      The parent theme's style.css carries `a:focus{outline:none !important;
      box-shadow:none !important}`. An !important author declaration beats any
      non-important one at any specificity, and :focus-visible is a subset of
      :focus, so EVERY focus outline this file declares was silently discarded.
      Measured on the homepage alone: 29 controls (.iwsbr x9, .iwsvt__card x12,
      .iwspw__go x4, .iwsstu__btn x2, .iwsbar a x2) declared an outline that
      never painted, plus every in-content link and Elementor button.
      Nothing anywhere restored it: across every served stylesheet the only two
      `outline...!important` rules were both `outline:none!important`.

      The fix is deliberately :focus-visible, not :focus, so a mouse click still
      shows no ring; only keyboard and programmatic focus do. That is why the
      theme's rule is neutralised rather than simply overridden with a permanent
      outline, which would have put a ring around every clicked button.
   ========================================================================== */

/* --- 1. reachable dropdowns ---------------------------------------------- */
.navbar-main-menu .menu-item-has-children:focus-within > .thim-ekits-menu__dropdown,
.navbar-main-menu .thim-ekits-menu__has-dropdown:focus-within > .thim-ekits-menu__dropdown{
  opacity:1!important;
  visibility:visible!important;
  pointer-events:auto!important;
}

/* --- 2. undo the theme's blanket outline kill, then define one ring ------- */
/* `revert` hands the property back to the browser default rather than guessing
   a value, so anything the UA would have drawn is drawn again. */
html body a:focus{outline:revert!important;box-shadow:revert!important;}
/* Mouse and touch focus stays clean. */
html body a:focus:not(:focus-visible){outline:none!important;}
/* One ring, everywhere, in the brand's own accent. Sky on white measures
   4.58:1, comfortably past the 3:1 that a non-text indicator needs. */
html body a:focus-visible,
html body button:focus-visible,
html body [role="button"]:focus-visible,
html body input:focus-visible,
html body select:focus-visible,
html body textarea:focus-visible{
  outline:2px solid var(--iws-sky,#0067E0)!important;
  outline-offset:3px!important;
  border-radius:3px;
}
/* On the dark system Sky is 2.87:1 on Royal and would fail, so the ring flips to
   Periwinkle there, the same handover 4.3b defines for the amber marker. */
html body .iws-dark a:focus-visible,
html body .on-dark a:focus-visible,
html body .iwshero a:focus-visible,
html body .iwsbar a:focus-visible,
html body .iws-ft a:focus-visible{
  outline-color:var(--iws-peri,#CFE0FF)!important;
}


/* ==========================================================================
   MOVED HERE FROM iws-home.css, 27 Jul 2026.

   The pathway-storyboard block (.iwssb) lived in iws-home.css, which
   functions.php enqueues only `if ( is_front_page() )`. When the section moved
   off the homepage both halves broke at once: the homepage, which no longer
   contains a single .iwssb element, kept shipping every rule, while
   /programmes/a-level/, which DOES render .iwssb, got none of them. Measured
   there: .iwssb__crests computed to display:block with grid-template-columns
   :none, so six 900x80 crests stacked one per line down 481px instead of a
   6-column grid capped at 56px tall.

   Same trap Website/STATE.md records for the .hl marker: anything used off the
   front page must not live in iws-home.css. Moved whole, not duplicated.

   The explorer (.iwsxp) rules that had been appended into the same banner
   section stay in iws-home.css, because the explorer IS homepage-only. One
   reduced-motion rule named both components and was split accordingly.
   ========================================================================== */

/* ==========================================================================
   THE UNIVERSITY AND CAREER PATHWAY STORYBOARD  (.iwssb)
   Built 26 Jul 2026, replacing a static six-logo grid.

   WHY. The grid showed the destination and nothing else, so a parent had to
   take the leap from "online school" to "Oxford" on trust. The storyboard
   shows the ROUTE: study, achieve, apply, recognised, beyond. The crests stop
   being decoration and become evidence at the stop where they are true.

   The claims discipline is IWS_DESIGN.md 8.6, written the same day after the
   rule was first drawn too broadly: recognition is a claim about the
   QUALIFICATION and is evidenced; placement is a claim about STUDENTS and
   needs destination data. A Levels are what UK universities admit on, so the
   crests belong here. The final stop uses three real named students rather
   than an invented outcome, because IWS publishes no destination data.
   ========================================================================== */
.iwssb{padding:clamp(66px,9vw,112px) 0 clamp(56px,8vw,92px);
  background:linear-gradient(180deg,#F8FAFC 0%,#FFFFFF 62%);}
.iwssb__in{max-width:820px;margin:0 auto clamp(34px,4.5vw,50px);padding:0 24px;
  text-align:center;box-sizing:border-box;}
.iwssb__ey{display:block;font-family:var(--iws-font-display);
  font-size:11.5px;font-weight:600;letter-spacing:.16em;text-transform:uppercase;
  color:var(--iws-sky,#0067E0);margin-bottom:14px;}
.iwssb__in h2{font-family:var(--iws-font-display)!important;
  font-size:clamp(27px,4vw,44px);font-weight:800;line-height:1.16;
  color:var(--iws-royal,#0A1776);margin:0 0 14px;text-wrap:balance;}
.iwssb__sub{font-family:var(--iws-font-body);
  font-size:clamp(15.5px,1.6vw,17px);line-height:1.62;color:#475569;margin:0;}

/* ---- the rail: five stops on one line, connected ----------------------- */
.iwssb__rail{position:relative;max-width:1080px;margin:0 auto clamp(30px,4vw,44px);
  padding:0 24px;box-sizing:border-box;display:grid;
  grid-template-columns:repeat(5,1fr);gap:0;}
/* the connecting thread, behind the nodes */
.iwssb__rail::before{content:"";position:absolute;left:calc(24px + 10%);right:calc(24px + 10%);
  top:21px;height:2px;background:rgba(10,23,118,.14);border-radius:2px;}
.iwssb__stop{position:relative;background:none;border:0;padding:0 6px;cursor:pointer;
  display:flex;flex-direction:column;align-items:center;gap:10px;
  font-family:var(--iws-font-display);}
.iwssb__stop:focus-visible{outline:3px solid var(--iws-sky,#0067E0);outline-offset:4px;border-radius:10px;}
.iwssb__dot{position:relative;z-index:1;width:42px;height:42px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  font-size:13px;font-weight:700;
  background:#fff;color:#5A6488;border:2px solid rgba(10,23,118,.16);
  transition:background .24s var(--iws-ease,cubic-bezier(.22,.61,.36,1)),
             color .24s,border-color .24s,box-shadow .24s,transform .24s;}
.iwssb__stop:hover .iwssb__dot{border-color:var(--iws-sky,#0067E0);color:var(--iws-royal,#0A1776);}
.iwssb__lbl{font-size:13px;font-weight:600;color:#6B7591;line-height:1.3;text-align:center;
  transition:color .24s var(--iws-ease,cubic-bezier(.22,.61,.36,1));}
.iwssb__stop.is-on .iwssb__dot{
  background:linear-gradient(135deg,var(--iws-royal,#0A1776),var(--iws-sky,#0067E0));
  border-color:transparent;color:#fff;transform:scale(1.06);
  box-shadow:0 8px 20px rgba(10,23,118,.26);}
.iwssb__stop.is-on .iwssb__lbl{color:var(--iws-royal,#0A1776);font-weight:700;}
/* stops already travelled read as done, so the rail shows progress */
.iwssb__stop.is-past .iwssb__dot{border-color:var(--iws-sky,#0067E0);color:var(--iws-sky,#0067E0);}

/* ---- the panels -------------------------------------------------------- */
.iwssb__panels{position:relative;max-width:1080px;margin:0 auto;padding:0 24px;box-sizing:border-box;}
.iwssb__panel{opacity:0;transform:translateY(10px);position:absolute;inset:0 24px;
  pointer-events:none;
  transition:opacity .26s var(--iws-ease,cubic-bezier(.22,.61,.36,1)),
             transform .34s var(--iws-ease,cubic-bezier(.22,.61,.36,1));}
.iwssb__panel.is-on{opacity:1;transform:none;position:relative;inset:auto;pointer-events:auto;}
.iwssb__card{background:#fff;border:1px solid rgba(10,23,118,.10);border-radius:20px;
  padding:clamp(26px,3.4vw,42px);box-shadow:0 18px 44px rgba(10,23,118,.09);}
.iwssb__kick{display:block;font-family:var(--iws-font-display);
  font-size:11.5px;font-weight:600;letter-spacing:.15em;text-transform:uppercase;
  color:var(--iws-amber-ink,#B45309);margin-bottom:11px;}
.iwssb__card h3{font-family:var(--iws-font-display)!important;
  font-size:clamp(21px,2.5vw,29px);font-weight:700;line-height:1.24;
  color:var(--iws-royal,#0A1776);margin:0 0 12px;}
.iwssb__card p{font-family:var(--iws-font-body);
  font-size:16.5px;line-height:1.68;color:#475569;margin:0;max-width:62ch;}

/* the crest grid, only inside the stop where it is a true statement */
.iwssb__crests{display:grid;grid-template-columns:repeat(6,1fr);gap:16px;
  align-items:center;margin-top:26px;}
.iwssb__crest{display:flex;align-items:center;justify-content:center;
  padding:14px 10px;border:1px solid rgba(10,23,118,.09);border-radius:12px;background:#fff;}
.iwssb__crest img{max-height:56px;max-width:100%;width:auto;object-fit:contain;
  filter:grayscale(1);opacity:.78;transition:filter .24s,opacity .24s;}
.iwssb__crest:hover img{filter:grayscale(0);opacity:1;}

/* real named students, the honest proof at the far end */
.iwssb__grads{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-top:26px;}
.iwssb__grad{padding:20px 18px;border-radius:14px;
  background:linear-gradient(180deg,rgba(0,103,224,.05),rgba(0,103,224,0));
  border:1px solid rgba(10,23,118,.10);}
.iwssb__gname{display:block;font-family:var(--iws-font-display);
  font-size:16px;font-weight:700;color:var(--iws-royal,#0A1776);margin-bottom:5px;}
.iwssb__gwhat{font-family:var(--iws-font-body);
  font-size:14.5px;line-height:1.55;color:#475569;}

@media (max-width:900px){
  .iwssb__rail{grid-template-columns:repeat(5,1fr);padding:0 12px;}
  .iwssb__rail::before{left:calc(12px + 10%);right:calc(12px + 10%);}
  .iwssb__dot{width:38px;height:38px;font-size:12px;}
  .iwssb__lbl{font-size:11px;}
  .iwssb__crests{grid-template-columns:repeat(3,1fr);gap:12px;}
  .iwssb__grads{grid-template-columns:1fr;}
  .iwssb__panel{inset:0 24px;}
}
@media (prefers-reduced-motion:reduce){
  .iwssb__panel,.iwssb__dot,.iwssb__lbl,.iwssb__crest img{transition:none;}
  .iwssb__panel{transform:none;}
  .iwssb__stop.is-on .iwssb__dot{transform:none;}
}


/* ---- Storyboard v2, 26 Jul: affordance and imagery -----------------------
   Burak: "hard to understand... add arrows so users know this section is
   interactive and those circle buttons are clickable... currently its only
   text and not super interactive, support the text with video/image assets".

   Three changes. The nodes now look pressable rather than decorative, there
   are explicit previous and next controls, and every stop carries a picture
   so the argument is shown as well as stated. */

/* the card becomes two columns: picture and words, side by side */
.iwssb__card{display:grid;grid-template-columns:minmax(0,.92fr) minmax(0,1fr);
  gap:clamp(22px,3vw,40px);align-items:center;}
.iwssb__shot{position:relative;border-radius:14px;overflow:hidden;
  aspect-ratio:4/3;background:#0B1444;box-shadow:0 14px 34px rgba(10,23,118,.16);}
.iwssb__shot img,.iwssb__shot video{width:100%;height:100%;object-fit:cover;display:block;}
.iwssb__words{min-width:0;}
/* the crest grid and the graduate cards span both columns, under the pair */
.iwssb__crests,.iwssb__grads{grid-column:1 / -1;}

/* nodes read as pressable: a ring on hover, and the cursor says so */
.iwssb__stop{border-radius:12px;transition:background .2s var(--iws-ease,cubic-bezier(.22,.61,.36,1));}
.iwssb__stop:hover{background:rgba(0,103,224,.05);}
.iwssb__stop:hover .iwssb__dot{transform:translateY(-2px);
  box-shadow:0 8px 18px rgba(10,23,118,.18);}
/* a one-time hint on the first node so the affordance is discoverable without
   hovering. It stops as soon as the visitor uses the rail. */
@keyframes iwssb-hint{0%,100%{box-shadow:0 0 0 0 rgba(0,103,224,.34);}
  50%{box-shadow:0 0 0 9px rgba(0,103,224,0);}}
.iwssb:not(.is-used) .iwssb__stop.is-on .iwssb__dot{animation:iwssb-hint 2.4s ease-out 3;}

/* explicit previous and next, because a rail alone is not an instruction */
.iwssb__nav{display:flex;align-items:center;justify-content:space-between;gap:14px;
  max-width:1080px;margin:20px auto 0;padding:0 24px;box-sizing:border-box;}
.iwssb__arw{display:inline-flex;align-items:center;gap:9px;
  min-height:44px;padding:11px 20px;border-radius:12px;cursor:pointer;
  border:1px solid rgba(10,23,118,.16);background:#fff;
  font-family:var(--iws-font-display);
  font-size:14px;font-weight:600;color:var(--iws-royal,#0A1776);
  transition:border-color .2s,box-shadow .2s,transform .2s,opacity .2s;}
.iwssb__arw:hover:not(:disabled){border-color:var(--iws-sky,#0067E0);
  box-shadow:0 8px 18px rgba(10,23,118,.12);transform:translateY(-1px);}
.iwssb__arw:focus-visible{outline:3px solid var(--iws-sky,#0067E0);outline-offset:3px;}
.iwssb__arw:disabled{opacity:.34;cursor:default;}
.iwssb__count{font-family:var(--iws-font-display);
  font-size:13px;font-weight:600;color:#6B7591;font-variant-numeric:tabular-nums;}

@media (max-width:900px){
  .iwssb__card{grid-template-columns:1fr;gap:20px;}
  .iwssb__shot{aspect-ratio:16/9;}
  .iwssb__nav{padding:0 16px;}
  .iwssb__arw{padding:11px 15px;font-size:13px;}
}
@media (prefers-reduced-motion:reduce){
  .iwssb:not(.is-used) .iwssb__stop.is-on .iwssb__dot{animation:none;}
  .iwssb__stop,.iwssb__arw{transition:none;}
  .iwssb__stop:hover .iwssb__dot{transform:none;}
}


/* Storyboard dot, fill fix 26 Jul. Burak: "the background colour is not full
   inside the circle". background-clip was border-box while background-origin
   was still the default padding-box, so the gradient was SIZED to the padding
   box but PAINTED across the border box, smearing its end colours into a ring
   at the edge. Origin and clip have to agree. */
.iwssb__dot{background-origin:border-box;background-clip:border-box;}


/* ---- Storyboard v3, 26 Jul ----------------------------------------------
   Burak: "make the circles get highlighted rather than highlighting a
   background box... make sure the circles have full background colour
   currently it looks bugged, make sure the gradient is smooth".

   THE BUG, and it is a CSS semantics one rather than a value one. The active
   rule sets `background: linear-gradient(...)`, and the SHORTHAND resets
   background-origin and background-clip to their initial values. My earlier
   `.iwssb__dot{background-origin:border-box}` was (0,1,0) against the
   shorthand's (0,3,0), so it never applied and the gradient stayed sized to
   the padding box while painting across the 2px border: a visible seam ring.
   The properties have to be set INSIDE the same rule, after the shorthand. */
.iwssb__stop.is-on .iwssb__dot{
  background-image:linear-gradient(140deg,#0A1776 0%,#0067E0 100%);
  background-color:#0A1776;          /* under the gradient, so no seam anywhere */
  background-origin:border-box;
  background-clip:border-box;
  border:2px solid transparent;
}
/* Highlight the circle itself. The rounded box behind the whole stop read as a
   stray panel rather than a control, which is what Burak means by unprofessional. */
.iwssb__stop:hover{background:none;}
.iwssb__stop:hover .iwssb__dot{
  border-color:var(--iws-sky,#0067E0);
  box-shadow:0 0 0 5px rgba(0,103,224,.14);
  transform:translateY(-2px);
}
.iwssb__stop.is-on:hover .iwssb__dot{
  border-color:transparent;
  box-shadow:0 0 0 6px rgba(0,103,224,.18),0 8px 20px rgba(10,23,118,.26);
}

@media (prefers-reduced-motion:reduce){
  .iwssb__stop:hover .iwssb__dot{transition:none;}
}


/* ==========================================================================
   ACCORDION STATE, ANNOUNCED  (27 Jul 2026)
   47 disclosure buttons across 7 pages (/faq/ alone has 23) toggled open and
   shut with no aria-expanded, so a screen-reader user was told nothing about
   whether an answer was open. The toggle itself is a delegated click listener in
   a page-level inline script, so rather than edit that in 7 places the state is
   mirrored from here, site-wide, in the capture phase's wake.
   ========================================================================== */

/* Contrast: #5A6488 measured 3.07:1 on white and fails the 4.5:1 bar for normal
   text. #5A6488 is already used elsewhere in this file and measures 5.81:1, so
   this adds no new value to the palette. */
.iwsxp__kicker{color:#5A6488;}


/* L4 (27 Jul): the mobile drawer injects an "All <section>" link as the first
   item of each submenu so the parent page stays reachable when the parent
   becomes a toggle. That injection runs at boot regardless of viewport, so on
   desktop the same link appeared inside the mega-menu too. The drawer lives
   below 1200px (the burger breakpoint), so the injected link is simply hidden
   above it. Cheaper and safer than re-running the DOM insert on every resize. */
@media (min-width:1200px){
  .iws-parent-link{display:none!important;}
}


/* ==========================================================================
   DESIGN-SYSTEM CONSOLIDATION  (27 Jul 2026, Burak: "do the design-system
   consolidation for buttons, eyebrows and colours")

   The site had grown 7 different primary-CTA treatments and ~9 eyebrow styles,
   in two typefaces, five sizes and a scatter of off-palette blues. The audit
   catalogued them. This block is the single source of truth that unifies the
   VISIBLE, brand-facing ones; the subtle section-background tints (#F8FAFC and
   friends) and non-rendering plugin defaults are deliberately left, because
   flattening those would damage intentional design, not fix inconsistency.
   ========================================================================== */

:root{
  /* The one primary-CTA gradient. 120deg is the §10 direction the header button
     already uses; the rest of the site is migrated onto it here. */
  --iws-grad-cta:linear-gradient(120deg,#B45309 0%,#7C2D12 100%);
  /* Hover reverses the same two named stops: no third colour enters the
     system, and the lighter stop still clears AA against white. */
  --iws-grad-cta-hover:linear-gradient(120deg,#7C2D12 0%,#B45309 100%);
}

/* --- 1. ONE PRIMARY BUTTON ------------------------------------------------
   Every primary "book a consultation / enquire" CTA class, unified to the §10
   treatment: Royal->Sky gradient, Sora 600, white, 8px. !important because the
   per-page gradients ship from <style> blocks inside Elementor HTML widgets.
   Deliberately NOT included: .mf-enq (already canonical, its own block above)
   and .iwshero__btn--primary (inside the hero Burak asked to leave alone). */
html body .au-cta-btn,
html body a.p,
html body .hb1,
html body .ipc__btn,
html body .pf-btn-primary,
html body .iwsp__btn,
html body .bkt2__tab,
html body a.b1,
html body a.b2{
  background-color:transparent!important;
  background-image:var(--iws-grad-cta)!important;
  background-size:150% 100%!important;
  background-position:0 0!important;
  color:#fff!important;
  font-family:var(--iws-font-display)!important;
  font-weight:600!important;
  border:0!important;
  border-radius:8px!important;
  transition:background-position .22s var(--iws-ease),transform .22s var(--iws-ease),
             box-shadow .22s var(--iws-ease)!important;
}
html body .au-cta-btn:hover,
html body a.p:hover,
html body .hb1:hover,
html body .ipc__btn:hover,
html body .pf-btn-primary:hover,
html body .iwsp__btn:hover,
html body .bkt2__tab:hover,
html body a.b1:hover,
html body a.b2:hover{
  background-position:100% 0!important;
  transform:translateY(-1px);
}
/* .b2 is the "explore programmes" secondary on the market pages: it was a
   near-invisible white 6-8% wash that even disagreed between the three otherwise
   identical pages. Made a proper Royal-outline ghost (§10 secondary), so primary
   and secondary read as one system. */
html body a.b2{
  background-image:none!important;
  background-color:transparent!important;
  color:var(--iws-royal,#0A1776)!important;
  border:2px solid var(--iws-royal,#0A1776)!important;
}
html body a.b2:hover{
  background-image:var(--iws-grad-cta)!important;
  color:#fff!important;border-color:transparent!important;
}

/* --- 2. ONE EYEBROW -------------------------------------------------------
   The section-intro eyebrow label. §4.1 + §14: Sora 700, 11px, 0.16em tracking,
   uppercase, Sky on light / Periwinkle on dark. This groups the ad-hoc classes
   the audit found (two typefaces, seven inks, five sizes, sub-floor tracking)
   onto one definition. Card-meta and functional labels (form steps, kickers)
   are NOT eyebrows and are handled by the colour tokens, not here. */
html body .au-hero-eye,
html body .au-vm-head-eye,
html body .ht-eye,
html body .au-accred-eye,
html body .au-faq-head-eye,
html body .au-cta-eye,
html body .iws-prog .ey,
html body .iws-mm-label,
html body .pf-eyebrow,
html body .ipc__eyebrow,
html body .eyebrow,
html body .ifc-eyebrow,
html body .iws-eyebrow{
  font-family:var(--iws-font-display)!important;
  font-weight:700!important;
  font-size:11px!important;
  letter-spacing:0.16em!important;
  text-transform:uppercase!important;
  color:var(--iws-sky,#0067E0)!important;
}
/* On a dark ground the eyebrow flips to Sky Light (§14: small labels on dark),
   not Sky, which is 2.87:1 on Royal. */
html body .iws-dark .au-hero-eye,
html body .on-dark .au-hero-eye,
html body .iwshero .au-hero-eye,
html body .iws-dark .iws-eyebrow,
html body .on-dark .iws-eyebrow{
  color:var(--iws-sky-light,#7BA7FF)!important;
}


/* Inner-page hero eyebrows (`.ph-eye`, `.pg-hero-eye`) sit on the dark navy hero.
   Unify the typeface and colour without forcing the size, so a hero eyebrow keeps
   its intended scale. (27 Jul design-system consolidation.) */
html body .ph-eye,
html body .pg-hero-eye{
  font-family:var(--iws-font-display)!important;
  font-weight:700!important;
  letter-spacing:0.16em!important;
  text-transform:uppercase!important;
  color:var(--iws-sky-light,#7BA7FF)!important;
}


/* ------------------------------------------------------------------
   NAV LABEL TYPEFACE, added 28 Jul 2026.

   The theme's hover animation splits every nav label into per-character
   spans inside a .js_hover wrapper. That wrapper is matched by the
   theme rule

       .inner-navigation, .inner-navigation span, ...
           { font-family:var(--iws-font-body) !important }

   while the link itself is matched by

       .elementor-nav-menu a, .main-navigation a, ...
           { font-family:var(--iws-font-display) !important }

   So the label CHANGED TYPEFACE mid-load, Sora then Inter, and narrowed
   from 102.4px to 97.7px ("For Schools", measured 28 Jul 2026). Every
   nav item shifted with it. That is what read as "the nav text gets
   bigger for a split second then goes back to normal".

   !important is required here: the theme's Inter rule carries it, so a
   plain declaration loses regardless of specificity. This selector is
   (0,3,5) against their (0,1,1), so among !important declarations this
   one wins.

   Two things are fixed together: identical metrics before and after the
   split, so no reflow; and the nav settles in Sora, which is what
   IWS_DESIGN.md specifies for nav links and labels. It had been
   settling in Inter, which was simply the wrong face.
   ------------------------------------------------------------------ */
html body .site-header .navbar-main-menu > li > a .js_hover,
html body .site-header .navbar-main-menu > li > a .js_hover span{
	font-family: inherit !important;
}

/* ============================================================================
   MOBILE CTA BAR: stop a transformed ancestor stealing its containing block.
   Added 30 Jul 2026.

   Symptom, measured at 390px with the CPU throttled 6x: the fixed bottom CTA
   bar was correct at t=1.2s, collapsed to 28x73 up in the header at t=2.3s,
   and returned to 390x73 at bottom at t=3.5s. Roughly 1.3 seconds of a
   visibly wrong CTA on every mobile page load.

   Cause. At the broken moment the element still computes
   `position:fixed; left:0; right:0; bottom:0` — the bar CSS was applying the
   whole time. It cannot be 28px wide against the viewport, and that is the
   tell: the viewport was not its containing block.
   `DIV.elementor-element-05fc3d0`, an Elementor entrance-animation container
   three levels above the CTA and inside #masthead, carries
   `will-change: opacity, transform` while its animation is armed.
   **A `will-change` that names `transform` creates a containing block for
   `position:fixed` descendants, exactly as a real `transform` does.** So the
   bar resolved left/right/bottom against that div instead of the viewport, and
   snapped back the moment Elementor cleared the hint.

   Fix. `will-change` is only a compositor hint, so clearing it does not stop
   the entrance animation: opacity and transform still animate. Measured at the
   broken moment, that ancestor's own `transform` was `none` — only the hint was
   set — so removing the hint is sufficient and nothing visual is lost.

   `:has()` is used deliberately instead of the literal `elementor-element-05fc3d0`
   class: Elementor regenerates those ids when a page is edited, so hardcoding it
   would silently stop working the first time somebody touches the header. The
   selector is scoped to the #masthead subtree so the `:has()` scan stays cheap,
   and to <=1199px because the fixed bar only exists there.
   ========================================================================== */
@media (max-width: 1199px) {
  #masthead .elementor-element:has(.mfhcta) {
    will-change: auto !important;
  }
}

/* ============================================================================
   RESERVE THE HERO IMAGE BOX. Added 30 Jul 2026.

   Measured layout shift, CPU throttled 4x, PerformanceObserver('layout-shift')
   with sources so the shifting node is named rather than guessed:
     /accreditations/  CLS 0.2377 mobile · 0.1736 desktop
     /results/         CLS 0.1397 mobile · 0.1914 desktop
     /reviews/         CLS 0.1012 mobile · 0.0732 desktop
   Top source on all three: DIV.pg-hero-img, going 0x330 -> 280x330 on mobile.

   Cause, read off the served markup rather than inferred:
     <div class="pg-hero-img">
       <img src="...webp" alt="IWS student" loading="lazy">   <- no width, no height
     <style>.pg-hero-img img{height:455px}</style>            <- height only, no width

   The image carries NO width/height attributes, so the browser has no intrinsic
   size to lay out from, and the container is zero wide until the file arrives.
   `loading="lazy"` makes it worse: every one of these is ABOVE THE FOLD on its
   own page, which is the classic lazy-loading anti-pattern.

   Every one of these images measures 1200x1000, i.e. 6:5 exactly, so declaring
   the ratio lets the browser reserve the correct box at first paint. Ratio
   rather than a fixed width because the rendered width differs per page and
   breakpoint (430px desktop, 280px mobile) while the ratio does not.

   `object-fit:cover` is set alongside so that if an image is ever swapped for
   one of a different ratio the box stays correct and the photograph crops,
   rather than the box distorting to match the file.
   ========================================================================== */
.pg-hero-img img,
.au-hero img {
  aspect-ratio: 6 / 5;
  object-fit: cover;
}

/* ============================================================================
   /accreditations/ HERO BOX: stop the photograph that is about to be deleted.
   Added 30 Jul 2026. Page 34846.

   Measured: CLS 0.2377 mobile, the worst on the site, source DIV.pg-hero-img.
   The page ships a photograph in .pg-hero-img, then iws-page.js block 3 REMOVES
   it (measured `hasImg:false` afterwards, children 2 -> 1) and injects
   .iws-acc-grid in its place, at a different height: 330 -> 212 mobile,
   470 -> 268 desktop. So the visitor sees a photograph that was never the
   intended content, and then the page jumps when it is deleted.

   Two things fixed at once, both in CSS, no JS touched:
   1. Hide anything in that box which is not the grid, so the doomed photograph
      and its badge never paint. This is the "no wrong intermediate state" rule:
      hiding content that is about to be removed is not the same as hiding
      content that is about to appear.
   2. Reserve the grid's real measured height so the injection moves nothing.

   Heights are the measured finals. The breakpoint is 1199/1200, matching the
   rest of the header work rather than introducing a fifth boundary.

   Trade-off, stated rather than hidden: with JavaScript disabled this box is now
   empty instead of showing a photograph. That is deliberate. The photograph is
   not the intended content of an accreditations panel, and the accreditation
   marks themselves appear elsewhere on the page.
   ========================================================================== */
body.page-id-34846 .pg-hero-img > *:not(.iws-acc-grid) { display: none !important; }
body.page-id-34846 .pg-hero-img { min-height: 212px; }
@media (min-width: 1200px) {
  body.page-id-34846 .pg-hero-img { min-height: 268px; }
}

/* ============================================================================
   HEADER, 30 Jul 2026 (second pass). Four changes, all at Burak's instruction.

   1. THE HEADER IS ONE THREE-COLUMN GRID, which is what fixes the symmetry.
      Measured before: outer edges were already balanced (154px each side) and
      everything was vertically centred at y=89, but the NAV BLOCK SAT 54.5px
      LEFT OF THE VIEWPORT CENTRE. With `justify-content:space-between` the
      middle child lands wherever the two outer children leave room, and the logo
      (120px) and the action cluster (230px) are not the same width, so the menu
      could never be centred. Equal `1fr` outer columns centre the middle column
      regardless of what the outer two contain. This is the standard three-column
      header pattern and it is stable across page changes because nothing depends
      on the children's measured widths.

   2. The WhatsApp button is hidden on desktop (Burak: "remove the whatsapp
      button, i will think of putting it somewhere else"). `display:none` rather
      than deleting the markup, so it stays out of the tab order, the GTM click
      trigger keyed on its wa.me href is untouched, and it is one line to restore.
      DELIBERATELY DESKTOP ONLY: on a phone that button is the sticky bar's
      primary contact route, and the instruction was about the nav bar. Flagged
      to Burak rather than assumed.

   3. Enquire Now becomes a deep amber gradient with white text.
      CONTRAST IS WHY THESE TWO STOPS AND NOT BRIGHTER ONES. White measures
      2.18:1 on the retired orange #FF9600 and 3.19:1 on amber #D97706, both
      below the 4.5:1 bar, and CLAUDE.md section 2 already states text on amber is
      never white. #B45309 gives white 5.02:1 and #7C2D12 gives 9.37:1, so the
      LIGHTEST stop clears AA, which is the test IWS_DESIGN.md sets for gradients.
      Burak chose this option on the record after seeing the measurements.
      ⚠️ #7C2D12 is not yet a named token. It already appears in the 2026
      Prospectus gradient, but IWS_DESIGN.md needs it naming, and section 3 still
      describes amber as a whisper accent rather than the primary CTA fill.

   4. The hero slide indicators are removed site-wide (Burak: "just something
      static staying there like 5 lines, delete those buttons completely, site
      wide and mobile, they add noise"). `display:none` also takes them out of
      the tab order, which a visibility or opacity approach would not.
   ========================================================================== */

@media (min-width: 1200px) {

  html body #masthead#masthead .navigation.container {
    display: grid !important;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    column-gap: 24px;
  }
  html body #masthead#masthead .navigation.container > .width-logo      { justify-self: start; }
  html body #masthead#masthead .navigation.container > .width-navigation { justify-self: center; }
  html body #masthead#masthead .navigation.container > .menu-right       { justify-self: end; }

  /* WhatsApp: desktop header only. The mobile sticky bar keeps it. */
  html body #masthead .mfhcta a.mf-wa { display: none !important; }
}

/* Enquire Now, every width and every header state. Appended last so it wins on
   source order at equal specificity against the Royal-to-Sky rules above. */
html body .mfhcta a.mf-enq.mf-enq.mf-enq,
html body.iws-transparent-hero .site-header:not(.iws-solid) .mfhcta a.mf-enq.mf-enq.mf-enq,
html body .site-header.iws-solid .mfhcta a.mf-enq.mf-enq.mf-enq {
  background-color: #B45309 !important;
  background-image: linear-gradient(120deg, #B45309 0%, #7C2D12 100%) !important;
  color: #FFFFFF !important;
  box-shadow: 0 8px 20px -10px rgba(124, 45, 18, .65) !important;
}
html body .mfhcta a.mf-enq.mf-enq.mf-enq:hover {
  box-shadow: 0 12px 26px -10px rgba(124, 45, 18, .8) !important;
}

/* Hero slide indicators: gone. */
.iwshero__dots { display: none !important; }

/* ============================================================================
   THE HEADER LOGO MUST RESERVE ITS OWN WIDTH. 30 Jul 2026.

   This was the last thing stopping the header settling as one unit. Measured on
   first load, CPU throttled 6x: the nav and the CTA were correct from the first
   rendered frame, but the logo went 0x48 -> 120x48. Three distinct header states
   instead of one, and it is the logo that causes the visible settle.

   Cause: the <img> carries no width/height attributes (natural size 281x113),
   the CSS sets only a height, and iws-global.css swaps the artwork with
   `content:url(...)`. A replaced element sized by `content:url()` has NO
   intrinsic size until that file arrives, so its width is zero at first paint
   and the whole left column is empty until the logo downloads.

   Declaring the ratio lets the browser compute the width immediately from the
   height it already has: 281/113 = 2.4867, so 48px tall resolves to 119.59px and
   41px tall to 101.96px, which are exactly the measured settled widths at
   desktop and mobile. One rule, both breakpoints, no magic numbers.

   Both logo files are the trimmed pair with matching ink bounding boxes, so the
   white and navy variants share this ratio and the swap does not resize anything.
   ========================================================================== */
#masthead .width-logo img,
#masthead .width-logo a > img {
  aspect-ratio: 281 / 113;
}

/* ============================================================================
   ACCREDITATION LOGOS: RESERVE THEIR BOXES. 30 Jul 2026.

   Measured on /accreditations/, CPU throttled 4x, comparing first paint with
   settled: `.ac-grid` grew +79px (618 -> 697) and `.iws-ft-accred` grew +78px
   (166 -> 244). All four marks carry `loading="lazy"` and NO width/height
   attributes, so their boxes are zero until the files arrive and both rows
   collapse then snap open.

   This is SITE-WIDE, not one page: the same four images sit in the footer of
   every page, which is where the +78px `.iws-ft-accred` shift comes from.

   Each mark has its own ratio, so one shared rule cannot work. These are the
   measured natural dimensions, per file:
     Cambridge   660x128    UKRLP  1168x274
     COBIS       275x128    OCN     232x128
   Matching on the filename rather than a wrapper class so the reservation holds
   in both the page grid and the footer row, at every breakpoint, without
   hardcoding any rendered pixel size.

   If a mark is ever re-exported at a different size, update the ratio here. A
   stale ratio would reserve a slightly wrong box, which is still far better than
   reserving none.
   ========================================================================== */
img[src*="cambridge-international-education-iws-online-school"] { aspect-ratio: 660 / 128; }
img[src*="iws-online-school-accredites-ukrlp"]                  { aspect-ratio: 1168 / 274; }
img[src*="iws-online-school-accredites-cobis"]                  { aspect-ratio: 275 / 128; }
img[src*="iws-online-school-accredites-ocn-london"]             { aspect-ratio: 232 / 128; }


/* ==========================================================================
   "BOOK A CONSULTATION" JOINS THE PRIMARY-CTA AMBER.
   30 Jul 2026, Burak: "make the book a consultation button orange gradient
   like the enquire now cta button."

   Same gradient as the header CTA, #B45309 -> #7C2D12 with white text. That is
   AA on both stops by the rule in CLAUDE.md section 2: white measures 5.02:1 on
   #B45309 and 9.37:1 on #7C2D12, so the LIGHTEST stop clears the 4.5:1 bar,
   which is the test for a gradient. White stays banned on #D97706 (3.19:1) and
   on the retired #FF9600 (2.18:1).

   SCOPE, measured rather than assumed: "Book a consultation" appears seven
   times on the homepage, but only TWO of those are filled primary buttons
   carrying the Royal->Sky gradient -- the drawer CTA and the hero CTA. The other
   five are ghost buttons or inline text links and are deliberately left alone,
   so this does not turn the page amber. Both filled primaries change together,
   because leaving one blue and one amber would put two different fills on one
   role, which is the incoherence R1 exists to prevent. */
html body .iws-mm-cta a.iws-mm-primary.iws-mm-primary,
html body .iwshero__cta a.iwshero__btn--primary.iwshero__btn--primary {
  background-color: #B45309 !important;
  background-image: linear-gradient(120deg, #B45309 0%, #7C2D12 100%) !important;
  color: #FFFFFF !important;
  border-color: transparent !important;
}

/* --- GRADIENT EMPHASIS, added 31 Jul 2026 (Burak) -------------------------
   Two accents on top of the flat .em above: amber for the leadership heading,
   blue for the what-makes-us-different heading. Both stops are named tokens
   (R5) and both are AA at the size they are used.
   Contrast, measured on white: #D97706 is 3.19:1, which FAILS the 4.5:1 bar
   for body text and PASSES the 3:1 bar for large text. These accents are only
   ever used inside an h2 of clamp(28px+) at weight 800, which is large text by
   the WCAG definition, so the amber pair is legal here and nowhere smaller.
   #B45309 is 5.02:1 and #0067E0 is 5.23:1, both safe at any size.
   The transparent fill is gated behind @supports so a browser without
   background-clip:text keeps the solid fallback colour instead of losing the
   words entirely. */
/* The what-makes-us-different heading carries the section, so it is sized as a
   main title rather than a section label (Burak, 31 Jul). */
.iws-why h2{font-size:clamp(32px,4.4vw,52px);line-height:1.1;}
@media(max-width:600px){.iws-why h2{font-size:clamp(27px,7vw,34px);}}


/* ── One action for the three-tier pricing grid ─────────────────────────────
   Added 2 Aug 2026 on Burak's ruling. The three per-card buttons read "Enrol to
   Academy / Bridge / Foundation" and ALL THREE pointed at /book-a-consultation/:
   three labels promising enrolment, one destination delivering a booking form.
   That breaches IWS_DESIGN §10 (one label per intent) and is the "unexpected
   destination" pattern Google's landing-page-experience model scores, on the
   five pages that take the UK and Türkiye Search spend.

   The buttons are gone from the cards; the grid now carries ONE CTA beneath it.
   Reuses .ipc__btn rather than inventing a button (R1), so it inherits the
   site-wide amber CTA token and the 8px control radius (R4) automatically.

   ⚠️ `iws-pricing-cta` MUST be added to the WP Rocket RUCSS safelist before the
   live push, or this rule is stripped and the CTA renders as bare blue text. */
.iws-pricing-cta{
  display:flex;
  justify-content:center;
  max-width:1140px;
  margin:26px auto 0;
}
/* The page's own inline rule sets .ipc__btn{display:block;padding:15px} at
   (0,1,0). These land at (0,2,0) so they win without !important. */
.iws-pricing-cta .ipc__btn{
  min-width:280px;
  padding-left:34px;
  padding-right:34px;
}
@media (max-width:520px){
  .iws-pricing-cta .ipc__btn{min-width:0;width:100%}
}


/* ── IWS CONSULTATION CTA NORMALISER (3 Aug 2026) ─────────────────────────────
   One geometry for every Book a Consultation button. Fill was already
   consistent; radius, height and type size were not. Doubled classes reach
   (0,2,1) so this survives the six sheets that load after this file. */
a.iwshero__btn--primary.iwshero__btn--primary,
a.ip-btn--primary.ip-btn--primary,
a.ipc__btn.ipc__btn,
a.iwf-btn-primary.iwf-btn-primary,
a.au-cta-btn.au-cta-btn,
a.pf-btn-primary.pf-btn-primary,
a.hb1.hb1,
a.iwsstu__btn.iwsstu__btn,
a.iwsxp__go.iwsxp__go{
  border-radius:8px;
  min-height:52px;
  font-size:16px;
  font-weight:600;
  line-height:1.2;
  padding:0 28px;
  display:inline-flex;
  align-items:center;
  justify-content:center;
  gap:10px;
  text-align:center;
}
/* the tier-card CTA carries a bare .p, so it is scoped by destination */
a.p[href*="book-a-consultation"]{
  border-radius:8px;
  min-height:52px;
  font-size:16px;
  font-weight:600;
  line-height:1.2;
  display:inline-flex;
  align-items:center;
  justify-content:center;
}
/* ─────────────────────────────────────────────────────────────────────────── */

/* geometry is authoritative: components kept their own padding and borders,
   which put heights at 52/54/55/57/59/61. */
a.iwshero__btn--primary.iwshero__btn--primary,
a.ip-btn--primary.ip-btn--primary,
a.ipc__btn.ipc__btn,
a.iwf-btn-primary.iwf-btn-primary,
a.au-cta-btn.au-cta-btn,
a.pf-btn-primary.pf-btn-primary,
a.hb1.hb1,
a.iwsstu__btn.iwsstu__btn,
a.iwsxp__go.iwsxp__go,
a.p[href*="book-a-consultation"]{
  box-sizing:border-box!important;
  height:52px!important;
  min-height:52px!important;
  padding:0 28px!important;
  border-width:0!important;
  font-size:16px!important;
  font-weight:600!important;
  line-height:1!important;
  border-radius:8px!important;
}
@media (max-width:640px){
  a.iwshero__btn--primary.iwshero__btn--primary,
  a.ip-btn--primary.ip-btn--primary,
  a.ipc__btn.ipc__btn,
  a.iwf-btn-primary.iwf-btn-primary,
  a.au-cta-btn.au-cta-btn,
  a.pf-btn-primary.pf-btn-primary,
  a.hb1.hb1,
  a.iwsstu__btn.iwsstu__btn,
  a.iwsxp__go.iwsxp__go,
  a.p[href*="book-a-consultation"]{
    height:auto!important;min-height:52px!important;padding:14px 22px!important;line-height:1.2!important;
  }
}

/* ── IWS RESPONSIVE FIXES 3 AUG 2026 ─────────────────────────────────────────
   1. .iws-pricing overflowed its container from 921px upward. iws-legacy.css:137
      stacks it only below 920px; above that the columns were CONTENT sized,
      because 1fr resolves to minmax(auto,1fr), and auto will not shrink below the
      content width. Measured at 1024: columns 316+271+351=937px inside an 849px
      container, cards reaching x=1061 in a 1024 viewport. minmax(0,1fr) lets
      them share the available width instead. Fixes every width, not just 1024. */
/* min-width:0 must apply at EVERY width: a grid item defaults to
   min-width:auto and will not shrink below its content, which is what put a
   351px card inside a 305px grid at 360px. */
.iws-pricing > *{min-width:0!important}
@media (min-width:921px){
  .iws-pricing{grid-template-columns:repeat(3,minmax(0,1fr))!important}
}
@media (max-width:920px){
  .iws-pricing{grid-template-columns:minmax(0,1fr)!important}
}

/* 2. /student-stories/ (page 37042) carries a Bootstrap .row with
      margin:0 -20px inside a .container.site-content whose padding is 0, so the
      negative gutter is never cancelled and real content (.iwsstu, the dome
      scrim) crossed the viewport edge by 5px at 768/1024/1025. The sections on
      this page are full-bleed by design, so the gutter is simply not wanted. */
body.page-id-37042 .container.site-content > .row{margin-left:0!important;margin-right:0!important}
body.page-id-37042 .container.site-content > .row > [class*="col-"]{padding-left:0!important;padding-right:0!important}
/* ─────────────────────────────────────────────────────────────────────────── */
/* ── WCAG 2.1 AA CONTRAST + LINK FIXES (3 Aug 2026) ───────────────────────────
   From the audit in Website/WCAG_AA_AUDIT_2026-08-03.md. Every value below is
   measured, not estimated. Doubled-up "html body" prefixes and !important are
   required because six stylesheets load after this one.

   1.4.3 Contrast (minimum), small text needs 4.5:1
   ------------------------------------------------
   Muted blue-greys on light grounds, all measured between 3.03:1 and 3.96:1.
   Slate --iws-slate #475569 is 7.26:1 on white and 6.33:1 on the #EEF1FB panel
   tint, so one token clears every one of them. */
html body .iws-legal-sub,                 /* was #7A8194, 3.89:1, on 5 legal pages */
html body .iwf-note,                      /* was #8792AD, 3.11:1 white / 2.75:1 tint */
html body .iwf-fthead .ps,                /* was #7A86A6, 3.21:1 on tint */
html body .pf-fhead p span,               /* was #73809B, 3.96:1 */
html body .iws-pr-nm small{               /* was #7A86A3, 3.64:1, on 5 programme pages */
  color:#475569!important;
}

/* An eyebrow on a DARK ground. Sky #0067E0 on Royal #0A1776 measures 2.87:1.
   Periwinkle #CFE0FF on Royal is 11.22:1 and is already the sanctioned
   "emphasis on dark" token, so the eyebrow keeps its accent character.
   Scoped to the two that actually sit on navy: the site-wide eyebrow rule still
   paints Sky on light grounds, where it is 5.32:1 and correct. */
html body .au-accred-eye,
html body .pf-example .eyebrow{
  color:var(--iws-peri,#CFE0FF)!important;
}

/* 1.4.1 Use of Colour
   -------------------
   Inline prose links are #111111 against #475569 body text, 2.49:1 where 3:1 is
   required, and carry no underline, so a colour-blind reader cannot tell they
   are links. Underlining is the cheapest compliant fix and does not touch the
   palette. Scoped to CLASSLESS links inside prose, so no button, chip, card or
   nav link is affected. */
html body main p > a:not([class]),
html body main li > a:not([class]),
html body .sub a:not([class]),
html body .pf-split .txt p > a:not([class]){
  text-decoration:underline!important;
  text-underline-offset:2px;
  text-decoration-thickness:1px;
}
/* the breadcrumb link measured 1.17:1 against its neighbouring text */
html body .thim-ekit-breadcrumb > a{
  text-decoration:underline!important;
  text-underline-offset:2px;
}

/* 2.5.5 target size is AAA, not AA, so this is a courtesy rather than a fix:
   the carousel dots measured 8x8 and 9x9. The visual dot is unchanged; only the
   hit area grows, via padding plus a transparent background-clip. */
html body .iws-pr-dot,
html body .iws-pr-dots button{
  min-width:24px;
  min-height:24px;
  background-clip:content-box;
  padding:8px;
  box-sizing:content-box;
}
/* ─────────────────────────────────────────────────────────────────────────── */

/* ── FOOTER LINKS: NO PERMANENT UNDERLINE (3 Aug 2026, Burak) ────────────────
   My own regression from the WCAG pass earlier today. The footer sits INSIDE
   <main> on this theme (there is no </main> before it), so the rule
   "html body main li > a:not([class])" added for WCAG 1.4.1 caught every footer
   link. That rule exists to make links in PROSE distinguishable without colour;
   a footer link list is not prose, its link-ness is obvious from context, so the
   underline is noise there. Hover still underlines, which is what Burak asked
   for and what the theme did before. */
html body .iws-ft a,
html body .iws-ft li > a,
html body .iws-ft p > a,
html body .iws-ft__col a,
html body .site-footer a{
  text-decoration:none!important;
}
html body .iws-ft a:hover,
html body .iws-ft a:focus-visible,
html body .site-footer a:hover,
html body .site-footer a:focus-visible{
  text-decoration:underline!important;
  text-underline-offset:2px;
}
/* ─────────────────────────────────────────────────────────────────────────── */

/* Doubled class, because the first attempt LOST on specificity. The WCAG
   underline rule is "html body main li > a:not([class])" = (0,1,5); the first
   footer rule was (0,1,4). Both carry !important, so the cascade is decided on
   specificity, and the class column outranks the element count: .iws-ft.iws-ft
   reaches (0,2,x) and wins outright. Same trap already recorded for this file. */
html body .iws-ft.iws-ft a,
html body .iws-ft.iws-ft li > a,
html body .iws-ft.iws-ft p > a{
  text-decoration:none!important;
}
html body .iws-ft.iws-ft a:hover,
html body .iws-ft.iws-ft a:focus-visible{
  text-decoration:underline!important;
  text-underline-offset:2px;
}

/* ── LEAD-JOURNEY RAIL (3 Aug 2026, Burak) ───────────────────────────────────
   The rail was shorter than the white form card beside it, so the two tiles did
   not bottom-align. Stretching the rail and letting the advisor block take the
   slack (margin-top:auto) makes the pair symmetrical without inventing a fixed
   height that would break when the copy changes. Serhat's portrait goes 56 to
   88px, which the markup now also declares, so no layout shift. */
html body .iwsld__rail{
  align-self:stretch!important;
  display:flex!important;
  flex-direction:column!important;
}
html body .iwsld__rail > ol{ margin-bottom:22px!important; }
html body .iwsld__adv{
  margin-top:auto!important;
  align-items:center!important;
}
html body .iwsld__adv img{
  width:88px!important;
  height:88px!important;
  border-radius:16px!important;
  object-fit:cover!important;
  flex:0 0 88px!important;
}
/* ─────────────────────────────────────────────────────────────────────────── */

/* The footer already draws its own gradient-blue underline on hover, so adding
   text-decoration on top painted a second WHITE line over it (Burak, 3 Aug).
   Remove the decoration entirely and let the theme's own effect show. The
   resting state stays undecorated, which is what the earlier fix established. */
html body .iws-ft.iws-ft a:hover,
html body .iws-ft.iws-ft a:focus-visible{
  text-decoration:none!important;
}

/* ── ENQUIRY BAND: NO HARD RECTANGLE (3 Aug 2026, Burak) ─────────────────────
   .iws-leadband rendered as a flat full-bleed slab with border-radius 0 between
   two white sections. Rounded to 22px, which is a step on the R4 radius scale
   (8 / 14 / 22 / 999), so it reads as a panel like the footer rather than a
   band. Its background and margin carry inline !important and cannot be
   overridden from a stylesheet; padding and radius can, which is enough.

   The bottom padding drops from 80px to 44px so "Let's Talk About Your Child"
   sits closer to the form beneath it and reads as that section's title rather
   than as a floating banner. Clearer labelling of the enquiry step is also the
   right side of Google's landing-page-experience guidance: it makes the page's
   purpose and the next action unambiguous, which is what quality score rewards.
   Nothing here changes a claim, a price or a destination. */
html body .iws-leadband{
  border-radius:22px!important;
  padding-top:64px!important;
  padding-bottom:44px!important;
  overflow:hidden;
}
/* pull the form up so band + form read as ONE enquiry section, not two */
html body .iws-leadband + *,
html body .iws-leadband + * .elementor-widget-container{
  margin-top:0!important;
}
@media(max-width:640px){
  html body .iws-leadband{ border-radius:14px!important; padding-top:44px!important; padding-bottom:32px!important; }
}
/* ─────────────────────────────────────────────────────────────────────────── */

/* iws-legacy.css:760 targets .e-con.e-parent:not(:has(...)) .iws-leadband, which
   outranks a plain html body .iws-leadband, so the radius above lost while the
   padding won. Doubling the class clears it. Measure the winner, never assume. */
html body .e-con .iws-leadband.iws-leadband,
html body .iws-leadband.iws-leadband{ border-radius:22px!important; }
@media(max-width:640px){
  html body .e-con .iws-leadband.iws-leadband,
  html body .iws-leadband.iws-leadband{ border-radius:14px!important; }
}

/* ── CONSULTATION CTA: BACK TO A PILL (3 Aug 2026, Burak) ────────────────────
   My 3 Aug normaliser set every consultation CTA to 8px, which read as a
   rectangle beside the hero's ghost button that was left at 999px. 999 is a
   step on the R4 radius scale, the pair was clearly designed as two pills, and
   Burak asked for the round version back. Applied to the SAME selector list as
   the normaliser so they stay identical to each other, which was the earlier
   instruction. Vertical padding is restored too: forcing padding:0 had made the
   primary 52px tall against the ghost's 59px. */
a.iwshero__btn--primary.iwshero__btn--primary,
a.ip-btn--primary.ip-btn--primary,
a.ipc__btn.ipc__btn,
a.iwf-btn-primary.iwf-btn-primary,
a.au-cta-btn.au-cta-btn,
a.pf-btn-primary.pf-btn-primary,
a.hb1.hb1,
a.iwsstu__btn.iwsstu__btn,
a.iwsxp__go.iwsxp__go,
a.p[href*="book-a-consultation"]{
  border-radius:999px!important;
  padding:16px 30px!important;
  min-height:52px!important;
}
/* ─────────────────────────────────────────────────────────────────────────── */

