/* ==========================================================================
   L4web — design system
   Hand-written, no framework, no build step.
   Sections: 1 tokens · 2 reset · 3 layout · 4 type · 5 components
             6 header · 7 hero · 8 sections · 9 forms · 10 footer · 11 motion
   ========================================================================== */

/* --- 1. Tokens ----------------------------------------------------------- */

:root {
  /* Ink — the canvas and the surfaces that sit on it.
     Not a neutral black: two or three points of green run through it, so the
     brand colour reads as native to the page rather than dropped onto it. */
  --ink:        #080a08;
  --ink-2:      #0e110d;
  --ink-3:      #151a14;

  /* Type — warm-neutral rather than the usual blue-grey, to sit with the green */
  --porcelain:  #eff1ec;   /* 17.5:1 */
  --muted:      #95998f;   /*  6.8:1 */
  --muted-dim:  #7f8479;   /*  5.1:1 — captions and the consent text are still
                                body copy, so this has to clear AA too */

  /* --brand is L4web's logo green and carries every interactive state:
     links, focus rings, buttons, eyebrows, numerals, lace nodes.
     --linen is the craft accent — unbleached thread against a leaf.
     Named by role, not by hue, so a future rebrand is a two-line change. */
  --brand:      #6cbb23;   /* 8.3:1 on --ink */
  --brand-lit:  #85d43c;   /* hover / links       */
  --brand-deep: #1d3410;   /* tinted surfaces     */
  --linen:      #c4b49a;   /* 9.8:1 on --ink      */

  /* Green is bright enough that white text on it fails WCAG (2.4:1).
     Anything sitting ON the brand colour uses ink instead — 8.3:1. */
  --on-brand:   #061006;

  --line:       rgb(239 241 236 / 9%);
  --line-lit:   rgb(239 241 236 / 18%);

  /* --- Koronka klockowa ---------------------------------------------------
     Bobowa is Poland's bobbin-lace town, and the whole background system is
     built from the real vocabulary of that craft rather than a generic grid:

       --lace        siatka   — the net ground. Every thread is a *twisted
                               pair*, which is why each line is doubled.
       --lace-rosette rozeta  — a full medallion: rings, radial bundles,
                               pajączki (spiders) and a picot edge.
       --lace-tape   taśma    — a torchon edging that tiles horizontally.

     The two larger motifs are separate files so they can be edited and
     previewed on their own; see README, "Koronka klockowa". */

  --lace: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='44' height='44'%3E%3Cg stroke='%23c4b49a' fill='none' stroke-linecap='round'%3E%3Cpath d='M0 0 44 44M44 0 0 44' stroke-width='.55' opacity='.55'/%3E%3Cpath d='M0 2.6 41.4 44M2.6 0 44 41.4M44 2.6 2.6 44M41.4 0 0 41.4' stroke-width='.4' opacity='.3'/%3E%3C/g%3E%3Cg fill='%23c4b49a' opacity='.85'%3E%3Ccircle cx='22' cy='22' r='1'/%3E%3Ccircle cx='0' cy='0' r='1'/%3E%3Ccircle cx='44' cy='0' r='1'/%3E%3Ccircle cx='0' cy='44' r='1'/%3E%3Ccircle cx='44' cy='44' r='1'/%3E%3C/g%3E%3C/svg%3E");

  --lace-rosette: url("/assets/img/lace-medallion.svg");
  --lace-tape:    url("/assets/img/lace-tape.svg");

  /* Faces. No webfont is loaded on purpose — see README before adding one.
     Display leans on the system's tightest grotesque; mono does the
     technical talking (eyebrows, metrics, labels). */
  --font-display: -apple-system, "SF Pro Display", "Segoe UI Variable Display",
                  "Segoe UI", Inter, Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-body:    -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto,
                  "Helvetica Neue", Arial, sans-serif;
  --font-mono:    ui-monospace, "SF Mono", "Cascadia Mono", "JetBrains Mono",
                  Menlo, Consolas, monospace;

  /* Fluid scale — one clamp per step, no breakpoint juggling */
  --t-display: clamp(2.75rem, 1.1rem + 6.6vw, 6.25rem);
  --t-h2:      clamp(1.9rem,  1.1rem + 2.7vw, 3.4rem);
  --t-h3:      clamp(1.15rem, 1.05rem + 0.4vw, 1.35rem);
  --t-lead:    clamp(1.06rem, 0.99rem + 0.35vw, 1.3rem);
  --t-body:    clamp(1rem,    0.97rem + 0.16vw, 1.09rem);
  --t-small:   0.875rem;
  --t-label:   0.72rem;

  --shell:  1280px;
  --gutter: clamp(1.25rem, 4vw, 3rem);
  --pad-section: clamp(4.5rem, 9vw, 9rem);

  --r-sm: 4px;
  --r:    10px;
  --r-lg: 18px;

  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* --- 2. Reset ------------------------------------------------------------ */

*, *::before, *::after { box-sizing: border-box; }

* { margin: 0; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 6rem;
}

body {
  background: var(--ink);
  color: var(--porcelain);
  font-family: var(--font-body);
  font-size: var(--t-body);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

img, svg, video { display: block; max-width: 100%; height: auto; }
button, input, select, textarea { font: inherit; color: inherit; }
ul, ol { list-style: none; padding: 0; }

a { color: inherit; text-decoration: none; }

:focus-visible {
  outline: 2px solid var(--brand-lit);
  outline-offset: 3px;
  border-radius: var(--r-sm);
}

::selection { background: var(--brand); color: var(--on-brand); }

.skip {
  position: absolute;
  left: var(--gutter);
  top: -100px;
  z-index: 200;
  padding: 0.75rem 1.25rem;
  background: var(--porcelain);
  color: var(--ink);
  border-radius: var(--r);
  font-weight: 600;
  transition: top 0.18s var(--ease);
}
.skip:focus { top: 1rem; }

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* --- 3. Layout ----------------------------------------------------------- */

.shell {
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section { padding-block: var(--pad-section); position: relative; }
/* Two plain sections in a row would otherwise stack a double gap. A ruled
   section keeps its own top padding, so it is excluded here rather than
   fighting this rule on specificity. */
.section + .section:not(.section--ruled) { padding-top: 0; }
.section--ruled { border-top: 1px solid var(--line); }
.page-head + .section { padding-top: clamp(2rem, 4vw, 3.5rem); }

/* A full rozeta behind a section. Used on "O nas", where the copy actually
   explains the koronka klockowa — the graphic and the text say the same thing.
   isolation:isolate keeps the z-index:-1 layer inside this section. */
.section--lace { isolation: isolate; overflow: hidden; }
/* Bottom-left, bleeding off both edges. That corner is empty — the heading
   sits above it and the prose is in the right-hand column — so the rozeta
   fills dead space instead of sitting under the text. */
.section--lace::before {
  content: "";
  position: absolute;
  left: clamp(-11rem, -6vw, -4rem);
  bottom: clamp(-11rem, -6vw, -4rem);
  inline-size: min(30rem, 70vw);
  aspect-ratio: 1;
  background: var(--lace-rosette) center / contain no-repeat;
  opacity: 0.42;
  z-index: -1;
  pointer-events: none;
}
@media (width < 60rem) {
  /* Single column here, so the prose drops over it — fade it right back */
  .section--lace::before { left: -30%; bottom: -22%; opacity: 0.2; }
}

.section__head {
  display: grid;
  gap: 1.25rem 3rem;
  margin-bottom: clamp(2.5rem, 5vw, 4rem);
}
@media (width >= 60rem) {
  .section__head { grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr); align-items: end; }
}

.stack   { display: grid; gap: 1.25rem; }
.cluster { display: flex; flex-wrap: wrap; gap: 0.75rem; align-items: center; }

/* --- 4. Type ------------------------------------------------------------- */

.eyebrow {
  font-family: var(--font-mono);
  font-size: var(--t-label);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--linen);
  display: flex;
  align-items: center;
  gap: 0.7rem;
}
.eyebrow::before {
  content: "";
  inline-size: 1.75rem;
  block-size: 1px;
  background: currentColor;
  opacity: 0.65;
  flex: none;
}
.eyebrow--plain::before { content: none; }

.display {
  font-family: var(--font-display);
  font-size: var(--t-display);
  font-weight: 800;
  line-height: 0.94;
  letter-spacing: -0.035em;
  text-wrap: balance;
}

h2, .h2 {
  font-family: var(--font-display);
  font-size: var(--t-h2);
  font-weight: 750;
  line-height: 1.03;
  letter-spacing: -0.025em;
  text-wrap: balance;
}

h3, .h3 {
  font-family: var(--font-display);
  font-size: var(--t-h3);
  font-weight: 650;
  line-height: 1.25;
  letter-spacing: -0.012em;
}

.lead {
  font-size: var(--t-lead);
  line-height: 1.55;
  color: var(--muted);
  max-width: 58ch;
  text-wrap: pretty;
}

.prose { color: var(--muted); max-width: 68ch; }
.prose p + p { margin-top: 1rem; }
.prose strong { color: var(--porcelain); font-weight: 600; }
.prose a { color: var(--brand-lit); text-decoration: underline; text-underline-offset: 3px; }

.mono {
  font-family: var(--font-mono);
  font-size: var(--t-label);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted-dim);
}

