/* ============================================================================
   96K AUTO CARE — base.css
   Design tokens, reset, typography, buttons, cursor, shared utilities.

   AESTHETIC DIRECTION — "Engineered Editorial"
   Monochrome brand (the supplied logo is pure ink on a pure plate — there is
   no colour in it), one burnished-metal accent, oversized grotesque display
   type, and a strict 1px hairline system. Colour arrives only as *light*
   inside the cinematic hero.
   ========================================================================= */

/* ---------------------------------------------------------------- tokens -- */
:root {
  /* ======================================================================
     GLOBAL COLOUR SYSTEM — one palette, one source of truth.

     White + near-black + charcoal. There is no decorative colour in the
     system any more: rules, ticks, separators, watermarks, marks and active
     states are all the SAME ink at different strengths, which is what stops
     them drifting apart. Sections must never declare their own.

     Everything below derives from two anchors — the heading ink on light
     surfaces, and the logo plate ivory on dark ones.
     ====================================================================== */

  /* ---- ink, on light --------------------------------------------------- */
  --color-heading: #0d0d0f;      /* primary — headings, titles, accents     */
  --color-text: #4b4b4f;         /* body                                    */
  /* THE 96K yellow, sampled from the 96K in the supplied logo: the most
     common value across those letterforms is #F5FF00, and the same value
     appears in both the upper wordmark and the Street Customs lockup. This
     is the brand accent, and it is the ONE place it is defined. */
  --color-brand: #F5FF00;

  /* The same accent where it sits on a WHITE ground.

     A neon this bright measures 1.09:1 on white — it is not a low-contrast
     choice, it is an invisible one. The supplied logo solves this itself:
     its light-background variant carries a deepened yellow rather than the
     neon. This token is that idea, taken a little further — the brand hue
     darkened and warmed a few degrees so it reads as yellow rather than the
     olive the logo's own #C1C703 turns into on white, and measuring 2.8:1
     instead of 1.8:1.

     Two tokens, not one, because the accent genuinely has two jobs: the
     neon owns every dark surface, this owns the light ones. */
  --color-muted: #C9B400;

  /* Hover on a dark ground: the neon lifted rather than dimmed, so the
     interaction reads as the brand getting brighter. */
  --color-brand-hover: #E2EA00;
  --color-border: #e5e2dc;       /* hairline                                */

  /* Decorative strengths of that same ink. Anything that used to be a gold
     line is one of these three — never a new value. */
  --color-rule: rgba(13, 13, 15, 0.3);        /* a line meant to be seen    */
  --color-rule-soft: rgba(13, 13, 15, 0.12);  /* separators                 */
  --color-wash: rgba(13, 13, 15, 0.05);       /* watermarks and tints       */

  /* The accent IS the ink. Kept as its own name so components read by intent
     rather than by shade, and so one edit re-points every accent at once. */
  --color-accent: var(--color-heading);

  /* ---- ink, on dark ----------------------------------------------------
     The same three strengths inverted. Dark sections use these instead of
     going black-on-black. */
  --color-onDark: var(--color-secondary);
  --color-onDark-soft: rgba(243, 241, 237, 0.62);
  --color-onDark-rule: rgba(243, 241, 237, 0.22);

  /* Focus must stay visible on either ground, so the dark sections re-declare
     this one token and every focus ring inside them follows. */
  --color-focus: var(--color-heading);

  /* ---- surfaces --------------------------------------------------------- */
  --color-bg: #ffffff;
  --color-bg-soft: #f7f4ef;      /* the warm off-white the sections sit on  */
  --color-dark: #090909;
  --color-dark-soft: #111111;

  /* Warm graphite, for the one dark transitional section. Deliberately not
     black — it has to read as a considered surface next to the warm off-white
     the rest of the page sits on, not as an absence of light. */
  --color-graphite-deep: #1b1b1a;

  /* Deep charcoal for the numbers strip. A touch cooler and darker than the
     graphite, so the strip reads as related to the dark section above it
     without being the same surface. */
  --color-charcoal: #111214;

  /* ---- brand, derived from assets/logo/26k-logo.png ---------------------
     The logo is monochrome: a pure-black field with an off-white plate. */
  --color-primary-dark: #000000;   /* logo field                             */
  --color-secondary: #f3f1ed;      /* logo plate, warmed                     */

  --color-bg-alt: var(--color-bg-soft);

  /* ---- type ------------------------------------------------------------ */
  /* One family, site-wide. The three names below are kept because the hero and
     the older sections reference them, but they all resolve to Inter — weight
     and tracking do the work that three separate faces used to do. */
  --font-sans: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-display: var(--font-sans);
  --font-body: var(--font-sans);
  --font-mono: var(--font-sans);
  /* The one exception to "one family, site-wide": the founder note's display
     type and watermark, which the approved reference sets in a serif. Nothing
     else may reach for this. */
  --font-serif: "Playfair Display", ui-serif, Georgia, "Times New Roman", serif;

  --fs-mega: clamp(2.9rem, 9.4vw, 10.5rem);
  --fs-display: clamp(2.3rem, 6.2vw, 6.4rem);
  --fs-h2: clamp(1.9rem, 4.4vw, 4.2rem);
  --fs-h3: clamp(1.3rem, 2.1vw, 1.9rem);
  --fs-lead: clamp(1.02rem, 1.28vw, 1.28rem);
  --fs-body: clamp(0.95rem, 1.02vw, 1.06rem);
  --fs-label: clamp(0.66rem, 0.78vw, 0.76rem);

  --lh-tight: 0.92;
  --lh-snug: 1.08;
  --lh-body: 1.62;

  /* ---- rhythm (8px base) ----------------------------------------------- */
  --s1: 0.5rem;
  --s2: 1rem;
  --s3: 1.5rem;
  --s4: 2rem;
  --s5: 3rem;
  --s6: 4.5rem;
  --s7: 6.5rem;
  --s8: 9rem;

  /* ---- container + spacing system --------------------------------------
     One container and three section rhythms, reused everywhere. Sections
     should pick a spacing token, never invent a padding.                  */
  --container-max: 1480px;
  --container-pad: clamp(1.25rem, 4.4vw, 5rem);

  --section-space-lg: clamp(5rem, 9vw, 9.5rem);
  --section-space-md: clamp(3.25rem, 6vw, 6rem);
  --section-space-sm: clamp(2rem, 3.5vw, 3.5rem);

  --gutter: var(--container-pad);   /* legacy alias */
  --maxw: var(--container-max);     /* legacy alias */
  --section-y: var(--section-space-lg);

  /* ======================================================================
     THE SECTION SYSTEM

     Every section below the hero is one of three rhythms and nothing else.
     Before this existed each section carried its own clamp() — nine of them,
     no two alike — which is why the page read as a stack of unrelated
     rectangles however good each one looked on its own.

     `--section-y-*` is the padding. `--zone-*` is the extra breathing room a
     section gets where it MEETS a change of ground, so a light-to-dark
     boundary is not the same distance as two light sections in a row.
     ====================================================================== */
  --section-y-lg: clamp(4.5rem, 6.4vw, 6.9rem);   /* full editorial section */
  --section-y-md: clamp(3.4rem, 4.6vw, 5rem);     /* compact               */
  --section-y-sm: clamp(2.4rem, 3.2vw, 3.4rem);   /* strips                */

  /* Two sections on the SAME ground sit closer: they are one zone, and the
     gap between them should not read as a boundary. */
  --zone-inner: clamp(2rem, 3vw, 3.2rem);

  /* ---- radius ----------------------------------------------------------
     Four steps, in a fixed ratio. Nothing may invent a value between them.
     The page had 26/36, 16/22, 10/16, 22, 12 and three bare 50%s. */
  --r-sm: 10px;                          /* chips, buttons, small UI       */
  --r-md: clamp(14px, 1.2vw, 18px);      /* cards, panels                  */
  --r-lg: clamp(20px, 2vw, 28px);        /* image panels                   */
  --r-xl: clamp(28px, 3.2vw, 44px);      /* full-bleed media               */
  /* The architectural one. Only the zone transitions use it, and it is a
     percentage so it stays a shallow arc at any width — a panel line, not a
     bubble. */
  --r-zone: 0 0 clamp(40px, 5vw, 78px) clamp(40px, 5vw, 78px) / 0 0 clamp(28px, 3vw, 46px) clamp(28px, 3vw, 46px);

  /* ---- one divider ------------------------------------------------------
     Two tokens, chosen by ground, and nothing else on the page draws a line.

     There were eight strengths before this: five on dark (0.22 / 0.16 / 0.10
     / 0.08 / 0.07) and three on light, with one component — the Principles
     rows — using two of them for the same divider. That is invisible in any
     single section and is precisely what stops a page reading as one system.

     These are stated as literals rather than pointing at --color-onDark-rule,
     which is a fill strength used for chips and inset shadows and should be
     free to move without dragging every hairline on the site with it.      */
  --rule: 1px solid rgba(13, 13, 15, 0.11);
  --rule-onDark: 1px solid rgba(243, 241, 237, 0.15);

  /* ---- one entrance -----------------------------------------------------
     Distance, duration and stagger for every section entrance on the page,
     so a card in Services and a column in Experience arrive the same way.
     sections.js reads these rather than carrying its own numbers. */
  --enter-lift: 22px;
  --enter-dur: 0.86s;
  --enter-stagger: 0.075s;

  /* ---- motion ----------------------------------------------------------- */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-inout: cubic-bezier(0.66, 0, 0.34, 1);
  --dur-fast: 0.28s;
  --dur: 0.6s;
  --dur-slow: 1.1s;

  --header-h: clamp(64px, 6vw, 88px);
}

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

