/* ==========================================================================
   NEXISTEK — Responsive
   Mobile-first. Every media query in the project lives in this file.
   Breakpoints: 480 / 640 / 768 / 1024 / 1280 / 1440
   ========================================================================== */

/* --------------------------------------------------------------------------
   Capability queries — run before size queries
   -------------------------------------------------------------------------- */

/* The custom cursor only exists for a precise pointer. Touch and hybrid
   devices keep the native affordances and never see it. */
@media (hover: hover) and (pointer: fine) {
  .cursor {
    display: block;
  }

  /* Hiding the system cursor is only safe once a replacement is guaranteed. */
  .has-custom-cursor,
  .has-custom-cursor a,
  .has-custom-cursor button,
  .has-custom-cursor [role="button"] {
    cursor: none;
  }
}

/* Short landscape (phones turned sideways): the hero must not lock the
   viewport to a full screen of art with the copy pushed out of reach. */
@media (max-height: 34rem) and (orientation: landscape) {
  .hero {
    min-height: auto;
    padding-block: calc(var(--nav-h) + var(--sp-7)) var(--sp-7);
  }

  .hero__features {
    margin-top: var(--sp-6);
  }
}

/* --------------------------------------------------------------------------
   480px — large phone
   -------------------------------------------------------------------------- */
@media (min-width: 30rem) {
  .site-footer__bar {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
  }

  /* Enough width for the hover cue and the full address on one line. */
  .channel__cue {
    display: block;
  }
}

/* --------------------------------------------------------------------------
   640px — phablet
   -------------------------------------------------------------------------- */
@media (min-width: 40rem) {
  .domains__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .cta__panel {
    padding: var(--sp-11) var(--sp-9);
  }

  .contact__row--split {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .site-footer__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  /* Alternating rows: icon/number flips to the opposite edge on even rows,
     so the list reads left-right-left instead of one flat column. Gated to
     this width so the flip never happens while text is still wrapping hard
     on a narrow phone. */
  .info-rows--alt > .info-row:nth-child(even) {
    flex-direction: row-reverse;
  }

  /* Ten industries split evenly two-up — no orphan row at any width. */
  .industries__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--sp-7) var(--sp-8);
  }
}

/* --------------------------------------------------------------------------
   768px — tablet
   -------------------------------------------------------------------------- */
@media (min-width: 48rem) {
  :root {
    --nav-h: 5rem;
  }

  .brand__logo {
    height: 2.125rem;
  }

  /* Programme carousel arrows: only once there is room for them not to
     crowd the gutter, and only once JS can actually drive them — without it
     the track is still fully usable by drag/swipe via native scroll-snap. */
  .js .programs__arrow {
    display: flex;
  }

  /* Enough width for a backdrop to sit beside the copy rather than behind
     it: it drops from full-bleed (see style.css) to 62% offset to one side,
     which is what --backdrop-x / --backdrop-y are tuned for, and goes back
     to full per-section strength now that no text sits on top of it.
     No height: the backdrop takes the image's own proportions at 62% width.
     Stretched to the section's full height instead, a tall section blew the
     photograph up far past its natural size and it stopped reading as depth
     behind the copy. */
  .section-backdrop {
    width: 62%;
  }

  .section-backdrop--right {
    left: auto;
    right: 0;
  }

  .section-backdrop--left {
    left: 0;
  }

  .section-backdrop__img {
    opacity: var(--backdrop-opacity, 0.6);
    -webkit-mask-image: radial-gradient(
      62% 78% at var(--backdrop-x, 78%) var(--backdrop-y, 62%),
      var(--c-void) 0%,
      transparent 72%
    );
    mask-image: radial-gradient(
      62% 78% at var(--backdrop-x, 78%) var(--backdrop-y, 62%),
      var(--c-void) 0%,
      transparent 72%
    );
  }

  /* Learning Methodology stops being one long column. The vertical spine
     gives way to a rule above each step — adjacent steps join into a single
     continuous line across each row, with the marker straddling it. */
  .flow {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--sp-9) var(--sp-7);
  }

  .flow::before {
    display: none;
  }

  .flow__step {
    border-top: 1px solid var(--border-soft);
    padding-left: 0;
    padding-top: 2.9rem;
    padding-bottom: 0;
  }

  .flow__marker {
    top: 0;
    left: 0;
    transform: translateY(-50%);
  }

  .flow__text {
    max-width: none;
  }

  /* Technologies network: the radial layout and its orbit are now in the base
     rules and animations.css, because the diagram is a circle at every width.
     Only the scale changes here — more room means a wider ring, larger icons
     and labels that no longer have to be tiny to fit. */
  .tech-network__stage {
    --network-radius: 9.5rem;

    max-width: 32rem;
  }

  .tech-network__node-btn {
    width: 5.5rem;
    padding: var(--sp-3);
  }

  .tech-network__node-object {
    width: 2.75rem;
    height: 2.75rem;
  }

  .tech-network__node-label {
    font-size: var(--fs-micro);
    letter-spacing: var(--tracking-wide);
  }
}

