/* ==========================================================================
   enhancements.css

   Kept separate from style.css on purpose: style.css is generated from
   public/scss/ by dart-sass, so anything written there is lost on the next
   build. Everything here is hand-authored and safe from that.

   1. Skeleton placeholders for JS-rendered content
   2. Footer layout + proportions
   3. About page (/about.html)
   4. Animated stat counters
   5. Story body
   6. Light stat strip (home page)
   7. Section lead colour fix
   8. Legal pages (/privacy.html, /terms.html)
   ========================================================================== */


/* ==========================================================================
   1. SKELETONS
   The portfolio grid and testimonials are filled in from JSON after load.
   These placeholders ship in the HTML so they paint on first frame, which
   replaces the empty-then-snap effect with a stable, sized layout.
   ========================================================================== */

.sk {
  display: block;
  position: relative;
  overflow: hidden;
  border-radius: 8px;
  background-color: rgba(255, 255, 255, 0.07);
}

/* Sweep is a pseudo-element so it never affects layout. */
.sk::after {
  content: "";
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(
    90deg,
    rgba(255, 255, 255, 0) 0%,
    rgba(255, 255, 255, 0.13) 50%,
    rgba(255, 255, 255, 0) 100%
  );
  animation: sk-sweep 1.5s ease-in-out infinite;
}

@keyframes sk-sweep {
  100% { transform: translateX(100%); }
}

/* Text-ish bars */
.sk-line { height: 12px; border-radius: 999px; margin-bottom: 10px; }
.sk-line--title { height: 18px; width: 62%; }
.sk-line--short { width: 40%; }
.sk-line:last-child { margin-bottom: 0; }

/* --- Portfolio grid ------------------------------------------------------ */
/* Fill .pf-thumb-wrap rather than declaring an aspect of our own: the real card
   gets its height from .pf-card, and the skeleton must resolve to exactly the
   same box or the grid jumps when the real cards replace it. */
.pf-skeleton .sk-thumb {
  width: 100%;
  height: 100%;
  border-radius: 8px;
}

.pf-skeleton .portfolio-box {
  pointer-events: none;
  background: transparent;
  box-shadow: none;
}

/* --- Filter pills --------------------------------------------------------- */
.sk-pill {
  display: inline-block;
  width: 92px;
  height: 38px;
  border-radius: 999px;
  margin: 0 .25rem .5rem;
}

/* --- Testimonials --------------------------------------------------------- */
.tm-skeleton { padding: 1.5rem 0; }
.tm-skeleton .sk-avatar {
  width: 64px; height: 64px;
  border-radius: 50%;
  margin: 0 auto 1rem;
}
.tm-skeleton .sk-line { margin-left: auto; margin-right: auto; }
.tm-skeleton .sk-line--w80 { width: 80%; }
.tm-skeleton .sk-line--w65 { width: 65%; }
.tm-skeleton .sk-line--w45 { width: 45%; }

