/* ============================================================
   RAIDEN ADVISORS — "Seismograph" (dark)

   NOTE: the above-the-fold rules (tokens, font-faces, base,
   field, grain, header, hero, seismograph shell) are mirrored
   as inline critical CSS in index.html's <style> block for
   first-paint speed. If you edit those rules here, update the
   inline copy too.

   The heading face ('Sora') is declared ONLY in that
   inline block, embedded as a data URI so the headline paints
   in its true face on the first frame.
   ============================================================ */

:root{
  --ink:        #0B0B0C;
  --ink-raise:  #121316;
  --bone:       #E8E4DC;
  --bone-dim:   #A9A69E;
  --bone-nav:   #C6C3BA;  /* nav labels: brighter than bone-dim, still below the --bone logo */
  --graphite:   #7E7F84;  /* lightened from spec's #6E6F73 to pass AA at 11–12px on --ink */
  --hairline:   #26272B;
  --pulse:      #C9C2B4;
  --field:      201, 194, 180;   /* ambient field lines (rgb channels, read by seismograph.js) */
  --head-veil:  rgba(11, 11, 12, .78);

  --shell-max:  1120px;
  --pad-x:      28px;
  --sect-y:     120px;
  --ease-out:   cubic-bezier(.22, 1, .36, 1);
}

/* Light theme — warm "paper" palette (a considered remap, not an inversion).
   Chosen by a pre-paint <head> script: a saved choice wins, else the visitor's
   local hour; the header toggle overrides and persists it. */
:root[data-theme="light"]{
  --ink:        #F3F0E9;
  --ink-raise:  #E9E4D9;
  --bone:       #1A1917;
  --bone-dim:   #5B584F;
  --bone-nav:   #413F39;
  --graphite:   #7E7B72;
  --hairline:   #D9D3C6;
  --pulse:      #8A6A3C;   /* deep bronze — carries on paper where bone-metal would vanish */
  --field:      120, 105, 80;
  --head-veil:  rgba(243, 240, 233, .82);
}

/* Smooth cross-fade only while the user is actively toggling (added/removed by
   main.js); page-load theme resolution stays instant. */
html.theme-x, html.theme-x *, html.theme-x *::before, html.theme-x *::after{
  transition: background-color .42s var(--ease-out), color .42s var(--ease-out),
              border-color .42s var(--ease-out), fill .42s var(--ease-out),
              stroke .42s var(--ease-out) !important;
}

/* ---------- Fonts (self-hosted, page-charset subsets) ---------- */

@font-face{
  font-family: 'Switzer';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/switzer-latin.woff2') format('woff2');
}
@font-face{
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/plexmono-400-latin.woff2') format('woff2');
}
@font-face{
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/assets/fonts/plexmono-500-latin.woff2') format('woff2');
}

/* Metric-compatible fallbacks — no layout shift on font swap */
@font-face{
  font-family: 'Newsreader-fallback';
  src: local('Georgia');
  size-adjust: 98%;
  ascent-override: 92%;
  descent-override: 24%;
  line-gap-override: 0%;
}
@font-face{
  font-family: 'Switzer-fallback';
  src: local('Arial');
  size-adjust: 100%;  /* Switzer advance matches Arial exactly — no wrap-shift on swap (CLS) */
  ascent-override: 90%;
  descent-override: 22.5%;
  line-gap-override: 0%;
}
@font-face{
  font-family: 'PlexMono-fallback';
  src: local('Courier New');
  size-adjust: 100%;  /* matches Plex Mono advance exactly — no wrap-shift on swap (CLS) */
  ascent-override: 94%;
  descent-override: 24%;
  line-gap-override: 0%;
}

/* ---------- Base ---------- */

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

html{ scrollbar-gutter: stable; }

