/*! FidoDesign Hero Game - generated by build-plugin.js. Do not edit directly.
    Edit snake/snake.js and snake/style.css, then re-run the build. */
/* Interactive Hero — FidoDesign
   The snake shares space with the copy: it passes behind text, treats the
   service tags as walls, and damages the layout when the visitor crashes. */
:root {
  --bg: #0b0f1c;
  --line: rgba(255, 255, 255, .12);
  --accent: #5b5bd6;
  --accent-2: #8f8ff0;
  --gold: #fbbf24;
  --danger: #f2555a;
  --text: #eef2fb;
  --muted: #a8b0c6;
  --font-display: "fidodesign", "Helvetica Now Display", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-body: "fidodesign", "Helvetica Now Display", "Helvetica Neue", Helvetica, Arial, sans-serif;
}






.hidden { display: none !important; }


/* ---------- Site nav ---------- */
/* ---------- Hero shell ---------- */
.fhg-hero { position: relative; overflow: hidden; }

/* Two canvases: one behind the copy, one in front.
   The front one is masked to only show where the snake has "surfaced". */
#boardBack, #boardFront {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  pointer-events: none;
}
#boardBack { z-index: 1; }
#boardFront { z-index: 4; }

/* Only the back canvas takes pointer input, for swipes */
#boardBack { pointer-events: auto; touch-action: none; }

body.playing .hero-veil { opacity: .32; }
/* ---------- Hero content ---------- */

body.playing .hero-content { opacity: .58; }


body.playing .hero-kicker { opacity: 0; }

/* while playing, the heading picks up a faint edge so the snake reads behind it */
body.playing .hero-title { text-shadow: 0 0 26px rgba(9, 12, 22, .95); }



body.playing .hero-sub { opacity: 0; }

/* ---------- Service tags: obstacles + objectives ---------- */
.fhg-tags {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 9px;
  margin: 36px auto 0;
  max-width: 660px;
}
.fhg-tags .fhg-tag {
  position: relative;
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: .09em;
  color: var(--muted);
  background: rgba(255, 255, 255, .06);
  border: 1px solid var(--line);
  padding: 11px 17px;
  border-radius: 5px;
  transition: color .3s, background .3s, border-color .3s, transform .3s cubic-bezier(.16, 1, .3, 1);
}

/* live wall while the game runs */
body.playing .fhg-tags .fhg-tag {
  border-color: rgba(143, 143, 240, .5);
  color: var(--text);
  background: rgba(91, 91, 214, .16);
}

/* claimed by encircling or touching in the right state */
.fhg-tags .fhg-tag.claimed {
  color: #fff;
  background: var(--accent);
  border-color: var(--accent-2);
  transform: translateY(-2px);
}
.fhg-tags .fhg-tag.claimed::after {
  content: "";
  position: absolute;
  inset: -5px;
  border-radius: 8px;
  border: 1px solid var(--accent-2);
  opacity: 0;
  animation: claimRing .6s cubic-bezier(.16, 1, .3, 1) forwards;
}
@keyframes claimRing {
  0% { opacity: .9; transform: scale(.9); }
  100% { opacity: 0; transform: scale(1.35); }
}

/* the tag the snake just hit */
.fhg-tags .fhg-tag.struck {
  border-color: var(--danger);
  color: #fff;
  background: rgba(242, 85, 90, .22);
  animation: strike .4s ease;
}
@keyframes strike {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-4px); }
  75% { transform: translateX(4px); }
}

body.playing .hero-ask { opacity: 0; }



body.playing .hero-cta, body.playing .hero-note { opacity: 0; pointer-events: none; }

/* ---------- Focus during play ----------
   While the game runs, everything that is not the board, the tags or the HUD
   steps back. Without this the marketing copy and the game compete at equal
   weight and the hero reads as clutter. The service tags stay bright because
   they are the objectives; the headline stays legible but quiet because the
   snake passes behind it. */
.fhg-hero .bde-heading-2540-101,
.fhg-hero .bde-rich-text-2540-103,
.fhg-hero .bde-heading-2540-236,
.fhg-hero .bde-div-2540-152 {
  transition: opacity .45s cubic-bezier(.16, 1, .3, 1),
              filter .45s cubic-bezier(.16, 1, .3, 1);
}
body.playing .fhg-hero .bde-heading-2540-101,
body.playing .fhg-hero .bde-rich-text-2540-103,
body.playing .fhg-hero .bde-heading-2540-236,
body.playing .fhg-hero .bde-div-2540-152,
body.playing .hero-kicker,
body.playing .hero-sub,
body.playing .hero-ask {
  opacity: .16;
  filter: saturate(.4);
  pointer-events: none;
}