/* Fade the swap in so the real content does not pop. */
.pf-fade-in { animation: pf-fade .28s ease-out both; }
@keyframes pf-fade {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

/* A shimmering block is decorative motion; honour the OS setting. */
@media (prefers-reduced-motion: reduce) {
  .sk::after { animation: none; }
  .pf-fade-in { animation: none; }
}


/* ==========================================================================
   2. FOOTER
   ========================================================================== */

/* The old footer stacked several competing layout systems (a centred flex
   container, a five-cell grid, a nested column grid). This replaces the lot
   with one grid: brand + three link columns, every cell a direct child so they
   all share the same top and left edge. */

.hud-footer .container {
  display: block;          /* was: row-reverse flex, which drove the wrapping */
}

/* brand | links | services | social */
/* justify-content is reset everywhere below: the previous flex-based rules set
   it to `center`, and it survives the switch to grid, where it centres the
   whole track instead of the items — which is what knocked the headings, the
   lists and the brand block out of alignment with each other. */
.hud-footer .footer-grid {
  display: grid;
  grid-template-columns: auto minmax(210px, 1.5fr) 1fr 1fr 1fr;
  grid-template-areas: "mascot brand company services social";
  align-items: start;
  justify-content: stretch;
  gap: 40px 32px;
}

/* Named areas so the mascot keeps the far-left column at every width instead
   of the grid deciding where to break the row. */
.hud-footer .footer-mascot   { grid-area: mascot; }
.hud-footer .footer-brand    { grid-area: brand; }
.hud-footer .footer-company  { grid-area: company; }
.hud-footer .footer-services { grid-area: services; }
.hud-footer .footer-social   { grid-area: social; }

/* Every column: heading flush left, list directly under it, no indent.
   .footer-social is named explicitly because the old rule made it a centred
   flex column, which pushed its heading and icons off the shared left edge. */
.hud-footer .footer-col,
.hud-footer .footer-social,
.hud-footer .footer-brand {
  display: block;
  min-width: 0;            /* let long labels shrink instead of forcing overflow */
  text-align: left;
  /* An old `justify-items: center` under 576px still applied here. Chrome now
     honours justify-items on block containers, so it was shrink-wrapping these
     columns and centring them — only on phones, which is why the alignment
     looked fine on desktop and broke on mobile. */
  justify-items: start;
}

.hud-footer .footer-col > *,
.hud-footer .footer-social > * {
  margin-inline: 0;
}

.hud-footer .footer-title {
  margin: 0 0 .9rem;
  font-size: .8rem;
  text-transform: uppercase;
  letter-spacing: .08em;
}

/* The old rule centred this grid's single track inside the ul, so each list
   was indented by a different amount depending on its longest label — which is
   why the links never lined up with their own heading. Pin the track to the
   start and drop the default ul padding. */
.hud-footer .footer-links {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  justify-content: start;
  justify-items: start;
  gap: .55rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.hud-footer .footer-links a {
  display: inline-block;
  font-size: .88rem;
}

.hud-footer .hud-social {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
  gap: .5rem;
  margin: 0;
}

/* --- Brand column --------------------------------------------------------- */
.hud-footer .footer-brand {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  justify-content: start;
  justify-items: start;
  align-items: start;
  align-content: start;
  gap: 14px;
}

.hud-footer .footer-tagline {
  margin: 0;
  max-width: 38ch;
  color: rgba(214, 229, 245, 0.78);
  font-size: .92rem;
  line-height: 1.6;
}

/* The mascot is a square source (360x360) that used to get an explicit width
   alongside a CSS height, which stretched it. Pin the ratio and let the height
   drive the width. */
.hud-footer .footer-mascot {
  margin: 0;
  /* The GIF has transparent padding above the character, so a plain top-align
     leaves it sitting visibly lower than the column headings next to it. This
     pulls the artwork up to optically match the first line of text. */
  margin-top: -14px;
}

#footer-img {
  height: clamp(96px, 9vw, 132px);
  width: auto;
  aspect-ratio: 1 / 1;
  object-fit: contain;
  display: block;
}

/* --- Availability badge --------------------------------------------------- */
.footer-status {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  padding: .3rem .7rem .3rem .55rem;
  border: 1px solid rgba(153, 215, 214, 0.35);
  border-radius: 999px;
  font-size: .78rem;
  color: #99d7d6;
  white-space: nowrap;
}

.footer-status__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #4ade80;
  box-shadow: 0 0 0 0 rgba(74, 222, 128, .6);
  animation: footer-pulse 2.4s ease-out infinite;
}

@keyframes footer-pulse {
  70%  { box-shadow: 0 0 0 7px rgba(74, 222, 128, 0); }
  100% { box-shadow: 0 0 0 0 rgba(74, 222, 128, 0); }
}

/* --- Footer CTA ----------------------------------------------------------- */
.footer-cta {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  margin-top: .25rem;
  padding: .6rem 1.15rem;
  border-radius: 999px;
  background: #0c8c8c;
  color: #fff;
  font-weight: 600;
  font-size: .9rem;
  text-decoration: none;
  transition: background .2s ease, transform .2s ease;
}

.footer-cta:hover,
.footer-cta:focus-visible {
  background: #0aa0a0;
  color: #fff;
  transform: translateY(-1px);
}

/* --- Base row ------------------------------------------------------------- */
.hud-footer .footer-base {
  padding-top: 18px;
}

@media (max-width: 600px) {
  .hud-footer .footer-base {
    justify-content: center;
    text-align: center;
  }
}