body{
  background: var(--ink);
  color: var(--bone);
  font-family: 'Switzer', 'Switzer-fallback', system-ui, sans-serif;
  font-weight: 300;
  font-size: 17px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

::selection{ background: var(--pulse); color: var(--ink); }

a{ color: inherit; }
a:focus-visible,
button:focus-visible{
  outline: 2px solid var(--pulse);
  outline-offset: 2px;
  border-radius: 1px;
}

/* Skip link: first focusable element, off-screen until focused (M2). */
.skip-link{
  position: fixed;
  left: 12px;
  top: -72px;
  z-index: 60;
  background: var(--ink-raise);
  color: var(--bone);
  padding: 12px 18px;
  border: 1px solid var(--pulse);
  border-radius: 2px;
  text-decoration: none;
  transition: top .2s ease;
}
.skip-link:focus{ top: 12px; }

.mono{
  font-family: 'IBM Plex Mono', 'PlexMono-fallback', monospace;
  font-weight: 400;
}
.nowrap{ white-space: nowrap; }  /* keep compounds like "co-founder" from breaking across lines */

.shell{
  max-width: var(--shell-max);
  margin: 0 auto;
  padding-left: var(--pad-x);
  padding-right: var(--pad-x);
}

/* ---------- Ambient field + grain ---------- */

/* The field is drawn by seismograph.js: faint seismic strata that
   drift with time and lean with scroll velocity. Hidden until JS
   activates it, and never shown under prefers-reduced-motion. */
.field{
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  display: none;
}

/* No mix-blend-mode. It forced the compositor to blend the whole viewport
   every frame (~2.3ms, more than both canvases combined) and on an ink
   ground `overlay` multiplies the noise down to almost nothing anyway.
   Straight alpha costs nothing measurable and shows the texture better.
   Spec 3.3: cut the grain if it costs repaints — this is that, fixed. */
.grain{
  position: fixed;
  inset: 0;
  z-index: 40;
  pointer-events: none;
  opacity: .03;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 120px 120px;
}

/* Content sits above the field. */
main, .site-foot{ position: relative; z-index: 1; }

/* ---------- Header ---------- */

.site-head{
  position: sticky;
  top: 0;
  z-index: 30;
}
.site-head::before{
  content: '';
  position: absolute;
  inset: 0;
  background: var(--head-veil);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--hairline);
  opacity: 0;
  transition: opacity .35s ease;
}
.site-head.is-scrolled::before{ opacity: 1; }

/* Condense on scroll: the bar settles a few px and the wordmark eases down a
   hair, reclaiming a sliver of viewport. Scroll-driven, so it runs on touch too;
   main.js reads the live header height, so anchor landing stays correct. */
.site-head.is-scrolled .head-row{ padding-top: 11px; padding-bottom: 11px; }
.site-head.is-scrolled .wordmark{ transform: scale(.93); }

.head-row{
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-top: 16px;
  padding-bottom: 16px;
  transition: padding-top .3s var(--ease-out), padding-bottom .3s var(--ease-out);
}

/* Stacked logo lockup: constellation mark over RAIDEN over ADVISORS.
   The 'Sora' heading subset is embedded as a data
   URI in index.html's inline critical CSS — it is not defined here. */
.wordmark{
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  text-decoration: none;
  color: var(--bone);
  line-height: 1;
  transform-origin: left center;
  transition: transform .3s var(--ease-out);
}
.logo-mark{ height: 29px; width: auto; display: block; }
.wm-lines{ opacity: .5; transition: opacity .25s ease; }
.wordmark:hover .wm-lines{ opacity: .82; }
.logo-name{
  margin-top: 9px;
  font-family: 'Sora', 'Switzer-fallback', sans-serif;
  font-weight: 500;
  text-transform: uppercase;
  font-size: 15.5px;
  letter-spacing: .34em;
  text-indent: .34em;
  color: var(--bone);
}
.logo-sub{ display: flex; align-items: center; gap: 9px; margin-top: 6px; }
.logo-rule{ width: 15px; height: 1px; background: var(--bone-dim); opacity: .7; }
.logo-sub-text{
  font-family: 'Sora', 'Switzer-fallback', sans-serif;
  font-weight: 500;
  text-transform: uppercase;
  font-size: 8.5px;
  letter-spacing: .3em;
  text-indent: .3em;
  color: var(--bone-dim);
}

