/* ==========================================================================
   Gameinfrasol — section stylesheet
   Ported from Claude Design export "Gameinfrasol Website.dc.html".

   This file carries three things the export could not:
     1. The 29 style-hover attributes, as real :hover rules.
     2. Responsive behaviour (the export has zero media queries).
     3. Keyboard focus states.

   Layout maths lives here rather than in block attributes on purpose: editing
   copy in Gutenberg then cannot break the grid.
   ========================================================================== */

:root {
  /* Palette — taken verbatim from the export, not from _ds/styles.css */
  --gis-navy:        #0B2447;
  --gis-navy-deep:   #081D3C;
  --gis-navy-line:   #143561;
  --gis-navy-rule:   #22497D;
  --gis-navy-mute:   #4A6F9F;
  --gis-red:         #EC3013;
  --gis-red-dark:    #B32410;
  --gis-red-deep:    #8E1B18;
  --gis-salmon:      #F77D5F;
  --gis-blush:       #FEEAE3;
  --gis-cream:       #F4F0E6;
  --gis-cream-line:  #E4DCC7;
  --gis-ink:         #16150E;
  --gis-ink-soft:    #4A463E;
  --gis-ink-mute:    #6F6A5E;
  --gis-on-navy:     #C3D0DE;
  --gis-on-navy-dim: #8FA5C1;

  --gis-shell: 1400px;
  --gis-gutter: 40px;
  --gis-section-y: 96px;

  --gis-font: "Hanken Grotesk", Archivo, "Helvetica Neue", Arial, sans-serif;
}

/* --------------------------------------------------------------------------
   Shell
   -------------------------------------------------------------------------- */

.gis-shell {
  max-width: var(--gis-shell);
  margin-inline: auto;
  padding-inline: var(--gis-gutter);
}

.gis-section { padding-block: var(--gis-section-y); }

/* Section heads: eyebrow + h2 on the left, standfirst on the right. */
.gis-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 40px;
  padding-bottom: 24px;
  border-bottom: 2px solid var(--gis-navy);
}
.gis-head--on-navy { border-bottom-color: var(--gis-navy-rule); }
.gis-head__standfirst { margin: 0; max-width: 38ch; }

/* --------------------------------------------------------------------------
   Interaction states — replaces every style-hover attribute
   -------------------------------------------------------------------------- */

.gis-navlink              { transition: color .15s ease; }
.gis-navlink:hover        { color: var(--gis-salmon); }

