/* Owled — India launch site. Ported from the "Scroll Lock" design. */

:root {
  --accent: #E1251B;
  --ink: #111;
  --rule: #ececec;
  --rule-header: #e2e2e2;
  --rule-strong: #cfcfcb;
  --muted: #8d8d8a;
  --faint: #a8a8a4;
  --body: #4a4a48;
  --placeholder: #f4f4f2;
  --field: #d8d8d4;
  --hot: radial-gradient(145% 190% at 100% 100%, #f5953f 0%, #d82505 26%, #d82505 56%, #25110e 112%);
  --sans: 'Helvetica Neue', Helvetica, Arial, sans-serif;

  /* One easing family for the whole page: a strong ease-out for anything
     entering or responding, a snappier one for press feedback. */
  --ease: cubic-bezier(.2, .7, .2, 1);
  --ease-press: cubic-bezier(.23, 1, .32, 1);
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }
html, body { margin: 0; padding: 0; background: #fff; }
html { scroll-behavior: smooth; scroll-padding-top: 80px; }

body {
  font-family: var(--sans);
  color: var(--ink);
  background: #fff;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--ink); text-decoration: none; transition: color .15s ease; }
a:hover { color: var(--accent); }
::selection { background: var(--ink); color: #fff; }

input, textarea { font-family: inherit; }
input:focus, textarea:focus { outline: none; border-color: var(--ink); }

/* Keyboard focus gets the same ink hairline the rest of the page is built
   from, instead of the browser default blue ring. Pointer focus shows nothing. */
:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
:focus:not(:focus-visible) { outline: none; }

/* Counted numbers must not jitter in width while they run up. */
[data-count] { font-variant-numeric: tabular-nums; }

/* ---------- scrollbar ----------
   The gate used to hold the page with overflow:hidden, so the native bar
   appeared 15px wide, grey and black, and shoved the layout sideways the
   moment the hero released. The page is now always scrollable (the lock
   intercepts input instead), the gutter is reserved so nothing ever shifts,
   and the bar is a 4px pill in a hairline-ruled gutter that reads as one
   more rule of the grid. */

html { scrollbar-gutter: stable; }

::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: #fff; }
::-webkit-scrollbar-track:vertical { border-left: 1px solid var(--rule); }
::-webkit-scrollbar-thumb {
  background-color: var(--rule-strong);
  background-clip: padding-box;
  border: 3px solid transparent;
  border-left-width: 4px;
  border-radius: 99px;
}
::-webkit-scrollbar-thumb:hover,
::-webkit-scrollbar-thumb:active { background-color: var(--ink); }
::-webkit-scrollbar-button { width: 0; height: 0; display: none; }
::-webkit-scrollbar-corner { background: #fff; }

/* Firefox has no scrollbar pseudo-elements; give it the same thin, quiet bar. */
@supports not selector(::-webkit-scrollbar) {
  html { scrollbar-width: thin; scrollbar-color: var(--rule-strong) #fff; }
}

/* ---------- shared type ---------- */

.eyebrow {
  font-size: 11px;
  letter-spacing: .16em;
  text-transform: uppercase;
}
.eyebrow--faint { color: var(--faint); }
.eyebrow--muted { color: var(--muted); }

.hot {
  background-image: var(--hot);
  background-clip: text;
  -webkit-background-clip: text;
  color: transparent;
}

/* ---------- animations ---------- */

@keyframes rise      { from { opacity: 0; transform: translateY(.24em); } to { opacity: 1; transform: none; } }
@keyframes numSlide  { from { opacity: 0; transform: translateY(.42em); } to { opacity: 1; transform: none; } }
@keyframes recBlink  { 0%, 45% { opacity: 1; } 55%, 100% { opacity: .15; } }
@keyframes marqx     { from { transform: translate3d(0, 0, 0); } to { transform: translate3d(-50%, 0, 0); } }

/* ---------- scroll reveals ----------
   Only when JS is running (the html.js hook), so the page never depends on
   an observer firing to be readable. Delay is set per element by script so
   siblings that arrive together cascade instead of popping in as one. */

.js [data-reveal] {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity .7s var(--ease), transform .7s var(--ease);
}
.js [data-reveal].is-in { opacity: 1; transform: none; }

/* ---------- header ---------- */

.header {
  position: sticky;
  top: 16px;
  z-index: 50;
  padding: 0 16px;
  margin-bottom: -62px;
}
.header__bar {
  max-width: 1360px;
  margin: 0 auto;
  height: 62px;
  padding: 0 20px;
  background: rgba(255,255,255,.86);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid var(--rule-header);
  box-shadow: 0 14px 34px -22px rgba(17,17,17,.3);
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
}
.header__nav { display: flex; gap: 34px; }
.header__nav a { color: var(--muted); }
.header__nav a:hover { color: var(--accent); }
.header__cta { display: flex; justify-content: flex-end; gap: 22px; color: var(--muted); }

/* ---------- hero ---------- */

.hero {
  height: 100svh;
  min-height: 540px;
  display: flex;
  flex-direction: column;
}
.hero__gap {
  flex: none;
  height: 92px;
  border-bottom: 1px solid var(--rule);
}
.hero__head {
  margin: 0;
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  font-size: min(11.4vw, 22svh, 230px);
  line-height: 1;
  font-weight: 400;
  letter-spacing: -.045em;
  text-transform: uppercase;
}
.hero__row {
  flex: none;
  height: .88em;
  display: flex;
  align-items: center;
  overflow: hidden;
  border-bottom: 1px solid var(--rule);
  padding: 0 22px 0 var(--indent);
  animation: rise .85s var(--ease) var(--delay, 0s) both;
}
.hero__row:nth-child(1) { --indent: 1.5%; --delay: 0s; }
.hero__row:nth-child(2) { --indent: 9%;   --delay: .08s; }
.hero__row:nth-child(3) { --indent: 18%;  --delay: .16s; }
.hero__row:nth-child(4) { --indent: 32%;  --delay: .24s; position: relative; }
.hero__line {
  display: block;
  white-space: nowrap;
  line-height: .84;
  will-change: transform;
}
.hero__foot {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 22px;
  padding: clamp(16px,3vh,30px) 22px clamp(20px,3.4vh,34px);
}
.hero__foot a {
  border-bottom: 1px solid var(--ink);
  padding-bottom: 3px;
  transition: color .15s ease, border-color .15s ease;
}
.hero__foot a:hover { border-color: var(--accent); }

/* The gate holds the page until a set amount of scroll intent (1500px on a
   wheel, 400px on touch, see script.js) has been spent on the hero. Without
   a cue that reads as a broken page; this hairline fills with the intent
   and fades once the page is free. Shown only while the
   lock is armed (html[data-locked], set by script). */
.hero__cue {
  display: flex;
  align-items: center;
  gap: 14px;
  color: var(--faint);
  opacity: 0;
  transition: opacity .35s ease;
}
html[data-locked] .hero__cue { opacity: 1; }
.hero__cue-track {
  display: block;
  width: 72px;
  height: 1px;
  background: var(--rule-header);
  overflow: hidden;
}
.hero__cue-bar {
  display: block;
  height: 100%;
  background: var(--ink);
  transform: scaleX(0);
  transform-origin: left center;
  will-change: transform;
}

/* ---------- reach ---------- */

.reach { padding: clamp(60px,10vh,120px) 22px 0; }

/* The figures sit in one ruled band that runs edge to edge, the way the hero
   rows do: a hairline above, one below, one between each figure. Nothing is
   boxed, so the numbers carry the weight. The negative margins pull the
   band out to the viewport edge while the text keeps the 22px gutter. */
.stats {
  margin: 0 -22px;
  padding: 0 22px;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}
.stats__grid {
  max-width: 1360px; /* the header bar's width, so the band sits under it */
  margin: 0 auto;
  display: grid;
  /* Figures are content-width tracks with a 1px rule track between them.
     space-between hands the leftover width out in equal shares, so the gap
     from a figure to the line beside it is the same in every cell, and the
     first and last figures sit flush with the column edges. */
  grid-template-columns: auto 1px auto 1px auto 1px auto;
  justify-content: space-between;
  align-items: stretch;
}
.stats__rule {
  width: 1px;
  background: var(--rule);
}
.stat {
  min-width: 0;
  padding: clamp(32px,4vh,44px) 0 clamp(38px,5vh,56px);
  display: flex;
  flex-direction: column;
  gap: clamp(44px,7vh,84px);
}
/* Labels run one or two lines; a fixed gap keeps the four figures on one
   baseline and lets the labels ragged-out below instead. */
.stat__value {
  font-size: clamp(44px,5.4vw,84px);
  line-height: .92;
  letter-spacing: -.05em;
  width: fit-content;
}
.stat__label {
  margin-top: 18px;
  max-width: 22ch;
  font-size: 13px;
  line-height: 1.4;
  color: var(--body);
  text-wrap: pretty;
}

/* ---------- services: PREVIOUS STYLE, ruled ink rows ----------
   Kept commented so the section can be swapped back. The markup is commented
   out in index.html at the same time; restoring means uncommenting both and
   taking .section--work's border-top back off, because this list closed on an
   ink rule that acted as the divider into launch films.

   Notes that were inline, kept as prose so this block can stay one comment:
   - Rules ran to the viewport edge like the reach band's so the two lined up,
     but in ink rather than hairline grey; the figures read quiet, the claim
     loud. Padding sat on the row, not the list, so the rules reached the edge
     while the text kept the page's 22px gutter.
   - Name left, index hard right, baseline aligned so the 11px index sat on the
     display type's baseline instead of floating mid-row.
   - The hot gradient was painted behind the glyphs from the start and the ink
     fill faded off it on hover, making the colour change a crossfade.

.services {
  list-style: none;
  margin: clamp(38px,6vh,72px) -22px 0;
  padding: 0;
  border-top: 1px solid var(--ink);
}
.service {
  margin: 0;
  padding: clamp(20px,3.2vh,36px) 22px;
  border-bottom: 1px solid var(--rule);
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 22px;
}
.service:last-child { border-bottom-color: var(--ink); }
.service__name {
  min-width: 0;
  font-size: clamp(30px,5.4vw,88px);
  line-height: 1;
  letter-spacing: -.04em;
  text-transform: uppercase;
  text-wrap: balance;
  background-image: var(--hot);
  background-clip: text;
  -webkit-background-clip: text;
  color: var(--ink);
  transition: color .32s var(--ease), transform .32s var(--ease);
}
.service__index {
  flex: none;
  transition: color .2s ease;
}
   ---------- end previous style ---------- */


/* ---------- services: highlight cards ----------
   Ported from a React + framer-motion "product highlight card". Everything the
   original did with motion values is done here with CSS custom properties that
   script.js writes on pointermove, and one rAF spring for the tilt; there is no
   bundler on this site to hang React, Tailwind or framer-motion off.

   The depth is real 3D, not a fake: perspective sits on each card (not on the
   grid, or all three would share one vanishing point and the outer two would
   shear), the tilt layer is preserve-3d, and body and mark sit on their own Z
   planes so they part as the card turns.

   One thing deliberately not copied: the original reset its motion values to 0
   on mouse leave, and since 0 maps to the top-left of its input range that
   snapped the card to a corner instead of flat. Here leaving springs it back
   to level. */

/* Sections carry no bottom padding by default, which was fine when the list
   closed on a rule. Cards need a floor, or they sit against the next section's
   hairline. */
.section--services { padding-bottom: clamp(60px,10vh,120px); }

.svc-cards {
  list-style: none;
  margin: clamp(38px,6vh,72px) 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0,1fr));
  gap: clamp(20px,2.6vw,38px);
}

.svc-card {
  min-width: 0;
  /* No aspect ratio: the card holds a title and a numeral and nothing else, so
     a fixed image-shaped box only opened dead space that read as a missing
     picture. Height comes from the body's own min-height instead -- enough
     room for the numeral to sit clear of a two-line title, no more. */
  display: flex;
  perspective: 1100px;
}

/* The layer the spring drives. Sized by the card, holds every 3D child. */
.svc-card__tilt {
  position: relative;
  width: 100%;
  border-radius: 20px;
  background: #fff;
  border: 1px solid var(--rule);
  box-shadow: 0 18px 44px -32px rgba(17,17,17,.5);
  transform-style: preserve-3d;
  transition: box-shadow .35s var(--ease), border-color .35s var(--ease);
  will-change: transform;
}
.svc-card[data-hot] .svc-card__tilt {
  box-shadow: 0 40px 80px -34px rgba(17,17,17,.55);
  border-color: var(--rule-strong);
}

/* Inset panel carrying the texture and the glow. Anything with overflow other
   than visible is forced back to a flat transform style, so this holds no 3D
   children -- the body and the mark are its siblings, not its descendants. */
.svc-card__panel {
  position: absolute;
  inset: 14px;
  border-radius: 13px;
  background: var(--placeholder);
  overflow: hidden;
  box-shadow: inset 0 1px 2px rgba(17,17,17,.05);
}
.svc-card__grid {
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(to right, rgba(17,17,17,.09) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(17,17,17,.09) 1px, transparent 1px);
  background-size: 32px 32px;
  -webkit-mask-image: radial-gradient(ellipse 60% 60% at 50% 50%, #000 55%, transparent 100%);
          mask-image: radial-gradient(ellipse 60% 60% at 50% 50%, #000 55%, transparent 100%);
}
/* --gx/--gy are written by script.js on pointermove. */
.svc-card__glow {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity .35s var(--ease);
  background: radial-gradient(130px circle at var(--gx,50%) var(--gy,50%),
              rgba(216,37,5,.34), rgba(245,149,63,.12) 44%, transparent 70%);
}
.svc-card[data-hot] .svc-card__glow { opacity: 1; }

/* Text rides forward of the panel so it separates as the card turns. It is
   also the only element in flow, so it -- not an aspect ratio -- sets the
   card's height. The margin matches the panel's inset so the two still line
   up; min-height keeps the three cards level when one title wraps shorter. */
.svc-card__body {
  position: relative;
  margin: 14px;
  min-height: clamp(140px,13vw,178px);
  padding: clamp(18px,1.7vw,26px);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  transform: translateZ(34px);
}
.svc-card__title {
  margin: 0;
  max-width: 11ch;
  font-size: clamp(22px,2.3vw,34px);
  line-height: 1.02;
  font-weight: 400;
  letter-spacing: -.035em;
  text-transform: uppercase;
  text-wrap: balance;
}

/* The index numeral stands in for the original's product shot: set large,
   furthest forward of all three planes, and it lifts and grows on hover the
   way that image did. Type, not a picture -- the page gains no new content,
   only depth.

   The original hung its image off the card's corner with negative insets. That
   cannot work in a three-up row: the overhang reaches into the gap and lands on
   the next card. This sits wholly inside its own card, diagonally opposite the
   title so the two never meet. */
.svc-card__art {
  position: absolute;
  top: 22px;
  right: 8%;
  /* Sized off the card's own height now that the card is text-tall: big enough
     to still read as the plate the title sits against, small enough that it
     clears a two-line title instead of forcing the box taller. */
  font-size: clamp(64px,6.2vw,96px);
  line-height: .9;
  letter-spacing: -.07em;
  color: var(--ink);
  opacity: .11;
  transform: translateZ(64px);
  transition: transform .45s var(--ease), opacity .45s var(--ease);
  pointer-events: none;
  user-select: none;
}
.svc-card[data-hot] .svc-card__art {
  opacity: .2;
  transform: translateZ(64px) scale(1.07) translate(3%, -6%);
}

/* ---------- section headers ---------- */

.section { padding: clamp(70px,12vh,150px) 22px 0; }
.section--work {
  /* Back on with the card layout: the ruled list used to close on an ink rule
     that divided this section off, and the cards end on nothing. Remove it
     again if the previous services style is restored. */
  border-top: 1px solid var(--rule);
  padding: clamp(60px,10vh,120px) 22px 0;
}
/* Eyebrow above, title across the full measure. The title used to sit in a 2fr
   column indented a third of the way in, which left "Films that put a product
   in front of the world" about 1240px of line to fit into 654px -- it broke
   over two lines at every size worth setting it at, and fitting it in that
   column would have meant 26px type. Across the full width it sets on one line
   at the size it already wants, and stays on one line down to 760px, below
   which the clamp floors at 26px and it wraps -- which is what a phone wants. */
.section__head {
  display: grid;
  gap: clamp(16px,2.4vh,26px);
  justify-items: start;
}
.section__title {
  margin: 0;
  font-size: clamp(26px,3.4vw,50px);
  line-height: 1.06;
  font-weight: 400;
  letter-spacing: -.035em;
  text-transform: uppercase;
  text-wrap: balance;
}

/* ---------- launch films ---------- */

.films {
  display: grid;
  grid-template-columns: repeat(3, minmax(0,1fr));
  gap: clamp(20px,2.6vw,38px);
  margin-top: clamp(40px,7vh,88px);
}
.film { min-width: 0; }
.film__frame {
  position: relative;
  display: block;
  width: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  background: var(--placeholder);
  overflow: hidden;
  aspect-ratio: 16 / 9;
  cursor: pointer;
  font: inherit;
  color: inherit;
  transition: transform .16s var(--ease-press);
}
.film__frame:active { transform: scale(.985); }
.film__frame img,
.film__frame video {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* The preview sits over the poster and fades in once it has frames to show. */
.film__frame video {
  opacity: 0;
  transition: opacity .28s linear;
}
.film__frame[data-playing] video { opacity: 1; }

.film__frame img {
  transition: transform .5s var(--ease);
}

.film__play {
  position: absolute;
  left: 14px;
  bottom: 14px;
  z-index: 2;
  width: 38px;
  height: 38px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  color: var(--ink);
  background: rgba(255,255,255,.86);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  box-shadow: 0 10px 24px -12px rgba(17,17,17,.55);
  transition: background-color .18s linear, color .18s linear, transform .28s var(--ease);
}
.film__frame:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

/* ---------- lightbox ----------
   Enters as a fade with the stage settling up from 97%; leaves faster, as a
   plain fade, so dismissing never feels slower than opening. */

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(16px, 4vw, 56px);
  background: rgba(255,255,255,.92);
  backdrop-filter: blur(18px) saturate(1.4);
  -webkit-backdrop-filter: blur(18px) saturate(1.4);
  opacity: 1;
  transition: opacity .26s ease;
}
@starting-style { .lightbox { opacity: 0; } }
.lightbox.is-closing { opacity: 0; pointer-events: none; transition-duration: .16s; }
.lightbox__stage {
  width: 100%;
  max-width: 1180px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  opacity: 1;
  transform: none;
  transform-origin: center;
  transition: opacity .34s var(--ease), transform .34s var(--ease);
}
@starting-style { .lightbox__stage { opacity: 0; transform: scale(.97) translateY(8px); } }
.lightbox.is-closing .lightbox__stage {
  opacity: 0;
  transform: scale(.985);
  transition-duration: .16s;
}
/* width:auto lets max-height shrink the box proportionally. With width:100%
   a tall film keeps full stage width and pillarboxes itself in black. */
.lightbox__stage video {
  display: block;
  width: auto;
  max-width: 100%;
  max-height: 78svh;
  margin: 0 auto;
  background: #000;
  border: 1px solid var(--rule);
}
.lightbox__title { color: var(--muted); }
.lightbox__close {
  position: absolute;
  top: clamp(12px, 2.4vw, 28px);
  right: clamp(12px, 2.4vw, 28px);
  width: 44px;
  height: 44px;
  border: 1px solid var(--rule-header);
  background: rgba(255,255,255,.86);
  color: var(--ink);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  transition: background-color .18s ease, color .18s ease, border-color .18s ease, transform .16s var(--ease-press);
}
.lightbox__close:hover { background: var(--accent); color: #fff; border-color: var(--accent); }
.lightbox__close:active { transform: scale(.94); }
.film__caption {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--rule);
}

.more {
  display: flex;
  justify-content: center;
  padding-top: 40px;
}
.link-button {
  background: none;
  border: 0;
  border-bottom: 1px solid var(--ink);
  padding: 0 0 3px;
  font-family: inherit;
  font-size: 11px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink);
  cursor: pointer;
  transition: color .15s ease, border-color .15s ease, transform .16s var(--ease-press);
}
.link-button:hover { color: var(--accent); border-bottom-color: var(--accent); }
.link-button:active { transform: scale(.97); }

/* ---------- influencer reels ---------- */

.reels {
  display: grid;
  grid-template-columns: repeat(4, minmax(0,1fr));
  gap: clamp(20px,2.6vw,38px);
  margin-top: clamp(40px,7vh,88px);
}
.reel { display: block; min-width: 0; color: inherit; }
.reel:hover { color: inherit; }
.reel__frame {
  position: relative;
  aspect-ratio: 9 / 16;
  background: var(--placeholder);
  overflow: hidden;
}
.reel__frame video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform .5s var(--ease);
}
.reel__caption {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--rule);
  display: flex;
  justify-content: space-between;
  gap: 10px;
}
.reel__views { color: var(--faint); }

.reel-more { min-width: 0; }
.reel-more__card {
  aspect-ratio: 9 / 16;
  border: 1px solid var(--rule);
  padding: 24px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}
.reel-more__value {
  font-size: clamp(40px,4.4vw,68px);
  line-height: 1;
  letter-spacing: -.04em;
  width: fit-content;
}
.reel-more__label {
  margin-top: 14px;
  font-size: 14px;
  line-height: 1.45;
  color: var(--body);
  text-wrap: pretty;
}
.reel-more__caption {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--rule);
}

/* ---------- owned distribution marquee ---------- */

.marquee {
  overflow: hidden;
  margin-top: clamp(40px,7vh,88px);
  margin-left: -22px;
  margin-right: -22px;
  padding: 0 22px;
}
.marquee__track {
  display: flex;
  width: max-content;
  gap: clamp(20px,2.6vw,38px);
  animation: marqx 70s linear infinite reverse;
}

.page-card {
  flex: none;
  width: clamp(300px,25vw,360px);
  border: 1px solid var(--rule);
  padding: 20px;
  color: inherit;
  display: flex;
  flex-direction: column;
  gap: 16px;
  transition: border-color .2s ease, color .15s ease;
}
.page-card:hover { color: inherit; }
.page-card__id {
  display: flex;
  align-items: center;
  gap: 14px;
  min-width: 0;
}
.page-card__avatar {
  flex: none;
  width: 56px; height: 56px;
  border-radius: 50%;
  background: var(--placeholder) no-repeat center / cover;
}
.page-card__handle {
  font-size: 15px;
  letter-spacing: -.015em;
  overflow: hidden;
  text-overflow: ellipsis;
}
.page-card__name {
  margin-top: 4px;
  font-size: 12px;
  color: var(--muted);
}
.page-card__metrics {
  display: grid;
  grid-template-columns: repeat(3, minmax(0,1fr));
  column-gap: 14px;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}
.page-card__metric { padding: 13px 0; }
.page-card__metric b {
  display: block;
  font-size: 17px;
  font-weight: 400;
  letter-spacing: -.02em;
}
.page-card__metric span {
  display: block;
  margin-top: 5px;
  font-size: 9px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--faint);
}
.page-card__bio {
  font-size: 13px;
  line-height: 1.45;
  color: var(--body);
  text-wrap: pretty;
}
.page-card__links {
  margin-top: auto;
  font-size: 10px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--faint);
}