/* --------------------------------------------------------------------------
   1024px — laptop
   -------------------------------------------------------------------------- */
@media (min-width: 64rem) {
  .hero__panels {
    display: block;
  }

  /* The photograph itself is in the base rule now (style.css) so it loads at
     every width. What changes here is only the composition: the scene has a
     half of the frame to itself from 1024px, so the top-to-bottom mobile
     fade becomes a window over that half, and the photo goes back to being
     dimmed harder — the desktop vignette is directional and no longer
     covers this side. */
  .hero__backdrop {
    background-position: 62% 55%;
    filter: saturate(0.75) brightness(0.6) contrast(1.05);
    /* Windowed to the same side of the frame the rig stands on, fading out
       toward the text column and the top edge rather than running edge to
       edge — so it reads as the bench under the scene, not a photo dropped
       in behind it. */
    -webkit-mask-image: radial-gradient(
      68% 85% at 74% 78%,
      var(--c-void) 0%,
      transparent 70%
    );
    mask-image: radial-gradient(
      68% 85% at 74% 78%,
      var(--c-void) 0%,
      transparent 70%
    );
  }

  /* The scene now sits in the right half, clear of the copy, so the flat
     mobile scrim gives way to a directional one that darkens only the text
     side and leaves the rig at full strength. */
  .hero__vignette {
    background:
      linear-gradient(
        90deg,
        rgb(var(--rgb-void) / 0.82) 0%,
        rgb(var(--rgb-void) / 0.45) 34%,
        transparent 58%
      ),
      linear-gradient(
        180deg,
        rgb(var(--rgb-void) / 0.6) 0%,
        transparent 20%,
        transparent 80%,
        rgb(var(--rgb-void) / 0.5) 100%
      );
  }

  .origin__grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 0.85fr);
    gap: var(--sp-10);
    align-items: center;
  }

  .origin--reverse .origin__body {
    order: 2;
  }

  /* The robot fills its column here rather than sitting capped and centred
     inside it — at its mobile width it left slack down both sides and the
     section read as half empty against the tall copy beside it. */
  .story__figure {
    max-width: none;
    margin-inline: 0;
  }

  /* --- Projects page (Innovation Lab) ------------------------------------ */

  /* What this is: the heading holds its own column with the argument running
     beside it — the same composition as the Career page's opening section. */
  .lab-intro__layout {
    display: grid;
    grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
    align-items: start;
    gap: var(--sp-10);
  }

  /* Build rows gain their index numeral here, as the focus rows do: at
     narrow widths the tech object alone carries the row. */
  .build-row {
    gap: var(--sp-8);
  }

  .build-row__num {
    display: inline;
  }

  .lab-log__panel {
    padding: var(--sp-10) var(--sp-9);
  }

  /* --- Career Development page ------------------------------------------ */

  /* Hero: copy against the drawn growth path. */
  .career-hero__layout {
    display: grid;
    grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
    align-items: center;
    gap: var(--sp-10);
  }

  .career-hero__art {
    max-width: none;
    margin-inline: 0;
  }

  /* Why: the heading holds its own column while the argument runs beside
     it, rather than sitting above a short block of text. */
  .career-why__layout {
    display: grid;
    grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
    align-items: start;
    gap: var(--sp-10);
  }

  /* Focus rows gain their index numeral here — at narrow widths the badge
     alone carries the row and the numeral only crowded it. */
  .focus-row {
    gap: var(--sp-8);
  }

  .focus-row__num {
    display: inline;
  }

  /* The two skill columns sit side by side with the join turned across
     between them. */
  .bridge__grid {
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    gap: var(--sp-6);
  }

  .bridge__join-icon {
    transform: none;
  }

  /* Organizations: the pitch and the list of areas share the panel. */
  .career-org__panel {
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
    gap: var(--sp-10);
    align-items: center;
    padding: var(--sp-10) var(--sp-9);
  }

  .career-cta__panel {
    padding: var(--sp-11) var(--sp-10);
  }

  .domains__head {
    flex-direction: row;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--sp-8);
  }

  .domains__grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }

  .hero__title {
    max-width: 16ch;
  }

  .hero__features {
    margin-top: var(--sp-10);
  }

  /* Three across rather than six: at six the columns were barely 200px and
     the copy broke mid-phrase with very ragged bottoms. */
  .flow {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--sp-10) var(--sp-8);
  }

  /* Heading fills the width: title left, lead alongside it, rather than
     both stacked in the left half with the right half empty. */
  .protocol .section-head,
  .industries .section-head {
    display: grid;
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
    grid-template-areas:
      "eyebrow eyebrow"
      "title lead";
    align-items: end;
    column-gap: var(--sp-10);
    max-width: none;
  }

  .protocol .section-head .eyebrow,
  .industries .section-head .eyebrow {
    grid-area: eyebrow;
  }

  .protocol .section-head__title,
  .industries .section-head__title {
    grid-area: title;
  }

  .protocol .section-head__lead,
  .industries .section-head__lead {
    grid-area: lead;
    max-width: none;
    padding-bottom: var(--sp-2);
  }

  .site-footer__grid {
    grid-template-columns: 1.6fr repeat(3, minmax(0, 1fr));
    gap: var(--sp-9);
  }

  .contact__grid {
    grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
    gap: var(--sp-10);
  }

  .contact__form {
    padding: var(--sp-8);
  }

  .pending {
    padding: var(--sp-11) var(--sp-9);
  }

  /* The contents list earns its space on a wide screen: roomier rows, and the
     numbers given a column of their own so the titles line up. */
  .toc__summary {
    padding: var(--sp-5) var(--sp-6);
  }

  .toc__nav {
    padding: 0 var(--sp-6) var(--sp-6);
  }

  .toc__link {
    font-size: var(--fs-body);
  }

  /* Courses — the detail modal takes its intended shape here: the drawn
     equipment pinned in its own column beside the copy, which is what the
     panel is designed around. Below this it stacks, art first. */
  .course-modal__layout {
    grid-template-columns: minmax(0, 0.72fr) minmax(0, 1fr);
    gap: var(--sp-9);
    padding: var(--sp-9) var(--sp-8);
    align-items: start;
  }

  /* Sticky so the subject stays on screen while a long panel is scrolled. */
  .course-modal__art {
    position: sticky;
    top: 0;
  }

  .library-closing__panel {
    padding: var(--sp-10) var(--sp-9);
  }

  /* About — Who We Serve: the seven groups beside the photograph rather
     than above it, so the section reads in one screen. */
  .serve__layout {
    display: grid;
    grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
    align-items: center;
    gap: var(--sp-10);
  }

  /* About — Our Approach: copy left, the practice loop right. */
  .approach__layout {
    display: grid;
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
    align-items: center;
    gap: var(--sp-10);
  }

  .approach__art {
    max-width: none;
    margin-inline: 0;
  }

  /* About — Vision & Mission: the single vision statement against the five
     mission commitments, the wider column going to the list. */
  .vm__grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
    align-items: start;
    gap: var(--sp-10);
  }

  /* Who We Train: the heading takes its own column and stays put while the
     four entries scroll past it, instead of the list sitting in a narrow
     strip with the right half of the section left empty. */
  .audience__layout {
    display: grid;
    grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
    align-items: start;
    gap: var(--sp-10);
  }

  .audience__head {
    position: sticky;
    top: calc(var(--nav-h) + var(--sp-8));
  }

  .audience .info-rows {
    margin-top: 0;
  }

  /* The rows are wider here than in a single column, so the numeral can
     carry more weight without crowding the text beside it. */
  .audience .info-row__num {
    font-size: clamp(2.5rem, 3.2vw, 3.5rem);
  }

  /* Mirror of Corporate Training: its backdrop sits right and the copy
     left, so here the backdrop sits left and the copy is pushed right,
     clear of the busiest part of the image. */
  .career__intro {
    max-width: 46rem;
    margin-inline-start: auto;
  }

  .career__services {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: var(--sp-10);
  }

  /* In two columns a single trailing rule no longer closes the list — both
     items on the final row need one. */
  .career__services > .info-row:nth-last-child(-n + 2) {
    border-bottom: 1px solid var(--border-hairline);
  }

  /* Corporate Training: the scene sits beside the heading, filling the space
     the copy leaves, and the services then run the full width below. Against
     the service list it was a short panel stranded atop a very tall column. */
  /* The heading keeps its own measure rather than running the full width —
     the backdrop occupies the right of the section, so the copy stops
     before it instead of sitting on top of the busiest part of the image. */
  .corporate__intro {
    max-width: 46rem;
  }

  .corporate__services {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: var(--sp-10);
  }

  /* In two columns a single trailing rule no longer closes the list — both
     items on the final row need one. */
  .corporate__services > .info-row:nth-last-child(-n + 2) {
    border-bottom: 1px solid var(--border-hairline);
  }

  .corporate__cta {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-8);
    padding: var(--sp-7) var(--sp-8);
  }

  /* Stage and panel sit side by side; the radius grows with the extra room. */
  .tech-network {
    display: grid;
    grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
    align-items: center;
    gap: var(--sp-9);
  }

  .tech-network__stage {
    max-width: 34rem;
    --network-radius: 11rem;
  }

  .tech-network__center {
    width: 9rem;
    height: 9rem;
  }
}

