/* Freddie Media — interaction states.
   The design tokens, typography, layout and responsive rules all live inline
   in each page (exported from the design). This file only restores the
   hover/focus states that the React components handled at runtime. */

/* ---------------- buttons ---------------- */
.fm-btn { -webkit-appearance: none; appearance: none; }
.fm-btn[data-variant="primary"]:hover   { background: #0B3540; }
.fm-btn[data-variant="accent"]:hover    { background: #28D486; border-color: #28D486; }
.fm-btn[data-variant="secondary"]:hover { background: var(--ink-8); }
.fm-btn[data-variant="ghost"]:hover     { background: var(--ink-8); }
.fm-btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(53, 242, 154, .55);
}
.fm-btn[disabled] { opacity: .4; cursor: not-allowed; }

/* ---------------- form fields ---------------- */
.fm-field:focus,
textarea:focus {
  border-color: var(--ink);
  box-shadow: 0 0 0 3px rgba(53, 242, 154, .35);
}

/* ---------------- buttons rendered as links ----------------
   Buttons are <a> rather than <button> so they're real, crawlable links.
   The design's styles assume <button>, so two things need restoring:
   1. its generic `a:hover { color: var(--green) }` was turning the label
      green-on-green (invisible) on the accent buttons;
   2. its `.btn-accent button` / `.btn-dark button` hover treatments never
      matched. Re-point both at the anchors. */
a.fm-btn:hover {
  opacity: 1 !important;
  text-decoration: none !important;
}
.btn-accent a.fm-btn {
  background: var(--green) !important;
  color: var(--ink) !important;
  border-color: var(--green) !important;
  transition: background .25s ease !important;
}
.btn-accent a.fm-btn:hover {
  background: linear-gradient(120deg, var(--green) 0%, var(--sky) 100%) !important;
  color: #0B3540 !important;
  border-color: transparent !important;
}
.btn-dark a.fm-btn {
  background: var(--ink) !important;
  color: var(--cream) !important;
  border-color: var(--ink) !important;
  transition: background .25s ease !important;
}
.btn-dark a.fm-btn:hover {
  background: radial-gradient(ellipse 90% 100% at 100% 115%,
              rgba(53, 242, 154, .65) 0%, rgba(53, 242, 154, .2) 45%, transparent 72%)
              var(--ink) !important;
  color: var(--cream) !important;
}
/* Unwrapped buttons keep a readable label on hover too. */
a.fm-btn[data-variant="accent"]:hover    { color: #0B3540 !important; }
a.fm-btn[data-variant="primary"]:hover   { color: var(--cream) !important; }
a.fm-btn[data-variant="secondary"]:hover,
a.fm-btn[data-variant="ghost"]:hover     { color: var(--ink) !important; }

/* ---------------- work grid ----------------
   Full-bleed mosaic: four across on desktop, spanning the whole viewport.
   On hover a gradient rises from the bottom of the tile and the copy comes
   with it. No flip, no client names.

   The grid carries [data-reveal], never the tiles - the reveal script writes
   inline transforms onto revealed elements and their direct children, which
   would fight anything animated inside a tile. */
.fm-tile-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 4px;
  width: 100%;
}
.fm-tile {
  position: relative;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  outline: none;
  background: var(--ink);
}
.fm-tile-media {
  position: relative;
  width: 100%;
  height: 100%;
}
.fm-tile-media img,
.fm-tile-media video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform .8s cubic-bezier(.22, .9, .24, 1);
}
.fm-tile:hover .fm-tile-media img,
.fm-tile:hover .fm-tile-media video,
.fm-tile:focus-visible .fm-tile-media img,
.fm-tile:focus-visible .fm-tile-media video { transform: scale(1.045); }

/* The resting still for video tiles. It sits above the video and only fades
   out once the video reports that it is actually playing (site.js adds
   .is-playing), so the tile never flashes a blank frame. */
.fm-tile-still {
  position: absolute;
  inset: 0;
  z-index: 1;
  opacity: 1;
  transition: opacity .35s ease, transform .8s cubic-bezier(.22, .9, .24, 1);
}
.fm-tile.is-playing .fm-tile-still { opacity: 0; }

.fm-tile-overlay {
  position: absolute;
  inset: 0;
  z-index: 2;              /* above .fm-tile-still, which sits at 1 */
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: 24px;
  pointer-events: none;
  color: var(--cream);
  background: linear-gradient(to top,
              rgba(6, 37, 45, .94) 0%,
              rgba(6, 37, 45, .78) 22%,
              rgba(6, 37, 45, .35) 48%,
              rgba(6, 37, 45, 0)   78%);
  opacity: 0;
  transition: opacity .4s ease;
}
.fm-tile:hover .fm-tile-overlay,
.fm-tile:focus-visible .fm-tile-overlay { opacity: 1; }

/* Footage that already carries burned-in subtitles or a lower-third logo:
   flip the gradient and the copy to the top so the two don't collide. */
.fm-tile-overlay--top {
  justify-content: flex-start;
  background: linear-gradient(to bottom,
              rgba(6, 37, 45, .94) 0%,
              rgba(6, 37, 45, .78) 22%,
              rgba(6, 37, 45, .35) 48%,
              rgba(6, 37, 45, 0)   78%);
}

