/* ════════════════════════════════════════════════════════ */
/* · PRODUCT LANDING TEMPLATE · shared across invoicing/booking/ */
/* repairs/timesheets. Only the accent hue differs per page —  */
/* set --color-accent (+ -dark/-light) in a small page-local  */
/* <style> block, plus --accent-photo for the CTA frame photo.*/
/* ════════════════════════════════════════════════════════ */
:root {

  /* derived from --color-accent — do not override these directly */
  --color-accent-pale: color-mix(in srgb, var(--color-accent) 12%, white);
  --color-accent-pale-border: color-mix(in srgb, var(--color-accent) 30%, white);
}

/* ════════════════════════════════════════════════════════ */
/* · NAV · floating bordered panel, sharp corners             */
/* ════════════════════════════════════════════════════════ */
.pf-nav-shell { position: fixed; top: 0; inset-inline: 0; z-index: 30; }
.scroll-ruler-fill { background: var(--color-accent); }
/* accent-light, not accent: a mid accent on the ink footer measures ~2-3:1 and reads
   as disabled — the same lesson the studio's own service cards already carry. */
.pf-foot-link { color: var(--color-accent-light); transition: color .2s ease; }
.pf-foot-link:hover { color: #fff; }
/* NOT a defect, measured: .bp-grid-dark draws its 1px lines in the studio's emerald
   #51BD87 at 13%. Re-deriving them from the page's own accent was tried and reverted —
   over this ink the lines composite to #183C2A against #1A3A2D, a 5.6 degree hue shift,
   below perception. What separates the footer from a product page is the INK itself
   (hue 150, the studio's family), not its sheet, and the ink is one colour sitewide. */
.pf-nav-float { padding-top: 10px; }
.pf-nav-panel {
  display: flex; align-items: center; justify-content: space-between;
  height: 56px;
  background: var(--color-page);
  border: 1px solid var(--color-concrete);
  transition: background-color .3s ease, border-color .3s ease, box-shadow .3s ease;
}
.pf-nav-shell.is-scrolled .pf-nav-panel {
  background: rgba(250,250,247,.96);
  backdrop-filter: blur(16px) saturate(160%);
  -webkit-backdrop-filter: blur(16px) saturate(160%);
  border-color: rgba(30,42,46,.16);
  box-shadow: 0 10px 28px rgba(20,24,26,.07);
}

.pf-nav-links { display: flex; align-items: center; gap: 2px; }
.pf-nav-link {
  font-family: var(--font-display); font-weight: 500;
  font-size: 11px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--color-muted);
  padding: 8px 14px;
  transition: color .2s ease, background-color .2s ease;
}
.pf-nav-link:hover { color: var(--color-ink); }
/* The nav demo button is an outline that fills on hover, so the hero's filled demo
   button is the one primary action. The section you are in fills ink, like the hub's. */
