/* FieldForce -- only the things Bricks globals and element controls cannot express.
   Everything else belongs in Bricks. If you find yourself adding a rule here that
   Bricks could hold, move it. See 01-DESIGN-TOKENS.md. */

/* --- Typography niceties Bricks has no control for -------------------------- */
h1, h2, h3, h4, .ff-balance { text-wrap: balance; }
p, .ff-pretty { text-wrap: pretty; }

/* --- The one shared transition. Subtle on purpose. -------------------------- */
a, button, .ff-card, .ff-btn, input, select, textarea {
  transition: color 140ms ease, background-color 140ms ease,
              border-color 140ms ease, box-shadow 140ms ease, transform 140ms ease;
}

/* --- Card hover: border picks up the service accent ------------------------- */
.ff-card { border: 1px solid var(--ff-sand); box-shadow: var(--ff-shadow-card); }
.ff-card:hover,
.ff-card:focus-within {
  border-color: var(--svc, var(--ff-sand-deep));
  box-shadow: var(--ff-shadow-hover);
}
.ff-card:hover .ff-readmore { color: var(--ff-navy-link-hover); }

/* --- Full-bleed band -------------------------------------------------------
   Bleeds by exactly the main column's padding, which is what the design does
   (margin-inline: -156px; padding-inline: 156px, at their gutter). Deliberately NOT
   width:100vw -- vw counts the scrollbar, so a 100vw band is ~15px wider than the
   content area: it forces a horizontal scrollbar AND shifts its inner content 7px out
   of alignment with every other section. Bleeding by the gutter keeps the inner content
   on the same left edge as the rest of the page and needs no overflow hacks.
   The three values match main's padding at each breakpoint (01-DESIGN-TOKENS §7). --- */
.ff-bleed {
  width: auto;
  max-width: none;
  margin-inline: calc(-1 * var(--ff-bleed, 56px));
  padding-inline: var(--ff-bleed, 56px);
  padding-block: 24px 30px;
}
@media (max-width: 900px) { .ff-bleed { --ff-bleed: 32px; } }
@media (max-width: 600px) { .ff-bleed { --ff-bleed: 20px; padding-block-start: 22px; } }

/* --- Mobile menu -----------------------------------------------------------
   Bricks' nav-menu ships a 300px off-canvas side drawer (.left/.right, translateX
   ±100%). 02-COMPONENT-LIBRARY.md §1 specifies something different: a full-width
   panel dropping *under* the header. That is not expressible through the element's
   controls, so it is rebuilt here -- which is what this file is for.

   No specificity war needed: everything Bricks ships sits in `@layer bricks`, and
   an unlayered rule beats any layered normal declaration regardless of specificity.
   !important appears only where Bricks itself used it. ------------------------- */
.brxe-nav-menu .bricks-mobile-menu-wrapper {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  bottom: auto;
  width: 100%;
  max-width: none;
  height: auto;
  transform: none !important;
  visibility: hidden;
  opacity: 0;
  z-index: 60;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 6px 20px 16px;
  background: var(--ff-nav);
  border-top: 1px solid var(--ff-sand);
  box-shadow: var(--ff-shadow-menu);
  transition: opacity 140ms ease, visibility 140ms ease;
}
/* !important is deliberate. Bricks marks opacity/transform !important on its own
   reveal rule, and its base rule keeps the panel visibility:hidden; matching that
   weight is the only way to win reliably across its @layer. */
.brxe-nav-menu.show-mobile-menu .bricks-mobile-menu-wrapper {
  visibility: visible !important;
  opacity: 1 !important;
}
/* Bricks paints a dark scrim via ::before; the design has none. */
.brxe-nav-menu .bricks-mobile-menu-wrapper::before { content: none; }

.brxe-nav-menu .bricks-mobile-menu-wrapper .bricks-nav-menu > li > a,
.brxe-nav-menu .bricks-mobile-menu-wrapper li a {
  display: block;
  width: 100%;
  padding: 13px 6px;
  font-size: 17px;
  font-weight: 600;
  line-height: 1.2;
  color: var(--ff-ink);
  text-decoration: none;
  border-bottom: 1px solid var(--ff-sand);
}
.brxe-nav-menu .bricks-mobile-menu-wrapper li:last-child a { border-bottom: 0; }
.brxe-nav-menu .bricks-mobile-menu-wrapper .current-menu-item > a {
  font-weight: 700;
  color: var(--ff-red-800);
}