/* --------------------------------------------------------------------------
   1280px — desktop. Primary navigation replaces the overlay menu here.

   This swap used to happen at 1024px, which was comfortable for six short
   labels. Seven destinations — one of them "Career Development" — need more
   room than that: at 1024 the row wrapped onto three lines and collided
   with the Enquire button. Below this width the overlay menu serves
   instead, and it already handles both dropdowns as separate accordions.

   main.js reads the same breakpoint to decide when to close that overlay.
   The two must stay in step: closing it at a width where the inline links
   are still hidden would leave no navigation at all.
   -------------------------------------------------------------------------- */
@media (min-width: 80rem) {
  .nav__links {
    display: flex;
  }

  .nav__cta {
    display: inline-flex;
  }

  .nav__toggle {
    display: none;
  }

  .domain-card {
    min-height: 24rem;
    padding: var(--sp-7);
  }

  .program-card {
    width: 17rem;
  }

  .cta__panel {
    padding: var(--sp-12) var(--sp-10);
  }
}

/* --------------------------------------------------------------------------
   1440px — wide desktop
   -------------------------------------------------------------------------- */
@media (min-width: 90rem) {
  .hero__lead {
    max-width: 48ch;
  }
}

/* --------------------------------------------------------------------------
   Print — collapse the experience to a readable document
   -------------------------------------------------------------------------- */