.pf-nav-link.is-active { background: var(--color-ink); color: #fff; }
.pf-nav-cta { border: 1px solid var(--color-accent-dark); color: var(--color-accent-dark); margin-left: 8px; }
.pf-nav-cta:hover { background: var(--color-accent); border-color: var(--color-accent); color: var(--accent-ink); }

/* burger — hand-built, no svg */
.pf-nav-burger {
  display: none;
  width: 40px; height: 40px; flex-shrink: 0;
  flex-direction: column; align-items: center; justify-content: center; gap: 5px;
  background: none; border: none; cursor: pointer;
}
.pf-nav-burger span { width: 18px; height: 1.5px; background: var(--color-ink); display: block; transition: transform .25s ease, opacity .25s ease; }
.pf-nav-shell.is-open .pf-nav-burger span:nth-child(1) { transform: translateY(6.5px) rotate(45deg); }
.pf-nav-shell.is-open .pf-nav-burger span:nth-child(2) { opacity: 0; }
.pf-nav-shell.is-open .pf-nav-burger span:nth-child(3) { transform: translateY(-6.5px) rotate(-45deg); }

/* mobile menu — the hub's drawer, in the product's own colours.
   The sheet this replaces dropped out of the nav panel and gave the links 11px
   uppercase at muted with no separators, leaving Contact as the quietest item in
   a menu that exists mostly to reach it. */
.pf-nav-overlay {
  position: fixed; inset: 0; z-index: 40;
  background: color-mix(in srgb, var(--color-ink) 30%, transparent);
  opacity: 0; visibility: hidden;
  transition: opacity .3s ease, visibility .3s ease;
}
.pf-nav-shell.is-open ~ .pf-nav-overlay { opacity: 1; visibility: visible; }

.pf-nav-drawer {
  position: fixed; top: 0; right: 0; z-index: 50;
  width: 18rem; max-width: 85%; height: 100%;
  background: var(--color-page);
  border-left: 1px solid var(--color-concrete);
  transform: translateX(100%);
  transition: transform .32s cubic-bezier(.22,1,.36,1);
  overflow-y: auto;
}
.pf-nav-shell.is-open ~ .pf-nav-drawer { transform: translateX(0); }
@media (prefers-reduced-motion: reduce) {
  .pf-nav-overlay, .pf-nav-drawer { transition: none; }
}
.pf-nav-drawer-inner {
  display: flex; flex-direction: column; min-height: 100%;
  padding: 1.1rem 1.5rem 2rem;
}
.pf-nav-close {
  align-self: flex-end; flex-shrink: 0;
  width: 40px; height: 40px;                       /* 40px so it clears the 44px tap floor with its row */
  background: none; border: none; cursor: pointer;
  font-family: var(--font-display); font-size: 26px; line-height: 1;
  color: var(--color-ink);
}
.pf-nav-drawer-nav { display: flex; flex-direction: column; margin-top: .25rem; }
.pf-drawer-link {
  display: block; padding: 14px 0;
  border-bottom: 1px solid color-mix(in srgb, var(--color-concrete) 60%, transparent);
  font-family: var(--font-display); font-size: 16px;
  color: var(--color-ink);
  transition: color .2s ease;
}
.pf-drawer-link:hover { color: var(--color-accent-dark); }
/* the one thing the menu is for, so it is the one filled control in it.
   Ink comes from the page's own --accent-ink, same token as the nav's active box. */
.pf-drawer-cta {
  margin-top: 1.5rem;
  display: inline-flex; align-items: center; justify-content: center;
  padding: 13px 16px;
  font-family: var(--font-display); font-size: 15px; font-weight: 500;
}
.pf-nav-drawer .pf-lang-row { margin-top: 1.5rem; border-top: none; padding: 0; }
.pf-nav-drawer-foot {
  margin-top: auto; padding-top: 2.5rem;
  font-family: var(--font-display); font-size: var(--text-xs);
  color: var(--color-muted); line-height: 1.7;
}
.pf-nav-drawer-foot span { display: block; }
.pf-nav-drawer-foot span + span { margin-top: 3px; letter-spacing: .14em; text-transform: uppercase; }
@media (min-width: 768px) { .pf-nav-overlay, .pf-nav-drawer { display: none; } }

@media (max-width: 767px) {
  .pf-nav-links { display: none; }
  .pf-nav-burger { display: flex; }
  /* the floating panel is a desktop gesture — a drawn object lying on a wide sheet.
     At phone width the panel already reaches both edges, so the 10px above it stops
     reading as float and starts reading as a bar that missed its mark, with whatever
     section is behind showing through the strip. Flush to the top, bottom edge only. */
  .pf-nav-float { padding-top: 0; }
  .pf-nav-panel { border-width: 0 0 1px; }
}


/* · LANGUAGE SWITCHER · the hub's control, in the product nav's type.
   <details> so it needs no JS, endonyms (never a flag), the active language
   as the trigger. The menu takes the nav sheet's own surface, not white:
   pure white on this site means "inside a drawn app". */
.pf-lang { position: relative; }
.pf-lang > summary { list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: 6px; }
.pf-lang > summary::-webkit-details-marker { display: none; }
.pf-lang > summary::after { display: none; }
.pf-lang[open] > summary { color: var(--color-ink); }
.pf-lang-chev { transition: transform .25s cubic-bezier(.2,.7,.2,1); }
@media (prefers-reduced-motion: reduce) { .pf-lang-chev { transition: none; } }
.pf-lang[open] .pf-lang-chev { transform: rotate(180deg); }
.pf-lang-menu {
  /* the trigger sits centred in the 56px panel, so half the panel below its centre is the panel's bottom edge */
  position: absolute; right: 0; top: calc(50% + 28px); min-width: 6.5rem; z-index: 30;
  background: var(--color-page); border: 1px solid var(--color-concrete);
}
.pf-lang-menu a {
  display: block; padding: 10px 14px;
  font-family: var(--font-display); font-size: 12px; letter-spacing: .04em;
  color: var(--color-muted);
  transition: background-color .2s ease, color .2s ease;
}
.pf-lang-menu a:hover { background: var(--color-section); color: var(--color-ink); }
.pf-lang-menu a[aria-current="true"] { color: var(--color-ink); font-weight: 700; }

/* · PRODUCTS MENU · the four sibling apps, same <details> as the language switcher.
   The page's own product is marked, not linked. */
.pf-prod-menu { left: 0; right: auto; min-width: 15rem; padding: 4px 0; }
.pf-prod-item {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 14px;
  font-family: var(--font-display);
  color: var(--color-ink);
  transition: background-color .2s ease;
}
.pf-prod-item > span { display: flex; flex-direction: column; line-height: 1.25; }
.pf-prod-item b { font-size: 13px; font-weight: 700; letter-spacing: .01em; }
.pf-prod-item small { font-size: 11px; letter-spacing: .04em; color: var(--color-muted); }
.pf-lang-menu a.pf-prod-item { display: flex; padding: 9px 14px; font-size: inherit; letter-spacing: 0; color: var(--color-ink); }
.pf-prod-menu a.pf-prod-item:hover { background: var(--color-section); }
.pf-prod-item[aria-current="page"] { background: var(--color-section); cursor: default; }
.pf-drawer-prods { display: grid; grid-template-columns: 1fr 1fr; gap: 0 12px; margin-top: 1.25rem; }
.pf-drawer-label {
  grid-column: 1 / -1; margin-bottom: 4px;
  font-family: var(--font-display); font-size: var(--text-xs);
  letter-spacing: .14em; text-transform: uppercase; color: var(--color-muted);
}
.pf-drawer-prods .pf-prod-item { padding: 10px 0; }
.pf-drawer-prods .pf-prod-item[aria-current="page"] { background: none; }
/* the studio that makes all four, set off below them by a rule */
.pf-prod-menu a.pf-prod-studio { border-top: 1px solid var(--color-concrete); margin-top: 4px; padding-top: 11px; }
.pf-drawer-prods .pf-prod-studio { grid-column: 1 / -1; border-top: 1px solid var(--color-concrete); margin-top: 6px; padding-top: 12px; }

/* the address beside the CTA button: a mailto button opens a mail client that
   may not exist, so the address itself has to be readable and copyable. Hover is
   a colour change, like every other link on the page — not a fade. */
.pf-mail-link {
  color: var(--color-ink);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
  text-decoration-color: var(--color-concrete);
  transition: color .2s ease, text-decoration-color .2s ease;
}
.pf-mail-link:hover { color: var(--color-accent-dark); text-decoration-color: var(--color-accent); }

/* the CTA card's own footer: the other ways in */
.pf-cta-channels {
  margin-top: 1.75rem; padding-top: 1.25rem; border-top: 1px solid var(--color-concrete);
  display: flex; flex-wrap: wrap; justify-content: center; gap: .5rem .9rem;
  font-family: var(--font-display); font-size: .875rem; letter-spacing: .02em; color: var(--color-muted);
}

/* the mobile sheet has no room for a dropdown — both languages sit side by side,
   the way the hub's own mobile menu lists them */
.pf-lang-row {
  display: flex; align-items: center; gap: 10px;
  font-family: var(--font-display); font-size: 13px;
}
.pf-lang-row > span { color: var(--color-concrete); }
.pf-lang-row a { color: var(--color-muted); transition: color .2s ease; }
.pf-lang-row a:hover { color: var(--color-ink); }
.pf-lang-row a[aria-current="true"] { color: var(--color-ink); font-weight: 700; }

/* ════════════════════════════════════════════════════════ */
/* · EDGE GUIDES · thin vertical column lines, hero→footer    */
/* (opacity set per-section via --edge-color; hero bolder)    */
/* ════════════════════════════════════════════════════════ */
.pf-edge-guides { position: absolute; inset: 0; pointer-events: none; }
.pf-edge-guides-inner {
  max-width: 90rem; height: 100%; margin: 0 auto;
  border-left: 1px solid var(--edge-color, rgba(30,42,46,.07));
  border-right: 1px solid var(--edge-color, rgba(30,42,46,.07));
}

/* ════════════════════════════════════════════════════════ */
/* · HERO TERMS · the documents the app issues, as drawn objects  */
/* ════════════════════════════════════════════════════════ */
/* A plain strip, not chips: a framed word reads as a button and this row leads nowhere.
   The only colour is the drawn 4px square between the words, in the product hue — the
   same geometry as the hub's service-card item strip. */
.pf-terms {
  display: flex; flex-wrap: wrap; justify-content: center; align-items: center;
  row-gap: .25rem; margin-top: 1.5rem; padding: 0; list-style: none;
}
.pf-terms li {
  font-family: var(--font-display);
  font-size: var(--text-xs);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--color-body);
}
.pf-terms li + li::before {
  content: ''; display: inline-block; width: 4px; height: 4px; margin-inline: .75em;
  background: var(--color-accent); vertical-align: .15em;
}