/* Burger: the design is an explicit 44x44 tap target (§1, and 06 §5's a11y floor).
   Bricks' own CSS pins the toggle to width:20px, hence the overrides. */
.brxe-nav-menu .bricks-mobile-menu-toggle,
.brxe-nav-menu.show-mobile-menu .bricks-mobile-menu-toggle {
  width: 44px;
  min-width: 44px;
  height: 44px;
  padding: 0;
  align-items: center;
  justify-content: center;
  background: var(--ff-white);
  border: 1px solid var(--ff-sand);
  border-radius: 10px;
  color: var(--ff-ink);
  cursor: pointer;
}
/* Bricks decides burger visibility from an inline rule inside @layer bricks. Because
   everything here is unlayered it would beat that rule and pin the burger to one
   state, so the show/hide has to be owned here too. 900px is the design's tablet
   breakpoint -- a media query cannot read a CSS variable, so the number is literal,
   same as .ff-bleed above. */
.brxe-nav-menu .bricks-mobile-menu-toggle { display: none; }
@media (max-width: 900px) {
  .brxe-nav-menu .bricks-mobile-menu-toggle { display: inline-flex; }
}
.brxe-nav-menu .bricks-mobile-menu-toggle .bar-top,
.brxe-nav-menu .bricks-mobile-menu-toggle .bar-center,
.brxe-nav-menu .bricks-mobile-menu-toggle .bar-bottom {
  width: 16px;
  height: 2.2px;
  border-radius: 2px;
  background: currentColor;
}

/* --- Chart bars: grow from the baseline, 50ms stagger ----------------------- */
.ff-bar {
  transform-origin: bottom center;
  animation: ffGrow 0.6s ease-out both;
  animation-delay: calc(var(--i, 0) * 50ms);
  /* The bar is a flex item in a fixed-height track. Without this it gets shrunk to
     fit and every tall bar clamps to the same value -- 338, 299 and 249 all came out
     62px, which silently flattens the chart. */
  flex-shrink: 0;
}
/* The 88px track holds the value label and the bar only; the axis label sits below it
   (02-COMPONENT-LIBRARY.md §12), or the bar loses that space too. */
.ff-bar-track {
  height: 96px;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: center;
  width: 100%;
}
.ff-bar[data-tone="pale"]      { background: var(--ff-chart-blue-pale); }
.ff-bar[data-tone="mid"]       { background: var(--ff-chart-blue-mid); }
.ff-bar[data-tone="highlight"] { background: var(--ff-chart-blue); }
.ff-bar[data-tone="negative"]  { background: var(--ff-red); }

/* --- KPI tile tones (02-COMPONENT-LIBRARY.md §12) ---------------------------
   The highlighted tile swaps background AND recolours both label and value. Driven
   by data-tone from ACF, so the template needs no per-tile settings. --------- */
/* Scoped to .ff-kpi on purpose. An unscoped [data-tone="highlight"] also matches the
   highlighted CHART BAR -- which carries the same data-tone -- and repainted it in the
   tile's tint instead of ff-chart-blue. */
.ff-kpi[data-tone="highlight"] { background-color: var(--ff-chart-blue-tint) !important; }
.ff-kpi[data-tone="highlight"] > * { color: var(--ff-chart-blue) !important; }

/* --- Feature-card icon tile -------------------------------------------------
   The mark is painted as a CSS mask, not an <img>: an SVG loaded through <img> is an
   isolated document, so its stroke="currentColor" resolves to black and no page variable
   reaches inside it. Masking a solid fill gives the accent colour and still takes the URL
   straight from ACF (--icon is set inline by the template). Falls back to red on pages
   with no service accent, which is what Company does in the design. --- */
.ff-icon-tile {
  background: var(--svc-tint, var(--ff-red-tint));
  border-radius: 10px;
  display: grid;
  place-items: center;
  flex: none;
}
.ff-icon-tile::before {
  content: "";
  width: 21px;
  height: 21px;
  background: var(--svc, var(--ff-red));
  -webkit-mask: var(--icon) center / contain no-repeat;
  mask: var(--icon) center / contain no-repeat;
}