/* ---------- hover states ----------
   Gated to devices that actually hover. On touch, :hover sticks after a tap,
   which would leave a tile zoomed and the marquee frozen. */

@media (hover: hover) and (pointer: fine) {
  .film__frame:hover img { transform: scale(1.03); }
  .film__frame:hover .film__play {
    background-color: var(--accent);
    color: #fff;
    transform: scale(1.06);
  }
  .reel:hover .reel__frame video { transform: scale(1.03); }
  .page-card:hover { border-color: var(--rule-strong); }
  .marquee:hover .marquee__track { animation-play-state: paused; }
}

/* ---------- contact ---------- */

.contact { padding: clamp(80px,13vh,170px) 22px 0; }
.contact__title {
  margin: 0;
  font-size: clamp(32px,6.6vw,120px);
  line-height: .98;
  font-weight: 400;
  letter-spacing: -.04em;
  text-transform: uppercase;
}
.contact__title span { display: block; }
.contact__title .hot { padding-left: 12%; width: fit-content; }
.contact__sla {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 26px;
  color: var(--muted);
}
.dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--accent);
  display: inline-block;
  animation: recBlink 1.4s steps(1, end) infinite;
}

.contact__body { width: 100%; margin: clamp(44px,7vh,84px) 0 0; }

/* One full-width rule-to-rule row: the whole band is the target, the arrow
   is the only ornament. Hover paints the arrow hot and nudges it up-right,
   the direction the link takes you. */