/* nav + theme toggle, dropped to the RAIDEN wordmark line (the mark on top pulls
   the lockup's optical center ~10px above it). */
.nav-tools{ display: flex; align-items: center; gap: 22px; transform: translateY(10px); }
.site-nav{ display: flex; gap: 36px; }
.theme-toggle{
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; padding: 0; flex: none;
  background: transparent; border: 1px solid var(--hairline); border-radius: 50%;
  color: var(--bone-dim); cursor: pointer;
  transition: color .2s ease, border-color .2s ease;
}
.theme-toggle:hover{ color: var(--bone); border-color: var(--pulse); }
.theme-toggle svg{ width: 15px; height: 15px; display: block; }
.theme-toggle .i-sun{ display: none; }
.theme-toggle .i-moon{ display: block; }
[data-theme="light"] .theme-toggle .i-sun{ display: block; }
[data-theme="light"] .theme-toggle .i-moon{ display: none; }
.site-nav a{
  font-family: 'IBM Plex Mono', 'PlexMono-fallback', monospace;
  font-size: 11.5px;
  letter-spacing: .16em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--bone-nav);
  position: relative;
  transition: color .2s ease;
}
.site-nav a:hover{ color: var(--bone); }
/* Scroll-progress underline: each link's hairline fills (scaleX) as you scroll
   toward its section and reads full as its heading reaches the header — a flowing
   position indicator. --fill is set per link from scroll in main.js; --nav-ul-bottom
   is measured on mobile so the underline lands on the logo's "— ADVISORS —" rule. */
.site-nav a::after{
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: var(--nav-ul-bottom, -3px);
  height: 1px;
  background: currentColor;
  transform: scaleX(var(--fill, 0));
  transform-origin: left center;
  transition: transform .12s linear;   /* gentle smoothing on the scroll-driven fill */
}
/* Hover and keyboard focus fill the whole underline, overriding the scroll fill. */
.site-nav a:hover::after,
.site-nav a:focus-visible::after{ transform: scaleX(1); }

@media (max-width: 680px){
  /* Full nav on mobile too (was Contact-only); tighten so all three fit. */
  .site-nav{ gap: 14px; }
  .site-nav a{ font-size: 10px; letter-spacing: .1em; }
  /* Underline vertical position (--nav-ul-bottom) is measured per-device in
     main.js so it lands exactly on the "— ADVISORS —" rule line (the 44px tap
     targets make a static offset unreliable across devices). */
  .logo-mark{ height: 25px; }
  .logo-name{ margin-top: 7px; font-size: 13.5px; }
  .logo-sub-text{ font-size: 7.5px; }
  .logo-rule{ width: 12px; }
}

/* ---------- Hero ---------- */

.hero{
  padding-top: clamp(120px, 22vh, 220px);
  padding-bottom: var(--sect-y);
}

.eyebrow{
  font-size: 11.5px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--graphite);
}
.hero-eyebrow{ margin-bottom: 40px; }

h1{
  font-family: 'Sora', 'Switzer-fallback', sans-serif;
  font-weight: 600;
  font-size: clamp(2.6rem, 6.4vw, 5rem);
  line-height: 1.04;
  letter-spacing: -0.018em;
  max-width: 11ch;
  text-wrap: balance;
}
/* The ampersand as a gentle emphasis (the connector), inline. */
.hero-amp{ color: var(--bone); padding: 0 .02em; }

/* Hero reveal — CSS only, and the H1 itself is never animated:
   it paints on the first frame (it is the LCP element) while the
   seismograph draw-on carries the load moment. */

/* Hero tagline: a mono caption that brackets with the eyebrow, framing
   the serif stack between two label lines. */
.hero-tag{
  font-family: 'IBM Plex Mono', 'PlexMono-fallback', monospace;
  font-weight: 400;
  font-size: 13px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--bone-dim);
  margin-top: 36px;
}