* { margin: 0; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: auto;            /* smooth-scroll is handled by Lenis */
}

/* The page opens in darkness — paint the ground dark before any CSS/video
   arrives so there is never a white flash. main.js swaps this to light once
   the walkthrough has been cleared. */
html,
body { background: var(--color-primary-dark); }

/* Set once the walkthrough has been cleared, so overscroll rubber-banding at
   the foot of the page reveals off-white rather than a slab of black. */
html.is-lit,
html.is-lit body { background: var(--color-bg-alt); }

body {
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--color-text);
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow-x: clip;
}

body.is-locked { overflow: hidden; height: 100%; }

img,
picture,
video,
svg { display: block; max-width: 100%; }

button,
input,
select,
textarea { font: inherit; color: inherit; }

button { background: none; border: 0; padding: 0; cursor: pointer; }

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

ul, ol { list-style: none; padding: 0; }

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 800;
  line-height: var(--lh-tight);
  letter-spacing: -0.03em;
  color: var(--color-heading);
  text-wrap: balance;
}

::selection { background: var(--color-heading); color: var(--color-secondary); }

/* ------------------------------------------------------------- focus ----- */
:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 3px;
  border-radius: 2px;
}

/* Dark surfaces re-declare the focus token; every ring inside them inherits
   it, so a black outline can never land on a black ground. */