/* --- 5. Components ------------------------------------------------------- */

.btn {
  --btn-bg: transparent;
  --btn-fg: var(--porcelain);
  --btn-bd: var(--line-lit);
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.85rem 1.5rem;
  background: var(--btn-bg);
  color: var(--btn-fg);
  border: 1px solid var(--btn-bd);
  border-radius: 100px;
  font-size: var(--t-small);
  font-weight: 600;
  letter-spacing: -0.01em;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.2s var(--ease), border-color 0.2s var(--ease),
              color 0.2s var(--ease), transform 0.2s var(--ease);
}
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0); }
.btn svg { flex: none; }

.btn--primary {
  --btn-bg: var(--brand);
  --btn-fg: var(--on-brand);
  --btn-bd: var(--brand);
}
.btn--primary:hover { --btn-bg: var(--brand-lit); --btn-bd: var(--brand-lit); }

.btn--ghost:hover { --btn-bd: var(--porcelain); }

.btn--lg { padding: 1rem 1.85rem; font-size: 0.95rem; }

/* Arrow link — the default way to leave a card */
.arrow {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-family: var(--font-mono);
  font-size: var(--t-label);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--brand-lit);
}
.arrow::after {
  content: "→";
  transition: transform 0.2s var(--ease);
}
.arrow:hover::after { transform: translateX(4px); }

.card {
  position: relative;
  padding: clamp(1.5rem, 2.5vw, 2rem);
  background: var(--ink-2);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  transition: border-color 0.25s var(--ease), background 0.25s var(--ease);
}
.card:hover { border-color: var(--line-lit); background: var(--ink-3); }

.tag {
  display: inline-block;
  padding: 0.28rem 0.6rem;
  border: 1px solid var(--line-lit);
  border-radius: var(--r-sm);
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
}
.tag--linen { color: var(--linen); border-color: rgb(196 180 154 / 38%); }

/* --- 6. Header ----------------------------------------------------------- */