.js .hero-eyebrow,
.js .hero-tag,
.js .hero-sub p{
  opacity: .001;
  transform: translateY(14px);
  animation: rise-in .9s var(--ease-out) forwards;
}
.js .hero-eyebrow{ animation-delay: .05s; }
.js .hero-tag{ animation-delay: .25s; }
.js .hero-sub p:nth-child(1){ animation-delay: .5s; }
.js .hero-sub p:nth-child(2){ animation-delay: .62s; }

@keyframes rise-in{ to{ opacity: 1; transform: translateY(0); } }


/* ---------- Reveals ----------
   Hidden states apply only once main.js has measured and split, so the
   page is never blank if JS fails. Transform + opacity only: these stay
   on the compositor and never force layout. */

/* main.js tags every reveal target with .rv, so the hidden and revealed
   states differ by exactly one class. Do NOT hide via element selectors
   like `.body-copy p` — those outrank `.is-in` and the reveal silently
   loses, leaving the text invisible forever. */
.reveals-ready .rv{
  opacity: 0;
  transform: translateY(12px);
  transition: opacity .7s ease-out, transform .7s ease-out;
}
.reveals-ready .rv.is-in{
  opacity: 1;
  transform: none;
}
.reveals-ready .rule.rv{
  opacity: 1;
  transform: scaleX(0);
  transition: transform 1.1s var(--ease-out);
}
.reveals-ready .rule.rv.is-in{ transform: scaleX(1); }

/* Headings: masked line-by-line rise, staggered by line index. */
.ln{ display: block; overflow: hidden; }
.ln-i{ display: block; }
.reveals-ready h2.split .ln-i{
  transform: translateY(110%);
  opacity: 0;
  transition: transform .9s var(--ease-out), opacity .9s var(--ease-out);
  transition-delay: calc(var(--i) * .08s);
}
.reveals-ready h2.split.is-in .ln-i{
  transform: none;
  opacity: 1;
}

/* ---------- Sections ---------- */

.section{
  padding-top: var(--sect-y);
  padding-bottom: var(--sect-y);
  position: relative;
  scroll-margin-top: 14px;  /* native-anchor fallback: section top tucks under the ~100px header so its 120px top padding lands the eyebrow ~34px below the nav. Mobile override below (72px padding). The Lenis click path computes this dynamically. */
}

.rule{
  position: absolute;
  top: 0;
  left: var(--pad-x);
  right: var(--pad-x);
  height: 1px;
  background: var(--hairline);
  transform-origin: left center;
}
.contact-band .rule{ left: 0; right: 0; }

.section .eyebrow{ margin-bottom: 28px; }

h2{
  font-family: 'Sora', 'Switzer-fallback', sans-serif;
  font-weight: 400;
  font-size: clamp(1.6rem, 2.8vw, 2.2rem);
  line-height: 1.28;
  letter-spacing: -0.008em;
  max-width: 20ch;       /* wrap headings to ~2 compact lines instead of one long line jutting past the body */
  margin-bottom: 28px;
  text-wrap: balance;    /* even lines, no orphaned last word */
}

.body-copy p{
  max-width: 58ch;
  color: var(--bone-dim);
  text-wrap: balance;   /* even line lengths (still left-aligned) — avoids the short loose line before "commercialization" */
}
.body-copy p + p{ margin-top: 1.2em; }

/* Operator: named grid areas on desktop (headline full width, portrait beside the
   body copy). DOM order is kicker, figure, headline, bio — grid placement ignores
   that order on desktop, and mobile relies on it to float the photo by the headline. */