.contact__cta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  width: 100%;
  padding: clamp(26px,4vh,40px) 0;
  border-top: 1px solid var(--ink);
  border-bottom: 1px solid var(--ink);
  color: var(--ink);
  transition: color .18s ease, transform .16s var(--ease-press);
}
.contact__cta-label {
  font-size: clamp(22px,3.2vw,44px);
  line-height: 1;
  letter-spacing: -.03em;
  text-transform: uppercase;
}
.contact__cta-arrow {
  flex: none;
  display: grid;
  place-items: center;
  width: clamp(44px,4.4vw,64px);
  height: clamp(44px,4.4vw,64px);
  border: 1px solid var(--rule-strong);
  border-radius: 50%;
  transition: background-color .18s ease, border-color .18s ease, color .18s ease, transform .28s var(--ease);
}
.contact__cta-arrow svg { display: block; width: 44%; height: 44%; }
.contact__cta:active { transform: scale(.99); }
.contact__cta:focus-visible { outline-offset: 6px; }
@media (hover: hover) and (pointer: fine) {
  .contact__cta:hover { color: var(--accent); }
  .contact__cta:hover .contact__cta-arrow {
    background: var(--accent);
    border-color: var(--accent);
    color: #fff;
    transform: translate(3px,-3px);
  }
}
.contact__note { margin-top: 18px; }

