/* Triple Boost motion layer. Loads last. Everything here is keyed on classes main.js adds
   (html.tb-m = motion allowed, html.tb-m-enter = hero entrance runs on this load), so with no
   JS, or with reduced motion, none of it applies and every word is visible where it stands.
   One easing family: expo out for anything arriving, expo in-out for the intro curtain. */

:root {
	--tb-m-out: cubic-bezier(.16, 1, .3, 1);
	--tb-m-inout: cubic-bezier(.87, 0, .13, 1);
	--tb-d0: 0ms;          /* hero entrance offset: 0 on a normal load, the intro's length on the first */
	--tb-start: left;      /* the reading start side, where rules begin to draw */
}
html[dir="rtl"] { --tb-start: right; }

/* Smooth scroll: Lenis moves the page, so the native smooth behaviour must not fight it. */
html.lenis { scroll-behavior: auto; }

/* Load veil: a dark frame until main.js has run, so the hero is never seen before its entrance.
   It matches the intro's room, lifts in .35s once the script is up, and expires on its own at .6s
   if the script never comes. */
html::before {
	content: ""; position: fixed; inset: 0; z-index: 999; pointer-events: none;
	background: #06070A;
	animation: tb-m-veil .01s linear .6s forwards;
}
html.tb-m-ready::before { animation: none; opacity: 0; visibility: hidden; transition: opacity .35s var(--tb-m-out), visibility 0s .35s; }
@keyframes tb-m-veil { to { opacity: 0; visibility: hidden; } }

/* ---------------------------------------------------------------------------------------------
   Keyframes
   --------------------------------------------------------------------------------------------- */
@keyframes tb-m-drop  { from { opacity: 0; transform: translateY(-22px); } }
@keyframes tb-m-rise  { from { opacity: 0; transform: translateY(22px); } }
@keyframes tb-m-draw  { from { transform: scaleX(0); } }
/* A line rises out of a mask: the clip follows the translate so the floor stays put. */
@keyframes tb-m-line {
	from { transform: translateY(108%); clip-path: inset(-.4em -.3em calc(108% + .4em) -.3em); }
	to   { transform: none;             clip-path: inset(-.4em -.3em -.4em -.3em); }
}
/* Stage fragments settle in from further back. */
@keyframes tb-m-settle { from { opacity: 0; translate: 0 8cqh; scale: .9; } }
/* Plates arrive by their face only (scale and lift, never opacity), so no frame catches them invisible. */
@keyframes tb-m-plate { from { scale: .86; translate: 0 44px; } }

/* ---------------------------------------------------------------------------------------------
   Intro (first page view of a session only). Pure CSS timeline, so it ends on its own even if
   a script stalls: the loop draws 0 to .6s, the curtain lifts .56s to 1.04s.
   --------------------------------------------------------------------------------------------- */