.standard,
.stats,
.cta,
.footer,
.close,
.svcard__link,
.about__badge { --color-focus: var(--color-onDark); }

/* Screen-reader only. Structural utility — carries no colour or type of its
   own, so it never competes with the global system. */
.u-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: fixed;
  top: 0;
  left: 50%;
  z-index: 9999;
  padding: 0.75rem 1.4rem;
  background: var(--color-secondary);
  color: var(--color-heading);
  font: 500 0.8rem/1 var(--font-mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  transform: translate(-50%, -140%);
  transition: transform var(--dur-fast) var(--ease-out);
}
.skip-link:focus-visible { transform: translate(-50%, 0); }

/* --------------------------------------------------------- primitives ---- */
/* ============================================================ CONTAINER == */
/* One container for the whole site — header, every section, footer. */
.site-container {
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--container-pad);
}
.shell { /* legacy alias, kept until the older sections are redesigned */
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--container-pad);
}

/* ====================================================== TYPE SYSTEM ====== */
/* The shared heading/subheading/body classes. Every section from here on
   uses these — no section defines its own heading sizing again. */

/* Brand kicker: an ink hairline, the tracked name, then a second hairline.
   This is the section opener — it replaces the old "ABOUT US" style heading. */
.section-kicker {
  display: flex;
  align-items: center;
  gap: clamp(0.75rem, 1.4vw, 1.15rem);
  font-size: clamp(0.64rem, 0.76vw, 0.74rem);
  font-weight: 600;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--color-heading);
}
/* Both sides, as the reference sets it. The trailing rule is capped so the
   kicker reads as a unit rather than stretching across the column. */