/* ---------- footer ---------- */

.footer {
  margin-top: clamp(80px,12vh,150px);
  border-top: 1px solid var(--rule);
  padding: 24px 22px;
}
.footer__inner {
  display: flex;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
  color: var(--faint);
}

/* ---------- responsive ---------- */

@media (max-width: 900px) {
  .header__nav { gap: 20px; }
  /* Two figures a row: the rule spans hide and cell borders draw the lines,
     one between the columns and one between the rows. nth-of-type counts
     only the .stat divs, skipping the hidden spans. */
  .stats__grid { grid-template-columns: repeat(2, minmax(0,1fr)); }
  .stats__rule { display: none; }
  .stat:nth-of-type(odd) { padding-right: 22px; }
  .stat:nth-of-type(even) { border-left: 1px solid var(--rule); padding-left: 22px; }
  .stat:nth-of-type(n+3) { border-top: 1px solid var(--rule); }
  .stat__value { font-size: clamp(40px,8vw,64px); }
  /* Three squares across is too narrow here; two up, and let them squat. */
  .svc-cards { grid-template-columns: repeat(2, minmax(0,1fr)); }
  /* Three into two columns leaves the last card alone in a half-width cell;
     let it take the whole row instead. It runs shorter than the pair above it
     because its title cannot wrap at that width -- that is fine, the height is
     the text's now. */
  .svc-card:last-child { grid-column: 1 / -1; }
  .svc-card__title { max-width: 10ch; }
  .films { grid-template-columns: repeat(2, minmax(0,1fr)); }
  .reels { grid-template-columns: repeat(2, minmax(0,1fr)); }
  .reel-more__card {
    aspect-ratio: auto;
    gap: 28px;
    padding: 22px;
  }
}