/* ════════════════════════════════════════════════════════ */
/* · HERO FRAME · the hub's bracket (.hero-rail / .hero-axis), recoloured for a light ground */
/* ════════════════════════════════════════════════════════ */
/* Rails sit .5rem inside the container edge and the text keeps the page spine, as on the hub. */
.pf-hero-frame { --rail: rgba(30,42,46,.28); --rail-strong: rgba(30,42,46,.45); margin-inline: -.75rem; }
/* the page's only "where am I", so it reads at section-rail size, not the hub's 10px annotation */
.pf-hero-frame .hero-axis { color: var(--color-accent-dark); font-size: var(--text-xs); }
@media (min-width: 1024px) {
  .pf-hero-frame .hero-axis { font-size: var(--text-base); }
  .pf-hero-frame .hero-axis::before, .pf-hero-frame .hero-axis::after { height: 13px; }
}
.pf-hero-frame-body { padding: 2.25rem .75rem 2rem; }
.pf-hero-fig {
  margin-top: .75rem; padding-inline: .75rem;
  font-family: var(--font-display); font-size: var(--text-micro); letter-spacing: .2em; text-transform: uppercase;
  color: var(--color-muted);
}
@media (min-width: 640px) {
  .pf-hero-frame { margin-inline: -1.5rem; }
  .pf-hero-frame-body { padding: 2.75rem 1.5rem 2.5rem; }
  .pf-hero-fig { padding-inline: 1.5rem; }
}
/* · SECTION RAIL · the hub's .sec-rail, recoloured for the dark Features ground */
.pf-rail-dark::before, .pf-rail-dark::after { background: var(--color-accent-light); }
.pf-rail-dark .sec-rail-label { color: var(--color-accent-light); }
.pf-rail-dark .sec-rail-num { color: rgba(255,255,255,.55); }
.pf-rail-dark .sec-rail-line { background: rgba(255,255,255,.15); }

