/* ============================================================================
   OTEO DESIGN SYSTEM — anchored on LESMANA, the template Alec paid for.
   ============================================================================

   CORRECTION, 2026-08-19. The first version of this file anchored the site on
   SIRUP_5TH_CLONE's faces (Glodok + Termina) because the djoteo-build skill
   calls that repo "the purchased $129 template / DESIGN SOURCE OF TRUTH". That
   is wrong. Alec: "siurp shouldve been nuked" / "i paid for lessman".

   The template he bought is LESMANA — the Framer build that IS the live
   homepage (/, /works, /blog), which check.sh has always described correctly:
   "index.html is the Velox Lesmana clone (Alec-verified target, 2026-07-19)".

   So the first pass had it backwards: it dragged the paid template onto a
   different template's typography, and deleted Geist, Geist Mono and Playfair
   Display as "off-system" — the three faces Lesmana actually uses.

   LESMANA'S OWN TYPE SYSTEM, read out of its CSS rather than guessed:

     preset            face                    size   weight  tracking
     9jiir1  hero      Playfair Display         56px    400    -.04em
     j77x7r  giant     Playfair Display        100px    400    -.03em
     yrtdmr  head      Playfair Display         38px    400    -.03em
     1e5hq0o card      Playfair Display         32px    400    -.03em
     7v93b9  quote     Playfair Display         18px    400    -.03em
     10o1gtm nav       Playfair Display         16px    400    -.02em
     19qorhk body      Geist                    16px    400    -.02em
     1y7c7cl small     Geist                    14px    400    -.02em
     23zch4  eyebrow   Geist Mono               12px    500     .14em

   Three faces, three jobs — Lesmana's, not mine:
     PLAYFAIR DISPLAY  every display size, and the nav
     GEIST             running copy
     GEIST MONO        eyebrows, labels, metadata

   This file's job is unchanged: make the seven hand-built routes speak the paid
   template's language, so both halves match. The direction is now hand-built ->
   Lesmana, instead of Lesmana -> somewhere else. Loaded last on every route.
   ========================================================================= */

/* Lesmana self-hosts these on its own routes; declared here so the hand-built
   pages can use the same files. Root-absolute paths work from both halves. */
/* NOTE: these MUST be the Latin subsets. The first attempt picked files by
   font-weight alone and landed on Google's CYRILLIC subsets (U+0460-052F),
   so every glyph outside that range fell back to a serif — visible as the
   italic "A" in REQUEST A DATE on mobile. Subsets carry their unicode-range
   through, exactly as Lesmana declares them. */