/* Visible keyboard focus for every footer control. */
.hud-footer a:focus-visible {
  outline: 2px solid #99d7d6;
  outline-offset: 3px;
  border-radius: 4px;
}

@media (prefers-reduced-motion: reduce) {
  .footer-status__dot { animation: none; }
  .footer-cta:hover, .footer-cta:focus-visible { transform: none; }
}

/* --- Responsive ----------------------------------------------------------- */
/* Three steps, each a plain column count: 4 → brand over 3 → brand over 2 → 1.
   The brand always spans the full width once it stops sharing a row, so the
   link columns stay evenly divided and aligned to the same left edge. */

/* Mascot stays pinned to the far-left column and spans both rows; the brand
   takes the top row and the three link columns line up underneath it. */
@media (max-width: 1100px) {
  .hud-footer .footer-grid {
    grid-template-columns: auto repeat(3, minmax(0, 1fr));
    grid-template-areas:
      "mascot brand   brand    brand"
      "mascot company services social";
    gap: 36px 32px;
  }
  .hud-footer .footer-tagline { max-width: 52ch; }
}

/* Below this a full-height mascot column leaves a large dead area on the left,
   so it stops spanning and just shares the top row with the brand. The link
   columns then start at the container edge like the copyright line does. */
@media (max-width: 820px) {
  .hud-footer .footer-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-template-areas:
      "mascot   brand"
      "company  services"
      "social   social";
    gap: 30px 24px;
  }
  .hud-footer .footer-mascot { align-self: center; margin-top: 0; }
}

/* Too narrow for a dedicated mascot column beside three link lists, so it
   shares the top row with the brand and the lists go full width below. */
@media (max-width: 560px) {
  .hud-footer .footer-grid {
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-areas:
      "mascot   brand"
      "company  company"
      "services services"
      "social   social";
    gap: 26px 20px;
  }
  .hud-footer .footer-mascot { margin-top: 0; align-self: center; }
  #footer-img { height: 92px; }
}


/* ==========================================================================
   3. ABOUT PAGE  (/about.html)
   ========================================================================== */

.about-hero {
  position: relative;
  padding: 160px 0 90px;
  background: linear-gradient(180deg, #150D44, #0c1b5f 45%, #0e3358);
  color: #fff;
  overflow: hidden;
}

.about-hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, .85fr);
  align-items: center;
  gap: 56px;
}

.about-kicker {
  margin: 0 0 .75rem;
  font-size: .82rem;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: #71C2C6;
}