.op-grid{
  display: grid;
  grid-template-columns: minmax(0, 1fr) 300px;
  column-gap: clamp(40px, 5vw, 76px);
  grid-template-areas:
    "kicker kicker"
    "title  title"
    "bio    photo";
  align-items: start;
}
.op-grid > .eyebrow{ grid-area: kicker; }
.op-grid > h2{ grid-area: title; }
.op-grid > .body-copy{ grid-area: bio; }
.portrait{ grid-area: photo; margin: 0; }
.portrait img{ width: 100%; height: auto; display: block; border-radius: 2px; filter: grayscale(1) contrast(1.03) brightness(.94); }
/* On paper the dark-tuned dimming reads heavy, and a light-grey photo edge
   would dissolve into the ground — so lift it and give it a hairline frame. */
[data-theme="light"] .portrait img{ filter: grayscale(1) contrast(1.04); box-shadow: 0 0 0 1px var(--hairline); }
@media (max-width: 680px){
  /* Magazine treatment: the kicker stays full width, then the headline and the
     opening bio wrap around a right-floated portrait — so the photo sits beside
     the headline ("the strategist"), not the kicker. */
  .op-grid{ display: flow-root; }
  .op-grid > .portrait{ float: right; width: 140px; margin: 4px 0 12px 20px; }
  /* Lengthen to a portrait rectangle so it fills the float cleanly (no odd gap
     under a near-square image); cover trims the sides, keeping the head centered. */
  .op-grid > .portrait img{ aspect-ratio: 4 / 5; object-fit: cover; object-position: center top; }
  /* Justify the bio so every paragraph reads as the same clean block with a
     flush right edge (they wrap ragged and uneven otherwise); hyphenation keeps
     the word spacing tight on the narrow column. */
  .op-grid .body-copy p{ text-align: justify; -webkit-hyphens: auto; hyphens: auto; text-wrap: auto; }
}

/* Practice rows */

.functions{ list-style: none; }
.fn-row{
  display: grid;
  grid-template-columns: 220px 1fr;
  gap: 24px;
  padding: 34px 0;
  border-top: 1px solid var(--hairline);
}
.fn-title{
  font-family: 'Sora', 'Switzer-fallback', sans-serif;
  font-weight: 500;
  font-size: 1.3rem;
  line-height: 1.3;
}
.fn-head{ display: flex; align-items: center; gap: 12px; }
.fn-mark{ width: 28px; height: 28px; flex: none; color: var(--bone-dim); }
.fn-body{
  max-width: 58ch;
  color: var(--bone-dim);
}
/* Hover wake: the row's constellation mark and detail lift as the cursor lands
   — an ambient "noticing," not a click affordance (the rows aren't links, so no
   pointer cursor and no motion). The mark's --pulse accent already carries. */
/* Hover wake: the row's mark and detail lift as the cursor lands — ambient
   "noticing", not a click affordance (the rows aren't links, so no pointer
   cursor and no motion). The mark's --pulse accent already carries. */
.fn-mark, .fn-body{ transition: color .25s var(--ease-out); }
.fn-row:hover .fn-mark{ color: var(--bone); }
.fn-row:hover .fn-body{ color: var(--bone-nav); }

@media (max-width: 680px){
  .fn-row{ grid-template-columns: 1fr; gap: 8px; padding: 28px 0; }
  /* Mobile: title + body sit flush-left (aligned with the rest of the page);
     the mark moves into the blank space after the title. */
  .fn-head{ gap: 14px; }
  .fn-mark{ order: 2; }
}

/* ---------- Contact ---------- */

.contact-band{
  background: var(--ink-raise);
  /* Last section before the footer — trim the tail so the page ends cleanly
     instead of trailing off into a void above the rule. */
  padding-bottom: 72px;
}
.contact-body{
  max-width: 58ch;
  color: var(--bone-dim);
}

.contact-cta{
  margin: 44px 0 28px;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 14px 20px;
}
.email{
  display: inline-block;
  font-size: clamp(1.15rem, 2.6vw, 1.7rem);
  font-weight: 500;
  letter-spacing: .02em;
  color: var(--bone);
  text-decoration: none;
  position: relative;
  padding-bottom: 6px;
  will-change: transform;
}

/* Copy-to-clipboard (M3). Hidden unless JS is present, so no-JS users
   see only the selectable address and the working mailto link. */