/* ════════════════════════════════════════════════════════ */
/* · FAQ ACCORDION · pure HTML, no JS                          */
/* ════════════════════════════════════════════════════════ */
.pf-faq summary { list-style: none; }
.pf-faq summary::-webkit-details-marker { display: none; }
.faq-body {
  overflow: hidden;
  max-height: 0;
  transition: max-height .38s cubic-bezier(.22,1,.36,1);
}
details.pf-faq[open] .faq-body { max-height: 500px; }
.faq-icon { flex-shrink: 0; margin-left: 1.25rem; margin-right: -.5rem; }
.faq-icon::before { content: '+'; }
details.pf-faq[open] summary .faq-icon::before { content: '\2212'; }

/* the OPEN question wears the page's own accent, the way the icon beside it already
   does. accent-DARK, not the raw accent: on the two light hues the raw accent measures
   2.13 and 1.65 on this card's ground, while -dark clears AA on all four
   (9.05 / 9.54 / 4.52 / 4.86). Unlayered, so it beats the summary's text-ink utility. */
details.pf-faq[open] summary { color: var(--color-accent-dark); }
details.pf-faq summary:hover .faq-icon { color: var(--color-accent); }

/* ════════════════════════════════════════════════════════ */
/* · HERO DASHBOARD MOCKUP · sidebar + KPIs + 3-column breakdown */
/* ════════════════════════════════════════════════════════ */

.pf-dash-panel {
  display: flex;
  width: 100%;
  min-height: 480px;
  background: #fff;
  border: 1px solid var(--color-concrete);
  overflow: hidden;
}

/* sidebar — accent-tinted, mirrors the real app's left menu */
.pf-dash-sidebar {
  width: 25%; min-width: 180px; max-width: 240px; flex-shrink: 0;
  background: var(--color-accent-pale);
  border-right: 1px solid var(--color-accent-pale-border);
  display: flex;
  flex-direction: column;
  padding: clamp(16px, 2.2vw, 24px) clamp(10px, 1.4vw, 16px);
}
.pf-dash-mark { display: none; }        /* the collapsed rail's logo, mobile only */
.pf-dash-brand {
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(12px, 1.3vw, 14px); color: var(--color-accent-dark);
  padding: 0 10px; margin-bottom: clamp(12px, 1.8vw, 20px);
}
.pf-dash-nav { display: flex; flex-direction: column; gap: 2px; }
.pf-dash-nav-item {
  font-family: var(--font-display); font-size: clamp(10px, 1.1vw, 12px);
  color: var(--color-muted);
  padding: clamp(6px, 1vw, 9px) 10px;
  border-left: 2px solid transparent;
  display: flex; align-items: center; gap: 8px;
}
.pf-dash-ico { flex-shrink: 0; }
.pf-dash-nav-item.is-active {
  background: linear-gradient(to right, color-mix(in srgb, var(--color-accent) 3%, white), color-mix(in srgb, var(--color-accent-dark) 32%, white));
  color: var(--color-ink); font-weight: 700;
  border-left-color: var(--color-accent);
}
.pf-dash-live {
  margin-top: auto; width: fit-content;
  display: inline-flex; align-items: center; gap: 7px;
  padding: 5px 11px;
  background: #fff; border: 1px solid var(--color-accent-pale-border);
  font-family: var(--font-display); font-size: clamp(9px, 1vw, 10px);
  letter-spacing: .1em; text-transform: uppercase; color: var(--color-muted);
}
.pf-dash-live-dot {
  width: 7px; height: 7px; border-radius: 50%; background: var(--color-accent); flex-shrink: 0;
  animation: pf-live-pulse 2.2s ease-in-out infinite;
}
@keyframes pf-live-pulse {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--color-accent) 55%, transparent); }
  70%  { box-shadow: 0 0 0 6px color-mix(in srgb, var(--color-accent) 0%, transparent); }
  100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--color-accent) 0%, transparent); }
}
@media (prefers-reduced-motion: reduce) { .pf-dash-live-dot { animation: none; } }

.pf-dash-body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  padding: clamp(18px, 2.6vw, 32px);
  gap: clamp(12px, 1.8vw, 18px);
}
.pf-dash-head {
  display: flex; justify-content: space-between;
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(12px, 1.5vw, 16px); letter-spacing: .08em;
  color: var(--color-ink); text-transform: uppercase;
  padding-bottom: 14px; border-bottom: 1px solid var(--color-concrete);
}
.pf-dash-period { color: var(--color-accent-dark); font-weight: 500; letter-spacing: .04em; }
/* the drawn app's primary action — filled with the page's accent, ink from the page's
   own token. Font size and weight are inherited from .pf-dash-head on purpose. */
.pf-dash-cta {
  flex-shrink: 0; display: inline-flex; align-items: center;
  background: var(--color-accent); color: var(--accent-ink);
  padding: 8px 13px; white-space: nowrap;
  text-transform: none; letter-spacing: normal;
}