.header {
  position: sticky;
  top: 0;
  z-index: 100;
  border-bottom: 1px solid transparent;
  background: rgb(8 10 8 / 0%);
  transition: background 0.3s var(--ease), border-color 0.3s var(--ease);
}
.header[data-stuck="true"] {
  background: rgb(8 10 8 / 82%);
  backdrop-filter: blur(14px) saturate(140%);
  border-bottom-color: var(--line);
}

.header__inner {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  min-height: 4.5rem;
}

.brand {
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: 800;
  letter-spacing: -0.03em;
  margin-right: auto;
  display: inline-flex;
  align-items: baseline;
  gap: 0.1em;
}
.brand b { color: var(--brand); font-weight: 800; }

.nav { display: none; }
@media (width >= 62rem) {
  .nav { display: flex; gap: 1.75rem; }
}
.nav a {
  font-size: var(--t-small);
  font-weight: 500;
  color: var(--muted);
  position: relative;
  padding-block: 0.4rem;
  transition: color 0.2s var(--ease);
}
.nav a:hover, .nav a[aria-current] { color: var(--porcelain); }
.nav a[aria-current]::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  block-size: 1px;
  background: var(--brand);
}

/* Language switch — two static files, no client-side i18n */
.lang {
  display: flex;
  align-items: center;
  font-family: var(--font-mono);
  font-size: var(--t-label);
  letter-spacing: 0.08em;
  border: 1px solid var(--line-lit);
  border-radius: 100px;
  overflow: hidden;
}
.lang a {
  padding: 0.4rem 0.7rem;
  color: var(--muted-dim);
  transition: color 0.2s var(--ease), background 0.2s var(--ease);
}
.lang a:hover { color: var(--porcelain); }
.lang a[aria-current] { background: var(--porcelain); color: var(--ink); }

/* Scoped to the bar, not the whole header — the drawer holds a button too */
.header__inner .btn { display: none; }
@media (width >= 48rem) { .header__inner .btn { display: inline-flex; } }

.burger {
  display: inline-grid;
  place-items: center;
  inline-size: 2.5rem;
  block-size: 2.5rem;
  background: none;
  border: 1px solid var(--line-lit);
  border-radius: 100px;
  cursor: pointer;
}
@media (width >= 62rem) { .burger { display: none; } }
.burger span {
  inline-size: 1rem;
  block-size: 1px;
  background: var(--porcelain);
  position: relative;
  transition: background 0.2s var(--ease);
}
.burger span::before, .burger span::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  block-size: 1px;
  background: var(--porcelain);
  transition: transform 0.25s var(--ease);
}
.burger span::before { top: -5px; }
.burger span::after  { top: 5px; }
.burger[aria-expanded="true"] span { background: transparent; }
.burger[aria-expanded="true"] span::before { transform: translateY(5px) rotate(45deg); }
.burger[aria-expanded="true"] span::after  { transform: translateY(-5px) rotate(-45deg); }

.drawer {
  position: fixed;
  inset: 4.5rem 0 auto;
  z-index: 99;
  background: rgb(8 10 8 / 97%);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--line);
  padding: 1.5rem var(--gutter) 2.5rem;
  display: grid;
  gap: 0.25rem;
}
.drawer[hidden] { display: none; }
/* :not(.btn) so the drawer's call to action keeps its own pill styling */
.drawer a:not(.btn) {
  padding: 0.9rem 0;
  border-bottom: 1px solid var(--line);
  font-family: var(--font-display);
  font-size: 1.4rem;
  font-weight: 650;
  letter-spacing: -0.02em;
}
.drawer .btn { margin-top: 1.25rem; justify-content: center; }

/* --- 7. Hero ------------------------------------------------------------- */

.hero {
  position: relative;
  padding-block: clamp(3.5rem, 8vw, 7rem) clamp(4rem, 8vw, 7rem);
  isolation: isolate;
  /* The rosette is positioned past the right edge on purpose, which would
     otherwise widen the document by up to 120px on a phone. `overflow: clip`
     removes that scrollable overflow — clip-path does not, and
     overflow-clip-margin leaks exactly its own width. Keep it at 0. */
  overflow: clip;
}

/* The lattice fades out as it falls, so the type never fights it. Starts at
   the hero's top edge rather than bleeding upward, because the clip above
   would cut the bleed anyway. */
.hero::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  block-size: min(120%, 60rem);
  background-image: var(--lace);
  opacity: 0.16;
  z-index: -2;
  mask-image: radial-gradient(115% 78% at 78% 0%, #000 8%, transparent 68%);
  pointer-events: none;
}
/* A rozeta bleeding off the top-right corner, lit from behind by the brand
   glow. Deliberately cropped: a lace medallion is usually seen as part of a
   larger piece, not centred like a logo. */
.hero::after {
  content: "";
  position: absolute;
  inset: -22% -14% auto auto;
  inline-size: min(46rem, 92vw);
  aspect-ratio: 1;
  background:
    var(--lace-rosette) center / contain no-repeat,
    radial-gradient(circle, rgb(108 187 35 / 14%) 0%, transparent 62%);
  opacity: 0.55;
  z-index: -1;
  pointer-events: none;
}
@media (width < 48rem) {
  /* On a phone the rosette would sit right under the headline. Shrink it and
     push it further out so it stays texture rather than clutter. */
  .hero::after { inset: -16% -32% auto auto; inline-size: 28rem; opacity: 0.4; }
}

.hero__grid {
  display: grid;
  gap: clamp(2.5rem, 5vw, 4rem);
  align-items: start;
}
@media (width >= 64rem) {
  .hero__grid { grid-template-columns: minmax(0, 1.35fr) minmax(19rem, 0.65fr); }
}

.hero .display { margin-block: 1.5rem 1.75rem; }
.hero .display em {
  font-style: normal;
  color: var(--brand-lit);
}