@font-face {
  font-family: "Geist";
  src: url("/_ext/fonts.gstatic.com/s/geist/v5/gyBhhwUxId8gMGYQMKR3pzfaWI_RnOM4mJPby1QNtA.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Geist";
  src: url("/_ext/fonts.gstatic.com/s/geist/v5/gyBhhwUxId8gMGYQMKR3pzfaWI_RQuQImpna.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Geist";
  src: url("/_ext/fonts.gstatic.com/s/geist/v5/gyBhhwUxId8gMGYQMKR3pzfaWI_Re-Q4mJPby1QNtA.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Geist Mono";
  src: url("/_ext/fonts.gstatic.com/s/geistmono/v6/or3lQ6H-1_WfwkMZI_qYFrItmBvj.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Geist Mono";
  src: url("/_ext/fonts.gstatic.com/s/geistmono/v6/or3lQ6H-1_WfwkMZI_qYFrItmBvj.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  --oteo-display: "Playfair Display", Georgia, serif;
  --oteo-body: "Geist", system-ui, sans-serif;
  --oteo-label: "Geist Mono", ui-monospace, monospace;

  /* Lesmana's steps, not invented ones. */
  --t-giant: clamp(56px, 7vw, 100px);
  --t-hero: clamp(38px, 4.4vw, 56px);
  --t-head: clamp(28px, 2.9vw, 38px);
  --t-card: clamp(24px, 2.2vw, 32px);
  --t-quote: 18px;
  --t-body: 16px;
  --t-small: 14px;
  --t-label: 12px;

  --oteo-gold: #c8a96a;
  --oteo-cream: #f1ede4;
  --oteo-ink: #08090b;
}

/* ---------------------------------------------------------------- DISPLAY */
h1, h2,
.about-title, .contact-hero-title, .section-title, .sound-head,
.contact-statement, .showcase-statement, .neo-hero-line,
.svc-hero h1, .res-hero h1, .agenda-hero h1, .label-hero h1,
.page-calendar .sync .h, .page-booking .sec > .head, .page-foowr .band .head {
  font-family: var(--oteo-display) !important;
  font-weight: 400 !important;
  letter-spacing: -.03em !important;
  line-height: 1.06;
  text-transform: none !important;
}
h1, .contact-hero-title, .about-title,
.svc-hero h1, .res-hero h1, .agenda-hero h1, .label-hero h1 {
  font-size: var(--t-hero) !important;
}
h2, .section-title, .sound-head, .contact-statement, .showcase-statement,
.page-calendar .sync .h, .page-booking .sec > .head, .page-foowr .band .head {
  font-size: var(--t-head) !important;
}
h3, h4, .pkg-card h3, .eqp-card h3, .card h3, .gear-cat, .past-title,
.mr-name, .edit-title, .room-idx {
  font-family: var(--oteo-display) !important;
  font-weight: 400 !important;
  font-size: var(--t-card) !important;
  letter-spacing: -.03em !important;
  text-transform: none !important;
}

/* Lesmana's accent inside a headline is the same face in gold — no italic
   serif, no second family. */
h1 em, h2 em, h3 em,
.svc-hero h1 em, .res-hero h1 em, .agenda-hero h1 em, .label-hero h1 em,
.contact-hero-title em, .about-title em, .neo-hero-line em,
.contact-statement em, .showcase-statement em {
  font-family: var(--oteo-display) !important;
  font-style: normal !important;
  font-weight: 400 !important;
  letter-spacing: -.03em !important;
  color: var(--oteo-gold) !important;
}

/* ------------------------------------------------------- LABELS / EYEBROWS */
.eyebrow, .kicker, .neo-kicker, .k, .meta .k, .stat-label, .card-tag, .tag,
.chip, .badge, .live-tag, .mr-tag, .page-booking .direct-line, .form-note,
.date-bar-label, .footer-nav a, .social a, .skip-link, .sec .n, .step .n {
  font-family: var(--oteo-label) !important;
  font-size: var(--t-label) !important;
  font-weight: 500 !important;
  letter-spacing: .14em !important;
  text-transform: uppercase !important;
}
.btn, .hero-cta, .header-cta, .book, .v-cta, .sync .cta, .mob-cta {
  font-family: var(--oteo-label) !important;
  font-size: var(--t-label) !important;
  font-weight: 500 !important;
  letter-spacing: .14em !important;
  text-transform: uppercase !important;
}
/* The one exemption: the header's Book OTEO. Lesmana does exactly this — its
   in-page buttons are Geist Mono labels ("BOOK A DATE →") while the header CTA
   is Playfair, mixed case. Matching that is what makes the header stop changing
   personality between the Framer homepage and the hand-built routes. Specific
   enough to beat .btn, which the markup also carries. */
.site-header .header-cta {
  font-family: var(--oteo-display) !important;
  font-size: 16px !important;
  font-weight: 400 !important;
  letter-spacing: -.03em !important;
  text-transform: none !important;
}

/* Nav and wordmark follow Lesmana: Playfair, mixed case, quiet. */
.nav-links a, .brand, .home-next .brand, .site-header.on-light .brand,
.site-footer .footer-brand {
  font-family: var(--oteo-display) !important;
  font-weight: 400 !important;
  letter-spacing: -.02em !important;
  text-transform: none !important;
}
.nav-links a { font-size: var(--t-body) !important; }
.brand, .home-next .brand, .site-header.on-light .brand,
.site-footer .footer-brand { font-size: 22px !important; }

/* ------------------------------------------------------------------ BODY */
body, p, li, dd, dt, input, textarea, select, button, label, figcaption,
.section-deck, .footer-copy, .contact-sub, .v-body p, .lede, .desc, .past-deck,
.summary, .sub, .edit-sub {
  font-family: var(--oteo-body);
  letter-spacing: -.02em;
}
p, li, .section-deck, .v-body p, .summary { font-size: var(--t-body); line-height: 1.6; }
.desc, .past-deck, .sub, .footer-copy, .contact-sub, .edit-sub,
small, .small { font-size: var(--t-small); line-height: 1.6; }
.lede, .section-deck { font-size: var(--t-quote); line-height: 1.5; }

/* ------------------------------------------------- THE LESMANA CLONE ROUTES */
/* The clone already renders its own presets correctly — it IS the spec — so it
   is left alone apart from the pieces Framer sets inline in the wrong face,
   and the nav parity the hand-built side now matches. A blanket
   `.framer-text *` rule is never acceptable here: it flattened the hero to body
   text on the first attempt. */
[style*="Times New Roman"], [style*="Times New Roman"] * {
  font-family: var(--oteo-display) !important;
}
[class*="framer-styles-preset-"] span, .framer-text span {
  font-family: inherit !important;
}

/* ---------------------------------------------------------- BLUE AS A FIELD */
.contact, .page-residencies .close-cta {
  background:
    radial-gradient(120% 90% at 50% 0%, rgba(36, 63, 156, .55), transparent 70%),
    var(--oteo-ink) !important;
  border-top: 1px solid rgba(200, 169, 106, .22) !important;
}
.contact-statement, .contact-hero-title { color: var(--oteo-cream) !important; }

/* ------------------------------------------------------------ DEAD SCROLL */
/* The stats section was 2,110px to deliver four numbers: a 560px sticky card
   plus a 1,350px empty scroll-trigger. Kept from the density pass — it is a
   layout fix, not a typography opinion, so the re-anchor does not undo it. */
[data-framer-name="Why us"] [data-framer-name="Scroll trigger"] {
  height: 420px !important;
  min-height: 0 !important;
}
@media (min-width: 900px) {
  [data-framer-name="Why us"] [data-framer-name="Middle"] {
    min-width: 382px !important;
    max-width: 420px !important;
  }
}
/* One statement of a number per page: the testimonials block carried a second
   copy of the venues counter with no heading. */
[data-framer-name="Testimonials"] .framer-1rwjy3b { display: none !important; }

/* --------------------------------------------------------- HOMEPAGE CUT */
/* Over half the homepage was the template's marketing funnel or a duplicate of
   /booking: services list, a four-step "how we work" that commits to nothing,
   two pricing tiers both priced "Custom", 12 generic archive tiles, and the FAQ
   in full. 839 -> 284 words, 15.9 -> 7.5 screens. Content, not type — kept. */
[data-framer-name="Expertise"],
[data-framer-name="How we work"],
[data-framer-name="Pricing"],
[data-framer-name="Design exploration"],
[data-framer-name="FAQ"] { display: none !important; }

/* CUT 2026-08-20, Alec: "extremely messy... looks like a bunch of shit went
   into a blender. How is this gonna get me paid?" He sells two things — live
   DJ sets and gear rentals — and neither was stated anywhere on the homepage.
   The two-service band now sits under the hero; these two sections are what it
   replaces, and both were sprawl rather than sales:

   Works       2,086px of near-empty black. Venue labels floating over unloaded
               tiles, and a giant washed-out "All Works" letterform. The venues
               are real proof, but this presentation buried them — and the page
               still carries the testimonials, which say the same thing in the
               venues' own words. /works survives in the footer.
   Why us      Scattered heading, a right-aligned orphan paragraph, and stats in
               dark gold on black that barely register — led by "15+ nights
               behind the decks", a number that undersells him. */
[data-framer-name="Works"],
[data-framer-name="Why us"] { display: none !important; }

/* Switzer is the hand-built system's body face and it is not in Lesmana's spec.
   It survives in two places, both set with !important by sheets that load
   before this one: uniform-next's body default, and oteo-type.css's overrides
   on three Framer presets. Mapped back to the faces Lesmana actually assigns
   each of those presets — 1y7c7cl/19qorhk are Geist, 23zch4 is Geist Mono, and
   7v93b9 (the hero quote) is Playfair, not body copy. */
.framer-styles-preset-1y7c7cl,
.framer-styles-preset-19qorhk { font-family: var(--oteo-body) !important; }
.framer-styles-preset-23zch4 {
  font-family: var(--oteo-label) !important;
  letter-spacing: .14em !important;
}
/* Lesmana's DISPLAY presets. These were rendering in Geist — every giant word
   on the site ("Proud", "Works", "All Works", "01."–"04.", "Night", "Archive",
   "Behind", "The Decks") came out as a body sans blown up to 140px, which is
   exactly the generic look Alec kept calling AI-made.

   The cause was mine: Framer authors these correctly as Playfair Display, but
   the preset elements are <p>, and the body rule above carries
   `font-family: ... !important` on p — so my own body mapping was overriding
   the paid template's display type. Naming the presets explicitly restores
   what Lesmana already specified:
     9jiir1 hero 56px · j77x7r giant 100px · yrtdmr head 38px
     1e5hq0o card 32px · 7v93b9 quote 18px · 10o1gtm nav 16px          */
.framer-styles-preset-9jiir1,
.framer-styles-preset-j77x7r,
.framer-styles-preset-yrtdmr,
.framer-styles-preset-1e5hq0o,
.framer-styles-preset-7v93b9,
.framer-styles-preset-10o1gtm,
.framer-styles-preset-18cbegu {
  font-family: var(--oteo-display) !important;
  letter-spacing: -.03em !important;
  text-transform: none !important;
}
body, p, li, dd, dt, input, textarea, select, button, label, figcaption,
.section-deck, .footer-copy, .contact-sub, .v-body p, .lede, .desc, .past-deck,
.summary, .sub, .edit-sub, .gear-card p, .gear-meta, .price, .rate {
  font-family: var(--oteo-body) !important;
}

/* Last Switzer holdouts, found by walking the painted nodes on the live pages
   rather than guessing selectors: the gear card's internals and two link/CTA
   classes. Assigned by role, same as everything above — "per night" and
   "BOOK THIS" are labels, the rest is running copy. */
.gear-per, .card-cta {
  font-family: var(--oteo-label) !important;
  letter-spacing: .14em !important;
  text-transform: uppercase !important;
}
.gear-qty, .gear-name, .gear-rate, .email-link {
  font-family: var(--oteo-body) !important;
}

/* Pointer target size — WCAG 2.2 SC 2.5.8 asks for 24x24 CSS px, and this
   applies at every width, not just on phones. Measured live at 1440: .card-cta
   (the "BOOK THIS" on every package) was 80x15, the footer nav 18px tall, the
   email links 16px. The first pass scoped this to max-width:900px, so desktop
   kept failing on 20 distinct targets across 7 pages.

   Only the hit area grows — Lesmana's type sizes are untouched. Targets that
   sit inline inside a sentence are exempt under 2.5.8 and are left alone. */
.card .card-cta, .card-cta {
  min-height: 46px;
  display: inline-flex;
  align-items: center;
}
.footer-nav a, .site-footer nav a, .social a, .label-line, .email-link {
  display: inline-block;
  padding: 11px 0;
}

/* ROOT FIX — Switzer at the source, not selector-by-selector.
   site.css:130 defines --sans:"Switzer", and every hand-built page reads it, so
   Switzer kept surfacing on /residencies, /about, /contact, /calendar and
   /foowr no matter how many individual classes got mapped. Switzer is not in
   Lesmana's spec at all; the site has three faces. Redefining the variable
   fixes every consumer at once — and it is why chasing selectors one at a time
   was never going to finish. */
:root { --sans: "Geist", system-ui, sans-serif; }

/* The elements --sans was feeding split cleanly in two, classified by their
   computed style rather than by guessing from class names: 17 are uppercase or
   small-and-tracked (labels -> Geist Mono), 6 are running copy (already correct
   as Geist via the variable above). The bare a/b/strong cases are scoped to the
   block they live in — a global `a` rule would have hit the nav. */
.nights, .past-eyebrow, .mr-head, .vital-k, .room-cat, .room-nights,
.field-label, .idx, .glyph, .full, .edit-meta, .label-line,
a.alt, a.btn,
.hero-index a, .stats b, .contact-facts strong, .sc-facade-label b,
.steps li span {
  font-family: var(--oteo-label) !important;
}

/* "ALOK , CAT DEALERS , BHASKAR" — a gap before every comma on /contact.
   Not letter-spacing, which was my first guess: site.css makes each fact line
   `display:inline-flex; gap:10px` so a decorative ::before dash sits away from
   the text. But gap applies between EVERY flex child, and in a flex container
   each inline run becomes its own item — so the commas were being spaced off
   the words they belong to. Measured: 8.33px, not the 1.92px tracking.

   The dash carries its own margin instead, and the line goes back to being a
   normal block of text, so the spaces in the markup do the spacing. */
.contact-facts span {
  display: block !important;
  gap: 0 !important;
}
.contact-facts span::before {
  display: inline-block;
  vertical-align: middle;
  margin-right: 10px;
}

/* The remaining sub-24px targets are bare <a> tags, so they are scoped to the
   block they live in — a global `a` rule would hit the nav and every inline
   link. Links that genuinely sit inside a sentence (p.sub, p.player-note) are
   exempt under 2.5.8 and are deliberately left alone. */
.sec-cta a, .direct-line a, .contact-facts a, .hero-index a,
.page-foowr .band p a, a.alt {
  display: inline-block;
  padding: 6px 0;
}

/* ── THE TWO SERVICES ────────────────────────────────────────────────────────
   Injected under the homepage hero by oteo-swap.js. Styled in Lesmana's own
   language — Playfair for the titles, Geist for copy, Geist Mono for the
   kicker and the CTA — so it reads as part of the template, not bolted on. */
.oteo-services {
  background: var(--oteo-ink);
  border-top: 1px solid rgba(200, 169, 106, .16);
  border-bottom: 1px solid rgba(200, 169, 106, .16);
  padding: clamp(48px, 6vw, 88px) 24px;
}
.oteo-services-wrap {
  max-width: 1120px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(16px, 2.4vw, 32px);
}
.oteo-service {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: clamp(24px, 3vw, 40px);
  border: 1px solid rgba(244, 241, 234, .10);
  border-radius: 3px;
  background: rgba(255, 255, 255, .022);
  text-decoration: none;
  transition: border-color .4s ease, transform .4s ease;
}
.oteo-service:hover {
  border-color: var(--oteo-gold);
  transform: translateY(-3px);
}
.oteo-service-k {
  font-family: var(--oteo-label);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--oteo-gold);
}
.oteo-service-t {
  font-family: var(--oteo-display);
  font-size: clamp(28px, 3vw, 40px);
  font-weight: 400;
  letter-spacing: -.03em;
  line-height: 1.05;
  color: var(--oteo-cream);
  margin: 0;
}
.oteo-service-c {
  font-family: var(--oteo-body);
  font-size: 15px;
  line-height: 1.6;
  letter-spacing: -.02em;
  color: rgba(244, 241, 234, .66);
  margin: 0;
}
.oteo-service-n {
  font-family: var(--oteo-label);
  font-size: 11px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: rgba(244, 241, 234, .42);
  margin-top: 2px;
}
.oteo-service-cta {
  font-family: var(--oteo-label);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--oteo-gold);
  margin-top: 14px;
  min-height: 24px;
  display: inline-flex;
  align-items: center;
}
.oteo-service-cta::after { content: " \2192"; margin-left: 8px; }
@media (max-width: 760px) {
  .oteo-services-wrap { grid-template-columns: 1fr; }
}

/* HERO — the headline was landing across Alec's face. Measured: the title box
   is x=430..1010 and the portrait is x=436..1004, i.e. the same column. That is
   Lesmana's type-over-portrait idea, and it works for the one short word the
   template was built around; "DJ & Producer" is two long lines, so "Producer"
   ran straight into his jaw. Text moves into the left column, portrait keeps
   the right — the photograph is never cropped or scaled, only uncovered. */
@media (min-width: 1000px) {
  [data-framer-name="Hero"] [data-framer-name="Title"],
  [data-framer-name="Hero"] [data-framer-name="Subtitle"] {
    transform: translateX(-215px);
    max-width: 470px;
  }
}

/* The footer printed oteo@djoteo.com twice — Lesmana has an Email slot and a
   Phone slot, and with no phone number the Phone slot was filled with the same
   address under a second label ("MAIL" and "BOOKINGS", identical values). One
   address, stated once, under the label that matters for a booking site. */
[data-framer-name="Contact"] [data-framer-name="Phone"] { display: none !important; }

/* Testimonials sat in 920px for a 520px card — 200px of padding above AND
   below, so the venues' own words floated in a field of black and the section
   read as empty rather than confident. The quotes are the strongest proof on
   the page (The H, AVA Mediterranean, La Herradura); they just needed to stop
   being marooned. Padding halved; nothing removed. */
[data-framer-name="Testimonials"] {
  padding-top: 96px !important;
  padding-bottom: 96px !important;
}

/* ── CATEGORY JUMP BAR (/rentals) ────────────────────────────────────────────
   The catalogue runs 11,689px — 17.6 phone screens — across eight sections,
   none of which had an id or a link to it. Someone who came for a speaker
   scrolled past 5,100px of mixers and players to reach one. The bar sticks
   under the fixed header (z-index below its 100) so it is still reachable at
   screen 12, and scrolls sideways on a phone instead of wrapping to three
   rows. Geist Mono, gold on active — Lesmana's label language. */
.cat-jump {
  position: sticky;
  top: var(--hdr-h, 64px);
  z-index: 60;
  display: flex;
  gap: 8px;
  overflow-x: auto;
  scrollbar-width: none;
  padding: 12px 0;
  margin-bottom: 8px;
  /* Opaque, not a fade: with a gradient the section heading scrolling under
     the bar stayed half-visible through the transparent edge, which read as a
     rendering fault. Solid ink plus a hairline gives a clean edge. */
  background: var(--oteo-ink);
  border-bottom: 1px solid rgba(244, 241, 234, .08);
  -webkit-overflow-scrolling: touch;
}
.cat-jump::-webkit-scrollbar { display: none; }
.cat-jump-link {
  flex: 0 0 auto;
  min-height: 34px;
  display: inline-flex;
  align-items: center;
  padding: 0 14px;
  border: 1px solid rgba(244, 241, 234, .16);
  border-radius: 999px;
  font-family: var(--oteo-label);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: rgba(244, 241, 234, .66);
  text-decoration: none;
  white-space: nowrap;
  transition: border-color .3s ease, color .3s ease;
}
.cat-jump-link:hover { border-color: var(--oteo-gold); color: var(--oteo-cream); }
.cat-jump-link.is-here { border-color: var(--oteo-gold); color: var(--oteo-gold); }
/* Anchored headings must clear the fixed header when jumped to. */
.gear-cat { scroll-margin-top: calc(var(--hdr-h, 64px) + 76px); }
@media (prefers-reduced-motion: no-preference) { html { scroll-behavior: smooth; } }

/* Venue names under the two service cards. The homepage carried no link to the
   track record in its body — only in the footer — so the strongest reason to
   book him was invisible at the top of the page. Names are lifted verbatim
   from /residencies; Debonair is the one current standing residency. */
.oteo-proof {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px 18px;
  max-width: 1120px;
  margin: clamp(20px, 2.4vw, 32px) auto 0;
  padding-top: clamp(18px, 2vw, 26px);
  border-top: 1px solid rgba(244, 241, 234, .09);
  text-decoration: none;
}
.oteo-proof-lead {
  font-family: var(--oteo-label);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--oteo-gold);
}
.oteo-proof-rooms {
  font-family: var(--oteo-body);
  font-size: 14px;
  letter-spacing: -.02em;
  color: rgba(244, 241, 234, .56);
}
.oteo-proof-cta {
  font-family: var(--oteo-label);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: rgba(244, 241, 234, .82);
  margin-left: auto;
  min-height: 24px;
  display: inline-flex;
  align-items: center;
}
.oteo-proof-cta::after { content: " \2192"; margin-left: 8px; }
.oteo-proof:hover .oteo-proof-cta { color: var(--oteo-gold); }
@media (max-width: 760px) {
  .oteo-proof-cta { margin-left: 0; }
}

/* The open mobile menu let page text ghost through behind the links. The panel
   was rgba(18,17,13,.94) — 6% transmission is enough for a heading and a body
   paragraph to read through on a dark page, which looks unfinished on the one
   surface a phone visitor needs to be unambiguous. Opaque, with the blur kept
   as a fallback for browsers that ignore it. */
@media (max-width: 900px) {
  .site-header.nav-open .nav-links {
    background: #12110d !important;
    -webkit-backdrop-filter: blur(18px);
    backdrop-filter: blur(18px);
  }
}

/* Case-study headings were breaking mid-word: "Approac / h", "Challeng / e" at
   140px on all four /works pages. Measured: "Approach" needs 581px, the column
   is 568px — it misses by 13px, and word-break:break-word splits the word
   rather than letting it sit. A display serif should never hyphenate itself.

   Only the break behaviour changes. The first version of this also tightened
   tracking site-wide to claw back the 13px, which would have deviated from
   Lesmana's -.03em on every giant word on the site to fix eight headings on
   four pages — more complexity than the problem was worth. */
.framer-styles-preset-j77x7r {
  word-break: normal !important;
  overflow-wrap: normal !important;
  hyphens: none !important;
}

/* REVERTED 2026-08-21. I hid the hero Slider and the footer image, calling them
   "ornament". The Slider is not ornament — it is Lesmana's animated hero
   marquee, the signature motion Alec paid $129 for. Hiding it is what made the
   site read as flat and AI-made, which is the opposite of what he asked for.
   Both are restored. If the hero needs work it gets tuned, never deleted. */