/* The headline recedes but stays readable: it is the occlusion surface. */
.fhg-hero .bde-heading-2540-233 {
  transition: opacity .45s cubic-bezier(.16, 1, .3, 1);
}
body.playing .fhg-hero .bde-heading-2540-233 { opacity: .42; }

/* ---------- Damage state ---------- */
body.damaged .hero-title {
  animation: glitch .55s steps(2) 3;
  color: #e7bfc2;
}
@keyframes glitch {
  0% { transform: translate(0, 0) skewX(0); text-shadow: 0 0 26px rgba(9,12,22,.95); }
  20% { transform: translate(-4px, 1px) skewX(-1.6deg); text-shadow: 3px 0 0 rgba(242,85,90,.75), -3px 0 0 rgba(91,91,214,.6); }
  40% { transform: translate(3px, -2px) skewX(1.2deg); text-shadow: -3px 0 0 rgba(242,85,90,.7), 3px 0 0 rgba(91,91,214,.55); }
  60% { transform: translate(-2px, 2px) skewX(-.8deg); text-shadow: 2px 0 0 rgba(242,85,90,.6); }
  100% { transform: translate(0, 0) skewX(0); text-shadow: 0 0 26px rgba(9,12,22,.95); }
}
body.damaged .fhg-tags .fhg-tag:nth-child(3) { transform: rotate(-4deg) translateY(5px); }
body.damaged .fhg-tags .fhg-tag:nth-child(6) { transform: rotate(3.5deg) translateY(-4px); }
body.damaged .hero-content { filter: saturate(.55); }

/* ---------- Assembling wireframe ---------- */
.build-panel {
  position: absolute;
  z-index: 6;
  right: clamp(18px, 3.4vw, 44px);
  top: 50%;
  transform: translateY(-50%);
  width: 152px;
  background: rgba(13, 17, 30, .84);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 14px;
  backdrop-filter: blur(10px);
  animation: slideIn .5s cubic-bezier(.16, 1, .3, 1);
}
@keyframes slideIn {
  from { opacity: 0; transform: translate(14px, -50%); }
  to { opacity: 1; transform: translate(0, -50%); }
}
@media (max-width: 900px) { .build-panel { display: none !important; } }