.copy-email{
  display: none;
  align-items: center;
  background: transparent;
  border: 1px solid var(--hairline);
  color: var(--bone-dim);
  font-size: 11.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  padding: 9px 14px;
  border-radius: 2px;
  cursor: pointer;
  transition: color .2s ease, border-color .2s ease;
}
.js .copy-email{ display: inline-flex; }
.copy-email:hover{ color: var(--bone); border-color: var(--pulse); }
.copy-email.is-copied{ color: var(--pulse); border-color: var(--pulse); }
.email::after{
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: var(--pulse);
  transform: scaleX(.35);
  transform-origin: left center;
  transition: transform .45s var(--ease-out);
}
.email:hover::after,
.email:focus-visible::after{ transform: scaleX(1); }

.contact-note{
  font-size: 14px;
  color: var(--graphite);
}

/* ---------- Footer ---------- */

.site-foot{
  border-top: 1px solid var(--hairline);
  padding: 44px 0 52px;
}
/* Bookends the header: identity on the left, presence on the right, spanning the
   same measure — so the top and bottom of the page mirror each other. Items are
   clustered by kind rather than strung out at equal weight. */
.foot-row{
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: baseline;
  gap: 14px 40px;
  font-size: 11.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--graphite);
  margin-bottom: 30px;
}
/* In-text link: underlined always so it reads as a link on the dark
   ground by more than color alone (M2). */
.foot-row a{
  color: var(--bone-dim);
  text-decoration: underline;
  text-underline-offset: 0.2em;
  text-decoration-thickness: 1px;
  transition: color .2s ease;
}
.foot-row a:hover{ color: var(--bone); }
/* Each cluster holds together tightly; the space between clusters carries the span. */
.foot-group{ display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px 26px; }
/* Legal descriptor reads in sentence case among the uppercase labels. */
.foot-entity{ text-transform: none; letter-spacing: .02em; }
/* Fine print sits below the meta row in the hierarchy, so it must not out-size
   it (11.5px). Sets as two balanced lines: the measure is capped near half the
   text's natural single-line width so the two lines come out close to equal,
   then justified (with hyphenation) so the first sits flush. */
.foot-legal{
  font-size: 12px;
  line-height: 1.7;
  color: var(--graphite);
  max-width: 434px;
  text-align: justify;
  -webkit-hyphens: auto;
  hyphens: auto;
}

/* ---------- Mobile spacing ---------- */

@media (max-width: 680px){
  :root{ --sect-y: 72px; --pad-x: 22px; }
  .section{ scroll-margin-top: 52px; }  /* 72px padding + this lands the eyebrow ~34px below the mobile header */
  .hero{ padding-top: 120px; }
  body{ font-size: 16.5px; }
  /* 44px minimum touch targets (M2). */
  .site-nav a{ display: inline-flex; align-items: center; min-height: 44px; }
  .email,
  .copy-email{ min-height: 44px; }
  /* The footer link sets at 18px; expand its hit area to 44px with a pseudo
     element so the target is reachable without inflating the footer row. */
  .foot-row a{ position: relative; }
  .foot-row a::after{
    content: '';
    position: absolute;
    left: 0; right: 0; top: 50%;
    height: 44px;
    transform: translateY(-50%);
  }
}

/* ---------- Reduced motion ---------- */

@media (prefers-reduced-motion: reduce){
  .js .hero-eyebrow,
  .js .hero-tag,
  .js .hero-sub p{
    animation: none !important;
    opacity: 1;
    transform: none;
  }
  /* Nothing hidden, nothing staggered, nothing to wait for. */
  .reveals-ready .rv,
  .reveals-ready h2.split .ln-i{
    opacity: 1 !important;
    transform: none !important;
  }
  .reveals-ready .rule.rv{ transform: scaleX(1) !important; }
  *, *::before, *::after{
    transition-duration: .01ms !important;
    animation-duration: .01ms !important;
  }
}