/* .section-kicker::before,
.section-kicker::after {
  content: "";
  height: 1px;
  background: var(--color-rule);
  flex: 0 0 auto;
  width: clamp(30px, 4vw, 58px);
} */
.section-kicker--onDark { color: var(--color-secondary); }

/* The one major heading style. Sentence case — never uppercased, never larger
   than the clamp below. Weight and tight leading carry the authority. */
.section-heading {
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: 40px;
  line-height: 1.05;
  letter-spacing: -0.028em;
  color: var(--color-heading);
  text-wrap: balance;
}
/* Highlighted words inside any heading. Reused site-wide. */
.section-heading-accent { color: var(--color-muted); font-weight: 700; }
/* The quieter half of a two-tone heading — colour only, same scale and weight
   as the heading it sits in. */
.section-heading-muted { color: var(--color-muted); }
.section-heading--onDark { color: var(--color-secondary); }
/* On the dark grounds the accent is the brand yellow, matching the 96K in
   the logo. 10.2:1 on the charcoal, so it is louder here than the near-white
   it replaced was, not quieter. */
.section-heading--onDark .section-heading-accent { color: var(--color-brand); }

/* Tracked line beneath a heading: PRECISION. PROTECTION. PERFECTION. */
.section-subheading {
  font-size: clamp(0.72rem, 0.9vw, 0.84rem);
  font-weight: 600;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--color-heading);
}

/* Section body copy. */
.section-description {
  font-size: clamp(1rem, 1.06vw, 1.1rem);
  font-weight: 400;
  line-height: 1.75;
  color: var(--color-text);
  max-width: 46ch;
  text-wrap: pretty;
}
/* Colour only, matching the --onDark pattern already used by the kicker and
   the heading. The type itself is unchanged. */
.section-description--onDark { color: rgba(243, 241, 237, 0.66); }

/* The closing statement: an ink vertical rule, a dark line, then a quieter one.
   Used wherever a section needs to land on a claim. */
.section-emphasis {
  position: relative;
  padding-left: clamp(1.15rem, 1.8vw, 1.6rem);
  font-size: clamp(1.02rem, 1.15vw, 1.22rem);
  line-height: 1.55;
  font-weight: 600;
  max-width: 30ch;
}
.section-emphasis::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.15em;
  bottom: 0.15em;
  width: 2px;
  background: var(--color-rule);
}
.section-emphasis b { display: block; color: var(--color-heading); font-weight: 700; }
.section-emphasis span { display: block; color: var(--color-text); font-weight: 600; }

/* The short ink rule that closes a block, with the diamond accent sitting on
   its left end. Decorative only — always aria-hidden in markup.

   The line is a real child rather than a pseudo-element so it can be scaled on
   its own: scaling the wrapper would stretch the diamond with it. */
.section-rule {
  display: block;
  position: relative;
  width: clamp(180px, 30vw, 430px);
  height: 8px;
  border: 0;
}
.section-rule > i {
  display: block;
  position: absolute;
  inset: 50% 0 auto 0;
  height: 1px;
  margin-top: -0.5px;
  background: var(--color-rule);
  transform-origin: 0 50%;
}
.section-rule::before {
  content: "";
  position: absolute;
  left: 3px;
  top: 50%;
  width: 7px;
  height: 7px;
  margin-top: -3.5px;
  background: var(--color-accent);
  transform: rotate(45deg);
}

/* A label is the small mono voice used throughout: section eyebrows, indices,
   HUD readouts. It is the third typeface and it does a lot of the "engineered"
   work in this design. */
.label {
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--color-muted);
}

.label--accent { color: var(--color-accent); }

.label--tick {
  display: inline-flex;
  align-items: center;
  gap: 0.85em;
}
.label--tick::before {
  content: "";
  width: clamp(28px, 3vw, 56px);
  height: 1px;
  background: currentColor;
  opacity: 0.5;
}