/* Live performance readout — the site measures itself instead of claiming */
.metrics {
  border: 1px solid var(--line-lit);
  border-radius: var(--r-lg);
  background: linear-gradient(180deg, var(--ink-3), var(--ink-2));
  overflow: hidden;
}
.metrics__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.9rem 1.25rem;
  border-bottom: 1px solid var(--line);
  font-family: var(--font-mono);
  font-size: var(--t-label);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}
.pulse {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  color: var(--brand);
}
.pulse::before {
  content: "";
  inline-size: 6px;
  block-size: 6px;
  border-radius: 50%;
  background: currentColor;
  animation: pulse 2.4s var(--ease) infinite;
}
@keyframes pulse {
  0%, 100% { opacity: 1; box-shadow: 0 0 0 0 rgb(108 187 35 / 45%); }
  50%      { opacity: 0.6; box-shadow: 0 0 0 6px rgb(108 187 35 / 0%); }
}

.metrics__list { display: grid; }
.metric {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  gap: 0.75rem;
  padding: 0.95rem 1.25rem;
}
.metric + .metric { border-top: 1px solid var(--line); }
.metric dt { font-size: var(--t-small); color: var(--muted); }
.metric dd {
  font-family: var(--font-mono);
  font-size: 1.35rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--porcelain);
  letter-spacing: -0.02em;
}
.metric dd small {
  font-size: 0.72rem;
  font-weight: 400;
  color: var(--muted-dim);
  margin-left: 0.15rem;
}
.metric[data-good="true"] dd { color: var(--brand); }

.metrics__note {
  padding: 0.85rem 1.25rem;
  border-top: 1px solid var(--line);
  font-size: 0.76rem;
  line-height: 1.5;
  color: var(--muted-dim);
  background: rgb(8 10 8 / 55%);
}

/* --- 8. Sections --------------------------------------------------------- */

/* Marquee-free proof strip: plain facts, evenly weighted */
.facts {
  display: grid;
  gap: 1px;
  background: var(--line);
  border-block: 1px solid var(--line);
}
@media (width >= 40rem) { .facts { grid-template-columns: repeat(2, 1fr); } }
@media (width >= 64rem) { .facts { grid-template-columns: repeat(4, 1fr); } }
.fact { background: var(--ink); padding: 1.75rem clamp(1rem, 2vw, 1.75rem); }
.fact dt { font-family: var(--font-mono); font-size: var(--t-label); letter-spacing: 0.12em;
           text-transform: uppercase; color: var(--muted-dim); margin-bottom: 0.5rem; }
.fact dd { font-family: var(--font-display); font-size: 1.3rem; font-weight: 700;
           letter-spacing: -0.02em; line-height: 1.25; }

/* Services, grouped by the divisions that actually exist */
.divisions { display: grid; gap: 1.25rem; }
/* Two divisions, so two columns with room to breathe. Add a third fraction
   here if a division is ever added back. */
@media (width >= 56rem) { .divisions { grid-template-columns: repeat(2, 1fr); gap: 2.5rem; } }

.division { display: grid; gap: 1.25rem; align-content: start; }
.division__title { display: flex; align-items: center; gap: 0.75rem; }
.division h3 { font-family: var(--font-mono); font-size: 0.82rem; letter-spacing: 0.14em;
               text-transform: uppercase; font-weight: 600; }
.division:nth-child(1) h3 { color: var(--brand-lit); }
.division:nth-child(2) h3 { color: var(--linen); }
.division__desc { font-size: var(--t-small); color: var(--muted-dim); }

.services { display: grid; gap: 1px; background: var(--line); border-radius: var(--r); overflow: hidden; }
.services > li { background: var(--ink-2); }
/* Direct children only — the row holds an inner <span> that must not inherit
   the row's padding and flex layout. */
.services > li > a, .services > li > span {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.85rem 1.1rem;
  font-size: var(--t-small);
  transition: background 0.2s var(--ease), color 0.2s var(--ease);
}
.services > li > a:hover { background: var(--ink-3); color: var(--brand-lit); }

/* Process — the one place a numeral is honest, because order matters */
.steps { display: grid; gap: 1px; background: var(--line); border-block: 1px solid var(--line); }
@media (width >= 52rem) { .steps { grid-template-columns: repeat(2, 1fr); } }
@media (width >= 76rem) { .steps { grid-template-columns: repeat(4, 1fr); } }

.step {
  background: var(--ink);
  padding: 2rem clamp(1.25rem, 2vw, 2rem) 2.25rem;
  display: grid;
  gap: 0.85rem;
  align-content: start;
  position: relative;
}
.step__n {
  font-family: var(--font-mono);
  font-size: var(--t-label);
  letter-spacing: 0.14em;
  color: var(--linen);
}
.step p { font-size: var(--t-small); color: var(--muted); }
.step__when { font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.1em;
              text-transform: uppercase; color: var(--muted-dim); }

/* Work — spec-sheet cards; a screenshot slot is optional, see README */
.work { display: grid; gap: 1.25rem; }
@media (width >= 44rem) { .work { grid-template-columns: repeat(2, 1fr); } }
@media (width >= 68rem) { .work { grid-template-columns: repeat(3, 1fr); } }

/* min-width:0 stops the grid track being widened by the card's min-content,
   and the meta row wraps so a long domain plus its tag can't force it. */