/* --- FieldForce method: numbered steps on a connecting rule -----------------
   The number is a CSS counter. Bricks' {loop_index} does not resolve inside a query loop
   -- it printed the literal string "{loop_index}" on the live page -- and the rule from
   05-BRICKS-BUILD-ORDER.md is that the step number is derived, never stored. A counter
   satisfies both. --- */
.ff-steps { counter-reset: ff-step; }
.ff-step {
  counter-increment: ff-step;
  position: relative;
  padding-top: 52px;
}
.ff-step::before {
  content: counter(ff-step);
  position: absolute;
  top: 0;
  left: 0;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--ff-white);
  border: 1.5px solid var(--svc, var(--ff-navy));
  color: var(--svc-deep, var(--ff-navy));
  font-size: 15px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
/* The rule joining one step to the next. Not on the last one, and not once the grid
   wraps -- a connector pointing at a step on another row reads as a mistake. */
.ff-step::after {
  content: "";
  position: absolute;
  top: 17.5px;
  left: 44px;
  right: 10px;
  height: 1px;
  background: var(--svc-border, var(--ff-sand));
}
.ff-step:last-child::after { content: none; }
@media (max-width: 900px) {
  .ff-step::after { content: none; }
}

/* --- Data-source pills inside the method panel ------------------------------ */
.ff-src-eyebrow { display: inline-flex; align-items: center; white-space: nowrap; }
.ff-src-eyebrow::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--ff-red);
  margin-right: 8px;
  flex: none;
}
.ff-src-pill {
  display: inline-block;
  background: var(--ff-white);
  border: 1px solid var(--ff-sand);
  border-radius: var(--ff-radius-pill);
  padding: 5px 11px;
  margin: 3px 6px 3px 0;
  font-size: 12.5px;
  font-weight: 700;
  line-height: 1.2;
  color: var(--ff-ink);
}

/* --- EN / FI switcher --------------------------------------------------------
   Two segments in one pill: the active language filled dark, the other plain. Built by
   ff_lang_switcher() so each link points at the translation of the current page. --- */
.ff-lang-switch { display: inline-flex; align-items: center; gap: 2px; }
.ff-lang {
  display: inline-block;
  padding: 5px 12px;
  border-radius: var(--ff-radius-pill);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.03em;
  line-height: 1;
  color: var(--ff-inactive);
  text-decoration: none;
}
.ff-lang:hover { color: var(--ff-ink); }
.ff-lang-on {
  background: var(--ff-ink);
  color: var(--ff-white);
}
.ff-lang-on:hover { color: var(--ff-white); }

/* --- Contact rows: an icon before the value ---------------------------------
   These four are fixed UI affordances tied to the field (an email row always gets an
   envelope), so unlike the feature-card icons they are not ACF-editable and live here.
   Painted as a mask so the mark takes the row's own colour. --- */