.rule {
  height: 1px;
  width: 100%;
  background: var(--color-border);
  border: 0;
}

.lead {
  font-size: var(--fs-lead);
  line-height: 1.56;
  color: var(--color-text);
  max-width: 46ch;
  text-wrap: pretty;
}

/* Line-mask primitive. `.ln` clips, `.ln > i` is the thing that travels.
   Every headline reveal in this build uses it, so the motion language is
   consistent from the hero all the way to the footer. */
.ln {
  display: block;
  overflow: hidden;
  padding-bottom: 0.06em;     /* protect descenders from the clip edge */
}
.ln > i {
  display: block;
  font-style: inherit;
  will-change: transform;
}

/* --------------------------------------------------------------- buttons - */
.btn {
  --btn-fg: var(--color-heading);
  --btn-bg: transparent;
  --btn-bd: var(--color-border);
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.9em;
  padding: 1.05em 1.9em;
  font-family: var(--font-mono);
  font-size: clamp(0.7rem, 0.82vw, 0.8rem);
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--btn-fg);
  background: var(--btn-bg);
  border: 1px solid var(--btn-bd);
  border-radius: 1px;                /* engineered, not a pill */
  overflow: hidden;
  isolation: isolate;
  transition: color var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out);
  will-change: transform;
}

/* Hover fill rises from the bottom edge rather than fading — reads as a
   mechanism moving, not a colour change. */
.btn::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--color-heading);
  transform: translate3d(0, 101%, 0);
  transition: transform var(--dur) var(--ease-out);
}

.btn__arrow {
  display: inline-block;
  transition: transform var(--dur) var(--ease-out);
}

@media (hover: hover) and (pointer: fine) {
  .btn:hover { color: var(--color-secondary); border-color: var(--color-heading); }
  .btn:hover::before { transform: translate3d(0, 0, 0); }
  .btn:hover .btn__arrow { transform: translate3d(0.35em, 0, 0); }
}
.btn:focus-visible { color: var(--color-secondary); }
.btn:focus-visible::before { transform: translate3d(0, 0, 0); }

.btn--solid {
  --btn-fg: var(--color-secondary);
  --btn-bg: var(--color-heading);
  --btn-bd: var(--color-heading);
}
.btn--solid::before { background: var(--color-accent); }
@media (hover: hover) and (pointer: fine) {
  .btn--solid:hover { color: var(--color-primary-dark); border-color: var(--color-accent); }
}

/* On the dark hero / dark CTA */
.btn--onDark {
  --btn-fg: var(--color-secondary);
  --btn-bd: rgba(243, 241, 237, 0.28);
}
.btn--onDark::before { background: var(--color-secondary); }
@media (hover: hover) and (pointer: fine) {
  .btn--onDark:hover { color: var(--color-primary-dark); border-color: var(--color-secondary); }
}

/* --------------------------------------------------- image placeholders --- */
/* Every future photograph already occupies its exact final box. The
   placeholder is a brand-tinted surface with a hairline frame, a slow
   diagonal sheen and the target path printed in mono — so a reviewer can see
   at a glance which file lands where. Swap `data-src` in for `src` when the
   real asset arrives; nothing else needs to change. */
.ph {
  position: relative;
  overflow: hidden;
  background: var(--color-bg-alt);
  border: 1px solid var(--color-border);
  isolation: isolate;
}

/* The surface itself. This element is what parallax and scale animations
   move, and it is exactly what the real photograph replaces:
       <span class="ph__inner"></span>   →   <img class="ph__inner" src="…">
   Nothing else in the markup changes. */
.ph__inner {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  background:
    linear-gradient(135deg, var(--color-wash), rgba(16, 17, 19, 0.035) 46%, var(--color-wash)),
    var(--color-bg-alt);
  will-change: transform;
}

img.ph__inner {
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: none;
}

.ph__inner::before {
  content: "";
  position: absolute;
  inset: -40%;
  background: linear-gradient(
    108deg,
    transparent 38%,
    rgba(255, 255, 255, 0.62) 50%,
    transparent 62%
  );
  transform: translate3d(-38%, 0, 0);
  animation: phSheen 7.5s var(--ease-inout) infinite;
  pointer-events: none;
}