.project { display: grid; gap: 1rem; align-content: start; min-width: 0; }
.project__meta { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 0.5rem 1rem; }
.project__name {
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 750;
  letter-spacing: -0.03em;
}
.project__name span { color: var(--muted-dim); font-weight: 400; }
.project p { font-size: var(--t-small); color: var(--muted); }
.project__shot {
  aspect-ratio: 16 / 10;
  border-radius: var(--r);
  border: 1px solid var(--line);
  background:
    linear-gradient(135deg, rgb(108 187 35 / 12%), transparent 55%),
    var(--lace) 0 0 / 72px 72px,
    var(--ink-3);
  background-blend-mode: normal, soft-light, normal;
}
.project a.project__link::after { content: ""; position: absolute; inset: 0; border-radius: inherit; }

/* --- Google reviews -------------------------------------------------------
   The whole section starts `hidden` and is only revealed once there is
   something real to show — an empty testimonials block is worse than none. */

.reviews { display: grid; gap: 1.25rem; }
@media (width >= 48rem) { .reviews { grid-template-columns: repeat(2, 1fr); } }
@media (width >= 70rem) { .reviews { grid-template-columns: repeat(3, 1fr); } }

.review {
  display: grid;
  gap: 1rem;
  align-content: start;
  padding: clamp(1.4rem, 2.5vw, 1.9rem);
  background: var(--ink-2);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  min-width: 0;
}

.review__stars { display: flex; gap: 0.15rem; color: var(--brand); }
.review__stars svg { inline-size: 1rem; block-size: 1rem; flex: none; }
.review__stars [data-off] { color: var(--muted-dim); }

.review__text {
  font-size: var(--t-small);
  line-height: 1.65;
  color: var(--porcelain);
  /* Long reviews are clamped so the grid stays even; the full text is one
     click away on the profile. */
  display: -webkit-box;
  -webkit-line-clamp: 7;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.review__by { display: flex; align-items: center; gap: 0.75rem; margin-top: auto; }
.review__avatar {
  inline-size: 2.25rem; block-size: 2.25rem;
  border-radius: 50%; flex: none;
  background: var(--ink-3);
  object-fit: cover;
}
.review__initials {
  display: grid; place-items: center;
  inline-size: 2.25rem; block-size: 2.25rem;
  border-radius: 50%; flex: none;
  background: var(--ink-3);
  border: 1px solid var(--line-lit);
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--linen);
}
.review__who { display: grid; gap: 0.1rem; min-width: 0; }
.review__who strong { font-size: var(--t-small); font-weight: 600; }
.review__who span {
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted-dim);
}

/* Aggregate score beside the section heading */
.reviews-score { display: flex; align-items: baseline; gap: 0.6rem; flex-wrap: wrap; margin-top: 1rem; }
.reviews-score b {
  font-family: var(--font-display);
  font-size: 2.25rem;
  font-weight: 800;
  letter-spacing: -0.03em;
  color: var(--brand);
}
.reviews-score span { font-size: var(--t-small); color: var(--muted); }

/* Service area — one card per town where a site of ours is actually live.
   Local SEO that points at real work rather than a list of city names. */
.places { display: grid; gap: 1px; background: var(--line); border: 1px solid var(--line);
          border-radius: var(--r-lg); overflow: hidden; }
@media (width >= 40rem) { .places { grid-template-columns: repeat(2, 1fr); } }
@media (width >= 64rem) { .places { grid-template-columns: repeat(3, 1fr); } }

.places > li { background: var(--ink-2); }
.places a {
  display: grid;
  gap: 0.3rem;
  align-content: start;
  padding: 1.4rem clamp(1.1rem, 2vw, 1.5rem);
  block-size: 100%;
  transition: background 0.2s var(--ease);
}
.places a:hover { background: var(--ink-3); }
.places strong {
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: 700;
  letter-spacing: -0.02em;
}
.places em {
  font-style: normal;
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted-dim);
}
.places span { font-size: var(--t-small); color: var(--muted); margin-top: 0.35rem; }
.places a:hover span { color: var(--brand-lit); }

.places__radius {
  margin-top: 1.5rem;
  font-size: var(--t-small);
  color: var(--muted-dim);
  max-width: 74ch;
}
.places__radius b { color: var(--muted); font-weight: 500; }

/* Reasons — asymmetric, so it doesn't read as a feature grid */
.reasons { display: grid; gap: 1px; background: var(--line); border: 1px solid var(--line);
           border-radius: var(--r-lg); overflow: hidden; }
@media (width >= 54rem) { .reasons { grid-template-columns: repeat(2, 1fr); } }
.reason { background: var(--ink-2); padding: clamp(1.75rem, 3vw, 2.5rem); display: grid;
          gap: 0.9rem; align-content: start; }
.reason__ix { font-family: var(--font-mono); font-size: var(--t-label); letter-spacing: 0.14em;
              color: var(--muted-dim); }
.reason p { font-size: var(--t-small); color: var(--muted); }

/* FAQ */
.faq { display: grid; border-top: 1px solid var(--line); }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  padding: 1.4rem 0;
  cursor: pointer;
  list-style: none;
  font-family: var(--font-display);
  font-size: clamp(1.05rem, 1rem + 0.35vw, 1.25rem);
  font-weight: 650;
  letter-spacing: -0.015em;
  transition: color 0.2s var(--ease);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary:hover { color: var(--brand-lit); }
.faq summary::after {
  content: "+";
  font-family: var(--font-mono);
  font-size: 1.4rem;
  font-weight: 300;
  color: var(--brand);
  flex: none;
  transition: transform 0.25s var(--ease);
}
.faq details[open] summary::after { transform: rotate(45deg); }
.faq details p { padding-bottom: 1.5rem; color: var(--muted); max-width: 72ch; font-size: var(--t-small); }

