/* KuarkTek — design system tokens, reset and the pieces every page shares.
   Load first: everything else leans on these tokens. */
:root{
  /* ============================================================
     DESIGN SYSTEM — the locked vocabulary. Nothing below the hero
     may invent a value: pick the nearest token or the scale is
     wrong. Full rationale in DESIGN-SYSTEM.md.
     Out of scope (deliberately untokenised): the `.pj-*` project
     detail route.
     ============================================================ */

  /* ---- type scale ---- */
  --fs-micro:10px;      /* chart annotations only                */
  --fs-tag:12px;        /* tags, chips, form labels, legal, dates */
  --fs-sm:14px;         /* small body, dense meta, badges         */
  --fs-ui:15px;         /* interactive pill labels: nav, buttons  */
  --fs-body:16px;       /* body base                              */
  --fs-lead:18px;       /* lead-in, eyebrow, small heading        */
  --fs-h4:20px;
  --fs-h3:22px;         /* card title, standfirst                 */
  --fs-h2:26px;
  --fs-h1:32px;
  --fs-display-sm:38px;
  --fs-display:45px;
  --fs-display-lg:52px; /* section h2                             */
  --fs-display-md:62px; /* compact page hero                       */
  --fs-display-xl:72px;
  --fs-hero:96px;
  --fs-hero-md:108px;
  --fs-hero-lg:144px;

  /* ---- weight ---- */
  --fw-regular:400; --fw-body:500; --fw-medium:600; --fw-bold:700; --fw-display:800;

  /* ---- line height ---- */
  --lh-none:1;          /* badges, icon labels, fixed-height chrome */
  --lh-tight:.9;        /* >=96px display                           */
  --lh-display:1.1;     /* 45-72px                                  */
  --lh-heading:1.2;     /* 20-38px                                  */
  --lh-text:1.3;        /* UI + meta text (default)                 */
  --lh-body:1.4;        /* paragraphs                               */
  --lh-reading:1.6;     /* long-form editorial content              */
  --lh-pill:20px;       /* pill labels: fixed line box so pill heights stay put */

  /* ---- tracking (em, so it tracks the size automatically) ---- */
  --ls-tight:-.025em;   /* >=45px display   */
  --ls-snug:-.02em;     /* 16-38px          */
  --ls-normal:-.01em;   /* <=15px           */
  --ls-caps:.04em;      /* uppercase micro  */

  /* ---- radius ---- */
  --r-hair:2px;         /* icon strokes            */
  --r-xs:8px;           /* small controls, chips   */
  --r-sm:14px;          /* media thumbs, inputs    */
  --r-md:24px;          /* cards + panels: default */
  --r-lg:40px;          /* full-bleed sections     */
  --r-pill:999px;
  --r-round:50%;

  /* ---- component spacing: --gap-N is N x 4px ---- */
  --gap-hair:2px;                 /* sub-component hairline           */
  --gap-1:4px;   --gap-2:8px;   --gap-3:12px;  --gap-4:16px;
  --gap-5:20px;  --gap-6:24px;  --gap-8:32px;  --gap-10:40px;
  --gap-16:64px;
  --gutter:clamp(16px, 1.4vw, 27px); /* the 12-column grid gutter */
  --gap-grid:4px;       /* the seam between cards in every grid */

  /* ---- section rhythm: 30px base ---- */
  --space-30:30px;   --space-60:60px;   --space-90:90px;
  --space-120:120px; --space-150:150px; --space-180:180px;

  /* ---- content widths ---- */
  --w-shell:75.5rem;      /* page shell            */
  --w-shell-wide:95rem;   /* >=1500px shell        */
  --measure-lg:720px;     /* wide prose            */
  --measure:620px;        /* headline + paragraph  */
  --measure-sm:520px;     /* narrow column         */

  /* ---- motion: two curves, four durations ---- */
  --ease:cubic-bezier(.22,1,.36,1);        /* standard: everything  */
  --ease-inout:cubic-bezier(.4,0,.2,1);    /* symmetric swaps only  */
  --dur-fast:.2s;    /* colour, opacity            */
  --dur:.3s;         /* hover state                */
  --dur-slow:.45s;   /* transform, roll            */
  --dur-slower:.6s;  /* size, layout, reveal       */
  --dur-intro:1s;    /* hero curtain, one-off      */

  /* ---- colour roles ---- */
  --ink:#1f252b;                        /* body type on light   */
  --muted:#7c899d;                      /* secondary type       */
  --brand:#004fa3;
  --brand-light:#0c71c3;
  --surface:#f5f5f5;                    /* page ground          */
  --surface-dark:#010203;               /* inverted sections    */
  --line:rgba(31,37,43,.14);            /* hairline on light    */
  --white:#ffffff;
  --on-dark-soft:rgba(255,255,255,.72); /* hero chrome, resting */
  --on-dark-muted:rgba(255,255,255,.6); /* secondary on dark    */
  --on-dark-faint:rgba(255,255,255,.48);/* labels on dark       */
  --line-dark:rgba(255,255,255,.16);

  /* ---- elevation: two layers each, a contact shade plus a wide soft one ---- */
  --shadow-soft:0 1px 2px rgba(31,37,43,.025), 0 6px 20px rgba(31,37,43,.03);
  --shadow-float:0 2px 6px rgba(31,37,43,.025), 0 14px 36px rgba(31,37,43,.04);
  --shadow-on-dark:0 8px 26px rgba(0,0,0,.28);
  --accent:#fb9826;                     /* rating stars, Clutch */

  /* KuarkTek Digital brand tokens */
  --kt-blue:#2252FF;
  --kt-ink:#0F1C3F;
  --kt-muted:#5C6478;
  --kt-light:#EEF1F8;
  --ui-ink:#0a0a0a;          /* chrome + button type, deliberately not navy */
  --mono:ui-monospace,"SF Mono",SFMono-Regular,"Roboto Mono","DejaVu Sans Mono",Menlo,Consolas,monospace;
  --sans:"Red Hat Display",-apple-system,system-ui,"Segoe UI",Roboto,sans-serif;
  --pad:38px;
  --hero-gutter:30px;  /* the hero's standfirst and filter sit closer in */
  --fs-mono:10.88px; --lh-mono:11.968px;
  --pill:rgba(255,255,255,.533);
}
*,*::before,*::after{box-sizing:border-box}
html,body{min-height:100%}
html{background:#f5f5f5}
body{
  margin:0;background:#f5f5f5;color:var(--kt-ink);
  font-family:var(--sans);font-size:var(--fs-body);font-weight:var(--fw-body);
  -webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
}
html{scroll-behavior:smooth}
button,a{font:inherit;color:inherit;-webkit-tap-highlight-color:transparent}
button{background:none;border:0;padding:0;cursor:pointer}
a{text-decoration:none}
ul,li{list-style:none;margin:0;padding:0}
::selection{background:var(--white);color:var(--ui-ink)}
.mono{font-family:var(--mono);font-size:var(--fs-mono);line-height:var(--lh-mono);font-weight:var(--fw-regular);text-transform:uppercase}
.langswitch:hover,.langswitch.roll-host:hover{color:var(--white)}
/* the roll lives on the inner span, so let the whole switch — globe included
   — drive it */
.langswitch:hover .roll i{transform:translateY(-100%)}
.langswitch:hover .roll i + i{transform:translateY(0)}
/* ---------- rolling button labels ----------
   One line-height of masked window, two stacked copies of the label. On hover
   both slide up together: the first leaves through the top, the second arrives
   from below. (A rotateX version cannot work here — overflow:hidden flattens
   the 3D context, so the flip renders as a squash.) */
.roll{
  display:inline-block;position:relative;overflow:hidden;vertical-align:middle;
  line-height:var(--lh-text);
}
.roll i{
  display:block;font-style:normal;white-space:nowrap;
  transition:transform var(--dur-slow) var(--ease-inout);
  will-change:transform;
}
.roll i + i{position:absolute;left:0;top:0;transform:translateY(100%)}
.roll-host:hover .roll i,
.roll-host:focus-visible .roll i{transform:translateY(-100%)}
.roll-host:hover .roll i + i,
.roll-host:focus-visible .roll i + i{transform:translateY(0)}
@media (prefers-reduced-motion:reduce){
  .roll i{transition:none}
  .roll i + i{display:none}
}
/* ============================================================
   PAGE BELOW THE HERO
   ============================================================ */
/* colour + spacing roles now live in :root; this block used to redeclare
   them, plus a --gap-30..180 set that duplicated --space-* one-for-one */
a { color: inherit; text-decoration: none; }
.section-shell {
  width: 100%;
  max-width: var(--w-shell);
  margin-inline: auto;
}
.text-base {
  margin: 0;
  color: var(--muted);
  font-size: var(--fs-body);
  font-weight: var(--fw-body);
  letter-spacing: var(--ls-snug);
  line-height: var(--lh-text);
}
.section-label {
  display: flex;
  align-items: center;
  gap: var(--gap-2);
  margin: 0;
  color: var(--ink);
  font-size: var(--fs-body);
  font-weight: var(--fw-medium);
  letter-spacing: var(--ls-snug);
  line-height: var(--lh-body);
}
.section-label__icon {
  position: relative;
  display: inline-block;
  width: 14px;
  height: 14px;
  flex: 0 0 14px;
  border-radius: var(--r-round);
  background: var(--ink);
}
.section-label__icon::before,
.section-label__icon::after {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 8px;
  height: 1.5px;
  border-radius: var(--r-hair);
  background: var(--white);
  content: "";
  transform: translate(-50%, -50%);
}
.section-label__icon::after { transform: translate(-50%, -50%) rotate(90deg); }
.hero-section-line {
  width: 100%;
  height: 1px;
  margin: 0 0 16px;
  border: 0;
  background: var(--line);
}
.services-section .section-label__icon { background: var(--white); }
.services-section .section-label__icon::before,
.services-section .section-label__icon::after { background: var(--ink); }
.about .section-label { grid-column: 1 / 4; }
.projects__header .section-label,
.clients__header .section-label { grid-column: 1 / 4; }
.why__header .section-label { grid-column: 1 / 4; }
.services-section__header .section-label {
  grid-column: 1 / 4;
  color: var(--white);
}
.about-us-section__header .section-label {
  grid-column: 1 / 4;
  align-items: flex-start;
}
.blog-section__lead .section-label { margin-bottom: var(--space-30); }
.primary-button,
.secondary-button {
  display: inline-flex;
  min-height: 40px;
  height: 40px;
  align-items: center;
  justify-content: center;
  padding: 0 20px;
  border: 0;
  border-radius: var(--r-pill);
  font-family: inherit;
  font-size: var(--fs-ui);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-normal);
  line-height: var(--lh-none);
  white-space: nowrap;
  cursor: pointer;
  transition:background-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.primary-button {
  background: var(--ink);
  color: var(--white);
}
.secondary-button {
  background: var(--white);
  color: var(--ink);
}
.button-arrow-icon {
  position: relative;
  display: block;
  width: 16px;
  height: 16px;
  flex: 0 0 16px;
  margin-left: 10px;
  overflow: hidden;
}
.button-arrow-icon i {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-style: normal;
  transition:transform var(--dur) var(--ease);
}
.button-arrow-icon svg {
  display: block;
  width: 14px;
  height: 14px;
  fill: none;
  stroke: currentColor;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-width: 1.15;
}
.button-arrow-icon i:last-child { transform: translate(-100%, 100%); }
@media (hover: hover){
  .primary-button:hover .button-arrow-icon i:first-child,
  .secondary-button:hover .button-arrow-icon i:first-child { transform: translate(100%, -100%); }

  .primary-button:hover .button-arrow-icon i:last-child,
  .secondary-button:hover .button-arrow-icon i:last-child { transform: translate(0); }
}
.primary-button:focus-visible .button-arrow-icon i:first-child,
.secondary-button:focus-visible .button-arrow-icon i:first-child { transform: translate(100%, -100%); }
.primary-button:focus-visible .button-arrow-icon i:last-child,
.secondary-button:focus-visible .button-arrow-icon i:last-child { transform: translate(0); }
.reveal { opacity: 1; transform: translateY(0); }
.reveal.is-visible { animation: reveal-in 800ms var(--ease) both; }
/* GSAP takes over the entrances when it loads, so the blanket section fade
   does not run underneath the per-element staggers */
.gsap-motion .reveal,
.gsap-motion .reveal.is-visible { animation: none; opacity: 1; transform: none; }
.gsap-motion .project-reveal,
.gsap-motion .project-reveal.is-visible { animation: none; opacity: 1; translate: none; }
.motion-ready .project-reveal:not(.is-visible) {
  opacity: 0;
  translate: 0 38px;
}
.project-reveal.is-visible {
  opacity: 1;
  translate: 0 0;
  animation: project-pop-in .7s var(--ease) var(--project-delay, 0ms) backwards;
}
@keyframes reveal-in {
  from { opacity: 0; transform: translateY(28px); }
  to { opacity: 1; transform: translateY(0); }
}
@keyframes project-pop-in {
  from { opacity: 0; translate: 0 38px; }
  to { opacity: 1; translate: 0 0; }
}
/* A field of fine pixels across the section, drawn on a canvas so they can be
   moved rather than merely lit. Near the pointer they gather toward it and
   grow, like a lens passing over the grid; away from it they sit still and
   almost invisible. Brightness barely changes, so nothing reads as a spot and
   nothing competes with the type. */
.dark-band__grid {
  position: absolute;
  inset: 0;
  z-index: -1;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
@media (min-width: 1500px){
  .section-shell { max-width: var(--w-shell-wide); }
}
@media (prefers-reduced-motion: reduce){
  html { scroll-behavior: auto; }
  .reveal { opacity: 1; transform: none; }
  .project-reveal { opacity: 1 !important; translate: none !important; }
}
@media (max-width:760px){
  :root{--pad:20px}
}

/* ---------- the scale on a phone ----------
   The display sizes were drawn for a 1440px canvas. At 375px a 52px section
   heading runs to five lines and stops being a heading. The top of the scale
   contracts; everything from --fs-display-sm down is already sized for the
   hand and stays where it is, so the ratios between body, lead and heading
   hold. Changing the tokens rather than the rules keeps every heading on the
   system — nothing gets a one-off size. */
@media (max-width: 700px) {
  :root {
    --fs-display-sm: 32px;
    --fs-display: 36px;
    --fs-display-lg: 40px;
    --fs-display-md: 46px;
    --fs-display-xl: 52px;
    --fs-hero: 64px;
    --fs-hero-md: 72px;
    --fs-hero-lg: 84px;

    /* the section rhythm contracts with it: 90px above and below every
       section is a third of a phone screen of nothing between two ideas */
    --space-90: 64px;
    --space-120: 80px;
    --space-150: 96px;
    --space-180: 112px;
  }
}
@media (prefers-reduced-motion:reduce){*{animation-duration:.001ms !important;transition-duration:.001ms !important}
}

/* ---------- narrow screens ----------
   The shell is 1208px wide and centred, so anything narrower than the shell
   plus its gutters ran the content into the edge of the screen. */
@media (max-width: 1284px) {
  .section-shell { padding-inline: var(--pad); }
}