@keyframes phSheen {
  0%, 62% { transform: translate3d(-38%, 0, 0); }
  100% { transform: translate3d(38%, 0, 0); }
}

.ph__meta {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 2;
  overflow-wrap: anywhere;
  display: flex;
  flex-direction: column;
  gap: 0.28em;
  padding: clamp(0.8rem, 1.4vw, 1.35rem);
  font-family: var(--font-mono);
  font-size: clamp(0.56rem, 0.66vw, 0.68rem);
  letter-spacing: 0.08em;
  color: rgba(16, 17, 19, 0.34);
  text-transform: none;
  line-height: 1.5;
}
.ph__meta b {
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--color-muted);
}

/* corner ticks — a survey-mark motif that repeats on the HUD and the gallery */
.ph__tick {
  position: absolute;
  z-index: 2;
  width: 14px;
  height: 14px;
  border: 1px solid rgba(16, 17, 19, 0.16);
  pointer-events: none;
}
.ph__tick--tl { top: 12px; left: 12px; border-right: 0; border-bottom: 0; }
.ph__tick--br { right: 12px; bottom: 12px; border-left: 0; border-top: 0; }

.ph > img {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Aspect helpers — these fix the geometry now so dropping the real files in
   later cannot reflow the page. */

/* ------------------------------------------------------- custom cursor --- */
.cursor {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 9000;
  pointer-events: none;
  mix-blend-mode: difference;
  opacity: 0;
  transition: opacity 0.3s linear;
}
.cursor.is-live { opacity: 1; }

.cursor__dot,
.cursor__ring {
  position: absolute;
  top: 0;
  left: 0;
  border-radius: 50%;
  will-change: transform;
}
.cursor__dot {
  width: 6px;
  height: 6px;
  margin: -3px 0 0 -3px;
  background: #fff;
}
.cursor__ring {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  margin: -23px 0 0 -23px;
  border: 1px solid rgba(255, 255, 255, 0.55);
  transition: width 0.4s var(--ease-out), height 0.4s var(--ease-out),
    margin 0.4s var(--ease-out), border-color 0.4s var(--ease-out),
    background-color 0.4s var(--ease-out);
}
.cursor__label {
  font-family: var(--font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.14em;
  color: #fff;
  opacity: 0;
  transform: scale(0.8);
  transition: opacity 0.3s var(--ease-out), transform 0.3s var(--ease-out);
}
.cursor.has-label .cursor__ring {
  width: 84px;
  height: 84px;
  margin: -42px 0 0 -42px;
  background: rgba(255, 255, 255, 0.1);
  border-color: rgba(255, 255, 255, 0.85);
}
.cursor.has-label .cursor__dot { opacity: 0; }
.cursor.has-label .cursor__label { opacity: 1; transform: scale(1); }

/* Touch and coarse pointers never see it. */
@media (hover: none), (pointer: coarse) {
  .cursor { display: none !important; }
}

/* ---------------------------------------------------- reveal primitives -- */
/* Elements start hidden only when JS is present and motion is allowed —
   `.js-motion` is added by main.js. Without JS everything is simply visible,
   which keeps the page readable as plain progressive enhancement. */
.js-motion [data-reveal] { opacity: 0; }
.js-motion [data-reveal="up"] { transform: translate3d(0, 34px, 0); }
/* `lines` reveals a headline through its own masks — the container stays
   visible so nothing pops, only the type travels. */
.js-motion [data-reveal="lines"] { opacity: 1; }
.js-motion [data-reveal="lines"] .ln > i { transform: translate3d(0, 110%, 0); }
.js-motion [data-reveal="clip"] { opacity: 1; clip-path: inset(0 0 100% 0); }

/* ------------------------------------------------------- reduced motion -- */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .ph__inner::before { display: none; }
  .cursor { display: none !important; }
  .js-motion [data-reveal] { opacity: 1 !important; transform: none !important; clip-path: none !important; }
  .js-motion [data-reveal="lines"] .ln > i { transform: none !important; }
}