/* Closing call to action */
.cta-band {
  position: relative;
  border: 1px solid var(--line-lit);
  border-radius: var(--r-lg);
  padding: clamp(2.5rem, 6vw, 4.5rem);
  background: linear-gradient(140deg, var(--ink-3), var(--ink-2) 60%);
  overflow: hidden;
  display: grid;
  gap: 1.75rem;
  justify-items: start;
}
.cta-band::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: var(--lace);
  opacity: 0.12;
  mask-image: linear-gradient(250deg, #000, transparent 55%);
  pointer-events: none;
}
.cta-band > * { position: relative; }

/* --- 9. Forms ------------------------------------------------------------ */

.contact-grid { display: grid; gap: clamp(2.5rem, 5vw, 4rem); align-items: start; }
@media (width >= 62rem) { .contact-grid { grid-template-columns: minmax(0, 1.1fr) minmax(17rem, 0.6fr); } }

.form { display: grid; gap: 1.1rem; }
.field { display: grid; gap: 0.45rem; }
.field label { font-family: var(--font-mono); font-size: var(--t-label); letter-spacing: 0.1em;
               text-transform: uppercase; color: var(--muted); }
.field label .req { color: var(--brand); }

.input {
  inline-size: 100%;
  padding: 0.85rem 1rem;
  background: var(--ink-2);
  border: 1px solid var(--line-lit);
  border-radius: var(--r);
  color: var(--porcelain);
  transition: border-color 0.2s var(--ease), background 0.2s var(--ease);
}
.input::placeholder { color: var(--muted-dim); }
.input:hover { border-color: rgb(238 241 246 / 26%); }
.input:focus { border-color: var(--brand); outline: none; background: var(--ink-3); }
.input:user-invalid { border-color: #ff7a7a; }
textarea.input { min-block-size: 8rem; resize: vertical; }
select.input { appearance: none; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' fill='none' stroke='%2395998f' stroke-width='1.5'%3E%3Cpath d='M1 1l5 5 5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 1rem center; padding-right: 2.5rem; }

.field-row { display: grid; gap: 1.1rem; }
@media (width >= 34rem) { .field-row { grid-template-columns: 1fr 1fr; } }

.consent { display: grid; grid-template-columns: auto 1fr; gap: 0.75rem; align-items: start; }
.consent input { inline-size: 1.1rem; block-size: 1.1rem; margin-top: 0.25rem; accent-color: var(--brand); }
.consent span { font-size: 0.8rem; line-height: 1.55; color: var(--muted-dim); }
.consent a { color: var(--muted); text-decoration: underline; text-underline-offset: 2px; }

/* Honeypot — never shown, never announced */
.pot { position: absolute; left: -9999px; opacity: 0; pointer-events: none; }

.form__status {
  padding: 0.85rem 1.1rem;
  border-radius: var(--r);
  font-size: var(--t-small);
  border: 1px solid var(--line-lit);
  background: var(--ink-2);
}
.form__status[hidden] { display: none; }
.form__status[data-state="ok"]   { border-color: rgb(108 187 35 / 45%); color: var(--brand); }
.form__status[data-state="fail"] { border-color: rgb(255 122 122 / 45%); color: #ff9b9b; }

.contact-details { display: grid; gap: 1.5rem; align-content: start; }
.contact-details dl { display: grid; gap: 0.3rem; }
.contact-details dt { font-family: var(--font-mono); font-size: var(--t-label);
                      letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted-dim); }
.contact-details dd a { font-size: 1.05rem; font-weight: 600; }
.contact-details dd a:hover { color: var(--brand-lit); }
/* Beats the rule above, which would otherwise render the directions link at
   phone-number size instead of as a mono label. */
.contact-details dd a.arrow { font-family: var(--font-mono); font-size: var(--t-label);
                              letter-spacing: 0.1em; }

/* --- 10. Footer ---------------------------------------------------------- */

/* The footer is edged with a real torchon lace tape instead of a hairline.
   An edging is what this kind of lace is actually for, so it is the one place
   the motif is used at full strength. */
.footer {
  position: relative;
  border-top: 1px solid var(--line);
  padding-block: calc(clamp(3rem, 6vw, 4.5rem) + 2.5rem) 2rem;
  margin-top: var(--pad-section);
}
.footer::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  block-size: 62px;
  /* Scaled up from the 46px source so the pajączki stay legible as lace
     rather than collapsing into a texture. */
  background: var(--lace-tape) repeat-x left top / auto 62px;
  opacity: 0.55;
  pointer-events: none;
}
.footer__grid { display: grid; gap: 2.5rem; }
@media (width >= 56rem) { .footer__grid { grid-template-columns: 1.4fr 1fr 1fr 1.2fr; } }
.footer h2 { font-size: var(--t-label); font-family: var(--font-mono); letter-spacing: 0.14em;
             text-transform: uppercase; color: var(--muted-dim); font-weight: 500; margin-bottom: 1rem; }
.footer ul { display: grid; gap: 0.6rem; }
.footer a { font-size: var(--t-small); color: var(--muted); transition: color 0.2s var(--ease); }
.footer a:hover { color: var(--porcelain); }
/* Beats `.footer a` on specificity so the wordmark keeps its size and colour */
.footer a.brand { font-size: 1.15rem; color: var(--porcelain); }
.footer address { font-style: normal; font-size: var(--t-small); color: var(--muted); line-height: 1.8; }
/* Registration numbers are reference data, not contact details — set in mono
   and dimmed so they read as a record rather than something to act on. */
.footer__reg {
  margin-top: 1rem;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  line-height: 1.9;
  color: var(--muted-dim);
}

.footer__bar {
  margin-top: clamp(2.5rem, 5vw, 4rem);
  padding-top: 1.5rem;
  border-top: 1px solid var(--line);
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 2rem;
  justify-content: space-between;
  align-items: center;
  font-size: 0.78rem;
  color: var(--muted-dim);
}
.footer__built { font-family: var(--font-mono); letter-spacing: 0.06em; }
.footer__built b { color: var(--brand); font-weight: 500; }