@media print {
  .page::before,
  .hero__stage,
  .hero__vignette,
  .cursor,
  .scroll-progress,
  .site-header,
  .site-footer__wordmark,
  /* The lockup in use is the on-dark variant — white on paper is invisible.
     The footer bar still prints the brand name as text. */
  .brand__logo {
    display: none !important;
  }

  body {
    background: var(--c-print-paper);
    color: var(--c-print-ink);
  }

  .hero {
    min-height: auto;
  }
}

/* --- Article contents, as a margin rail ------------------------------------
 * The article column is 58rem and centred, which leaves an empty margin either
 * side on a large screen. Above this width there is room to put the contents
 * list in the left one, where it stays visible while the article is read — and
 * the highlight showing which section you are in becomes worth having, rather
 * than scrolling out of sight with the card.
 *
 * The rail is absolutely positioned and spans the article's full height; the
 * list inside it is sticky. That combination is what makes a sticky element
 * stop at the end of the article instead of following the reader into the
 * share row and the author block.
 *
 * Deliberately does NOT widen .post .container. The heading, the cover, the
 * body and the footer keep the one measure and the one edge they were given;
 * the rail hangs outside that column and moves none of it.
 * -------------------------------------------------------------------------- */
@media (min-width: 1440px) {
  .post__reading--toc .post__rail {
    position: absolute;
    top: 0;
    left: calc(-1 * (14rem + var(--sp-7)));
    width: 14rem;
    height: 100%;
  }

  .post__reading--toc .toc {
    position: sticky;
    top: calc(var(--nav-h) + var(--sp-5));
    margin-bottom: 0;
    background-color: transparent;
    border: 0;
    border-left: 1px solid var(--border-hairline);
    border-radius: 0;
  }

  /* Out here it is a label, not a control: there is no room to collapse into
     and nothing gained by doing so. */
  .post__reading--toc .toc__summary {
    padding: 0 0 var(--sp-3) var(--sp-5);
    cursor: default;
    pointer-events: none;
  }

  .post__reading--toc .toc__meta,
  .post__reading--toc .toc__chevron {
    display: none;
  }

  .post__reading--toc .toc__nav {
    padding: 0;
    border-top: 0;
  }

  .post__reading--toc .toc__list {
    margin-top: 0;
  }

  .post__reading--toc .toc__link {
    padding: var(--sp-2) 0 var(--sp-2) var(--sp-5);
    font-size: var(--fs-xs);

    /* The marker for the current section rides the rail's own line. */
    border-left: 2px solid transparent;
    margin-left: -1px;
    transition: color var(--dur-base) var(--ease-out),
      border-color var(--dur-base) var(--ease-out);
  }

  .post__reading--toc .toc__link.is-current {
    border-left-color: var(--text-energised);
  }

  /* The numbers are the rail's rhythm at this size; the sub-heading rules
     would crowd a 14rem column, so they go and the indent carries it. */
  .post__reading--toc .toc__item--l3 > .toc__link::before,
  .post__reading--toc .toc__item--l4 > .toc__link::before,
  .post__reading--toc .toc__item--l5 > .toc__link::before {
    display: none;
  }

  .post__reading--toc .toc__item--l3 > .toc__link {
    padding-left: var(--sp-8);
  }
}