.ff-ico { display: inline-flex; align-items: center; gap: 9px; }
.ff-ico::before {
  content: "";
  width: 17px;
  height: 17px;
  flex: none;
  background: currentColor;
  -webkit-mask: var(--ico) center / contain no-repeat;
  mask: var(--ico) center / contain no-repeat;
}
.ff-ico-mail { --ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='5' width='18' height='14' rx='2'/%3E%3Cpath d='M3 7l9 6 9-6'/%3E%3C/svg%3E"); }
.ff-ico-phone { --ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 4h4l2 5-3 2a14 14 0 006 6l2-3 5 2v4a2 2 0 01-2 2A17 17 0 013 6a2 2 0 012-2z'/%3E%3C/svg%3E"); }
.ff-ico-clock { --ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 7v5l3 2'/%3E%3C/svg%3E"); }
.ff-ico-pin { --ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 21s-7-5.5-7-11a7 7 0 0114 0c0 5.5-7 11-7 11z'/%3E%3Ccircle cx='12' cy='10' r='2.5'/%3E%3C/svg%3E"); }
/* The pin is the one that carries colour of its own -- red, per the design. */
.ff-ico-pin::before { background: var(--ff-red); }

/* --- Person card: portrait down the left ----------------------------------- */
.ff-person { overflow: hidden; }
.ff-person-photo { background: var(--ff-sand); }
.ff-person-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
@media (max-width: 600px) {
  .ff-person { flex-direction: column; }
  .ff-person-photo { width: 100% !important; height: 200px; }
}

/* --- Service icons: 84px, accent-coloured, inlined so currentColor works ---- */
.ff-svc-icon svg { width: 100%; height: 100%; display: block; }
.ff-svc-icon { color: var(--svc); opacity: 0.92; }

/* --- LIVE badge ------------------------------------------------------------ */
.ff-live { color: var(--ff-green); background: var(--ff-green-tint); }
.ff-live-dot {
  background: currentColor;
  animation: ffBlink 1.6s ease-in-out infinite;
}

/* --- Blog post row --------------------------------------------------------- */
.ff-post-row { overflow: hidden; }
.ff-post-row:hover { border-color: var(--ff-sand-hover); box-shadow: var(--ff-shadow-hover); }
/* The gradient well must not collapse when the row has little text. */
.ff-post-row > :first-child { min-height: 100%; }

/* Stretched link. The design makes the whole card an <a>; a Bricks loop cannot, because
   `tag => 'a'` on the loop element breaks the `.brxe-<loop> .brxe-<child>` descendant
   scoping Bricks generates and drops every child style. Stretching the title's anchor over
   the card gives the same click target with one anchor, one tab stop, and the title as the
   accessible name. The meta row stays above it so text is still selectable. */
.ff-post-row .ff-post-title a::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
}
.ff-post-row .ff-post-title a { text-decoration: none; color: inherit; }
.ff-post-row:hover .ff-readmore { color: var(--ff-navy-link-hover); }

/* The well's centred 40px line mark. Purely decorative -- it is the placeholder for a
   featured image nobody uploaded, so it is styling, not content, and belongs here rather
   than in an ACF field or a Bricks element. stroke is ff-sand-ink at 55%, per the design. */
.ff-post-thumb { position: relative; }
.ff-post-thumb::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 40px;
  height: 40px;
  transform: translate(-50%, -50%);
  opacity: 0.55;
  background-repeat: no-repeat;
  background-size: contain;
  /* --topic-mark comes from the [data-topic] map; the tag icon is the fallback for a
     category that has no mark of its own yet. */
  background-image: var(--topic-mark, url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' fill='none' stroke='%23AA9E82' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M54 18 H30 a5 5 0 0 0-5 5 V47 a5 5 0 0 0 1.5 3.5 L52 76 a3 3 0 0 0 4 0 L78 54 a3 3 0 0 0 0-4 z'/%3E%3Ccircle cx='41' cy='33' r='4'/%3E%3C/svg%3E"));
}
/* A real featured image replaces the mark rather than sitting behind it. */
.ff-post-thumb:has(img)::after { content: none; }
.ff-post-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* --- Topic + badge pills ---------------------------------------------------
   Colours come from the [data-topic] / [data-badge] maps in tokens.css, so one rule
   covers every category and the template carries no per-category settings. --- */
.ff-topic-pill,
.ff-badge-pill {
  font-size: 10px;
  font-weight: 700;
  line-height: 1.35;
  text-transform: uppercase;
  border-radius: var(--ff-radius-pill);
  white-space: nowrap;
}
.ff-topic-pill {
  letter-spacing: 0.06em;
  color: var(--topic-ink);
  background: var(--topic-bg);
  padding: 3px 8px;
}
.ff-badge-pill {
  letter-spacing: 0.05em;
  color: var(--badge-ink);
  background: var(--badge-bg);
  border: 1px solid var(--badge-border);
  padding: 2px 8px;
}

/* --- Capability chips on the Services index cards -------------------------
   Accent at 15% behind, 32% as the border, --svc-deep as the text -- the design's
   rgba(<accent>, .15)/.32 pair, resolved through the [data-accent] map so one rule
   covers all three services. --- */
.ff-chip {
  font-size: 12px;
  font-weight: 700;
  line-height: 1.2;
  color: var(--svc-deep);
  background: var(--svc-chip);
  border: 1px solid var(--svc-chip-border);
  padding: 6px 11px;
  border-radius: 8px;
  white-space: nowrap;
}

/* --- Most-read rail: 01 / 02 / 03 ------------------------------------------
   A CSS counter, not a loop index -- Bricks' {loop_index} does not resolve inside a
   query loop, so the number cannot come from the template. --- */
.ff-most-list { counter-reset: ff-most; }
.ff-most-row {
  counter-increment: ff-most;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: 10px;
  align-items: start;
}
.ff-most-row::before {
  content: counter(ff-most, decimal-leading-zero);
  font-size: 12px;
  font-weight: 700;
  line-height: 1.35;
  color: var(--ff-sand-hover);
  font-variant-numeric: tabular-nums;
}

/* --- Sidebar filter pills --------------------------------------------------
   Inactive: white on a sand hairline. Selected: filled with that filter's own colour,
   which is --pill-on from the same maps in tokens.css. data-active is computed in PHP
   (ff_filter_active) because the selection lives in a query string and Bricks only sets
   aria-current from the path. --- */
/* The BASE lives here too, not in Bricks. Bricks writes per-element CSS as `#brxe-<id>
   { background-color: ... }`, and an ID selector outranks any class+attribute rule -- so a
   Bricks-owned base made the selected state unstylable without !important. A pill is a
   component with states; owning both here keeps one cascade instead of two. */
.ff-filter-pill {
  font-size: 12.5px;
  font-weight: 700;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  padding: 8px 14px;
  border-radius: var(--ff-radius-pill);
  color: var(--ff-ink);
  background: var(--ff-white);
  border: 1px solid var(--ff-sand);
  text-decoration: none;
}
.ff-filter-pill:hover { border-color: var(--ff-ink); }
.ff-filter-pill[data-active="true"] {
  color: var(--ff-white);
  background: var(--pill-on, var(--ff-ink));
  border-color: var(--pill-on, var(--ff-ink));
}
/* The design separates the topic filters from the flag filters with a hairline. */
.ff-filter-rule { width: 100%; height: 1px; background: var(--ff-hairline); margin: 3px 0; }

/* --- Customer cards: a fixed 48px well so logos of different aspect ratios sit on
       one optical baseline; per-logo max-height still comes from ACF. ------------ */
.ff-logo-well img {
  max-height: var(--logo-h, 40px);
  max-width: 170px;
  width: auto;
  height: auto;
  object-fit: contain;
  display: block;
}

/* --- Trusted-by wall: optical sizing per logo, set from ACF ----------------- */
.ff-logo-wall img {
  max-height: var(--logo-h, 40px);
  max-width: var(--logo-w, 150px);
  width: auto;
  height: auto;
  object-fit: contain;
}

/* --- Service icons inherit the accent -------------------------------------- */
.ff-svc-icon { color: var(--svc); }
.ff-svc-icon svg { stroke: currentColor; fill: none; }

/* --- Accessibility floor --------------------------------------------------- */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--ff-navy);
  outline-offset: 2px;
}
.ff-tap { min-width: 44px; min-height: 44px; }

/* --- Newsletter / CTA form states ------------------------------------------ */
.ff-form[data-state="error"] .ff-input { border-color: var(--ff-red-700); }
.ff-form-error { color: var(--ff-red-700); }
.ff-form[data-state="error"] .ff-form-error,
.ff-form[data-state="success"] .ff-form-success { display: block; }
.ff-form-error, .ff-form-success { display: none; }
/* 02-COMPONENT-LIBRARY.md §8: the success panel *replaces* the form, it does not
   join it. .ff-form-row is the input+button row. */
.ff-form[data-state="success"] .ff-form-row { display: none; }
.ff-form-success {
  background: var(--ff-green-ok-tint);
  color: var(--ff-green-ok);
}
.ff-form-success .ff-check { background: var(--ff-green-ok-circle); }

@media (prefers-reduced-motion: reduce) {
  .ff-bar, .ff-live-dot { animation: none !important; }
  * { scroll-behavior: auto !important; }
}
.ff-chart-idle .ff-bar { animation-play-state: paused; }