/* KPI tiles — hero headline numbers */
.pf-dash-kpis { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(10px, 1.6vw, 14px); }
.pf-dash-kpi { border: 1px solid var(--color-concrete); padding: clamp(12px, 1.8vw, 18px); display: flex; flex-direction: column; gap: 6px; }
.pf-dash-kpi-label { font-family: var(--font-display); font-size: clamp(9px, 1vw, 11px); letter-spacing: .1em; text-transform: uppercase; color: var(--color-muted); }
.pf-dash-kpi-value { font-family: var(--font-display); font-weight: 700; font-size: clamp(17px, 2.2vw, 24px); color: var(--color-ink); }

/* 3-column breakdown */
.pf-dash-cols { flex: 1; display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(10px, 1.6vw, 16px); }
.pf-dash-col { border: 1px solid var(--color-concrete); padding: clamp(12px, 1.6vw, 16px); display: flex; flex-direction: column; gap: clamp(10px, 1.5vw, 14px); }
/* The status chips sat wherever the amount beside them happened to end, so four
   rows put them on four different verticals — 850,00 EUR is two characters shorter
   than 1.190,00 EUR and the chip moved with it. The fix belongs to the AMOUNT, not
   the chip: the face is mono and the figures are already tabular, so giving the
   amount the width of its longest value (10 characters x 0.6em) and right-aligning
   it pins the chip column. The chips keep their own widths on purpose — SENT and
   OVERDUE are different words, and a fixed chip box would pad SENT with air. */
.pf-dash-amt { min-width: 6em; text-align: right; }