.tb-intro {
	position: fixed; inset: 0; z-index: 1000; display: grid; place-items: center;
	background: #06070A; cursor: pointer;
	clip-path: inset(0 0 0 0);
	animation: tb-m-curtain .48s var(--tb-m-inout) .56s forwards;
}
.tb-intro::after {
	content: ""; position: absolute; inset: 0; pointer-events: none;
	background: var(--grain); background-size: 180px; opacity: .06;
}
.tb-intro__loop { width: clamp(150px, 20vw, 240px); overflow: visible; animation: tb-m-intro-lift .48s var(--tb-m-inout) .56s forwards; }
.tb-intro__loop path {
	fill: none; stroke: url(#tbIntroGrad); stroke-width: 1.35; stroke-linecap: round; stroke-linejoin: round;
	stroke-dasharray: 100; stroke-dashoffset: 100;
	animation: tb-m-intro-draw .55s cubic-bezier(.65, 0, .35, 1) forwards;
}
.tb-intro.is-skip { animation: tb-m-curtain-skip .3s var(--tb-m-inout) forwards; }
.tb-intro.is-skip .tb-intro__loop { animation: none; opacity: 0; transition: opacity .15s; }
@keyframes tb-m-intro-draw { to { stroke-dashoffset: 0; } }
@keyframes tb-m-intro-lift { to { transform: translateY(-40px); opacity: 0; } }
@keyframes tb-m-curtain { to { clip-path: inset(0 0 100% 0); } }
@keyframes tb-m-curtain-skip { to { clip-path: inset(0 0 100% 0); } }

/* ---------------------------------------------------------------------------------------------
   Hero entrance (every load)
   --------------------------------------------------------------------------------------------- */
html.tb-m-enter .tb-header { animation: tb-m-drop .9s var(--tb-m-out) calc(var(--tb-d0) + 40ms) backwards; }
/* The open mobile menu is positioned against the viewport: nothing may transform the header then. */
body.nav-open .tb-header { animation: none !important; }

/* Home: mast, two headline lines through a mask, lead, CTA, then the stage settles layer by layer. */
html.tb-m-enter .tb-hero--home .tb-hero__mast { animation: tb-m-rise .9s var(--tb-m-out) calc(var(--tb-d0) + 60ms) backwards; }
html.tb-m-enter .tb-hero--home .tb-hero__mast-rule { transform-origin: var(--tb-start) center; animation: tb-m-draw 1.2s var(--tb-m-out) calc(var(--tb-d0) + 260ms) backwards; }
html.tb-m-enter .tb-hero--home .tb-hero__title { animation: none; }
html.tb-m-enter .tb-hero--home .tb-hero__line { animation: tb-m-line 1.05s var(--tb-m-out) calc(var(--tb-d0) + 120ms) backwards; }
html.tb-m-enter .tb-hero--home .tb-type { animation: tb-m-line 1.05s var(--tb-m-out) calc(var(--tb-d0) + 220ms) backwards; }
html.tb-m-enter .tb-hero--home .tb-hero__lead { animation: tb-m-rise 1s var(--tb-m-out) calc(var(--tb-d0) + 380ms) backwards; }
html.tb-m-enter .tb-hero--home .tb-hero__actions { animation: tb-m-rise 1s var(--tb-m-out) calc(var(--tb-d0) + 480ms) backwards; }
html.tb-m-enter .tb-hero--home .tb-stage__layer > * { animation: tb-m-settle 1.4s var(--tb-m-out) calc(var(--tb-d0) + var(--sd, 200ms)) backwards; }
html.tb-m-enter .tb-stage__layer--field > * { --sd: 140ms; }
html.tb-m-enter .tb-stage__layer--ad > *    { --sd: 300ms; }
html.tb-m-enter .tb-stage__layer--clip > *  { --sd: 420ms; }
html.tb-m-enter .tb-stage__layer--wa > *    { --sd: 640ms; }
html.tb-m-enter .tb-stage__layer--d1 > *    { --sd: 720ms; }
html.tb-m-enter .tb-stage__layer--d2 > *    { --sd: 820ms; }

/* Inner heroes: main.js tags each piece of the copy column with its own delay (--ed). */
html.tb-m-enter .tb-hero .tb-m-e { animation: tb-m-rise .95s var(--tb-m-out) calc(var(--tb-d0) + var(--ed, 0ms)) backwards; }
html.tb-m-enter .tb-hero .tb-split { animation: none; }
html.tb-m-enter .tb-plate__face { animation: tb-m-plate 1.5s var(--tb-m-out) calc(var(--tb-d0) + 200ms) backwards; }

/* ---------------------------------------------------------------------------------------------
   Headings split into words (main.js), revealed line by line through a mask
   --------------------------------------------------------------------------------------------- */
.tb-m .tb-split .tb-w { display: inline-block; transform: translateY(108%); clip-path: inset(-.4em -.3em calc(108% + .4em) -.3em); }
.tb-m .tb-split.is-in .tb-w,
.tb-m .tb-m-host.is-in .tb-split .tb-w {
	animation: tb-m-line 1.05s var(--tb-m-out) calc(var(--sd, 0ms) + var(--l, 0) * 90ms) both;
}
.tb-m .tb-hero .tb-split { --sd: calc(var(--tb-d0) + 110ms); }

/* A section head that holds a split heading stops fading as one block; its label leads and its
   lead line follows the heading instead. */
.tb-m [data-reveal].tb-m-host { opacity: 1; transform: none; }
.tb-m .tb-m-host > .tb-label, .tb-m .tb-m-host > p {
	opacity: 0; transform: translateY(16px);
	transition: opacity .9s var(--tb-m-out), transform .9s var(--tb-m-out);
}
.tb-m .tb-m-host > p { transition-delay: .32s; }
.tb-m .tb-m-host.is-in > .tb-label, .tb-m .tb-m-host.is-in > p { opacity: 1; transform: none; }

/* ---------------------------------------------------------------------------------------------
   Rules draw in from the reading start side
   --------------------------------------------------------------------------------------------- */
.tb-m .tb-label::before { transform: scaleX(0); transform-origin: var(--tb-start) center; transition: transform 1.1s var(--tb-m-out) .12s; }
.tb-m .tb-label.is-drawn::before { transform: none; }
.tb-m .tb-hero .tb-label::before { transition-delay: calc(var(--tb-d0) + 260ms); }

/* ---------------------------------------------------------------------------------------------
   Depth parallax on lit slabs and plates (main.js writes --tb-py while they are on screen)
   --------------------------------------------------------------------------------------------- */
.tb-m-px:not(.tb-plate) { translate: 0 var(--tb-py, 0px); }
.tb-plate.tb-m-px { transform: translate3d(0, var(--tb-py, 0px), 0); }

@media (prefers-reduced-motion: reduce) {
	html::before { content: none; }
	.tb-intro { display: none; }
	.tb-m .tb-split .tb-w { transform: none; clip-path: none; }
	.tb-m .tb-m-host > .tb-label, .tb-m .tb-m-host > p { opacity: 1; transform: none; }
	.tb-m .tb-label::before { transform: none; }
	.tb-m-px:not(.tb-plate) { translate: none; }
	.tb-plate.tb-m-px { transform: none; }
}

/* Legibility pass: decorative numerals and small labels stay visible on the dark theme (≥3:1 for large type, ≥4.5:1 for small). */
.tb-section .tb-goal-card__step { color: rgba(255, 255, 255, .5); opacity: 1; }
.tb-section .tb-goals__grid > .tb-card:first-child .tb-goal-card__step, .tb-section .tb-pillars__grid > .tb-card:first-child .tb-goal-card__step { color: rgba(255, 255, 255, .62); }
.tb-group__num { color: rgba(255, 255, 255, .42); }
.tb-room--blue .tb-group__num { color: rgba(255, 255, 255, .5); }
.tb-svc__num { color: rgba(255, 255, 255, .85); }
.tb-brandbook__palette i[style*="02CDFD"] b { color: #0A0A0A; }
.tb-goal-card:hover .tb-goal-card__tools { color: #fff; }