.fm-tile-copy {
  transform: translateY(10px);
  transition: transform .45s cubic-bezier(.22, .9, .24, 1);
}
.fm-tile-overlay--top .fm-tile-copy { transform: translateY(-10px); }
.fm-tile:hover .fm-tile-copy,
.fm-tile:focus-visible .fm-tile-copy { transform: translateY(0); }

.fm-tile-title {
  font-size: clamp(18px, 1.5vw, 23px); line-height: 1.14;
  letter-spacing: -.02em; font-weight: 700; margin: 0;
}
.fm-tile-result {
  margin-top: 8px;
  font-size: 12px; line-height: 1.45; font-weight: 400;
  color: rgba(249, 249, 240, .8);
}
.fm-tile:focus-visible { box-shadow: inset 0 0 0 3px var(--green); }

/* Touch: there is no hover, so the copy is always on. */
@media (hover: none) {
  .fm-tile-overlay { opacity: 1; }
  .fm-tile-copy { transform: none; }
}

/* ---- always-on mode ----
   Titles permanently visible, every video looping. The gradient is lighter
   than the hover version: it is on screen the whole time, so it only has to
   carry the text, not announce itself. Hover still deepens it and nudges the
   image, so the tiles keep responding to the pointer. */
.fm-tile-grid--always .fm-tile-overlay {
  opacity: 1;
  background: linear-gradient(to top,
              rgba(6, 37, 45, .88) 0%,
              rgba(6, 37, 45, .62) 24%,
              rgba(6, 37, 45, .22) 50%,
              rgba(6, 37, 45, 0)   78%);
  transition: background .4s ease;
}
.fm-tile-grid--always .fm-tile-overlay--top {
  background: linear-gradient(to bottom,
              rgba(6, 37, 45, .88) 0%,
              rgba(6, 37, 45, .62) 24%,
              rgba(6, 37, 45, .22) 50%,
              rgba(6, 37, 45, 0)   78%);
}
.fm-tile-grid--always .fm-tile-copy { transform: none; }
.fm-tile-grid--always .fm-tile:hover .fm-tile-overlay,
.fm-tile-grid--always .fm-tile:focus-visible .fm-tile-overlay {
  background: linear-gradient(to top,
              rgba(6, 37, 45, .96) 0%,
              rgba(6, 37, 45, .8) 24%,
              rgba(6, 37, 45, .38) 50%,
              rgba(6, 37, 45, 0)  80%);
}

@media (max-width: 1100px) {
  .fm-tile-grid { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 820px) {
  .fm-tile-grid { grid-template-columns: repeat(2, 1fr); }
  .fm-tile-overlay { padding: 18px; }
  .fm-tile-title { font-size: 17px; }
  .fm-tile-result { font-size: 11px; margin-top: 6px; }
}
@media (max-width: 460px) {
  .fm-tile-grid { grid-template-columns: 1fr; }
  .fm-tile-overlay { padding: 26px; }
  .fm-tile-title { font-size: 24px; }
  .fm-tile-result { font-size: 13px; }
}
@media (prefers-reduced-motion: reduce) {
  .fm-tile-media img, .fm-tile-media video, .fm-tile-copy { transition: none; }
  .fm-tile:hover .fm-tile-media img,
  .fm-tile:hover .fm-tile-media video { transform: none; }
}

/* ---------------- links ---------------- */
a { color: inherit; }
a:focus-visible {
  outline: 2px solid var(--green);
  outline-offset: 2px;
}

/* ---------------- images ---------------- */
img { height: auto; }

/* ---------------- mobile: stop horizontal overflow ----------------
   The exported design targets inline styles as `gap: 96px` (with a space),
   but they serialise as `gap:96px`, so its wrap rules never matched and the
   footer rows forced the page ~265px wider than the screen. Match both forms.
   (Deliberately not using overflow-x:hidden on html/body — that would break
   the sticky header.) */
@media (max-width: 720px) {
  footer [style*="display:flex"],
  footer [style*="display: flex"] { flex-wrap: wrap !important; }

  footer [style*="justify-content:space-between"],
  footer [style*="justify-content: space-between"] {
    flex-direction: column !important;
    align-items: flex-start !important;
    gap: 28px !important;
  }

  footer [style*="gap:96px"], footer [style*="gap: 96px"],
  footer [style*="gap:64px"], footer [style*="gap: 64px"],
  footer [style*="gap:88px"], footer [style*="gap: 88px"] { gap: 28px !important; }

  /* same defensive wrap for wide rows elsewhere in the page */
  [data-sec] [style*="gap:96px"], [data-sec] [style*="gap: 96px"],
  [data-sec] [style*="gap:64px"], [data-sec] [style*="gap: 64px"] {
    flex-wrap: wrap !important;
    gap: 28px !important;
  }
}

/* Very narrow phones (320px, e.g. iPhone SE 1st gen): section header rows
   pair a heading with a "nowrap" link and won't fit side by side. */
@media (max-width: 480px) {
  [data-sec] [style*="justify-content: space-between"],
  [data-sec] [style*="justify-content:space-between"] {
    flex-wrap: wrap !important;
    gap: 20px !important;
  }
  [data-sec] [style*="gap: 48px"], [data-sec] [style*="gap:48px"] { gap: 20px !important; }
}

/* Keep the reveal animations from hiding content if JS fails to run. */
.no-js [data-reveal],
.no-js [data-card],
.no-js [data-step] { opacity: 1 !important; transform: none !important; filter: none !important; }