.pf-dash-col-head { font-family: var(--font-display); font-size: clamp(8px, .9vw, 10px); letter-spacing: .1em; text-transform: uppercase; color: var(--color-muted); }
.pf-dash-item { display: flex; flex-direction: column; gap: 5px; }
.pf-dash-item-top { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; font-family: var(--font-display); }
.pf-dash-item-top span:first-child { font-weight: 700; font-size: clamp(10px, 1.1vw, 12px); color: var(--color-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pf-dash-item-top span:last-child { font-size: clamp(9px, 1vw, 10.5px); color: var(--color-muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.pf-dash-barbg { height: 6px; background: var(--color-concrete); position: relative; overflow: hidden; }
.pf-dash-barfill { position: absolute; inset: 0 auto 0 0; background: var(--color-accent); transform-origin: left center; animation: pf-bar-grow .7s cubic-bezier(.2,.8,.2,1) both; }

/* bars grow in — column by column, ~1s apart */
@keyframes pf-bar-grow { from { transform: scaleX(0); } to { transform: scaleX(1); } }
.pf-dash-col:nth-child(1) .pf-dash-item:nth-child(2) .pf-dash-barfill { animation-delay: .80s; }
.pf-dash-col:nth-child(1) .pf-dash-item:nth-child(3) .pf-dash-barfill { animation-delay: .88s; }
.pf-dash-col:nth-child(1) .pf-dash-item:nth-child(4) .pf-dash-barfill { animation-delay: .96s; }
.pf-dash-col:nth-child(1) .pf-dash-item:nth-child(5) .pf-dash-barfill { animation-delay: 1.04s; }
.pf-dash-col:nth-child(1) .pf-dash-item:nth-child(6) .pf-dash-barfill { animation-delay: 1.12s; }
.pf-dash-col:nth-child(2) .pf-dash-item:nth-child(2) .pf-dash-barfill { animation-delay: 1.80s; }
.pf-dash-col:nth-child(2) .pf-dash-item:nth-child(3) .pf-dash-barfill { animation-delay: 1.88s; }
.pf-dash-col:nth-child(2) .pf-dash-item:nth-child(4) .pf-dash-barfill { animation-delay: 1.96s; }
.pf-dash-col:nth-child(3) .pf-dash-item:nth-child(2) .pf-dash-barfill { animation-delay: 2.80s; }
.pf-dash-col:nth-child(3) .pf-dash-item:nth-child(3) .pf-dash-barfill { animation-delay: 2.88s; }
.pf-dash-col:nth-child(3) .pf-dash-item:nth-child(4) .pf-dash-barfill { animation-delay: 2.96s; }
.pf-dash-col:nth-child(3) .pf-dash-item:nth-child(5) .pf-dash-barfill { animation-delay: 3.04s; }
@media (prefers-reduced-motion: reduce) { .pf-dash-barfill { animation: none; } }

/* size tiers — bigger on large desktop, smaller on laptop */
@media (min-width: 1536px) { .pf-dash-panel { min-height: 580px; } }
@media (max-width: 1279px) { .pf-dash-panel { min-height: 460px; } }

/* short viewports (13" laptops) — shrink so the hero fits without cutting */
@media (max-height: 900px) { .pf-dash-panel { min-height: 420px; } }
@media (max-height: 880px) { .pf-hero-mt { margin-top: 2rem !important; } .pf-hero-section { padding-bottom: 2.25rem !important; } }
@media (max-height: 820px) { .pf-dash-panel { min-height: 360px; } .pf-hero-h1 { font-size: clamp(1.7rem, 3.4vw, 2.7rem) !important; } }

/* mobile — the sidebar COLLAPSES, it does not become a top bar.
   This panel is a drawing of the product, so its architecture is part of what it
   claims: reflowed into a horizontal bar it depicted an app with a nav, which is not
   the app. A real sidebar collapses to a rail of icons, so this one does too. */
@media (max-width: 640px) {
  .pf-dash-panel { min-height: 0; }
  .pf-dash-sidebar {
    width: auto; min-width: 0; max-width: none; flex: 0 0 auto;
    padding: 12px 6px;
  }
  /* the rail's logo is the mark itself, not the name cut down to a letter */
  .pf-dash-brand { margin: 0 0 12px; padding: 0; display: flex; justify-content: center; }
  .pf-dash-brand span { display: none; }
  .pf-dash-mark { display: block; width: 18px; height: 18px; }
  .pf-dash-nav-item { padding: 8px 9px 8px 8px; }
  .pf-dash-ico + span { display: none; }
  .pf-dash-live { display: none; }
  .pf-dash-body { padding: 14px; gap: 12px; }
  /* the rail costs the body ~45px, which is one character too many for three money
     columns: 33.527,20 EUR needs 112px and the cell had 69px, so every value wrapped
     onto its own line. Two columns give it 121px. !important because the column count
     is written inline, per page. */
  .pf-dash-kpis { grid-template-columns: 1fr 1fr !important; }
  /* only where there are exactly three: a two-KPI page must stay a plain pair */
  .pf-dash-kpi:first-child:nth-last-child(3) { grid-column: span 2; }
  .pf-dash-cols { grid-template-columns: 1fr; gap: 12px; }
}

/* ════════════════════════════════════════════════════════ */
/* · FEATURES · infinite marquee                               */
/* (TestSprite card recipe: w-[70vw] sm:380 md:400 lg:500,     */
/* py-[40] sm:60 md:100)                                       */
/* ════════════════════════════════════════════════════════ */
.pf-marquee-viewport { position: relative; overflow: hidden; margin-top: 1rem; border: 1px solid rgba(255,255,255,.1); }
.pf-marquee-track { display: flex; width: max-content; animation: pf-marquee 35s linear infinite; }
@media (hover:hover) and (pointer:fine) { .pf-marquee-viewport:hover .pf-marquee-track { animation-play-state: paused; } }
.pf-marquee-viewport.is-tapped .pf-marquee-track { animation-play-state: paused; }
@keyframes pf-marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }
/* margin, NOT the track's flex `gap`: 8 cards (4 plus their duplicates) give only 7
   gaps, so half the track is 4 cards + 3.5 gaps while the duplicate set starts at
   4 cards + 4 gaps — the -50% loop point landed half a gap short and the seam jumped
   10px every cycle. The hub hit this first and fixed it the same way.
   Heights: one step below the hub's card at each breakpoint, on purpose — the hub's
   body runs ~6 lines plus an item strip, a feature card's runs ~3, so copying its box
   would only reopen the emptiness this change exists to close. */
.pf-feature-card {
  flex-shrink: 0; border-color: rgba(30,42,46,.18);
  min-height: 24rem; margin-right: 1.25rem;
  background-color: var(--color-accent);
  /* Grid on top, a lit patch underneath — and the patch lives ONLY in the card's empty
     upper zone, behind the icon, fading to the flat accent before the title starts.

     That confinement is forced, not styling. Measured on Invoicing: the accent can go
     darker by ~3 lightness points before the far corner drops under 2:1 against the ink
     band and melts into it, and lighter by ~4 before body text falls under 4.5. A
     3-point swing is invisible, so a FULL-card gradient is not available here at all.
     Where there is no body text, there is room.

     Both derive from --accent-ink, which is why this works on four different accents
     instead of only on teal: the site's grid is always drawn in its ground's own ink —
     dark on a light ground, light on a dark one — and a card carrying ink text IS a
     light ground. Measured per page: grid line 4.3 / 2.7 / 2.7 / 2.4 L*, all above the
     ~1.5 where a line starts to be seen; icon on the patch 4.20 / 4.47 / 5.99 / 7.54,
     against the 3.0 a graphic needs. The two ink-text pages come out safer than the
     white-text ones, because their patch darkens and that helps their own text. */
  background-image:
    linear-gradient(to right, color-mix(in srgb, var(--accent-ink) 6%, transparent) 1px, transparent 1px),
    linear-gradient(to bottom, color-mix(in srgb, var(--accent-ink) 6%, transparent) 1px, transparent 1px),
    radial-gradient(ellipse 60% 42% at 22% 4%,
                    color-mix(in srgb, var(--accent-ink) 12%, var(--color-accent)) 0%,
                    var(--color-accent) 100%);
  background-size: 2rem 2rem, 2rem 2rem, cover;
}
.pf-feature-card p { color: rgba(30,42,46,.72) !important; }
/* the card's last row is its item strip. The rule above it derives from --accent-ink,
   so it is a light line on the white-text cards and an ink line on the others — and it
   lives here instead of in eight copies of the same class list per page. */
.pf-feature-card > div:last-child {
  color: rgba(30,42,46,.55) !important;
  margin-top: 1.25rem; padding-top: 1rem;
  border-top: 1px solid color-mix(in srgb, var(--accent-ink) 25%, transparent);
}
/* the strip's square follows its own label instead of being a fixed colour, so it
   cannot drift across four accents and two ink treatments */
.pf-feature-card .svc-items span + span::before { background: currentColor; }
@media (min-width: 640px) { .pf-feature-card { min-height: 26rem; } }
@media (min-width: 1024px) { .pf-feature-card { min-height: 28rem; } }
@media (prefers-reduced-motion: reduce) { .pf-marquee-track { animation: none; } }

/* feature-card icons — same shapes as the hero rail icons, recoloured for dark cards */
/* the icon sits in its own square, same move as the studio's service cards: a frame
   means 'a discrete object'. Ink on an accent-filled card, so the tile mirrors the
   studio's (which is accent on ink) — ink edge, ink wash, radius 0. */
.pf-feat-tile {
  /* the default lives HERE, not on the icon. It used to sit on .pf-feat-icon, which is
     a descendant — so a page setting --feat-ink:#fff on the tile had its value thrown
     away one level down and the icon stayed ink on an accent card: 2.93 on Invoicing's
     teal, 2.74 on Repairs' blue, both under the 3.0 a graphic needs. The white icon
     those pages have been asking for since 11.09 had never once rendered. */
  --feat-ink: var(--color-ink);
  display: flex; align-items: center; justify-content: center;
  width: 3.5rem; height: 3.5rem;
  border: 1px solid var(--feat-edge, rgba(30,42,46,.28));
  background: var(--feat-wash, rgba(30,42,46,.06));
}
/* the icon's colour is a token, not a constant: a page whose card went dark needs the
   drawing to follow the text. Default stays ink, so nothing changes where the card is
   still a light accent fill. */
.pf-feat-icon { position: relative; width: 30px; height: 30px; }
.pf-feat-icon--clock { border: 2.5px solid var(--feat-ink); border-radius: 50%; }
.pf-feat-icon--clock::after {
  content: ''; position: absolute; top: 4px; left: 50%;
  width: 2.5px; height: 9px; background: var(--feat-ink);
  transform-origin: bottom center; transform: translateX(-50%) rotate(35deg);
}
.pf-feat-icon--trend { display: flex; align-items: flex-end; gap: 3px; }
.pf-feat-icon--trend span { width: 6px; background: var(--feat-ink); display: block; }
.pf-feat-icon--trend span:nth-child(1) { height: 10px; }
.pf-feat-icon--trend span:nth-child(2) { height: 18px; }
.pf-feat-icon--trend span:nth-child(3) { height: 28px; }
.pf-feat-icon--doc { border: 2.5px solid var(--feat-ink); padding: 5px 4px; display: flex; flex-direction: column; gap: 3px; justify-content: center; }
.pf-feat-icon--doc span { display: block; height: 2px; background: var(--feat-ink); }
.pf-feat-icon--doc span:nth-child(1) { width: 100%; }
.pf-feat-icon--doc span:nth-child(2) { width: 70%; }
.pf-feat-icon--doc span:nth-child(3) { width: 85%; }
.pf-feat-icon--tiers { display: flex; flex-direction: column; align-items: center; gap: 4px; justify-content: center; }
.pf-feat-icon--tiers span { height: 4px; background: var(--feat-ink); display: block; }
.pf-feat-icon--tiers span:nth-child(1) { width: 26px; }
.pf-feat-icon--tiers span:nth-child(2) { width: 18px; }
.pf-feat-icon--tiers span:nth-child(3) { width: 10px; }

/* ════════════════════════════════════════════════════════ */
/* · CTA + FAQ · ONE photo-backed frame, full width to the     */
/* guides; two equal-height white cards float on top           */
/* (page overrides .pf-cta-frame background-image to add its  */
/* own hero photo as the top layer — a relative url() inside a */
/* custom property resolves against THIS file's path, not the */
/* page's, so it can't be set via a shared --accent-photo var) */
/* ════════════════════════════════════════════════════════ */
.pf-cta-frame {
  position: relative; overflow: hidden;
  margin: 0 -2rem;                 /* bleed to the vertical guides (negates the container's sm:px-8) */
  border: 1px solid var(--color-concrete);
  background-image:
    radial-gradient(circle at 50% 45%, var(--color-accent-light) 0%, var(--color-accent) 20%, var(--color-accent-dark) 42%, color-mix(in srgb, var(--color-accent-dark) 50%, var(--color-ink)) 70%, var(--color-ink) 100%);
  background-size: cover;
  background-position: center;
}
.pf-cta-grid {
  position: absolute; inset: 0; pointer-events: none;
  background-image:
    linear-gradient(to right, rgba(255,255,255,.16) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(255,255,255,.16) 1px, transparent 1px);
  background-size: 48px 48px;
}
.pf-cta-inner {
  position: relative;
  display: grid;
  grid-template-columns: 5fr 7fr;   /* the FAQ carries the content; the CTA is four lines */
  gap: 2rem;
  align-items: start;              /* each card is its own height, photo shows below the short one */
  padding: 4.5rem;                 /* thicker photo margin around the cards */
}
.pf-cta-card, .pf-faq-card {
  background: var(--color-page);
  border: 1px solid var(--color-concrete);
  box-shadow: 0 16px 40px rgba(30,42,46,.18);
  padding: 1.75rem 2rem;
}
.pf-cta-card { display: flex; flex-direction: column; }
@media (max-width: 900px) {
  .pf-cta-inner { grid-template-columns: 1fr; gap: 1.25rem; padding: 1.5rem; }
}
@media (max-width: 640px) {
  .pf-cta-frame { margin: 0 -1.25rem; }   /* mobile container uses px-5 */
  .pf-cta-inner { padding: 1rem; }
  .pf-cta-card, .pf-faq-card { padding: 1.5rem 1.5rem; }
}

/* ════════════════════════════════════════════════════ */
/* · DEMO DIALOG · email request left, app video right   */
/* ════════════════════════════════════════════════════ */
.pf-demo {
  /* ~70% of the screen, never narrower than the two columns need */
  width: min(56rem, max(70vw, 40rem), calc(100vw - 2rem)); max-height: calc(100svh - 4rem);
  margin: auto; padding: 0; border: 1px solid var(--color-concrete);
  background: var(--color-page); color: var(--color-body);
  box-shadow: 0 24px 60px rgba(15,41,28,.35);
}
.pf-demo[open] { display: grid; grid-template-columns: 1fr 1fr; }
.pf-demo::backdrop { background: rgba(15,41,28,.6); }

.pf-demo-body {
  position: relative; display: flex; flex-direction: column; justify-content: safe center;
  padding: 2.25rem 2rem 1.75rem; overflow-y: auto;
}
/* sits on the video pane (right on desktop, top on phones), so it is light */
.pf-demo-close {
  position: absolute; top: .5rem; right: .5rem; z-index: 1; width: 44px; height: 44px;
  font-size: 1.6rem; line-height: 1; color: rgba(255,255,255,.75);
}
.pf-demo-close:hover { color: #fff; }
.pf-demo-kicker {
  font-family: var(--font-display); font-size: .7rem; letter-spacing: .18em; text-transform: uppercase;
  color: var(--color-accent-dark);
}
.pf-demo-title {
  margin-top: .75rem; font-family: var(--font-display); font-weight: 700;
  font-size: clamp(1.35rem, 2.2vw, 1.7rem); line-height: 1.15; letter-spacing: -.02em; color: var(--color-ink);
}
.pf-demo-lead { margin-top: .75rem; font-family: var(--font-display); font-size: .85rem; line-height: 1.6; }

.pf-demo-form { margin: 1.5rem 0 2rem; display: flex; flex-direction: column; }
.pf-demo-close, .pf-demo-send { cursor: pointer; }
.pf-demo-label {
  font-family: var(--font-display); font-size: .75rem; letter-spacing: .12em; text-transform: uppercase;
  color: var(--color-muted);
}
.pf-demo-input {
  margin-top: .4rem; padding: .75rem .9rem; width: 100%;
  font-family: var(--font-display); font-size: .95rem; color: var(--color-ink);
  background: #fff; border: 1px solid var(--color-concrete);
}
.pf-demo-input:focus { outline: 2px solid var(--color-accent); outline-offset: -1px; border-color: var(--color-accent); }
.pf-demo-trap { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; }
.pf-demo-send {
  margin-top: .75rem; padding: .8rem 1.5rem;
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  font-family: var(--font-display); font-size: .875rem; font-weight: 500;
  background: var(--color-accent); color: var(--accent-ink); transition: opacity .2s ease;
}
.pf-demo-send:hover { opacity: .9; }
.pf-demo-send:disabled { opacity: .55; cursor: wait; }
.pf-demo-status { margin-top: .75rem; font-family: var(--font-display); font-size: .85rem; line-height: 1.5; }
.pf-demo-status:empty { display: none; }
.pf-demo-status[data-state="ok"] { color: var(--color-accent-dark); }
.pf-demo-status[data-state="error"] { color: #B42318; }
.pf-demo-form.is-sent .pf-demo-input, .pf-demo-form.is-sent .pf-demo-send, .pf-demo-form.is-sent .pf-demo-label { display: none; }
.pf-demo-note { margin-top: .75rem; font-family: var(--font-display); font-size: .75rem; color: var(--color-muted); }

.pf-demo-alt {
  padding-top: 1.5rem; border-top: 1px solid color-mix(in srgb, var(--color-muted) 45%, var(--color-concrete));
  display: flex; flex-wrap: wrap; align-items: center; gap: .5rem .9rem;
  font-family: var(--font-display); font-size: .8rem; color: var(--color-muted);
}
.pf-demo-account {
  width: 100%; display: inline-flex; align-items: center; justify-content: center; gap: .4rem; padding: .8rem 1.5rem;
  font-size: .875rem; border: 1px solid var(--color-ink); color: var(--color-ink); font-weight: 500;
  transition: background .2s ease, color .2s ease;
}
.pf-demo-account:hover { background: var(--color-ink); color: #fff; }
.pf-demo-alt small { width: 100%; font-size: .75rem; }

.pf-demo-media { background: var(--color-ink); display: flex; align-items: center; justify-content: center; min-height: 0; }
.pf-demo-video { width: 100%; height: 100%; max-height: calc(100svh - 2rem); object-fit: contain; display: block; }

@media (max-width: 720px) {
  .pf-demo[open] { grid-template-columns: 1fr; overflow-y: auto; }
  .pf-demo-media { order: -1; height: 38svh; }
  /* portrait video fills the width, no side bars */
  .pf-demo-video { object-fit: cover; }
  .pf-demo-body { padding: 2rem 1.25rem 1.5rem; overflow: visible; }
}
@media (prefers-reduced-motion: reduce) { .pf-demo-send, .pf-demo-account { transition: none; } }
