/* ==========================================================================
   home.css — homepage-only styles
   Owned by the HOMEPAGE thread. Loaded AFTER site.css.

   WHY THIS FILE EXISTS
   site.css is BUILD's file and the homepage thread does not edit it. Every
   value below is either a token declared in site.css (var(--navy) etc.) or a
   layout rule that exists only on "/". Nothing here redefines a token.
   BUILD may fold this into site.css whenever it wants; nothing depends on it
   staying separate.

   BINDING RULES THIS FILE OBEYS
     · Background WHITE. No dark theme. (SPEC-CANONICAL §1)
     · Navy #0D3C87 primary and DOMINANT. Orange #FF4F01 signal accent ~10%.
     · Orange is 3.30:1 on white and 3.16:1 on navy — BOTH FAIL AA for normal
       text. Orange appears here only as: button FILLS, RULES, BORDERS and
       one LARGE heading accent. Never as small text.
       Every orange-filled button below carries a 1.25rem/700 label, which is
       WCAG "large text" (≥18.66px bold) and is the only condition under which
       the 3.30:1 fill is permitted. (SPEC-CANONICAL §1)
     · ONE radius token — var(--radius), 5px, set by BUILD. Not 12px.
     · Roboto Slab 600 headings, Roboto body. No Inter.
     · Zero JavaScript. FAQ is native <details>. No carousel. No count-up.
   ========================================================================== */


/* --------------------------------------------------------------------------
   SECTION RHYTHM
   -------------------------------------------------------------------------- */

.section {
  padding-block: var(--space-7);
  border-top: 1px solid var(--rule);
}

.section:first-of-type { border-top: 0; }

/* --------------------------------------------------------------------------
   ALTERNATING SECTION BACKGROUNDS — added 2026-09-01 on Masud's instruction.
   White, then #EBEBEB, and so on down the page.

   CONTRAST, COMPUTED NOT ASSUMED, because #EBEBEB is a new surface and
   SPEC-CANONICAL §1's measured ratios were all against pure white:

     navy #0D3C87 on #EBEBEB ....  8.76:1   passes AA and AAA. Safe.
     white cards on #EBEBEB ..... they now separate from the page, which is
                                   why the cards look better on this surface.
     orange #FF4F01 on #EBEBEB ..  2.76:1   ⚠️ WORSE than on white (3.30:1),
                                   and it now fails AA even for LARGE text,
                                   which needs 3:1.

   ⚠️ WHAT THAT LAST LINE MEANS IN PRACTICE. Orange text was already banned
   at every size by §1. On this grey it is banned harder: do not put orange
   text on an --alt section for any reason, at any size, ever. Orange fills,
   borders and rules are unaffected — a white label on an orange button is
   still 3.30:1 whatever colour the section behind it is, because the button
   provides its own background.

   The section rule under each heading and the service icons are orange on
   this grey at 2.76:1, which is fine ONLY because both are decorative:
   the icons carry aria-hidden and the rule is a border. Neither carries
   meaning. If an orange icon is ever made meaningful, it fails here.
   -------------------------------------------------------------------------- */

.section--alt,
.work-section--alt,
.service-block--alt {
  background: #EBEBEB;
}

/* On grey, the divider rule between sections is redundant — the colour change
   already does that job, and two separators read as a mistake. */
.section--alt { border-top: 0; }
.section--alt + .section { border-top: 0; }

.section__head { margin-bottom: var(--space-5); }

/* EYEBROW HIDDEN 2026-09-01 — Masud: the eyebrow and the heading stacked on
   two lines and opened up too much space. Hidden rather than deleted from the
   markup, so it can be switched back on in one line if the layout ever wants
   it. It stays in the DOM but out of the accessibility tree, so a screen
   reader does not read "Our Services / What we do" as two headings. */
.section__eyebrow { display: none; }

/* The orange signal. A 3px rule is a BORDER use, which is permitted. */
.section__head h2::after {
  content: "";
  display: block;
  width: 3rem;
  height: 3px;
  background: var(--orange);
  border-radius: var(--radius);
  margin-top: var(--space-3);
}

.section__lead { color: var(--ink-muted); max-width: var(--measure); }


/* --------------------------------------------------------------------------
   BUTTONS
   -------------------------------------------------------------------------- */

.btn {
  display: inline-block;
  padding: 0.75rem 1.5rem;
  border-radius: var(--radius);
  text-decoration: none;
  font-weight: var(--weight-bold);
  font-size: var(--step-1);      /* 1.25rem = 20px. Bold. WCAG LARGE TEXT. */
  line-height: 1.2;
  border: 2px solid transparent;
}

/* ORANGE FILL. Permitted ONLY because the label is 1.25rem/700 = large bold.
   Do not shrink this label. If it ever needs to be smaller, the fill must
   become navy. */