.socials { display: flex; gap: 0.5rem; }
.socials a {
  display: grid;
  place-items: center;
  inline-size: 2.25rem;
  block-size: 2.25rem;
  border: 1px solid var(--line-lit);
  border-radius: 50%;
  transition: border-color 0.2s var(--ease), color 0.2s var(--ease);
}
.socials a:hover { border-color: var(--porcelain); color: var(--porcelain); }

/* --- 11. Motion ---------------------------------------------------------- */

/* One reveal primitive, driven by IntersectionObserver. Elements are visible
   by default so the page still reads correctly if the script never runs. */
.js [data-reveal] {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 0.6s var(--ease), transform 0.6s var(--ease);
  transition-delay: var(--d, 0ms);
}
.js [data-reveal].is-in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .js [data-reveal] { opacity: 1; transform: none; }
}

/* --- Inner page header --------------------------------------------------- */

.page-head { padding-block: clamp(3rem, 7vw, 5.5rem) clamp(2.5rem, 5vw, 4rem); position: relative; }
.page-head::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  block-size: 100%;
  background-image: var(--lace);
  opacity: 0.13;
  mask-image: radial-gradient(100% 80% at 85% 0%, #000, transparent 65%);
  pointer-events: none;
}
.page-head > * { position: relative; }
.page-head .display { font-size: clamp(2.4rem, 1.4rem + 4.2vw, 4.5rem); margin-block: 1.25rem 1.5rem; }

.breadcrumb { display: flex; gap: 0.5rem; font-family: var(--font-mono); font-size: var(--t-label);
              letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted-dim); }
.breadcrumb a:hover { color: var(--porcelain); }

/* --- Service detail rows (uslugi.html / services.html) ------------------- */

.svc-list { border-top: 1px solid var(--line); }

.svc {
  display: grid;
  gap: 1rem 3rem;
  padding-block: clamp(2.25rem, 4vw, 3.25rem);
  border-bottom: 1px solid var(--line);
  scroll-margin-top: 6rem;
}
@media (width >= 58rem) {
  .svc { grid-template-columns: 12rem minmax(0, 1fr) 12rem; align-items: start; }
}

.svc__ix { font-family: var(--font-mono); font-size: var(--t-label); letter-spacing: 0.14em;
           text-transform: uppercase; color: var(--linen); }
.svc__body { display: grid; gap: 0.85rem; }
.svc__body h3 { font-size: clamp(1.3rem, 1.1rem + 0.8vw, 1.7rem); font-weight: 750; letter-spacing: -0.025em; }
.svc__body p { color: var(--muted); max-width: 62ch; font-size: var(--t-small); }
.svc__body ul { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.25rem; }

.svc__price { display: grid; gap: 0.25rem; align-content: start; }
.svc__price dt { font-family: var(--font-mono); font-size: 0.66rem; letter-spacing: 0.12em;
                 text-transform: uppercase; color: var(--muted-dim); }
.svc__price dd { font-family: var(--font-display); font-size: 1.15rem; font-weight: 700;
                 letter-spacing: -0.02em; }
.svc__price dd small { display: block; font-family: var(--font-body); font-size: 0.76rem;
                       font-weight: 400; color: var(--muted-dim); letter-spacing: 0; margin-top: 0.2rem; }
/* On the work pages this cell holds a link, not a price — restore the label face */
.svc__price dd .arrow { font-family: var(--font-mono); font-size: var(--t-label);
                        font-weight: 600; letter-spacing: 0.1em; }

/* --- Cookie consent ------------------------------------------------------
   Anchored bottom-left rather than stretched across the viewport: it is a
   question, not an interstitial, and it must not bury the page it sits on.
   Nothing is loaded until the visitor answers, so there is no dark pattern to
   compensate for — accept and reject carry equal visual weight. */

.consent-bar {
  position: fixed;
  z-index: 150;
  inset: auto var(--gutter) var(--gutter) var(--gutter);
  max-inline-size: 32rem;
  padding: clamp(1.25rem, 3vw, 1.6rem);
  background: var(--ink-2);
  border: 1px solid var(--line-lit);
  border-radius: var(--r-lg);
  box-shadow: 0 24px 60px -20px rgb(0 0 0 / 80%);
  display: grid;
  gap: 1rem;
}
.consent-bar[hidden] { display: none; }

@media (prefers-reduced-motion: no-preference) {
  .consent-bar { animation: consent-in 0.45s var(--ease) both; }
  @keyframes consent-in {
    from { opacity: 0; transform: translateY(12px); }
    to   { opacity: 1; transform: none; }
  }
}

.consent-bar h2 {
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: -0.015em;
  font-family: var(--font-display);
}
.consent-bar p { font-size: 0.84rem; line-height: 1.6; color: var(--muted); }
.consent-bar a { color: var(--brand-lit); text-decoration: underline; text-underline-offset: 3px; }
.consent-bar .cluster { gap: 0.6rem; }
.consent-bar .btn { padding: 0.7rem 1.15rem; font-size: 0.82rem; }

/* "Settings" is a third, quieter action — but reject stays exactly as
   prominent as accept, which is the part regulators actually check. */