@media (max-width: 600px) {
  .header__bar { grid-template-columns: 1fr auto; }
  .header__nav { display: none; }
  .stat { padding-top: 20px; padding-bottom: 24px; gap: 28px; }
  .stat:nth-of-type(odd) { padding-right: 18px; }
  .stat:nth-of-type(even) { padding-left: 18px; }
  .stat__value { font-size: 40px; }
  /* One per row, and short, so three cards do not become three screens. */
  .svc-cards { grid-template-columns: minmax(0,1fr); gap: 16px; }
  .svc-card__body { min-height: 132px; }
  .svc-card__title { max-width: none; font-size: clamp(24px,7vw,32px); }
  /* One card per row is wide enough that "LAUNCH VIDEOS" fits on one line,
     while the longer two still wrap -- so the three cards disagreed about
     where their accent word sits. Break before it on all three instead of
     leaning on the wrap. fit-content keeps the gradient box hugging the
     word, the way it does when the line breaks on its own. */
  .svc-card__title .hot { display: block; width: fit-content; }
  .svc-card__art { font-size: clamp(72px,20vw,104px); }
  .films { grid-template-columns: minmax(0,1fr); }
  .reels { grid-template-columns: minmax(0,1fr); }
  .reel-more__card {
    gap: 20px;
    padding: 22px;
  }
  .reel-more__value { font-size: 44px; }
  .reel-more__label { margin-top: 10px; }
}

/* Reduced motion means fewer and gentler animations, not none: fades stay,
   movement goes. Press feedback stays because it is tiny and confirms input. */
@media (prefers-reduced-motion: reduce) {
  .film__frame img { transition: none; }
  .film__frame:hover img { transform: none; }
  .reel__frame video { transition: none; }
  .reel:hover .reel__frame video { transform: none; }
  .lightbox { transition: none; }
  .lightbox__stage { transition: none; }
  .marquee__track { animation: none; }
  .hero__row { animation: none; }
  .hero__cue { display: none; }
  .dot { animation: none; }
  .contact__cta-arrow { transition: background-color .18s ease, border-color .18s ease, color .18s ease; }
  .contact__cta:hover .contact__cta-arrow { transform: none; }
  /* script.js skips the tilt and the glow entirely under reduced motion; this
     stops the numeral drifting on hover as well. */
  .svc-card__art { transition: opacity .3s ease; }
  .svc-card[data-hot] .svc-card__art { transform: translateZ(64px); }
  .js [data-reveal] { opacity: 1; transform: none; transition: none; }
  html { scroll-behavior: auto; }
}