.bp-label {
  font-size: 9.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: #7d879f;
  margin-bottom: 11px;
}
.bp-frame { display: flex; flex-direction: column; gap: 5px; }
.bp-row { display: grid; grid-template-columns: 1fr 1fr; gap: 5px; }
.bp-slot {
  display: block;
  height: 15px;
  border-radius: 3px;
  border: 1px dashed rgba(255, 255, 255, .16);
  transition: background .45s cubic-bezier(.16, 1, .3, 1), border-color .45s, transform .45s;
}
.bp-slot[data-slot="hero"] { height: 30px; }
.bp-slot[data-slot="content"] { height: 22px; }
.bp-slot.filled {
  border-style: solid;
  border-color: transparent;
  background: linear-gradient(120deg, var(--accent), var(--accent-2));
  transform: scale(1.03);
}
.bp-slot[data-slot="hero"].filled {
  background: linear-gradient(120deg, #4747c4, var(--accent-2));
}

/* ---------- Nudge ---------- */
/* Pinned to the bottom-right corner of the hero, out of the centre column
   entirely, and styled as a game control rather than a caption: a pulsing
   pellet in the board's gold, the arrow keys as real keycaps, and the tagline
   demoted to a quiet second line. */
.play-nudge {
  position: absolute;
  z-index: 7;
  right: clamp(16px, 2.4vw, 34px);
  bottom: clamp(16px, 2.6vh, 28px);
  left: auto;
  transform: none;
  display: flex;
  align-items: center;
  gap: 12px;
  color: var(--muted);
  text-align: left;
  transition: opacity .4s ease, border-color .3s ease;
  padding: 10px 16px 10px 13px;
  border-radius: 14px;
  background: rgba(9, 12, 22, .88);
  border: 1px solid rgba(143, 143, 240, .28);
  backdrop-filter: blur(10px);
  box-shadow: 0 10px 30px rgba(2, 6, 18, .42);
  max-width: calc(100% - 32px);
}
.fhg-hero:hover .play-nudge { border-color: rgba(143, 143, 240, .5); }

/* The pellet the snake is chasing, same gold as the board. */
.nudge-food {
  width: 9px;
  height: 9px;
  border-radius: 3px;
  background: var(--gold);
  box-shadow: 0 0 12px rgba(251, 191, 36, .85);
  flex: 0 0 auto;
  animation: nudgePellet 1.7s ease-in-out infinite;
}
@keyframes nudgePellet {
  0%, 100% { transform: scale(1); opacity: 1; }
  50% { transform: scale(.72); opacity: .55; }
}

.nudge-text { display: flex; flex-direction: column; gap: 3px; }
.nudge-text b {
  display: flex;
  align-items: center;
  gap: 7px;
  font-weight: 600;
  color: var(--text);
  font-size: 12px;
}
.nudge-keys { display: inline-flex; gap: 3px; }
.nudge-keys kbd {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 17px;
  height: 17px;
  border-radius: 4px;
  border: 1px solid rgba(255, 255, 255, .2);
  border-bottom-width: 2px;
  background: rgba(255, 255, 255, .1);
  color: #fff;
  font-family: var(--font-body);
  font-size: 9.5px;
  line-height: 1;
}
.nudge-verb { font-size: 12px; letter-spacing: .01em; }
.nudge-tag {
  font-style: normal;
  font-size: 10.5px;
  color: var(--muted);
  opacity: .8;
}
/* The nudge no longer overlaps the centre column, so the hero keeps exactly
   the spacing the page builder defines: no padding override needed. */
body.playing .play-nudge { opacity: 0; pointer-events: none; }
/* ---------- HUD ---------- */
.play-hud {
  position: absolute;
  z-index: 8;
  top: clamp(72px, 10.5vh, 94px);
  left: 50%;
  display: flex;
  align-items: center;
  gap: 20px;
  background: rgba(14, 18, 32, .86);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 10px 12px 10px 22px;
  backdrop-filter: blur(10px);
  transform: translateX(-50%);
  animation: dropIn .45s cubic-bezier(.16, 1, .3, 1);
}
@keyframes dropIn {
  from { opacity: 0; transform: translate(-50%, -10px); }
  to { opacity: 1; transform: translate(-50%, 0); }
}
.ph-item {
  display: flex;
  align-items: baseline;
  gap: 7px;
  white-space: nowrap;
  flex: 0 0 auto;
}
.ph-label { font-size: 10px; letter-spacing: .15em; text-transform: uppercase; color: var(--muted); }
.ph-value {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 19px;
  font-variant-numeric: tabular-nums;
  min-width: 1ch;
}
.ph-total { font-size: 12px; color: #7d879f; }
.ph-value.alt { color: var(--accent-2); }
.ph-exit {
  background: rgba(255, 255, 255, .08);
  border: none;
  color: var(--muted);
  font-family: var(--font-body);
  font-size: 12.5px;
  padding: 8px 15px;
  border-radius: 999px;
  cursor: pointer;
  transition: color .15s, background .15s;
}
.ph-exit:hover { color: var(--text); background: rgba(255, 255, 255, .14); }

@media (max-width: 520px) {
  .play-hud {
    gap: 14px;
    padding: 9px 10px 9px 16px;
  }
  .ph-label { font-size: 9px; letter-spacing: .12em; }
  .ph-value { font-size: 18px; min-width: auto; }
  .ph-total { font-size: 11px; margin-left: -4px; }
  /* 44px is the smallest reliable touch target. The Exit control was 45x32,
     which is why leaving the game on a phone was so easy to miss. */
  .ph-exit {
    padding: 12px 18px;
    font-size: 13px;
    min-height: 44px;
    min-width: 64px;
  }
  .result-actions {
    display: grid;
    grid-template-columns: 1fr 1fr;
    width: 100%;
  }
  .result-actions .btn,
  .result-actions a,
  .result-actions button {
    width: 100%;
    justify-content: center;
    text-align: center;
  }



}

@media (max-width: 360px) {
  .result-actions { grid-template-columns: 1fr; }
}

/* ---------- Mobile: not applicable ----------
   The game is desktop-only. On phones the plugin never injects its chrome,
   so there are no touch controls, no Play button and no touch layout rules
   to define. The hero renders exactly as the page builder authored it. */


/* ---------- Desktop headline ----------
   The builder locks the headline to 874px, which wraps it onto three lines
   and makes the hero too tall for short laptop screens. It needs ~1030px at
   85px type to sit on two lines, so widen it and let the size flex down on
   narrower windows rather than gaining a third line.

   IMPORTANT: this hook is `body.fhg-armed`, a class PHP prints into the
   server HTML, NOT `.fhg-hero`, which the deferred script adds after first
   paint. Anchoring a *layout* rule to a JS-added class means the browser
   paints the builder's 874px (three lines), then reflows to two lines when
   the script runs. That visible jump on every load was the bug. Anything
   here that changes geometry must stay on a server-rendered hook; only
   paint-level rules (opacity, filter) may key off `.fhg-hero`.

   The desktop gate is the media query, which mirrors the script's own
   isDesktop() test, so this stays correct under a shared mobile/desktop
   cache: the class ships to every device, and only desktop matches. */
@media (pointer: fine) and (min-width: 1000px) {
  body.fhg-armed .bde-heading-2540-233 {
    width: min(1060px, 92vw) !important;
    max-width: min(1060px, 92vw) !important;
    font-size: clamp(52px, 5.4vw, 85px) !important;
    line-height: 1.06 !important;
    text-wrap: balance;
  }
}
/* Shorter laptops: trade type size for vertical room. */
@media (pointer: fine) and (max-height: 820px) {
  body.fhg-armed .bde-heading-2540-233 {
    font-size: clamp(46px, 4.4vw, 66px) !important;
  }
}

/* ---------- Result ---------- */
/* Every rule here is defensive. Embedded in a page builder, the surrounding
   theme styles h2/p/button globally, which previously inflated the card
   title to 48px and forced the copy into a narrow column. Explicit values
   keep the card identical wherever it is embedded. */
.result {
  position: absolute;
  z-index: 9;
  left: 50%;
  top: 50%;
  text-align: center;
  background: rgba(13, 17, 30, .95);
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 32px 34px;
  backdrop-filter: blur(14px);
  box-shadow: 0 30px 80px rgba(2, 6, 18, .72);
  transform: translate(-50%, -50%);
  animation: riseIn .5s cubic-bezier(.16, 1, .3, 1);
  width: min(430px, calc(100vw - 32px));
  max-width: min(430px, calc(100vw - 32px));
  box-sizing: border-box;
}
@keyframes riseIn {
  from { opacity: 0; transform: translate(-50%, calc(-50% + 16px)); filter: blur(4px); }
  to { opacity: 1; transform: translate(-50%, -50%); filter: none; }
}
.result-title {
  font-family: var(--font-display);
  /* !important is warranted: the host theme targets `.breakdance h2`, which
     otherwise wins and blows the title up to 48px inside the card. */
  font-size: clamp(21px, 5.2vw, 27px) !important;
  line-height: 1.22 !important;
  letter-spacing: -.02em;
  margin: 0 !important;
  color: #fff;
  text-wrap: balance;
}
.result-title span { color: var(--gold); }
.result-sub {
  color: var(--muted);
  font-size: 14px !important;
  line-height: 1.6 !important;
  margin: 12px 0 24px !important;
}
.result-actions { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }

/* Tertiary action: quiet, but always present so the card is never a dead end. */
.result-dismiss {
  display: block;
  margin: 16px auto 0;
  background: none;
  border: none;
  color: var(--muted);
  font-family: var(--font-body);
  font-size: 12.5px !important;
  line-height: 1.2 !important;
  padding: 10px 14px !important;
  min-height: 40px;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
  transition: color .18s ease;
}
.result-dismiss:hover { color: var(--text); }
@media (max-width: 520px) {
  /* Comfortable touch target on phones. */
  .result-dismiss { min-height: 44px; font-size: 13px !important; }
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  cursor: pointer;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 14px !important;
  line-height: 1.2 !important;
  border-radius: 7px;
  text-decoration: none;
  /* 44px is the smallest reliably tappable target. */
  min-height: 44px;
  padding: 13px 20px !important;
  transition: transform .18s ease, box-shadow .18s ease, background .18s;
}
.btn:hover { transform: translateY(-2px); box-shadow: 0 14px 40px rgba(2, 6, 18, .55); }
.btn-primary { background: var(--accent); color: #fff; }
.btn-primary:hover { background: #6a6ae0; }
.btn-whatsapp { background: #21b45f; color: #fff; }



/* ---------- Reduced motion ---------- */
/* Visitors who ask for less motion get the composed hero with a single
   static frame: no loop, no pulsing, no entrance animations.

   Scoped to the plugin's own elements. A bare `*` here would disable every
   animation and transition on the whole site, including on phones where the
   game never loads, which is not this plugin's decision to make. */
@media (prefers-reduced-motion: reduce) {
  .fhg-chrome *,
  .fhg-chrome *::before,
  .fhg-chrome *::after,
  .fhg-hero > .fhg-canvas,
  .fhg-hero > .fhg-veil {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .nudge-food { animation: none; }
}