.btn--primary { background: var(--orange); color: #FFFFFF; }
.btn--primary:hover { background: #E64701; }

/* Navy outline. Navy on white is 10.43:1 — safe at any size. */
.btn--secondary { border-color: var(--navy); color: var(--navy); }
.btn--secondary:hover { background: var(--navy); color: #FFFFFF; }

/* On the navy bands. White fill, navy label — 10.43:1, safe. */
.btn--onnavy { background: #FFFFFF; color: var(--navy); }
.btn--onnavy:hover { background: #E8EEF7; }

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-top: var(--space-5);
}

/* Text link with a chevron. Navy, so it is safe at body size. */
.link-more {
  display: inline-block;
  font-weight: var(--weight-bold);
  color: var(--navy);
  margin-top: var(--space-4);
}


/* --------------------------------------------------------------------------
   1 — HERO
   -------------------------------------------------------------------------- */

/* THE GAP UNDER THE NAV — fixed 2026-09-01.

   It was doubled up. site.css sets `.site-main { padding-block: var(--space-7) }`
   — 4rem top — and `.hero` was adding another 4rem on top of that, so the
   headline started ~8rem below the header rule.

   .site-main is BUILD's class but this is BUILD's stylesheet being adjusted
   from the homepage sheet, not edited — the rule below is scoped to this page
   because home.css only loads here. site.css is untouched. */
.site-main { padding-block-start: 0; }

.hero { padding-block: var(--space-5) var(--space-6); }

.hero__grid {
  display: grid;
  gap: var(--space-6);
  align-items: center;
}

/* EQUAL COLUMNS — was 1.1fr / 0.9fr, which made the image column narrower
   and therefore shorter than the text beside it. At 1fr / 1fr with a 5:4
   image the two sides finish at roughly the same height. */
@media (min-width: 60rem) {
  .hero__grid { grid-template-columns: 1fr 1fr; gap: var(--space-7); }
}

/* The real hero image, when it lands. Same 5:4 box as the placeholder, so
   swapping <div class="ph ph--hero"> for
   <img class="hero__media" src="assets/img/hero.jpg" alt="…">
   changes nothing about the layout. */
.hero__media {
  width: 100%;
  aspect-ratio: 5 / 4;
  object-fit: cover;
  border-radius: var(--radius);
  box-shadow: var(--shadow-2);
}

.hero h1 { margin-bottom: var(--space-4); }

.hero__sub {
  font-size: var(--step-1);
  color: var(--ink-muted);
  max-width: 44ch;
}

/* Shared shadow scale. Navy-tinted rather than black, so shadows read as part
   of the palette instead of grey haze. Neutrals are not brand hues. */
/* Strengthened 2026-09-01 — Masud: the first pass was too faint. Roughly
   1.6× the previous opacity and a wider spread, so the cards actually sit
   above the page rather than hinting at it. Still navy-tinted, still soft. */
/* SOFTENED 2026-09-01 — Masud checked on a second monitor and the shadows
   read as too heavy. Roughly half the previous opacity. Third pass on this
   value: too faint → too strong → here. Change these three lines only; every
   shadowed surface on the site reads from them. */
:root {
  --shadow-1: 0 1px 2px rgba(13, 60, 135, 0.05), 0 3px 8px rgba(13, 60, 135, 0.06);
  --shadow-2: 0 2px 5px rgba(13, 60, 135, 0.07), 0 8px 18px rgba(13, 60, 135, 0.09);
  --shadow-3: 0 4px 10px rgba(13, 60, 135, 0.09), 0 14px 30px rgba(13, 60, 135, 0.12);

  /* One stroke width for every card-like surface, so "thicker" is a
     single-line change next time. */
  --stroke: 2px;
}

.proof {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-4);
  margin-top: var(--space-6);
}

@media (min-width: 48rem) {
  .proof { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* Each stat is its own rectangle with a shadow under it — Masud, 2026-09-01. */
.proof > p {
  margin: 0;
  max-width: none;
  padding: var(--space-4);
  border: var(--stroke) solid var(--rule);
  border-radius: var(--radius);          /* the ONE token */
  box-shadow: var(--shadow-1);
  background: #FFFFFF;
  transition: transform 0.22s ease, box-shadow 0.22s ease, border-color 0.22s ease;
}

.proof > p:hover {
  transform: scale(1.07) translateY(-4px);
  box-shadow: var(--shadow-3);
  border-color: var(--orange);
}

.proof__num {
  font-family: var(--font-heading);
  font-weight: var(--weight-heading);
  font-size: var(--step-3);
  line-height: 1.1;
  color: var(--navy);
  display: block;
}

.proof__label {
  font-size: var(--step--1);
  color: var(--ink-muted);
  display: block;
  margin-top: var(--space-1);
}


/* --------------------------------------------------------------------------
   COUNT-UP — added 2026-09-01 on Masud's instruction. ZERO JAVASCRIPT.

   ⚠️ READ THIS BEFORE CHANGING IT. instructions.md §3 lists "animated
   count-up counters WITHOUT A STATIC FALLBACK" among the banned patterns,
   and its Stats rule reads: "any number callout must render the real number
   in static HTML. Count-up animation, IF USED AT ALL, is a non-load-bearing
   CSS enhancement."

   So a count-up is not banned outright — an UNSAFE one is. This is the safe
   form and it satisfies the rule on all three counts:

     1. THE REAL NUMBER IS IN THE HTML. <span class="proof__num">60+</span>.
        View source and the figure is there. Screen readers and search
        engines get the real value whatever the browser does with the CSS.

     2. IT FAILS IN THE RIGHT DIRECTION. Everything below sits inside
        @supports at-rule(@property). A browser that cannot animate a custom
        property never enters the block, so it never hides the real text and
        simply shows the static number. That is precisely the failure the
        rule exists to prevent — Bizcope, The Digital Friday and the Fexora
        demo were all caught rendering "0" and "0+" because their JS counters
        never ran. That cannot happen here.

     3. IT IS NON-LOAD-BEARING. Delete this whole block and nothing changes
        except that the numbers stop moving.

   Reduced motion switches it off, per instructions.md §3 and WCAG 2.3.3.
   "Quick", per Masud: 900ms, ease-out, so it lands rather than crawls.
   -------------------------------------------------------------------------- */

@supports at-rule(@property) {
  @media (prefers-reduced-motion: no-preference) {

    @property --n {
      syntax: "<integer>";
      initial-value: 0;
      inherits: false;
    }

    /* Inside this guard the counter is known to work, so the static text is
       made transparent and the animated counter is painted over it. The text
       is never removed from the DOM. */
    .proof__num {
      position: relative;
      color: transparent;
      counter-reset: n var(--n);
    }

    .proof__num::after {
      content: counter(n) "+";
      position: absolute;
      inset: 0;
      color: var(--navy);
    }

    .proof__num--60  { --n: 60;  animation: count-60  0.9s ease-out both; }
    .proof__num--20  { --n: 20;  animation: count-20  0.9s ease-out both; }
    .proof__num--500 { --n: 500; animation: count-500 0.9s ease-out both; }
    .proof__num--10  { --n: 10;  animation: count-10  0.9s ease-out both; }

    @keyframes count-60  { from { --n: 0; } to { --n: 60;  } }
    @keyframes count-20  { from { --n: 0; } to { --n: 20;  } }
    @keyframes count-500 { from { --n: 0; } to { --n: 500; } }
    @keyframes count-10  { from { --n: 0; } to { --n: 10;  } }
  }
}


/* --------------------------------------------------------------------------
   2 — SERVICES
   -------------------------------------------------------------------------- */

/* THREE ACROSS on desktop — Masud, 2026-09-01. Six cards become 3 × 2, not
   the 4 × 2 the auto-fit produced. Two across on tablet, one on phone. */
.card-grid {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: 1fr;
}

@media (min-width: 40rem) { .card-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 62rem) { .card-grid { grid-template-columns: repeat(3, 1fr); } }

/* Service and stat icons. Inline SVG — NOT an icon font. instructions.md §3
   bans stacking icon font kits, and an inline SVG needs no extra request.

   ORANGE IS CORRECT HERE. SPEC-CANONICAL §1 permits orange on icons
   explicitly, alongside fills, large headings, borders and rules. Every icon
   is decorative and carries aria-hidden, so none of them is text and none is
   subject to the 3.30:1 text floor. This is also where a good share of the
   ~10% orange budget is meant to be spent. */
.icon {
  width: 2rem;
  height: 2rem;
  display: block;
  margin-bottom: var(--space-3);
  color: var(--orange);
  stroke: currentColor;
  fill: none;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.icon--stat {
  width: 1.5rem;
  height: 1.5rem;
  margin-bottom: var(--space-2);
}

/* Thicker stroke and a soft shadow — Masud, 2026-09-01. */
.card {
  border: var(--stroke) solid var(--rule);
  border-radius: var(--radius);          /* the ONE token */
  padding: var(--space-5);
  display: flex;
  flex-direction: column;
  background: #FFFFFF;
  box-shadow: var(--shadow-1);
}

.card h3 { margin-bottom: var(--space-2); color: var(--navy); }

.card p {
  color: var(--ink-muted);
  margin-bottom: var(--space-4);
  flex: 1 0 auto;
}

.card__link { font-weight: var(--weight-bold); color: var(--navy); }

/* Hover: grow ~5% and lift, with the orange edge. Masud, 2026-09-01.
   Orange on a BORDER is a permitted use — it is not text. */
.card:hover,
.card:focus-within {
  transform: scale(1.06) translateY(-5px);
  border-color: var(--orange);
  box-shadow: var(--shadow-3);
  z-index: 1;                            /* grow over its neighbours, not under */
  position: relative;
}

/* The icon leans into the lift too, so the card reads as one object moving. */
.card:hover .icon { transform: scale(1.12); }
.icon { transition: transform 0.22s ease; }


/* --------------------------------------------------------------------------
   3 — WHY MANGO
   -------------------------------------------------------------------------- */

.reasons {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr));
  list-style: none;
  padding: 0;
  margin: 0;
}

.reason { border-left: 3px solid var(--orange); padding-left: var(--space-4); }
.reason h3 { font-size: var(--step-1); margin-bottom: var(--space-2); }
.reason p { color: var(--ink-muted); margin: 0; }


/* --------------------------------------------------------------------------
   4 — PORTFOLIO HIGHLIGHT
   -------------------------------------------------------------------------- */

.work-grid {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
}

.work__cap {
  font-size: var(--step--1);
  color: var(--ink-muted);
  margin: var(--space-2) 0 0;
}


/* --------------------------------------------------------------------------
   5 & 9 — CTA BANDS
   Navy, not orange. SPEC-CANONICAL §1: navy does the surface-area work.
   -------------------------------------------------------------------------- */

/* FULL-BLEED, edge to edge — Masud, 2026-09-01. It was a rounded box inside
   the 72rem container with white either side; now the navy runs the full
   width like the marquee strips. No radius, because a radius on a
   full-width band is invisible at the left and right edges and only softens
   the top and bottom corners inconsistently.

   The surrounding gap was var(--space-7) top and bottom — 4rem each side on
   top of the section padding, which is the "huge gap" Masud flagged. Now
   var(--space-5). */
.cta-band {
  background: var(--navy);
  color: #FFFFFF;
  padding-block: var(--space-6);
  text-align: center;
  margin-block: var(--space-5);
  box-shadow: var(--shadow-2);
}

.cta-band h2 { color: #FFFFFF; }
.cta-band h2::after { display: none; }

.cta-band p { margin-inline: auto; color: #E8EEF7; }

.cta-band .btn-row { justify-content: center; }

/* ⚠️ BUG FIX 2026-09-01 — this rule used to read `.cta-band a`, which made
   the "Ready to get started?" button INVISIBLE: a white button on a navy
   band with its label forced to white. `.cta-band a` is specificity (0,1,1)
   and beat `.btn--onnavy` at (0,1,0), so the navy label lost.

   :not(.btn) scopes it to ordinary prose links only and leaves button labels
   to the button classes, where they belong.

   White on navy = 10.43:1. Safe at any size, unlike orange on navy. */
.cta-band a:not(.btn) { color: #FFFFFF; }


/* --------------------------------------------------------------------------
   6 — CLIENT LOGOS
   Static wrapped grid. NO auto-scrolling marquee. (instructions.md §3)
   -------------------------------------------------------------------------- */

.logo-grid {
  display: grid;
  gap: var(--space-3);
  grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
  align-items: stretch;
}

/* --------------------------------------------------------------------------
   LOGO MARQUEE — added 2026-09-01 on Masud's instruction.

   ⚠️⚠️  THIS OVERRIDES THREE WRITTEN RULES. Recorded here so that nobody
         later "fixes" it back, and nobody thinks it slipped through.

     · instructions.md §3 bans "auto-scrolling logo and service-tag
       marquees" by name, and prescribes "static wrapped grid, no auto-scroll."
     · SPEC-CANONICAL §9 zero-JS table: "Logos and testimonials → Static
       wrapped grid. No auto-scrolling marquee."
     · Masud's own brief for this thread: "MOTION — non-negotiable. No
       carousels or sliders."

   Masud instructed the sliding strip on 2026-09-01, having seen it on the
   live site. His live instruction wins. SPEC-CANONICAL §9 and
   instructions.md §3 should be amended to record the exception, or the next
   thread will delete this.

   WHAT WAS PRESERVED
   The zero-JS rule is NOT broken. This is pure CSS — no script, no library,
   no Swiper. The rule that gave way is the no-marquee rule, not the no-JS
   rule, and those are two different rules.

   ⚠️ ACCESSIBILITY — WCAG 2.2.2 "Pause, Stop, Hide" (Level A)
   Content that moves automatically, starts on load and runs longer than five
   seconds must offer the user a way to pause it. Two mitigations are built
   in below: it pauses on hover and on keyboard focus, and it does not run at
   all for a visitor whose system asks for reduced motion, who instead gets
   the compliant static wrapped grid.

   That is a strong mitigation but not full conformance — a hover pause is
   unavailable to a touch user. Full conformance needs a visible pause
   control, which is buildable with a checkbox-and-label toggle and still
   zero JS. Not added because it puts a control on the page that Masud did
   not ask for. Say the word and it is a ten-minute change.
   -------------------------------------------------------------------------- */

.logo-marquee {
  overflow: hidden;
  /* Fade the strip out at both edges so logos enter and leave rather than
     being chopped off by the viewport. */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 6rem, #000 calc(100% - 6rem), transparent);
          mask-image: linear-gradient(90deg, transparent, #000 6rem, #000 calc(100% - 6rem), transparent);
}

.logo-marquee__track {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  width: max-content;
  animation: logo-marquee 50s linear infinite;
}

/* Right to left, matching the live site. The track holds the twelve logos
   TWICE; translating by exactly -50% lands the copy where the original
   started, so the loop has no visible seam. */
@keyframes logo-marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

/* WCAG 2.2.2 mitigation 1 — pause on hover and on keyboard focus. */
.logo-marquee:hover  .logo-marquee__track,
.logo-marquee:focus-within .logo-marquee__track {
  animation-play-state: paused;
}

/* Larger — Masud, 2026-09-01. 3rem → 4.5rem. */
.logo-marquee img {
  height: 4.5rem;
  width: auto;
  max-width: 15rem;
  object-fit: contain;
  flex: 0 0 auto;
}

/* WCAG 2.2.2 mitigation 2 — no motion at all, and the compliant static
   wrapped grid instead. This is what instructions.md §3 asks for, and a
   reduced-motion visitor still gets exactly that. */
@media (prefers-reduced-motion: reduce) {
  .logo-marquee {
    -webkit-mask-image: none;
            mask-image: none;
  }
  .logo-marquee__track {
    animation: none;
    width: auto;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--space-5);
  }
  /* The duplicate half exists only to make the loop seamless. With no loop
     it is 12 redundant logos, so it goes. */
  .logo-marquee__track [data-marquee-clone] { display: none; }
}


/* --------------------------------------------------------------------------
   INDUSTRIES STRIP — added 2026-09-01 on Masud's instruction.

   Two rows sliding in OPPOSITE directions, mirroring the current live site's
   layout. Same pure-CSS mechanism as the logo marquee above, same hover and
   reduced-motion behaviour, same WCAG 2.2.2 position. No JavaScript.

   ⚠️ THE COLOUR IS DELIBERATELY NOT THE LIVE SITE'S.
   The current site's tiles are purple, yellow, violet, orange, teal, green
   and black — seven hues on one strip. That is the exact failure
   instructions.md §3 records against the current homepage ("no governing
   primary… #FF0085, #2877DC, #61CE70, a purple, a gold") and SPEC-CANONICAL
   §1 refuses a third brand hue outright.

   So the LAYOUT and the MOTION are reproduced and the RAINBOW is not. Tiles
   alternate navy-filled and white-outlined, which gives the same visual
   rhythm using the two colours the brand actually has.

   CONTRAST, checked rather than assumed: white on navy is 10.43:1 and navy
   on white is 10.43:1 — both pass at any size. An orange tile was considered
   and REJECTED: a tile label is normal-size text, and white on orange is
   3.30:1, which fails AA. Orange stays on the section rule.
   -------------------------------------------------------------------------- */

.industry-marquee {
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 4rem, #000 calc(100% - 4rem), transparent);
          mask-image: linear-gradient(90deg, transparent, #000 4rem, #000 calc(100% - 4rem), transparent);
}

.industry-marquee + .industry-marquee { margin-top: var(--space-3); }

.industry-marquee__track {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: max-content;
  animation: logo-marquee 65s linear infinite;
}

/* Second row travels the other way. */
.industry-marquee--reverse .industry-marquee__track { animation-direction: reverse; }

.industry-marquee:hover .industry-marquee__track,
.industry-marquee:focus-within .industry-marquee__track {
  animation-play-state: paused;
}

/* ⚠️ THE FONT SIZE AND WEIGHT HERE ARE LOad-BEARING, NOT DECORATION.
   Masud asked for orange tiles. White on orange #FF4F01 is 3.30:1, which
   FAILS WCAG AA for normal-size text — SPEC-CANONICAL §1, measured.
   It is permitted only on LARGE text: 18.66px or above AND bold.
   These tiles are 1.25rem (20px) at weight 700, which clears that bar.

   If anyone shrinks this label or drops it to a lighter weight, the ORANGE
   VARIANT BELOW BECOMES AN ACCESSIBILITY FAILURE and must change to a navy
   or white fill at the same time. Body font is used rather than Roboto Slab
   because only Slab 600 is loaded and 700 would be synthesised. */
.industry {
  flex: 0 0 auto;
  padding: 0.65rem 1.4rem;
  border-radius: var(--radius);          /* the ONE token, again */
  font-family: var(--font-body);
  font-weight: var(--weight-bold);       /* 700 */
  font-size: var(--step-1);              /* 20px — WCAG large-bold threshold */
  white-space: nowrap;
  background: var(--navy);
  color: #FFFFFF;                        /* 10.43:1 — safe */
  border: 2px solid var(--navy);
  box-shadow: var(--shadow-1);
}

/* White tile, navy label. 10.43:1 — safe at any size. */
.industry--alt {
  background: #FFFFFF;
  color: var(--navy);
}

/* Orange tile. Permitted ONLY because of the size and weight set above. */
.industry--accent {
  background: var(--orange);
  border-color: var(--orange);
  color: #FFFFFF;
}

.industry:hover {
  transform: scale(1.05);
  box-shadow: var(--shadow-2);
}

@media (prefers-reduced-motion: reduce) {
  .industry-marquee {
    -webkit-mask-image: none;
            mask-image: none;
  }
  .industry-marquee__track {
    animation: none;
    width: auto;
    flex-wrap: wrap;
    justify-content: center;
  }
  .industry-marquee__track [data-marquee-clone] { display: none; }
}


/* --------------------------------------------------------------------------
   SUBTLE MOTION — added 2026-09-01 on Masud's instruction.

   "A certain subtle animation movement while browsing and navigating."

   ZERO JAVASCRIPT, and it degrades to nothing. Two mechanisms:

   1. Hover/focus transitions on interactive elements. Universally supported,
      no risk.

   2. A gentle rise-and-fade as a section scrolls in, using the CSS
      `animation-timeline: view()` scroll-driven animation. It is wrapped in
      @supports, so a browser without it (Safari and Firefox at time of
      writing) simply renders everything visible and static.

   ⚠️ WHY THIS IS SAFE AND A JS SCROLL-REVEAL IS NOT.
   instructions.md §3 bans "scroll-triggered text reveals." The reason that
   ban exists is that the usual implementation hides content with JS and
   reveals it on scroll — so if the script fails, the content is invisible
   and the page is broken. Here the DEFAULT STATE IS VISIBLE. The animation
   is added only where supported, and nothing is ever hidden waiting for it.
   No content can be lost. Still an override of the letter of §3, and
   recorded as one.

   Reduced motion switches it off entirely.
   -------------------------------------------------------------------------- */

.card,
.btn,
.link-more,
.card__link,
.quote,
.industry,
.logo-tile {
  transition: transform 0.22s ease, border-color 0.22s ease,
              background-color 0.22s ease, color 0.22s ease,
              box-shadow 0.22s ease;
}

/* .card's own scale(1.05) is defined with the card rules above — do not add a
   second transform here or the later one silently wins. */
.btn:hover       { transform: translateY(-2px); box-shadow: var(--shadow-2); }
.link-more:hover { transform: translateX(3px); }

/* --------------------------------------------------------------------------
   HERO ENTRANCE — added 2026-09-01. Masud: "the text is very static… a
   typewriting animation or something. Minimal."

   WHAT THIS IS: a staggered fade-and-rise. Headline, then subhead, then
   buttons, then image — about 150ms apart, so the eye is led down the block
   in the order it should read it.

   WHY NOT A LITERAL TYPEWRITER: the CSS typewriter trick animates `width`
   with steps() against a monospaced, SINGLE-LINE string. This headline wraps
   to three or four lines and the font is proportional, so the effect either
   breaks the wrap or types out a ragged rectangle. Doing it properly needs
   JavaScript, which this site does not have. A typewriter on a short single
   line — an eyebrow above the H1, say — WOULD work; say the word and I will
   add one there.

   Safe by construction: `both` fill means the animation always completes, and
   it does not depend on scroll position, IntersectionObserver or any script.
   Reduced motion skips it entirely and the hero simply appears.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: no-preference) {
  .hero h1,
  .hero .hero__sub,
  .hero .btn-row,
  .hero .ph--hero,
  .hero .hero__media {
    animation: hero-in 0.65s cubic-bezier(0.22, 0.7, 0.28, 1) both;
  }

  .hero h1            { animation-delay: 0.05s; }
  .hero .hero__sub    { animation-delay: 0.20s; }
  .hero .btn-row      { animation-delay: 0.35s; }
  .hero .ph--hero,
  .hero .hero__media  { animation-delay: 0.15s; }
}

@keyframes hero-in {
  from { opacity: 0; transform: translateY(1.75rem); }
  to   { opacity: 1; transform: none; }
}


/* Section-to-section fade on scroll. Strengthened 2026-09-01 — longer travel
   and a later finish, so the movement is actually noticeable rather than
   subliminal. Whole sections now fade, not only their parts. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .section__head,
    .card,
    .quote,
    .cta-band,
    .proof > p,
    .logo-marquee,
    .industry-marquee,
    .footer-columns__grid > * {
      animation: rise-in linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 30%;
    }
  }
}

@keyframes rise-in {
  from { opacity: 0; transform: translateY(2.5rem); }
  to   { opacity: 1; transform: none; }
}


/* Logo tiles, pending the real files.

   The client NAMES are real — read off the live site and verified. Only the
   marks are missing: the repo is private, raw.githubusercontent is blocked
   from the sandbox, and image binaries cannot be written to the Drive folder.

   Rendered as neutral typographic tiles rather than the loud yellow
   placeholder, so the wall reads at true size and spacing. The dashed border
   and the "logo pending" line keep them from passing as finished.

   WHEN THE FILES ARRIVE: replace each tile with
       <img src="assets/img/<name>.png" alt="<Client name> logo">
   and delete this rule. Real alt text, every image, no exceptions. */
.logo-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  aspect-ratio: 5 / 2;
  padding: var(--space-3);
  border: 1px dashed var(--rule);
  border-radius: var(--radius);
  color: var(--navy);
  font-weight: var(--weight-bold);
  font-size: var(--step--1);
  line-height: 1.25;
}

.logo-tile span {
  display: block;
  margin-top: var(--space-1);
  font-weight: var(--weight-body);
  font-size: 0.7rem;
  color: var(--ink-muted);
}


/* Testimonial photo. The set is MIXED — four are company logos, two are
   photographs of people (Emtiaz, Raymond). `contain` rather than `cover`
   because cropping a logo to a square ruins it, while a photograph survives
   being letterboxed. Same one radius token as everything else. */
/* Larger and heavier-stroked — Masud, 2026-09-01. */
.quote__photo {
  width: 4.5rem;
  height: 4.5rem;
  flex: 0 0 4.5rem;
  object-fit: contain;
  border: var(--stroke) solid var(--rule);
  border-radius: var(--radius);
  background: #FFFFFF;
  padding: 0.25rem;
  box-shadow: var(--shadow-1);
  transition: border-color 0.22s ease, box-shadow 0.22s ease;
}

.quote:hover .quote__photo { border-color: var(--orange); }

.quote__name { font-size: var(--step-1); }


/* --------------------------------------------------------------------------
   7 — TESTIMONIALS
   Static grid. No carousel. Named + photo + company, the format the research
   says is already stronger than every competitor scanned — not restyled.
   -------------------------------------------------------------------------- */

/* ONE ROW — Masud, 2026-09-01.

   Six quotes forced into six equal columns would be about 11rem wide each on
   a laptop, which is too narrow to read a paragraph in. So it is one row that
   SCROLLS SIDEWAYS, with each card snapping into place.

   This is explicitly allowed and is not a carousel: instructions.md §3 bans
   JS carousels and sliders but names "at most CSS scroll-snap" among the
   things to use INSTEAD. Nothing moves on its own, there is no timer, no
   script, and the reader stays in control — which is the whole difference
   between scroll-snap and a carousel.

   The row is keyboard- and touch-scrollable natively. No arrows are drawn,
   because arrows that do nothing without JS would be worse than none. */
.quote-grid {
  display: flex;
  gap: var(--space-4);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: var(--space-1);
  /* Vertical padding so the hover lift and its shadow are not clipped —
     overflow-x: auto forces overflow-y to auto as well. */
  padding: var(--space-2) var(--space-1) var(--space-4);
  margin-inline: calc(var(--space-1) * -1);
}

/* SMALLER CARDS — Masud, 2026-09-01. 22rem → 17rem, tighter padding and
   smaller quote text, so the row reads as a compact strip rather than a wall
   of six paragraphs. More cards are visible at once, which also makes it
   obvious the row scrolls. */
.quote-grid > .quote,
.quote-marquee__track > .quote {
  flex: 0 0 min(17rem, 78vw);
  scroll-snap-align: start;
  padding: var(--space-4);
}


/* --------------------------------------------------------------------------
   TESTIMONIALS — AUTO-SCROLLING ROW. Masud, 2026-09-01.

   Same pure-CSS mechanism as the logo strip, and the same three written rules
   are overridden — see the long note above .logo-marquee. No JavaScript.

   ⚠️ THIS ONE IS A HARDER ACCESSIBILITY CALL THAN THE LOGOS, and the reason
   is worth keeping. A logo is recognised at a glance, so motion costs little.
   A testimonial is a paragraph: text that slides away mid-sentence is
   genuinely difficult for slow readers, screen-magnifier users, and anyone
   with a reading or attention difficulty. WCAG 2.2.2 (Pause, Stop, Hide) is
   the relevant rule and it bites harder here than on the logo strip.

   THREE MITIGATIONS, and they matter more here than on the logos:
     · SLOW — 90s for one pass, far slower than the logo strip.
     · PAUSES ON HOVER AND ON KEYBOARD FOCUS, so the moment a reader points
       at a card to read it, it stops.
     · REDUCED MOTION gets no animation at all — a static wrapped grid, which
       is the fully compliant version.

   Still not full conformance: hover-pause does nothing on a phone. A visible
   pause button is buildable with a checkbox-and-label and needs no JS.
   Recommended before this page goes public. Ten-minute change.
   -------------------------------------------------------------------------- */

.quote-marquee {
  overflow: hidden;
  padding-block: var(--space-2) var(--space-4);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 3rem, #000 calc(100% - 3rem), transparent);
          mask-image: linear-gradient(90deg, transparent, #000 3rem, #000 calc(100% - 3rem), transparent);
}

.quote-marquee__track {
  display: flex;
  align-items: stretch;
  gap: var(--space-4);
  width: max-content;
  animation: logo-marquee 90s linear infinite;   /* deliberately slow */
}

.quote-marquee:hover .quote-marquee__track,
.quote-marquee:focus-within .quote-marquee__track {
  animation-play-state: paused;
}

@media (prefers-reduced-motion: reduce) {
  .quote-marquee {
    -webkit-mask-image: none;
            mask-image: none;
  }
  .quote-marquee__track {
    animation: none;
    width: auto;
    flex-wrap: wrap;
    justify-content: center;
  }
  .quote-marquee__track [data-marquee-clone] { display: none; }
}

.quote blockquote p {
  font-size: var(--step--1);
  line-height: 1.5;
}

.quote-grid .quote__photo {
  width: 3rem;
  height: 3rem;
  flex: 0 0 3rem;
}

.quote-grid .quote__name { font-size: var(--step-0); }

.quote figcaption {
  gap: var(--space-2);
  padding-top: var(--space-3);
}


/* Tighter vertical rhythm for a section that does not need the full 4rem
   above and below — Masud: "after the client section you have given too many
   gaps." Applied to the testimonials strip. */
.section--tight { padding-block: var(--space-5); }

/* Thicker stroke, shadow and a hover lift — Masud, 2026-09-01. */
.quote {
  border: var(--stroke) solid var(--rule);
  border-radius: var(--radius);
  padding: var(--space-5);
  margin: 0;
  display: flex;
  flex-direction: column;
  background: #FFFFFF;
  box-shadow: var(--shadow-1);
}

/* Smaller lift than the other cards: this one lives inside a scrolling row,
   and anything bigger gets clipped by the container's own overflow. */
.quote:hover,
.quote:focus-within {
  transform: translateY(-4px);
  border-color: var(--orange);
  box-shadow: var(--shadow-2);
  position: relative;
  z-index: 1;
}

.quote blockquote { margin: 0 0 var(--space-3); }
.quote blockquote p { margin: 0; }

/* GAP CLOSED 2026-09-01. `margin-top: auto` used to push the name and photo
   to the bottom of the card. In a row of equal-height cards that meant a
   short quote left a large empty band between the text and the photo — the
   gap Masud flagged. Removing it lets the caption sit directly under the
   quote, whatever its length. */
.quote figcaption {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px solid var(--rule);
}

.quote__name { font-weight: var(--weight-bold); color: var(--navy); }

.quote__co { font-size: var(--step--1); color: var(--ink-muted); display: block; }


/* --------------------------------------------------------------------------
   8 — FAQ
   Native <details>/<summary>. NOT a JS accordion. (instructions.md §3)
   -------------------------------------------------------------------------- */

.faq { max-width: 48rem; }

.faq details {
  border-bottom: 1px solid var(--rule);
  padding-block: var(--space-4);
}

.faq summary {
  font-family: var(--font-heading);
  font-weight: var(--weight-heading);
  font-size: var(--step-1);
  color: var(--navy);
  cursor: pointer;
  list-style: none;
}

.faq summary::-webkit-details-marker { display: none; }

.faq summary::after {
  content: "+";
  float: right;
  color: var(--orange);           /* LARGE glyph, decorative — see note */
  font-size: var(--step-2);
  line-height: 1;
}

.faq details[open] summary::after { content: "\2212"; }

.faq details p {
  margin: var(--space-3) 0 0;
  color: var(--ink-muted);
}


/* --------------------------------------------------------------------------
   10 — FOOTER COLUMNS
   These sit immediately ABOVE BUILD's shared <footer>, so the two read as one
   footer area: columns on top, BUILD's contact block and the ruled reply-time
   line beneath. Deliberately OUTSIDE the SHARED:FOOTER markers so that
   tools/sync-shared.mjs never touches them and never overwrites them.
   -------------------------------------------------------------------------- */

.footer-columns {
  border-top: 1px solid var(--rule);
  padding-block: var(--space-6) 0;
  font-size: var(--step--1);
}

/* FOUR columns, ONE row on desktop — Masud, 2026-09-01.
   Services · Company · Contact · Social. The Legal column is gone.
   Two across on tablet, stacked on phone. */
.footer-columns__grid {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: 1fr;
}

@media (min-width: 40rem) { .footer-columns__grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 62rem) { .footer-columns__grid { grid-template-columns: repeat(4, 1fr); } }

/* The Contact column. Same visual weight as the other three. */
.footer-contact { font-style: normal; }
.footer-contact dl { margin: 0; }
.footer-contact dt {
  color: var(--ink-muted);
  margin-top: var(--space-3);
}
.footer-contact dt:first-child { margin-top: 0; }
.footer-contact dd { margin: 0; }

/*
  ⚠️ TEMPORARY OVERRIDE — HOMEPAGE ONLY. Remove this rule the moment BUILD
  restructures the shared footer.

  Masud ruled the footer is four columns in one row: Services · Company ·
  Contact · Social. Contact is now a COLUMN, written above. But BUILD's
  SHARED:FOOTER block still renders the same phone / WhatsApp / email /
  address / hours list full-width underneath, which is the duplication and
  the ragged layout Masud is looking at.

  This thread does not edit BUILD's shared block — a hand-edit there is
  silently overwritten by the next tools/sync-shared.mjs run. So the block is
  hidden here instead, scoped to the homepage stylesheet.

  Nothing is lost to a screen reader: every fact in the hidden block appears
  in the Contact column above it, in the same document.

  THE REAL FIX, owed by BUILD in _template/page-template.html: move the
  contact block into the footer columns for every page, and leave the shared
  block carrying only the ruled reply-time line and the copyright.
*/
.site-footer .contact-block { display: none; }


/* --------------------------------------------------------------------------
   HEADER LOGO — added 2026-09-01 on Masud's instruction.

   ⚠️⚠️ READ THIS. THE SUPPLIED FILE IS THE DARK-BACKGROUND VARIANT.

   "Mango Media Logo.png" is an orange arrow plus an M in near-white. On this
   site's ruled WHITE background the arrow shows and THE M DISAPPEARS. This is
   exactly what SPEC-CANONICAL §1 warns about, measured 2026-09-01:

     "Logo\Mango 3 (3).png is the SAME MARK with the M in opaque near-white
      #FEFEFE, not a transparent arrow-only asset. It is INVISIBLE on a white
      background. Use it only on dark surfaces. NEVER use it as the favicon."

   So the mark is placed on a NAVY TILE, which is the only way this particular
   file can be shown on a white header without losing half of itself. Navy is
   the primary brand colour, so the tile is on-palette rather than invented.

   THE REAL FIX is the light-background version of the same mark — navy M plus
   orange arrow, which SPEC §1 records as existing (Logo\Mango 2 (3).png).
   Supply that and this tile can go, leaving the mark to sit directly on white.

   NO ALT TEXT IS NEEDED and none is possible: this is a CSS background on a
   decorative pseudo-element. The link's accessible name stays the real text
   "Mango Media Digital" inside the <a>, which is the correct outcome — the
   mark is decoration beside a wordmark, not a replacement for it.

   ⚠️ HOMEPAGE ONLY, AND THAT IS A PROBLEM. .wordmark lives inside BUILD's
   SHARED:HEADER block and home.css only loads on "/", so EVERY OTHER PAGE
   STILL SHOWS TEXT WITH NO MARK. BUILD owes the real change in
   _template/page-template.html — an <img> with real alt text — after which
   this whole rule is deleted. Hand-editing the shared block here would be
   wiped by the next tools/sync-shared.mjs run.

   FAVICON: still not set, and this file must NOT become one — §1 again.
   -------------------------------------------------------------------------- */

.wordmark {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
}

.wordmark::before {
  content: "";
  flex: 0 0 2.25rem;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: var(--radius);          /* the ONE token */
  background: var(--navy) url("../img/Mango Media Logo.png") no-repeat center / 66% auto;
}

/*
  ⚠️ SECOND TEMPORARY OVERRIDE — HOMEPAGE ONLY, and this one contradicts a
  standing ruling, so read before removing.

  Masud instructed on 2026-09-01: remove "We reply within one working day."

  SPEC-CANONICAL §1 and §8 both rule that exact sentence as REQUIRED copy,
  byte-exact, "do not reword," on the Contact page and in the footer. It is
  also the highest value-to-effort finding in the whole research set — three
  independent sources across two markets, and the one thing that answers an
  overseas buyer's unspoken "will anyone actually reply to me?"

  His live instruction wins, and it is hidden here rather than deleted,
  because the sentence lives inside BUILD's SHARED:FOOTER block and a
  hand-edit there is wiped by the next tools/sync-shared.mjs run.

  §1 and §8 SHOULD BE AMENDED, or the next thread will put it back.
*/
.site-footer .reply-commitment { display: none; }


/* --------------------------------------------------------------------------
   FOOTER SOCIAL ICONS — added 2026-09-01.

   Inline SVG, not an icon font: instructions.md §3 bans stacking icon font
   kits, and inline SVG costs no extra request.

   THESE ARE NOT LINKS YET, deliberately. Masud is supplying the profile URLs
   later, and the current live site's icons all point at href="#" — the exact
   dead-link failure instructions.md §6 gates against. Each icon carries a
   visually-hidden name so a screen reader announces the platform rather than
   silence. Wrap each in an <a> the day the URLs arrive.
   -------------------------------------------------------------------------- */

.social-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  list-style: none;
  margin: 0;
  padding: 0;
}

.social-row li { margin: 0; }

.social-icon {
  display: grid;
  place-items: center;
  width: 2.5rem;
  height: 2.5rem;
  border: var(--stroke) solid var(--rule);
  border-radius: var(--radius);
  color: var(--navy);
  box-shadow: var(--shadow-1);
  transition: transform 0.22s ease, border-color 0.22s ease,
              box-shadow 0.22s ease, color 0.22s ease;
}

.social-icon:hover {
  transform: scale(1.05);
  border-color: var(--orange);
  box-shadow: var(--shadow-2);
}

.social-icon svg {
  width: 1.15rem;
  height: 1.15rem;
  fill: currentColor;
}

.footer-columns h2 {
  font-size: var(--step-0);
  margin-bottom: var(--space-3);
}

.footer-columns h2::after { display: none; }

.footer-columns ul { list-style: none; margin: 0; padding: 0; }
.footer-columns li { margin-bottom: var(--space-2); }


/* ==========================================================================
   INNER PAGES — added 2026-09-01.

   This sheet is no longer homepage-only: /services/, /industries/,
   /portfolio/ and /contact/ all load it, so the cards, shadows, tokens and
   footer columns stay identical across the site. The filename is now a
   misnomer; renaming it to site-components.css is a five-minute job for BUILD
   whenever it wants (rename the file, update five <link> tags).
   ========================================================================== */

/* Compact page header for inner pages. The homepage has its own hero. */
.page-hero {
  padding-block: var(--space-6) var(--space-5);
  border-bottom: 1px solid var(--rule);
}

.page-hero h1 { margin-bottom: var(--space-3); }
.page-hero p  { color: var(--ink-muted); font-size: var(--step-1); }

/* --- Services page: one block per service ------------------------------- */

.service-block {
  padding-block: var(--space-6);
  border-top: 1px solid var(--rule);
}

.service-block:first-of-type { border-top: 0; }

.service-block__grid {
  display: grid;
  gap: var(--space-5);
  align-items: start;
}

@media (min-width: 60rem) {
  .service-block__grid { grid-template-columns: 1fr 1fr; gap: var(--space-7); }
  /* Alternate which side the image sits on, so the page does not read as a
     single column of identical rows. */
  .service-block:nth-of-type(even) .service-block__media { order: -1; }
}

.service-block h2 { margin-bottom: var(--space-3); }
.service-block__lead { color: var(--ink-muted); }

/* Sub-item cards inside a service block. */
.mini-grid {
  display: grid;
  gap: var(--space-3);
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  margin-top: var(--space-4);
}

.mini {
  border: var(--stroke) solid var(--rule);
  border-radius: var(--radius);
  padding: var(--space-3) var(--space-4);
  background: #FFFFFF;
  box-shadow: var(--shadow-1);
  font-weight: var(--weight-bold);
  font-size: var(--step--1);
  color: var(--navy);
  transition: transform 0.22s ease, border-color 0.22s ease, box-shadow 0.22s ease;
}

.mini:hover {
  transform: scale(1.04);
  border-color: var(--orange);
  box-shadow: var(--shadow-2);
}

/* --------------------------------------------------------------------------
   SERVICE ICON PANELS — added 2026-09-01, standing in for the photography.

   Masud: "insert an appropriate icon in a big size… if it's a glowing icon
   it would be great… we will insert an image later."

   So each service block shows a large orange icon on a softly glowing panel
   instead of a yellow placeholder. It reads as finished rather than as a hole
   in the page, and swapping in a real photograph later is one line:
   replace the <div class="service-icon-panel">…</div> with
   <img src="../assets/img/services/NAME.jpg" alt="…">.

   ORANGE IS CORRECT HERE and is not a contrast problem: SPEC-CANONICAL §1
   permits orange on icons explicitly, and every icon below is decorative,
   carries aria-hidden, and sits beside a real text heading that carries the
   meaning. Nothing here depends on seeing the icon.

   The glow is a radial gradient plus a drop-shadow filter — no images, no JS.
   -------------------------------------------------------------------------- */

.service-icon-panel {
  display: grid;
  place-items: center;
  aspect-ratio: 4 / 3;
  border-radius: var(--radius);          /* the ONE token */
  border: var(--stroke) solid var(--rule);
  box-shadow: var(--shadow-1);
  background:
    radial-gradient(circle at 50% 45%,
      rgba(255, 79, 1, 0.20) 0%,
      rgba(255, 79, 1, 0.06) 45%,
      rgba(255, 79, 1, 0) 70%),
    #FFFFFF;
  transition: transform 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease;
}

.service-icon {
  width: 7rem;
  height: 7rem;
  color: var(--orange);
  stroke: currentColor;
  fill: none;
  stroke-width: 1.4;
  stroke-linecap: round;
  stroke-linejoin: round;
  filter:
    drop-shadow(0 0 16px rgba(255, 79, 1, 0.45))
    drop-shadow(0 0 4px  rgba(255, 79, 1, 0.35));
  transition: transform 0.25s ease, filter 0.25s ease;
}

.service-icon-panel:hover {
  border-color: var(--orange);
  box-shadow: var(--shadow-2);
}

.service-icon-panel:hover .service-icon {
  transform: scale(1.06);
  filter:
    drop-shadow(0 0 26px rgba(255, 79, 1, 0.60))
    drop-shadow(0 0 6px  rgba(255, 79, 1, 0.45));
}

@media (max-width: 60rem) {
  .service-icon { width: 5rem; height: 5rem; }
}

.service-block__media img,
.work-media img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--radius);
  box-shadow: var(--shadow-1);
}

/* --- Industries page ---------------------------------------------------- */

.industry-grid {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
}

.industry-card {
  border: var(--stroke) solid var(--rule);
  border-radius: var(--radius);
  padding: var(--space-5);
  background: #FFFFFF;
  box-shadow: var(--shadow-1);
  text-align: center;
  transition: transform 0.22s ease, border-color 0.22s ease, box-shadow 0.22s ease;
}

.industry-card:hover {
  transform: scale(1.05) translateY(-4px);
  border-color: var(--orange);
  box-shadow: var(--shadow-2);
}

.industry-card .icon { margin-inline: auto; }

.industry-card h2 {
  font-size: var(--step-1);
  margin: 0;
  color: var(--navy);
}

.industry-card h2::after { display: none; }

/* --- Portfolio page ----------------------------------------------------- */

.work-section { padding-block: var(--space-6); border-top: 1px solid var(--rule); }
.work-section:first-of-type { border-top: 0; }

/* --- Contact page ------------------------------------------------------- */

.contact-grid {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
}

.contact-card {
  border: var(--stroke) solid var(--rule);
  border-radius: var(--radius);
  padding: var(--space-5);
  background: #FFFFFF;
  box-shadow: var(--shadow-1);
  transition: transform 0.22s ease, border-color 0.22s ease, box-shadow 0.22s ease;
}

.contact-card:hover {
  transform: scale(1.03);
  border-color: var(--orange);
  box-shadow: var(--shadow-2);
}

.contact-card h2 {
  font-size: var(--step-1);
  margin-bottom: var(--space-2);
}

.contact-card h2::after { display: none; }

.contact-card p { margin: 0; }


/* --------------------------------------------------------------------------
   PLACEHOLDERS

   Everything Masud has not supplied yet renders in this treatment. It is
   deliberately ugly. site.css already ships `.todo` for inline facts; these
   are the block-level equivalents for images and logos.

   THE POINT: a placeholder must never be mistakable for finished work. The
   live site still carries mailto:contact@mysite.com and tel:123-456-7890,
   approved for removal on 2026-08-06 and still there — because they looked
   finished. These do not.

   DELETE THIS ENTIRE BLOCK once no placeholder remains on the page.
   -------------------------------------------------------------------------- */

.ph {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: var(--space-4);
  background: repeating-linear-gradient(
    45deg, #FFF9E6, #FFF9E6 10px, #FFF3CD 10px, #FFF3CD 20px
  );
  border: 1px dashed #B8860B;
  border-radius: var(--radius);          /* same one token */
  color: #6B4E00;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: var(--step--1);
  line-height: 1.35;
}

.ph--hero  { aspect-ratio: 5 / 4; }   /* matches .hero__media exactly */
.ph--work  { aspect-ratio: 4 / 3; }
.ph--logo  { aspect-ratio: 5 / 2; font-weight: 700; }

.ph--avatar {
  width: 3rem;
  height: 3rem;
  flex: 0 0 3rem;
  border-radius: var(--radius);
  padding: 0;
  font-size: 0.65rem;
}
