/* 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; }
}

@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; }