.about-hero__text h1 { color: #fff; }

.about-lead {
  margin: 1.25rem 0 0;
  max-width: 54ch;
  font-size: 1.06rem;
  line-height: 1.75;
  color: rgba(224, 236, 250, .84);
}

/* --- Portrait -------------------------------------------------------------
   The photo is applied as a background-image. If the file is not there yet the
   frame simply shows the brand gradient with the logo mark on it, instead of a
   broken-image icon. Save the photo to: public/images/about/founder.jpg */
.about-portrait {
  margin: 0;
  display: grid;
  justify-items: center;
  gap: 1rem;
}

/* The frame itself is the placeholder: brand gradient with the logo mark on it. */
.about-portrait__frame {
  position: relative;
  width: 100%;
  max-width: 340px;
  aspect-ratio: 4 / 5;
  border-radius: 22px;
  border: 1px solid rgba(153, 215, 214, .3);
  box-shadow: 0 24px 60px rgba(5, 10, 40, .45);
  overflow: hidden;
  background-color: #10214f;
  background-image:
    linear-gradient(160deg, rgba(113, 194, 198, .28), rgba(122, 157, 210, .14) 55%, transparent 85%),
    url("../../images/sombre-S.png");
  background-size: cover, 118px auto;
  background-position: center, center;
  background-repeat: no-repeat, no-repeat;
}

/* The photo is a separate layer stacked on top. If founder.jpg is not there
   yet this element is simply transparent and the branded frame shows through,
   so a missing file never produces a broken-image icon. */
.about-portrait__photo {
  position: absolute;
  inset: 0;
  background-image: url("../../images/about/founder.jpg");
  background-size: cover;
  background-position: center top;
  background-repeat: no-repeat;
}

.about-portrait__caption {
  display: grid;
  justify-items: center;
  gap: .15rem;
  text-align: center;
}

.about-portrait__name {
  font-weight: 700;
  font-size: 1.02rem;
  color: #fff;
}

.about-portrait__role {
  font-size: .85rem;
  color: rgba(214, 229, 245, .7);
}

/* ==========================================================================
   4. ANIMATED STAT COUNTERS
   ========================================================================== */

.stats-section {
  padding: 84px 0;
  background: linear-gradient(180deg, #0e3358, #133b56);
  color: #fff;
}

.stats-heading {
  margin: 0;
  text-align: center;
  font-size: clamp(1.6rem, 3.4vw, 2.4rem);
  font-weight: 700;
}

.stats-grid {
  list-style: none;
  margin: 3rem 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 24px;
}

.stat {
  display: grid;
  justify-items: center;
  align-content: start;
  gap: .35rem;
  padding: 30px 18px;
  text-align: center;
  border: 1px solid rgba(153, 215, 214, .22);
  border-radius: 18px;
  background: rgba(255, 255, 255, .045);
  transition: transform .25s ease, border-color .25s ease;
}

.stat:hover {
  transform: translateY(-4px);
  border-color: rgba(153, 215, 214, .5);
}

.stat__num {
  font-size: clamp(2.4rem, 5vw, 3.4rem);
  font-weight: 800;
  line-height: 1;
  color: #71C2C6;
  /* Digits change width as they animate; tabular figures stop the number
     jittering sideways while it counts. */
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
}

.stat__label {
  margin-top: .45rem;
  font-size: .95rem;
  font-weight: 600;
  color: #fff;
}

.stat__note {
  font-size: .8rem;
  line-height: 1.45;
  color: rgba(214, 229, 245, .62);
}

@media (prefers-reduced-motion: reduce) {
  .stat:hover { transform: none; }
}

/* ==========================================================================
   5. STORY BODY
   ========================================================================== */

.about-story {
  padding: 90px 0;
  background: linear-gradient(180deg, #133b56, #0c1b5f);
  color: #fff;
}

.story {
  max-width: 68ch;
  margin: 0 auto;
}

.story__h {
  margin: 2.75rem 0 1rem;
  font-size: clamp(1.35rem, 2.8vw, 1.85rem);
  font-weight: 700;
  color: #fff;
}

.story__h:first-child { margin-top: 0; }

.story p {
  margin: 0 0 1.15rem;
  font-size: 1.03rem;
  line-height: 1.85;
  color: rgba(224, 236, 250, .84);
}

.story__pull {
  margin: 1.75rem 0;
  padding: 1.1rem 0 1.1rem 1.5rem;
  border-left: 3px solid #71C2C6;
  font-size: 1.12rem !important;
  font-weight: 500;
  color: #fff !important;
}

.story__sign {
  margin-top: 2.5rem;
  display: grid;
  gap: .1rem;
}

.story__sign-name {
  font-size: 1.5rem;
  font-weight: 700;
  color: #71C2C6;
}

.story__sign-role {
  font-size: .85rem;
  color: rgba(214, 229, 245, .7);
}

.story__cta { margin-top: 2.5rem; }

/* --- About page responsive ------------------------------------------------ */
@media (max-width: 900px) {
  .about-hero { padding: 130px 0 70px; }
  .about-hero__grid {
    grid-template-columns: minmax(0, 1fr);
    gap: 40px;
  }
  /* Photo first on narrow screens: it is the reason people opened the page. */
  .about-portrait { order: -1; justify-items: start; }
  .about-portrait__caption { justify-items: start; text-align: left; }
  .about-portrait__frame { max-width: 260px; }

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

@media (max-width: 560px) {
  .about-hero { padding: 116px 0 56px; }
  .stats-section, .about-story { padding: 64px 0; }
  .stats-grid { gap: 16px; }
  .stat { padding: 24px 14px; }

  /* A full-width 4:5 portrait is ~470px tall on a phone, which pushed the
     headline off the first screen. Keep it to a profile-photo size so the
     headline still lands above the fold. */
  .about-portrait {
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    gap: .9rem;
  }
  .about-portrait__frame {
    width: 96px;
    max-width: 96px;
    aspect-ratio: 1 / 1;
    border-radius: 16px;
  }
  .about-portrait__frame { background-size: cover, 62px auto; }
  .about-portrait__caption { align-self: center; }
}

@media (max-width: 380px) {
  .stats-grid { grid-template-columns: minmax(0, 1fr); }
}


/* ==========================================================================
   6. LIGHT STAT STRIP  (home page, directly under the hero wave)
   ========================================================================== */

/* The hero ends in a white wave that flows into the white services section, so
   the home-page strip has to be light. Only the colours change: the grid,
   spacing and counter behaviour are shared with the dark version on /about. */
.stats-section--light {
  padding: 8px 0 56px;
  background: transparent;      /* sits on the white body, continues the wave */
  color: #150D44;
}

.stats-section--light .stat {
  border-color: rgba(21, 13, 68, .10);
  background: #f6f9fc;
}

.stats-section--light .stat:hover {
  border-color: rgba(12, 140, 140, .45);
}

/* #71C2C6 is too pale to read on white. This darker teal clears 3:1 at the
   large size the numbers are rendered at. */
.stats-section--light .stat__num { color: #0c8c8c; }
.stats-section--light .stat__label { color: #150D44; }
.stats-section--light .stat__note { color: rgba(21, 13, 68, .58); }

.stats-more {
  margin: 1.5rem 0 0;
  text-align: center;
}

.stats-more a {
  font-size: .92rem;
  font-weight: 600;
  color: #0c8c8c;
  text-decoration: none;
}

.stats-more a:hover,
.stats-more a:focus-visible { text-decoration: underline; }

/* ==========================================================================
   7. SECTION LEAD COLOUR FIX
   ========================================================================== */

/* .services-lead was white, but both sections that use it render on the white
   body, so the paragraph under "Our Services" and under "Get started" was
   invisible. */
#services .services-lead,
#contact .services-lead {
  color: rgba(21, 13, 68, .75);
}

/* ==========================================================================
   8. LEGAL PAGES  (/privacy.html, /terms.html)
   ========================================================================== */

.legal-page {
  padding: 150px 0 90px;
  background: linear-gradient(180deg, #150D44, #0c1b5f 45%, #0e3358);
  color: #fff;
}

.legal {
  max-width: 74ch;
  margin: 0 auto;
}

.legal__title {
  margin: 0;
  font-size: clamp(2rem, 5vw, 3rem);
  font-weight: 800;
}

.legal__updated {
  margin: .75rem 0 0;
  font-size: .88rem;
  color: #99d7d6;
}

.legal__intro {
  margin: 1.5rem 0 0;
  font-size: 1.05rem;
  line-height: 1.75;
  color: rgba(224, 236, 250, .86);
}

.legal h2 {
  margin: 2.75rem 0 .9rem;
  font-size: clamp(1.2rem, 2.6vw, 1.5rem);
  font-weight: 700;
  color: #fff;
}

.legal h3 {
  margin: 1.75rem 0 .6rem;
  font-size: 1.02rem;
  font-weight: 700;
  color: #99d7d6;
}

.legal p,
.legal li {
  font-size: .99rem;
  line-height: 1.8;
  color: rgba(224, 236, 250, .82);
}

.legal p { margin: 0 0 1rem; }

.legal ul,
.legal ol {
  margin: 0 0 1.25rem;
  padding-left: 1.25rem;
}

.legal li { margin-bottom: .5rem; }

.legal a {
  color: #71C2C6;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.legal a:hover { color: #99d7d6; }

.legal__table-wrap { overflow-x: auto; margin: 0 0 1.5rem; }

.legal table {
  width: 100%;
  border-collapse: collapse;
  font-size: .92rem;
}

.legal th,
.legal td {
  padding: .7rem .8rem;
  text-align: left;
  border-bottom: 1px solid rgba(153, 215, 214, .18);
  color: rgba(224, 236, 250, .82);
  vertical-align: top;
}

.legal th {
  color: #fff;
  font-weight: 700;
  white-space: nowrap;
}

/* Anything the owner still has to fill in is marked so it cannot ship unnoticed. */
.legal mark {
  padding: .1rem .35rem;
  border-radius: 4px;
  background: rgba(255, 209, 102, .22);
  color: #ffd166;
  font-weight: 600;
}

@media (max-width: 560px) {
  .legal-page { padding: 120px 0 64px; }
}