.btn--quiet {
  --btn-bd: transparent;
  --btn-fg: var(--muted);
  padding-inline: 0.5rem;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.btn--quiet:hover { --btn-fg: var(--porcelain); }

/* --- Consent preferences dialog ------------------------------------------ */

.consent-modal {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  place-items: center;
  padding: var(--gutter);
  background: rgb(4 6 4 / 72%);
  backdrop-filter: blur(6px);
}
.consent-modal[hidden] { display: none; }

.consent-modal__panel {
  position: relative;
  inline-size: min(38rem, 100%);
  max-block-size: min(42rem, 90dvh);
  overflow-y: auto;
  padding: clamp(1.5rem, 4vw, 2.25rem);
  background: var(--ink-2);
  border: 1px solid var(--line-lit);
  border-radius: var(--r-lg);
  box-shadow: 0 32px 80px -24px rgb(0 0 0 / 85%);
  display: grid;
  gap: 1.25rem;
}
@media (prefers-reduced-motion: no-preference) {
  .consent-modal__panel { animation: consent-in 0.3s var(--ease) both; }
}

.consent-modal h2 {
  font-size: clamp(1.2rem, 1.1rem + 0.6vw, 1.5rem);
  font-weight: 750;
  letter-spacing: -0.02em;
}
.consent-modal__intro { font-size: var(--t-small); color: var(--muted); }
.consent-modal a { color: var(--brand-lit); text-decoration: underline; text-underline-offset: 3px; }

.consent-modal__close {
  position: absolute;
  inset-block-start: 0.85rem;
  inset-inline-end: 0.85rem;
  inline-size: 2.25rem;
  block-size: 2.25rem;
  display: grid;
  place-items: center;
  background: none;
  border: 1px solid var(--line-lit);
  border-radius: 50%;
  color: var(--muted);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  transition: color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.consent-modal__close:hover { color: var(--porcelain); border-color: var(--porcelain); }

.consent-cats { display: grid; gap: 1px; background: var(--line); border: 1px solid var(--line);
                border-radius: var(--r); overflow: hidden; }
.consent-cats > li { background: var(--ink); }

/* The whole row is the label, so the switch has a large hit area */
.cat {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.9rem;
  align-items: start;
  padding: 1rem 1.1rem;
  cursor: pointer;
}
.cat:has(input:disabled) { cursor: default; }
.cat__text strong { display: block; font-size: var(--t-small); font-weight: 650; margin-bottom: 0.2rem; }
.cat__text span { display: block; font-size: 0.78rem; line-height: 1.55; color: var(--muted-dim); }
.cat__text code { font-family: var(--font-mono); font-size: 0.72rem; color: var(--muted); }

/* Switch — a real checkbox, visually replaced */
.cat input {
  appearance: none;
  inline-size: 2.4rem;
  block-size: 1.35rem;
  margin: 0.1rem 0 0;
  border-radius: 100px;
  background: var(--ink-3);
  border: 1px solid var(--line-lit);
  position: relative;
  cursor: inherit;
  flex: none;
  transition: background 0.2s var(--ease), border-color 0.2s var(--ease);
}
.cat input::after {
  content: "";
  position: absolute;
  inset-block-start: 50%;
  inset-inline-start: 3px;
  translate: 0 -50%;
  inline-size: 0.85rem;
  block-size: 0.85rem;
  border-radius: 50%;
  background: var(--muted);
  transition: translate 0.2s var(--ease), background 0.2s var(--ease), inset-inline-start 0.2s var(--ease);
}
.cat input:checked { background: var(--brand); border-color: var(--brand); }
.cat input:checked::after { inset-inline-start: calc(100% - 0.85rem - 3px); background: var(--on-brand); }
.cat input:disabled { opacity: 0.65; }
.cat input:disabled:checked { background: var(--muted-dim); border-color: var(--muted-dim); }

.consent-modal__actions { display: flex; flex-wrap: wrap; gap: 0.6rem; }
.consent-modal__actions .btn { padding: 0.75rem 1.25rem; font-size: 0.84rem; }

/* --- Cookie tables in the privacy policies -------------------------------- */

.legal .table-wrap { overflow-x: auto; margin-top: 1rem; }
.legal table { inline-size: 100%; border-collapse: collapse; min-inline-size: 34rem; }
.legal th, .legal td {
  text-align: start;
  padding: 0.6rem 0.75rem;
  border-bottom: 1px solid var(--line);
  font-size: 0.8rem;
  vertical-align: top;
}
.legal th {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted-dim);
  font-weight: 500;
  border-bottom-color: var(--line-lit);
}
.legal td { color: var(--muted); }
.legal td code { font-family: var(--font-mono); font-size: 0.76rem; color: var(--linen); }

/* --- reCAPTCHA -----------------------------------------------------------
   The floating badge is hidden. Google allows this only if the disclosure
   below is displayed instead — do not delete `.recaptcha-note` from the
   contact pages. */

.grecaptcha-badge { visibility: hidden; }

.recaptcha-note {
  font-size: 0.74rem;
  line-height: 1.55;
  color: var(--muted-dim);
}
.recaptcha-note a { color: var(--muted); text-decoration: underline; text-underline-offset: 2px; }
.recaptcha-note a:hover { color: var(--porcelain); }

/* --- Legal / long-form pages -------------------------------------------- */

.legal { max-width: 74ch; }
.legal h2 { font-size: clamp(1.3rem, 1.1rem + 0.8vw, 1.7rem); margin-top: 2.75rem; }
.legal h2:first-child { margin-top: 0; }
.legal h3 { margin-top: 1.75rem; }
.legal p, .legal li { color: var(--muted); font-size: var(--t-small); }
.legal p + p { margin-top: 0.9rem; }
.legal ul { list-style: none; margin-top: 0.75rem; display: grid; gap: 0.5rem; }
.legal ul li { padding-left: 1.25rem; position: relative; }
.legal ul li::before { content: "—"; position: absolute; left: 0; color: var(--brand); }
.legal a { color: var(--brand-lit); text-decoration: underline; text-underline-offset: 3px; }
.legal time { color: var(--muted-dim); }