.gis-btn                  { display: inline-block; transition: background-color .15s ease, color .15s ease; }
.gis-btn--primary:hover   { background: var(--gis-red-dark); color: #fff; }
.gis-btn--ghost:hover     { background: #fff; color: var(--gis-navy); }
.gis-btn--navy:hover      { background: var(--gis-navy-deep); }
.gis-btn--white:hover     { background: var(--gis-cream); }
.gis-btn--outline:hover   { background: #fff; color: var(--gis-red); }

.gis-underline            { transition: color .15s ease; }
.gis-underline:hover      { color: var(--gis-red); }
.gis-underline--on-navy:hover { color: var(--gis-salmon); }

.gis-footlink             { transition: color .15s ease; }
.gis-footlink:hover       { color: #fff; }

/* Per the Modernist readme: never leave the default focus ring. */
a:focus-visible,
button:focus-visible,
summary:focus-visible,
.gis-navtoggle:focus-visible {
  outline: 2px solid var(--gis-red);
  outline-offset: 2px;
}
.gis-header a:focus-visible,
footer a:focus-visible { outline-color: var(--gis-salmon); }

/* --------------------------------------------------------------------------
   Header
   -------------------------------------------------------------------------- */

.gis-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--gis-navy);
  border-bottom: 2px solid var(--gis-navy-line);
}
.gis-header__bar {
  height: 82px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 40px;
}
/* The wordmark is inlined SVG, not <img>, so it inherits the page font. */
.gis-header__mark svg { height: 30px; width: auto; display: block; }

.gis-nav { display: flex; align-items: center; gap: 34px; }

/* Pure-CSS disclosure for the mobile menu — no JS, so nothing to enqueue.
   The checkbox is clipped rather than display:none so it stays focusable and
   Space still toggles the menu for keyboard users. */
.gis-navtoggle { display: none; }
.gis-navtoggle-box {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.gis-navtoggle-box:focus-visible ~ .gis-header__bar .gis-navtoggle {
  outline: 2px solid var(--gis-salmon);
  outline-offset: 2px;
}

/* --------------------------------------------------------------------------
   Hero
   -------------------------------------------------------------------------- */

.gis-hero { position: relative; background: var(--gis-navy); overflow: hidden; }
.gis-hero__bg {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  opacity: .55;
}
.gis-hero__scrim {
  position: absolute; inset: 0;
  background: linear-gradient(90deg,
    var(--gis-navy) 0%,
    rgba(11,36,71,.92) 38%,
    rgba(11,36,71,.25) 100%);
}
.gis-hero__inner {
  position: relative;
  padding-block: 112px 96px;
  display: flex; flex-direction: column;
  align-items: flex-start;
  gap: 34px;
}
.gis-hero__title {
  margin: 0;
  max-width: 16ch;
  color: #fff;
  /* 86px at desktop, but it has to survive a 320px viewport. */
  font-size: clamp(2.375rem, 6.2vw, 5.375rem);
  line-height: .96;
  font-weight: 800;
  letter-spacing: -.03em;
  text-wrap: balance;
}
.gis-hero__lede { margin: 0; max-width: 56ch; color: var(--gis-on-navy); font-size: 19px; line-height: 1.55; }

.gis-eyebrow { display: flex; align-items: center; gap: 14px; }
.gis-eyebrow__rule { display: block; width: 44px; height: 3px; background: var(--gis-red); flex: none; }

/* Stat bar. Dividers are drawn with gap + background bleed so they never
   double up when cells wrap. */
.gis-stats-band { position: relative; background: var(--gis-navy-deep); border-top: 2px solid var(--gis-navy-line); }
.gis-stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  background: var(--gis-navy-rule);
}
.gis-stats > * { background: var(--gis-navy-deep); padding: 30px 34px; }
.gis-stats__n { color: #fff; font-size: 38px; font-weight: 800; letter-spacing: -.02em; line-height: 1; }
.gis-stats__l { margin-top: 8px; color: var(--gis-on-navy-dim); font-size: 13px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase; }

/* --------------------------------------------------------------------------
   Hairline grids
   The export draws 1px dividers by gapping the grid and letting a background
   colour bleed through. Reproduced here so the effect survives reflow.
   -------------------------------------------------------------------------- */

.gis-hairgrid {
  display: grid;
  gap: 1px;
  background: var(--gis-cream-line);
  border: 1px solid var(--gis-cream-line);
}
.gis-hairgrid > * { background: #fff; }
.gis-hairgrid--cream > * { background: var(--gis-cream); }
.gis-hairgrid > .gis-cell--navy { background: var(--gis-navy); }

.gis-grid-2 { grid-template-columns: repeat(2, 1fr); }
.gis-grid-3 { grid-template-columns: repeat(3, 1fr); }
.gis-grid-4 { grid-template-columns: repeat(4, 1fr); }
.gis-grid-6 { grid-template-columns: repeat(6, 1fr); }

/* Solutions: the football cell is a 2x2 feature tile. */
.gis-solutions__feature { grid-column: span 2; grid-row: span 2; position: relative; min-height: 400px; overflow: hidden; }
.gis-solutions__feature img { width: 100%; height: 100%; object-fit: cover; display: block; }
.gis-solutions__caption {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 32px;
  background: linear-gradient(180deg, rgba(11,36,71,0) 0%, rgba(11,36,71,.92) 70%);
}

/* --------------------------------------------------------------------------
   Process
   -------------------------------------------------------------------------- */

.gis-process { display: grid; grid-template-columns: repeat(6, 1fr); gap: 28px; margin-top: 52px; }
.gis-process__step { border-top: 3px solid var(--gis-navy-rule); padding-top: 20px; }
.gis-process__step:first-child { border-top-color: var(--gis-red); }
.gis-figures { display: grid; grid-template-columns: repeat(4, 1fr); gap: 24px; margin-top: 64px; }
.gis-figures figure { margin: 0; }
.gis-figures img { width: 100%; height: 270px; object-fit: cover; display: block; }
.gis-figures figcaption { margin-top: 12px; color: var(--gis-on-navy-dim); font-size: 13px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; }

/* --------------------------------------------------------------------------
   Projects
   -------------------------------------------------------------------------- */

.gis-projects { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; margin-top: 44px; }
.gis-project { background: #fff; border: 1px solid var(--gis-cream-line); }
.gis-project img { width: 100%; height: 280px; object-fit: cover; display: block; }
.gis-project__body { padding: 26px; }

/* --------------------------------------------------------------------------
   Surfaces table
   -------------------------------------------------------------------------- */

.gis-table { width: 100%; border-collapse: collapse; margin-top: 36px; font-size: 16px; }
.gis-table thead tr { border-bottom: 2px solid var(--gis-navy); }
.gis-table th {
  text-align: left; padding: 16px 20px;
  color: var(--gis-navy); font-size: 13px; font-weight: 800;
  letter-spacing: .12em; text-transform: uppercase;
}
.gis-table td { padding: 20px; color: var(--gis-ink-soft); }
.gis-table tbody tr { border-bottom: 1px solid var(--gis-cream-line); }
.gis-table tbody tr:last-child { border-bottom: 0; }
.gis-table th:first-child, .gis-table td:first-child { padding-left: 0; }
.gis-table th:last-child,  .gis-table td:last-child  { padding-right: 0; }
.gis-table td:first-child { color: var(--gis-navy); font-weight: 800; }

/* --------------------------------------------------------------------------
   CTA + footer
   -------------------------------------------------------------------------- */

.gis-cta { background: var(--gis-red); }
.gis-cta__inner {
  padding-block: 88px;
  display: grid;
  grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr);
  gap: 64px;
  align-items: center;
}
.gis-cta__title { margin: 0; color: #fff; font-size: clamp(2rem, 4vw, 3.625rem); line-height: 1; font-weight: 800; letter-spacing: -.03em; max-width: 18ch; }
.gis-cta__actions { display: flex; flex-direction: column; gap: 14px; }
.gis-cta__actions > a { width: 100%; font-size: 17px; font-weight: 700; padding: 20px 26px; }

.gis-foot { background: var(--gis-navy); }
.gis-foot__cols {
  padding-block: 64px 32px;
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) repeat(3, minmax(0, 1fr));
  gap: 48px;
}
.gis-foot__col { display: flex; flex-direction: column; gap: 12px; }
.gis-foot__legal {
  padding-block: 24px 40px;
  border-top: 1px solid var(--gis-navy-rule);
  display: flex; justify-content: space-between; gap: 24px; flex-wrap: wrap;
}

/* --------------------------------------------------------------------------
   Responsive. None of this exists in the export.
   Breakpoints chosen off the content, not off device widths: each one is the
   point where a specific grid stops fitting its own copy.
   -------------------------------------------------------------------------- */

@media (max-width: 1180px) {
  .gis-process { grid-template-columns: repeat(3, 1fr); row-gap: 40px; }
  .gis-nav { gap: 22px; }
}

@media (max-width: 1024px) {
  :root { --gis-gutter: 28px; --gis-section-y: 72px; }

  .gis-two-col,
  .gis-cta__inner { grid-template-columns: 1fr; gap: 40px; }

  .gis-head { flex-direction: column; align-items: flex-start; gap: 18px; }
  .gis-head__standfirst { max-width: 60ch; }

  .gis-grid-4 { grid-template-columns: repeat(2, 1fr); }
  .gis-projects { grid-template-columns: repeat(2, 1fr); }
  .gis-figures  { grid-template-columns: repeat(2, 1fr); }
  .gis-foot__cols { grid-template-columns: repeat(2, 1fr); gap: 36px; }

  /* Collapse the nav to a disclosure. Checkbox + sibling selector, no JS. */
  .gis-nav {
    display: none;
    position: absolute;
    left: 0; right: 0; top: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    background: var(--gis-navy-deep);
    border-bottom: 2px solid var(--gis-navy-line);
    padding: 8px 0 16px;
  }
  .gis-nav > a { padding: 15px var(--gis-gutter); font-size: 16px; }
  /* .gis-nav sits inside .gis-header__bar, so it is a *descendant* of the
     checkbox's sibling — not a sibling itself. */
  .gis-navtoggle-box:checked ~ .gis-header__bar .gis-nav { display: flex; }
  .gis-navtoggle {
    display: flex; flex-direction: column; justify-content: center; gap: 5px;
    width: 44px; height: 44px;
    background: none; border: 0; cursor: pointer; padding: 0;
  }
  .gis-navtoggle span { display: block; height: 2px; background: #fff; transition: transform .2s ease, opacity .2s ease; }
  .gis-navtoggle-box:checked ~ .gis-header__bar .gis-navtoggle span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
  .gis-navtoggle-box:checked ~ .gis-header__bar .gis-navtoggle span:nth-child(2) { opacity: 0; }
  .gis-navtoggle-box:checked ~ .gis-header__bar .gis-navtoggle span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
}

@media (max-width: 860px) {
  .gis-stats { grid-template-columns: repeat(2, 1fr); }
  .gis-hero__inner { padding-block: 72px 64px; gap: 26px; }
  .gis-solutions__feature { min-height: 300px; }
}

@media (max-width: 700px) {
  .gis-process { grid-template-columns: repeat(2, 1fr); }
  .gis-projects,
  .gis-figures { grid-template-columns: 1fr; }
  .gis-hero__lede { font-size: 17px; }

  /* The spec table has four columns of real content; it cannot shrink, so it
     becomes a stack of labelled rows. Labels come from data-label. */
  .gis-table thead { display: none; }
  .gis-table, .gis-table tbody, .gis-table tr, .gis-table td { display: block; width: 100%; }
  .gis-table tr { border-bottom: 1px solid var(--gis-cream-line); padding-block: 20px; }
  .gis-table td { padding: 4px 0; }
  .gis-table td::before {
    content: attr(data-label);
    display: block;
    color: var(--gis-navy); font-size: 11px; font-weight: 800;
    letter-spacing: .12em; text-transform: uppercase;
    margin-bottom: 3px;
  }
  .gis-table td:first-child::before { content: none; }
  .gis-table td:first-child { font-size: 19px; margin-bottom: 8px; }
}

@media (max-width: 560px) {
  :root { --gis-gutter: 20px; --gis-section-y: 56px; }

  .gis-grid-4,
  .gis-grid-2,
  .gis-process { grid-template-columns: 1fr; }
  .gis-solutions__feature { grid-column: span 1; grid-row: span 1; min-height: 240px; }
  .gis-stats { grid-template-columns: 1fr; }
  .gis-stats > * { padding: 22px 24px; }
  .gis-foot__cols { grid-template-columns: 1fr; }
  .gis-cta__actions > a { padding: 17px 22px; font-size: 16px; }
  .gis-figures img { height: 220px; }
}

/* Quality floor: honour a reduced-motion preference. */
@media (prefers-reduced-motion: reduce) {
  * { transition-duration: .01ms !important; animation-duration: .01ms !important; }
}

/* ==== gis:content-classes ==== */
/* Written by 02-front-page.php. Text and component classes for the block
   markup on the front page. Structural rules live above this marker. */

/* Core's flow layout adds margin-block-start to sibling blocks, which would
   fight every grid below. Neutralised on grid containers only. */
.gis-hairgrid > *,
.gis-stats > *,
.gis-process > *,
.gis-figures > *,
.gis-projects > * { margin-block-start: 0; margin-block-end: 0; }

/* Kickers. The --rule variant draws the hero's short red dash as a pseudo
   element so the text stays a single editable paragraph. */
.gis-kicker {
  margin: 0;
  color: var(--gis-red);
  font-size: 13px; font-weight: 800;
  letter-spacing: .18em; text-transform: uppercase;
}
.gis-kicker--on-navy { color: var(--gis-salmon); }
.gis-kicker--rule {
  display: flex; align-items: center; gap: 14px;
  color: #fff; letter-spacing: .18em;
}
.gis-kicker--rule::before {
  content: ""; flex: none;
  width: 44px; height: 3px;
  background: var(--gis-red);
}

.gis-h2 { margin: 14px 0 0; color: var(--gis-navy); font-size: clamp(2rem, 3.4vw, 3rem); }
.gis-h2--on-navy { color: #fff; }
.gis-h2 em { font-style: normal; color: var(--gis-red); }

.gis-standfirst { margin: 0; max-width: 38ch; color: var(--gis-ink-mute); font-size: 16px; line-height: 1.55; }
.gis-standfirst--on-navy { color: var(--gis-on-navy-dim); max-width: 34ch; }

/* Numbered cards in the Positioning grid. */
.gis-numcard { padding: 32px; }
.gis-numcard__n { margin: 0; color: var(--gis-red); font-size: 13px; font-weight: 800; letter-spacing: .14em; }
.gis-numcard__h { margin: 14px 0 10px; color: var(--gis-navy); font-size: 21px; font-weight: 800; letter-spacing: -.01em; }
.gis-numcard__p { margin: 0; color: var(--gis-ink-mute); font-size: 15px; line-height: 1.55; }

/* Solutions tiles. */
.gis-tile { padding: 30px; }
.gis-tile__h { margin: 0; color: var(--gis-navy); font-size: 20px; font-weight: 800; letter-spacing: 0; }
.gis-tile__p { margin: 8px 0 0; color: var(--gis-ink-mute); font-size: 14px; line-height: 1.5; }
.gis-cell--navy .gis-tile__h { color: #fff; }
.gis-cell--navy { display: flex; flex-direction: column; justify-content: space-between; }

.gis-solutions__feature figure,
.gis-solutions__feature .wp-block-image { margin: 0; height: 100%; }
.gis-solutions__caption__h { margin: 0; color: #fff; font-size: 30px; font-weight: 800; letter-spacing: -.02em; }
.gis-solutions__caption__p { margin: 8px 0 0; color: var(--gis-on-navy); font-size: 15px; }

/* Hero. The background is a core image block, so the <figure> is positioned
   and the <img> inside it does the covering. */
.gis-hero__bg { position: absolute; inset: 0; margin: 0; z-index: 0; }
.gis-hero__bg img { width: 100%; height: 100%; object-fit: cover; opacity: .55; display: block; }
.gis-hero__scrim { z-index: 1; }
.gis-hero__inner { z-index: 2; }

/* Buttons — core emits .wp-block-button > a.wp-block-button__link, so the
   variant class sits on the wrapper and styles the link inside it. */
.gis-actions { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.gis-actions .wp-block-button__link {
  border-radius: 0;
  font-size: 16px; font-weight: 700;
  padding: 17px 30px;
  transition: background-color .15s ease, color .15s ease;
}
.gis-btn--primary .wp-block-button__link { background: var(--gis-red); color: #fff; border: 0; }
.gis-btn--primary .wp-block-button__link:hover { background: var(--gis-red-dark); color: #fff; }
.gis-btn--ghost .wp-block-button__link {
  background: transparent; color: #fff;
  border: 2px solid #fff; padding: 15px 28px;
}
.gis-btn--ghost .wp-block-button__link:hover { background: #fff; color: var(--gis-navy); }

/* Standalone underlined text links. */
.gis-textlink {
  display: inline-block;
  color: var(--gis-red-deep); font-size: 16px; font-weight: 700;
  border-bottom: 2px solid var(--gis-red);
  padding-bottom: 3px;
  transition: color .15s ease;
}
.gis-textlink:hover { color: var(--gis-red); }
.gis-textlink--on-navy { color: #fff; }
.gis-textlink--on-navy:hover { color: var(--gis-salmon); }
.gis-textlink--ink { color: var(--gis-navy); }

.gis-lede { margin: 0; max-width: 42ch; color: var(--gis-ink-soft); font-size: 17px; line-height: 1.6; }

/* ==== gis:content-classes-b ==== */
/* Written by 03-front-page-b.php. */

/* Process */
.gis-process__n { margin: 0; color: var(--gis-on-navy-dim); font-size: 12px; font-weight: 800; letter-spacing: .16em; }
.gis-process__h { margin: 12px 0 10px; color: #fff; font-size: 19px; font-weight: 800; letter-spacing: 0; }
.gis-process__p { margin: 0; color: var(--gis-on-navy-dim); font-size: 14px; line-height: 1.55; }
.gis-figures .wp-block-image { margin: 0; }
.gis-figures figcaption,
.gis-figures .wp-element-caption {
  margin-top: 12px;
  color: var(--gis-on-navy-dim);
  font-size: 13px; font-weight: 600;
  letter-spacing: .06em; text-transform: uppercase;
  text-align: left;
}

/* Projects */
.gis-project .wp-block-image { margin: 0; }
.gis-project__kicker { margin: 0; color: var(--gis-red); font-size: 12px; font-weight: 800; letter-spacing: .14em; text-transform: uppercase; }
.gis-project__h { margin: 12px 0 8px; color: var(--gis-navy); font-size: 23px; font-weight: 800; letter-spacing: -.02em; }
.gis-project__p { margin: 0; color: var(--gis-ink-mute); font-size: 15px; line-height: 1.55; }

/* Surfaces table.
   The core table block puts className on the <figure>, not the <table>, so
   the table itself is reached as a descendant. These rules come after the
   ones above the first marker and deliberately override them. */
.gis-table { width: 100%; margin-top: 36px; }
.gis-table table { width: 100%; border-collapse: collapse; font-size: 16px; }
.gis-table thead tr { border-bottom: 2px solid var(--gis-navy); }
.gis-table td, .gis-table th { border: 0; }

/* Clients */
.gis-client { padding: 26px 24px; }
.gis-client__kicker { margin: 0; color: var(--gis-red); font-size: 12px; font-weight: 800; letter-spacing: .12em; text-transform: uppercase; }
.gis-client__name { margin: 10px 0 0; color: var(--gis-navy); font-size: 18px; font-weight: 800; letter-spacing: -.01em; }
.gis-client__place { margin: 6px 0 0; color: var(--gis-ink-mute); font-size: 14px; }
.gis-cell--navy .gis-client__name { color: #fff; }

/* CTA */
.gis-cta__lede { margin: 22px 0 0; max-width: 48ch; color: var(--gis-blush); font-size: 18px; line-height: 1.55; }
.gis-cta__actions .wp-block-button__link {
  display: block; width: 100%;
  border-radius: 0;
  font-size: 17px; font-weight: 700;
  padding: 20px 26px;
  text-align: left;
  transition: background-color .15s ease, color .15s ease;
}
.gis-btn--navy .wp-block-button__link { background: var(--gis-navy); color: #fff; border: 0; }
.gis-btn--navy .wp-block-button__link:hover { background: var(--gis-navy-deep); }
.gis-btn--white .wp-block-button__link { background: #fff; color: var(--gis-navy); border: 0; }
.gis-btn--white .wp-block-button__link:hover { background: var(--gis-cream); }
.gis-btn--outline .wp-block-button__link {
  background: transparent; color: #fff;
  border: 2px solid #fff; padding: 18px 24px;
}
.gis-btn--outline .wp-block-button__link:hover { background: #fff; color: var(--gis-red); }

@media (max-width: 700px) {
  /* Table header cells are hidden in the stacked view; keep the filter's
     data-label as the only visible label. */
  .gis-table table, .gis-table thead, .gis-table tbody,
  .gis-table tr, .gis-table td { display: block; width: 100%; }
}

/* ==== gis:chrome-classes ==== */
/* Written by 04-fix-chrome.php.
   These replace the inline style attributes that used to sit on the header and
   footer links. Inline styles win over class selectors no matter the
   specificity, so while they were there every :hover below was inert. */

.gis-navlink {
  color: #FFFFFF;
  font-size: 15px; font-weight: 500;
  letter-spacing: .01em;
}
.gis-navlink:hover { color: var(--gis-salmon); }

.gis-header__cta {
  background: var(--gis-red);
  color: #FFFFFF;
  font-size: 15px; font-weight: 700;
  letter-spacing: .01em;
  padding: 13px 22px;
  transition: background-color .15s ease;
}
.gis-header__cta:hover { background: var(--gis-red-dark); color: #FFFFFF; }

.gis-foot__blurb {
  margin: 22px 0 0;
  max-width: 34ch;
  color: var(--gis-on-navy-dim);
  font-size: 15px; line-height: 1.6;
}
.gis-foot__head {
  color: #FFFFFF;
  font-size: 12px; font-weight: 800;
  letter-spacing: .14em; text-transform: uppercase;
}
.gis-footlink {
  color: var(--gis-on-navy-dim);
  font-size: 15px;
  transition: color .15s ease;
}
.gis-footlink:hover { color: #FFFFFF; }

.gis-foot__addr {
  margin: 0;
  color: var(--gis-on-navy-dim);
  font-size: 15px; line-height: 1.55;
  font-style: normal;
}
.gis-foot__copy { color: var(--gis-navy-mute); font-size: 13px; }
.gis-foot__legal-links { display: flex; gap: 26px; }
.gis-footlink--legal { color: var(--gis-navy-mute); font-size: 13px; }

@media (max-width: 560px) {
  .gis-foot__legal-links { gap: 18px; }
}

/* ==== gis:image-fixes ==== */
/* Written by 05-fix-images.php.

   Core's `.wp-block-image img { height: auto }` is one class + one element —
   exactly the same specificity as `.gis-project img`. Equal specificity means
   source order decides, and relying on that was the bug. Every selector below
   is deliberately more specific than core's, so these win outright no matter
   how the stylesheets end up ordered. */

/* Solutions feature tile. The <img> had no rule at all before this. */
.gis-hairgrid .gis-solutions__feature { position: relative; overflow: hidden; }
.gis-hairgrid .gis-solutions__feature .wp-block-image {
  margin: 0;
  height: 100%;
  display: block;
}
.gis-hairgrid .gis-solutions__feature .wp-block-image img {
  width: 100%;
  height: 100%;
  min-height: 400px;
  object-fit: cover;
  display: block;
}
.gis-hairgrid .gis-solutions__caption {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: 32px;
  background: linear-gradient(180deg, rgba(11,36,71,0) 0%, rgba(11,36,71,.92) 70%);
}

/* Project cards — fixed 280px image band so cards align across the row. */
.gis-projects .gis-project .wp-block-image { margin: 0; }
.gis-projects .gis-project .wp-block-image img {
  width: 100%;
  height: 280px;
  object-fit: cover;
  display: block;
}

/* Process figures — fixed 270px band. */
.gis-figures .wp-block-image { margin: 0; }
.gis-figures .wp-block-image img {
  width: 100%;
  height: 270px;
  object-fit: cover;
  display: block;
}

/* Hero background. */
.gis-hero .gis-hero__bg { position: absolute; inset: 0; margin: 0; z-index: 0; }
.gis-hero .gis-hero__bg img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: .55;
  display: block;
}

/* Contrast fix. #4A6F9F on #0B2447 measured 2.98:1 against a 4.5:1
   requirement. #8FA5C1 on the same ground measures 6.11:1. */
.gis-foot__copy,
.gis-footlink--legal { color: var(--gis-on-navy-dim); }

@media (max-width: 1024px) {
  .gis-hairgrid .gis-solutions__feature .wp-block-image img { min-height: 300px; }
}
@media (max-width: 700px) {
  .gis-projects .gis-project .wp-block-image img { height: 240px; }
  .gis-figures .wp-block-image img { height: 220px; }
}
@media (max-width: 560px) {
  .gis-hairgrid .gis-solutions__feature .wp-block-image img { min-height: 240px; }
  /* Four stacked stat cells eat a lot of screen; tighten them up. */
  .gis-stats > * { padding: 18px 20px; }
  .gis-stats__n { font-size: 30px; }
}

/* ==== gis:equal-heights ==== */
/* Written by 06-equal-heights.php.

   Grid items with align-self:auto under align-items:normal are supposed to
   stretch to the row height. Measured on this page they did not — the row was
   451px and the shorter cards stayed at their 423px content height. Rather
   than rely on that behaviour, every cell is explicitly full-height and lays
   its children out as a column so one child can absorb the slack. */

/* Project cards: image band fixed, text body takes the remainder. */
.gis-projects > .gis-project {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-self: stretch;
}
.gis-projects > .gis-project > .gis-project__body {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
}
/* Keep the description hugging the top rather than centring in the slack. */
.gis-projects > .gis-project > .gis-project__body > .gis-project__p {
  margin-bottom: auto;
}

/* Hairline grids. A short cell here doesn't just look uneven — it breaks the
   1px divider, because the divider IS the container background showing through
   the gap. */
.gis-hairgrid > * {
  height: 100%;
  align-self: stretch;
}

/* The navy "Something else?" / "Your ground next" cells push their link to the
   bottom of whatever height the row ends up. */
.gis-hairgrid > .gis-cell--navy {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

/* Process steps: the red/blue top rules should all start on the same line, and
   the six columns should read as one band. */
.gis-process > .gis-process__step {
  height: 100%;
  align-self: stretch;
}

/* Process figures: caption sits directly under a fixed-height image, so the
   figures are already uniform — but pin them anyway for when a caption wraps
   to two lines on a narrow viewport. */
.gis-figures > .wp-block-image {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-self: stretch;
}

/* Stat cells. */
.gis-stats > * { align-self: stretch; }

@media (max-width: 560px) {
  /* Stacked, forcing full height on a single-column grid just adds dead space. */
  .gis-projects > .gis-project,
  .gis-hairgrid > *,
  .gis-process > .gis-process__step,
  .gis-figures > .wp-block-image { height: auto; }
}

/* ==== gis:hero-fixes ==== */
/* Written by 07-fix-hero.php. */

/* ---- 1. Stacking order inside the hero -------------------------------------
   The scrim sits at z-index 1 and covers the whole hero box, stats bar
   included. Everything that must read over it needs an explicit layer. */
.gis-hero { position: relative; isolation: isolate; }
.gis-hero > .gis-hero__bg     { z-index: 0; }
.gis-hero > .gis-hero__scrim  { z-index: 1; }
.gis-hero > .gis-hero__inner  { position: relative; z-index: 2; }
.gis-hero > .gis-stats-band   { position: relative; z-index: 3; }

/* The band is its own opaque surface — the photo should not bleed into it. */
.gis-hero > .gis-stats-band { background: var(--gis-navy-deep); }

/* ---- 2. Remove the top-level block gaps -----------------------------------
   Core adds margin-block-start: var(--wp--style--block-gap) to every sibling
   after the first inside .wp-site-blocks. That put 19px of white between the
   header and the hero, and the same again above the footer. Each section
   already carries its own padding. */
.wp-site-blocks > * + * { margin-block-start: 0; }
.wp-site-blocks > .entry-content,
.wp-site-blocks > .wp-block-post-content { margin-block: 0; }

/* Belt and braces: the first block inside the content should not add a top
   margin either. */
.entry-content > *:first-child { margin-block-start: 0; }

/* ---- 3. Ease the scrim ----------------------------------------------------
   Photo up from 0.55 to 0.68, gradient eased at every stop. Behind the
   headline the combined density is still ~0.94, so white type there stays
   far above the 4.5:1 line. */
.gis-hero > .gis-hero__bg img { opacity: .68; }

.gis-hero > .gis-hero__scrim {
  background: linear-gradient(
    90deg,
    rgba(11, 36, 71, .94) 0%,
    rgba(11, 36, 71, .72) 40%,
    rgba(11, 36, 71, .18) 100%
  );
}

/* On narrow viewports the headline sits over the middle of the photo rather
   than the left edge, so a horizontal gradient stops protecting it. Switch to
   a vertical one that keeps the top of the frame readable. */
@media (max-width: 860px) {
  .gis-hero > .gis-hero__scrim {
    background: linear-gradient(
      180deg,
      rgba(11, 36, 71, .90) 0%,
      rgba(11, 36, 71, .82) 55%,
      rgba(11, 36, 71, .70) 100%
    );
  }
  .gis-hero > .gis-hero__bg img { opacity: .6; }
}

/* ==== gis:two-col ==== */
/* Written by 08-fix-two-col.php.

   The base rule that was missing. The 1024px media query further down has
   always been collapsing this to a single column — but with no base grid to
   collapse FROM, the section simply rendered as a block and the tiles fell
   below the text instead of sitting beside it.

   Proportions are the export's: the text column is narrower than the tile
   grid, 80px gutter, both columns aligned to the top so the heading and the
   first row of tiles start on the same line. minmax(0, Nfr) rather than plain
   Nfr so a long unbroken word in a tile cannot force the column wider than
   its share. */

.gis-two-col {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.4fr);
  gap: 80px;
  align-items: start;
}

/* The intermediate step: below 1180px the 80px gutter is more than the layout
   can afford, but there is still room for two columns. */
@media (max-width: 1180px) {
  .gis-two-col { gap: 48px; }
}

/* IMPORTANT: this repeats the collapse that already exists earlier in the file.
   Media queries add no specificity — they only gate when a rule applies. The
   base rule above is appended at the end of the stylesheet, so at widths under
   1024px it would otherwise beat the earlier override on source order and the
   section would stay two-column on a phone. Re-declaring it here, after the
   base rule, is what actually makes the collapse hold. */
@media (max-width: 1024px) {
  .gis-two-col {
    grid-template-columns: 1fr;
    gap: 40px;
  }
}

/* ==== gis:flow-margins ==== */
/* Written by 09-fix-flow-margins.php.

   Core's flow layout emits roughly:

     .wp-container-core-group-is-layout-XXX
       > :where(:not(.alignleft):not(.alignright):not(.alignfull))
       { margin-block-start: var(--wp--style--block-gap); }

   :where() contributes nothing to specificity, so that selector weighs
   (0,1,0) — identical to `.gis-process > *`. Equal weight means load order
   decides, and core's generated styles come later. Every selector below is
   (0,2,0) or higher so it wins outright.

   The gap between cells is the grid's own `gap` property. These margins were
   only ever additive noise on top of it. */

/* Grid items must not carry flow margins — the grid gap already spaces them,
   and a margin on all-but-the-first staggers the row. */
.gis-process > .gis-process__step,
.gis-projects > .gis-project,
.gis-hairgrid > .wp-block-group,
.gis-stats > .wp-block-group,
.gis-figures > .wp-block-image,
.gis-cta__actions > .wp-block-button {
  margin-block-start: 0;
  margin-block-end: 0;
}

/* With the margin gone, stretch resolves to the full row height and the cards
   equalise without being forced. Kept explicit so it does not depend on the
   default alignment behaviour. */
.gis-projects > .gis-project { height: 100%; }
.gis-process > .gis-process__step { height: 100%; }
.gis-hairgrid > .wp-block-group { height: 100%; }

/* Sections are siblings inside .entry-content and were each picking up a 19px
   top margin from the same flow rule. Between a navy section and a cream one
   that reads as a blank strip across the page. Each section carries its own
   padding, so no margin is wanted between them at all. */
.entry-content > *,
.wp-block-post-content > * {
  margin-block-start: 0;
  margin-block-end: 0;
}

/* Guard: the reset above is broad, so restore the intentional offsets that the
   design does want inside sections. */
.gis-process { margin-top: 52px; }
.gis-figures { margin-top: 64px; }
.gis-projects { margin-top: 44px; }
.gis-table { margin-top: 36px; }

@media (max-width: 560px) {
  /* Single column: full-height cells would only add dead space. */
  .gis-projects > .gis-project,
  .gis-process > .gis-process__step,
  .gis-hairgrid > .wp-block-group { height: auto; }
}

/* ==== gis:offsets ==== */
/* Written by 10-fix-offsets.php.

   Core's flow layout zeroes the margins of every direct child of a container
   whose blockGap is 0 — and does it at (0,1,0), the same weight as a bare
   `.gis-process`, while printing after this stylesheet. So every offset below
   is written as `.gis-shell > x` at (0,2,0) to take load order out of it.

   These are the design's own values, not new spacing. */

/* Process: continuous head divider, then a clear gap, then the six step rules
   as separate segments. Without this the rules land on the divider and read as
   one broken line. */
.gis-shell > .gis-process { margin-top: 52px; }

/* The photo strip below the six steps. */
.gis-shell > .gis-figures { margin-top: 64px; }

/* Projects card grid, below its section head. */
.gis-shell > .gis-projects { margin-top: 44px; }

/* Surfaces spec table, below its section head. */
.gis-shell > .gis-table { margin-top: 36px; }

/* Hairline grids that sit under a section head. The Solutions and Clients
   grids carry inline margin-top attributes which already win, but declaring it
   here too means the layout does not depend on those inline styles surviving
   an edit in the block editor. */
.gis-shell > .gis-hairgrid { margin-top: 36px; }
.gis-solutions .gis-shell > .gis-hairgrid { margin-top: 1px; }

@media (max-width: 1024px) {
  .gis-shell > .gis-process  { margin-top: 40px; }
  .gis-shell > .gis-figures  { margin-top: 44px; }
  .gis-shell > .gis-projects { margin-top: 32px; }
  .gis-shell > .gis-table    { margin-top: 28px; }
  .gis-shell > .gis-hairgrid { margin-top: 28px; }
  .gis-solutions .gis-shell > .gis-hairgrid { margin-top: 1px; }
}

@media (max-width: 560px) {
  .gis-shell > .gis-process  { margin-top: 32px; }
  .gis-shell > .gis-figures  { margin-top: 32px; }
  .gis-shell > .gis-projects { margin-top: 24px; }
  .gis-shell > .gis-table    { margin-top: 24px; }
  .gis-shell > .gis-hairgrid { margin-top: 24px; }
  .gis-solutions .gis-shell > .gis-hairgrid { margin-top: 1px; }
}

/* ==== gis:spacing ==== */
/* Written by 11-fix-spacing.php.

   Every rule here exists only to out-specify core's flow-layout margin reset.
   The values are the design's own — nothing new is being introduced. Each
   selector adds an ancestor class purely to reach (0,2,0), because core's
   equivalent is (0,1,0) and prints later in the document.

   If you add spacing to this stylesheet later, scope it to a parent the same
   way or it will not apply. */

/* ---- Section heads -------------------------------------------------------- */
.gis-shell .gis-h2 { margin: 14px 0 0; }

/* ---- Positioning cards ---------------------------------------------------- */
.gis-hairgrid .gis-numcard__h { margin: 14px 0 10px; }
.gis-hairgrid .gis-numcard__n,
.gis-hairgrid .gis-numcard__p { margin: 0; }

/* ---- Solutions tiles ------------------------------------------------------ */
.gis-hairgrid .gis-tile__h { margin: 0; }
.gis-hairgrid .gis-tile__p { margin: 8px 0 0; }
.gis-hairgrid .gis-solutions__caption__h { margin: 0; }
.gis-hairgrid .gis-solutions__caption__p { margin: 8px 0 0; }

/* ---- Hero stat bar -------------------------------------------------------- */
.gis-stats .gis-stats__n { margin: 0; }
.gis-stats .gis-stats__l { margin: 8px 0 0; }

/* ---- Process steps -------------------------------------------------------- */
.gis-process .gis-process__n { margin: 0; }
.gis-process .gis-process__h { margin: 12px 0 10px; }
.gis-process .gis-process__p { margin: 0; }

/* ---- Project cards -------------------------------------------------------- */
.gis-projects .gis-project__kicker { margin: 0; }
.gis-projects .gis-project__h { margin: 12px 0 8px; }
.gis-projects .gis-project__p { margin: 0; }

/* ---- Client cells --------------------------------------------------------- */
.gis-hairgrid .gis-client__kicker { margin: 0; }
.gis-hairgrid .gis-client__name { margin: 10px 0 0; }
.gis-hairgrid .gis-client__place { margin: 6px 0 0; }

/* ---- CTA ------------------------------------------------------------------ */
.gis-cta__inner .gis-cta__title { margin: 0; }
.gis-cta__inner .gis-cta__lede { margin: 22px 0 0; }

/* CTA buttons must fill their column. Core's flex layout sets
   align-items:flex-start on .wp-block-buttons, which shrink-wraps each button
   wrapper to its label — so a width:100% on the inner link achieves nothing.
   Stretch the container and widen the wrappers. */
.gis-cta__actions.wp-block-buttons {
  align-items: stretch;
  width: 100%;
}
.gis-cta__actions.wp-block-buttons > .wp-block-button {
  width: 100%;
  max-width: none;
}
.gis-cta__actions.wp-block-buttons > .wp-block-button > .wp-block-button__link {
  display: block;
  width: 100%;
  text-align: left;
}

/* ---- Hero copy ------------------------------------------------------------ */
.gis-hero__inner .gis-hero__title { margin: 0; }
.gis-hero__inner .gis-hero__lede { margin: 0; }
.gis-hero__inner .gis-kicker { margin: 0; }

/* ---- Between sections ----------------------------------------------------- */
/* The 19px white strip. Core's post-content flow rule is (0,1,0); doubling the
   class on the same element gets us to (0,2,0) without adding a wrapper. */
.entry-content.wp-block-post-content > * {
  margin-block-start: 0;
  margin-block-end: 0;
}

/* ---- Process figure captions --------------------------------------------- */
.gis-figures .wp-block-image .wp-element-caption,
.gis-figures .wp-block-image figcaption { margin: 12px 0 0; }

/* ==== gis:mobile ==== */
/* Written by 14-mobile.php.

   This block comes last in the stylesheet on purpose: it must override the
   single-column rules declared in the earlier media queries, and media queries
   contribute no specificity of their own — only source order decides. */

@media (max-width: 560px) {

  /* ---- Stat bar: 2x2 rather than a 384px stack -------------------------- */
  .gis-stats { grid-template-columns: repeat(2, 1fr); }
  .gis-stats > * { padding: 18px 16px; }
  .gis-stats__n { font-size: 28px; }
  .gis-stats__l { font-size: 11px; letter-spacing: .08em; }

  /* ---- Process steps: titles are one or two words ---------------------- */
  .gis-process { grid-template-columns: repeat(2, 1fr); gap: 22px; }
  .gis-process > .gis-process__step { height: auto; }

  /* ---- Process photos: two up, shorter ---------------------------------- */
  .gis-figures { grid-template-columns: repeat(2, 1fr); gap: 12px; }
  .gis-figures .wp-block-image img { height: 150px; }
  .gis-figures figcaption,
  .gis-figures .wp-element-caption { font-size: 11px; letter-spacing: .04em; }

  /* ---- Solutions tiles: two up. The feature photo keeps the full width,
          since it is the section's only image and carries the headline. ---- */
  .gis-solutions .gis-hairgrid { grid-template-columns: repeat(2, 1fr); }
  .gis-solutions .gis-solutions__feature { grid-column: span 2; }
  .gis-solutions .gis-hairgrid .gis-solutions__feature .wp-block-image img { min-height: 200px; }
  .gis-solutions .gis-tile { padding: 20px 16px; }
  .gis-solutions .gis-hairgrid .gis-tile__h { font-size: 17px; }
  .gis-solutions .gis-hairgrid .gis-tile__p { font-size: 13px; }
  /* The "Something else?" cell reads better across the full width. */
  .gis-solutions .gis-hairgrid > .gis-cell--navy { grid-column: span 2; }

  /* ---- Positioning cards: two up ---------------------------------------- */
  .gis-positioning .gis-hairgrid { grid-template-columns: repeat(2, 1fr); }
  .gis-positioning .gis-numcard { padding: 20px 16px; }
  .gis-positioning .gis-hairgrid .gis-numcard__h { font-size: 17px; margin: 10px 0 8px; }
  .gis-positioning .gis-hairgrid .gis-numcard__p { font-size: 13px; }

  /* ---- Project cards: shorter image band -------------------------------- */
  .gis-projects .gis-project .wp-block-image img { height: 180px; }
  .gis-projects > .gis-project > .gis-project__body { padding: 20px; }
  .gis-projects .gis-project__h { font-size: 20px; }

  /* ---- Touch targets ----------------------------------------------------- */
  /* Footer links measured 24px tall. Padding brings them to ~44px without
     changing the visual rhythm much, and the column gap shrinks to compensate
     so the footer does not get taller overall. */
  .gis-foot .gis-foot__col { gap: 0; }
  .gis-foot .gis-footlink {
    display: block;
    padding-block: 10px;
    line-height: 1.4;
  }
  .gis-foot__legal-links .gis-footlink--legal { padding-block: 10px; }

  /* Standalone underlined links measured 31px. */
  .gis-textlink { padding-block: 8px; }
}

/* Clients cells carry the longest strings on the page — "Basketball · 8 layer
   acrylic" over a school name over a district. Two columns only once there is
   enough width for that not to become a column of single words. */
@media (min-width: 400px) and (max-width: 560px) {
  .gis-clients-section .gis-hairgrid { grid-template-columns: repeat(2, 1fr); }
  .gis-clients-section .gis-hairgrid > .gis-cell--navy { grid-column: span 2; }
  .gis-clients-section .gis-client { padding: 18px 14px; }
  .gis-clients-section .gis-hairgrid .gis-client__kicker { font-size: 11px; }
  .gis-clients-section .gis-hairgrid .gis-client__name { font-size: 16px; }
  .gis-clients-section .gis-hairgrid .gis-client__place { font-size: 13px; }
}

/* Below 400px everything that is text-dense goes back to one column. */
@media (max-width: 399px) {
  .gis-clients-section .gis-hairgrid { grid-template-columns: 1fr; }
}

/* ==== gis:clients-bp ==== */
/* Written by 15-clients-bp.php.

   Supersedes the min-width:400px gate from the gis:mobile block above. 400px
   sat just above iPhone 12/13/14 (390px) and iPhone 15/16 (393px), so the
   phones most visitors actually hold were getting the single-column fallback.
   360px covers those and leaves the very smallest devices stacked. */

@media (min-width: 360px) and (max-width: 560px) {
  .gis-clients-section .gis-hairgrid { grid-template-columns: repeat(2, 1fr); }
  .gis-clients-section .gis-hairgrid > .gis-cell--navy { grid-column: span 2; }
  .gis-clients-section .gis-client { padding: 16px 13px; }
  .gis-clients-section .gis-hairgrid .gis-client__kicker { font-size: 10.5px; letter-spacing: .08em; }
  .gis-clients-section .gis-hairgrid .gis-client__name { font-size: 15px; margin: 8px 0 0; }
  .gis-clients-section .gis-hairgrid .gis-client__place { font-size: 12.5px; margin: 4px 0 0; }
}

/* Below 360px the cells become a column of single words — keep them stacked. */
@media (max-width: 359px) {
  .gis-clients-section .gis-hairgrid { grid-template-columns: 1fr; }
}