/*
 * Flow page.
 *
 * The theme sets `html{font-size:calc(100vw / 1920)}`, so 1rem === 1px in the
 * 1920-wide Figma frame and design values transfer verbatim.
 *
 * Grid geometry is derived from the design's cell widths (547 / 855 / 1163 /
 * 1780): solving 4c+3g=547 and 6c+5g=855 gives column 86rem, gap 68rem, and
 * 12c+11g = 1780rem total — the exact content width (x 70 → 1850).
 */

.flow-page {
	background: #fff;
	/* Clears the fixed .nav now that the hero wordmark section is gone —
	   whichever block ends up first (showreel, or the teaser row if there's
	   no showreel) needs this regardless, so it lives on the page container
	   rather than on any one block. 120rem accounts for the taller nav below
	   (30 top + 57 pill row + 30 bottom, per Figma), not just the pills'
	   own height. */
	padding-top: 120rem;
}

/* ---------- Pill nav (WORK / ♺ RANDOM / ∷ GRID) ---------- */

/* main.css's shared .header ISN'T a flex container — brand/header__left's
   horizontal layout comes from .brand{float:left} + .header__left's own
   margin-left:auto, not flexbox. That's fine when header__left is the last
   thing in the row, but Studio/Get-in-touch (header.php) are now its
   siblings, and plain content after a float+auto-margin pair has nowhere
   left to sit on that "line" — it wraps below instead of sitting inline,
   which is the wrap the mockup obviously isn't showing. Flow page only. */
.flow-page .header {
	display: flex;
	align-items: center;
	flex-wrap: nowrap;
}

/* main.css's shared .header__left is a fixed 50% width — sized for the
   other pages' short main-menu text. The pill group's own content needs
   more than that at real window widths, and .flow-nav__pills' overflow:
   hidden (needed to clip the blur ::before to the pill's rounded shape)
   was silently clipping GRID/List off the right edge instead of letting
   the flex chain wrap or grow — invisible, not just badly laid out.
   Sized to content instead, now that Studio/Get-in-touch are its own
   siblings rather than sharing this box (see header.php). */
.flow-page .header__left {
	width: auto;
	/* header__left ITSELF is the flex child of .header that must not
	   shrink (see the flex-shrink note below .flow-nav) — flex-shrink on
	   its .flow-nav grandchild alone doesn't stop header__left, the actual
	   item .header's own flex algorithm operates on, from compressing. */
	flex-shrink: 0;
	/* Keeps main.css's own margin-left:auto — that's what pushes
	   header__left (and now, following it in the row, Studio/CTA) away
	   from the brand rather than sitting flush against it. */
}

.flow-page .brand {
	float: none;
	flex-shrink: 0;
}

/* All 4 flex children (brand, .header__left, Studio, CTA) default to
   flex-shrink:1 — at real window widths narrower than the 1920 Figma
   frame, that proportionally compressed EVERYTHING including the pill
   group, which clipped (overflow:hidden) instead of visibly shrinking:
   RANDOM truncated to "RAN", GRID/List vanished entirely. The tabs are
   interactive controls; they're the one thing here that must never
   silently lose content, so they're exempted and Studio/CTA absorb the
   squeeze instead (plain text links tolerate tighter spacing fine). */
.flow-page .flow-nav {
	flex-shrink: 0;
}

.flow-page .flow-nav__pill {
	flex-shrink: 1;
	/* Remeasured against the rebuilt menu (Figma Group 2087329661, "пересобрал
	   меню"): tab group ends x:1543, Studio 1549–1679, Get in touch
	   1685–1880. Every gap in the bar is the same 6rem — the old 4/5rem
	   figures came from the previous version of this frame. */
	margin-left: 6rem;
	white-space: nowrap;
}

/* The shared .header/.nav (main.css) have zero vertical padding of their
   own — every other page relies on .brand's all-around 20rem padding to
   set the effective header height. Flow's pills replace that padding with
   horizontal-only (to match the pill shape), so without this the whole row
   sits flush at the true viewport top instead of Figma's 30rem gap
   (Group 2087329658 starts at y:30 in the frame). */
.flow-page .header {
	padding-top: 30rem;
	padding-bottom: 30rem;
	/* Figma Group 2087329661 spans x:40 → x:1880 in the 1920 frame, so 40rem
	   each side — not the 30rem main.css gives every other template. */
	padding-left: 40rem;
	padding-right: 40rem;
}

/* These sit inside the theme's own navbar, replacing Work/Laba/Studio on
   this template (see header.php). Every #f8f8f8-looking pill in the design
   (Rectangles 24/26/27/28 — the view-tab group, brand, Studio, Get in
   touch) is actually frosted glass, not flat grey — and the nav bar itself
   has no fill at all now (was solid #fff; main.css's shared .nav, now
   overridden to transparent here). */
.flow-nav {
	justify-content: flex-start;
}

.flow-page .nav {
	background-color: transparent;
	/* The site-wide Webflow IX2 interaction hides the nav on scroll-down
	   via an inline transform — explicitly NOT wanted on /flow, the nav
	   should always stay put. !important is required: it's the one case
	   that beats even an inline style, which this otherwise is. */
	transform: none !important;
	/* Webflow also sets `transform-style: preserve-3d` inline here. That
	   establishes a 3D rendering context, which acts as a BACKDROP ROOT —
	   so the pills' backdrop-filter had nothing behind it to sample and
	   rendered as a flat tint with no blur at all, no matter how the
	   filter itself was tuned. Flattening it is what actually makes the
	   glass work. */
	transform-style: flat !important;
}

.flow-nav__pills,
.flow-page .brand,
.flow-nav__pill {
	position: relative; /* positioning context for ::before below */
	display: inline-flex;
	align-items: center;
	height: 57rem;
	border-radius: 28.5rem;
	overflow: hidden; /* clips the ::before's extended sampling area to this pill's rounded shape */
	color: #000;
	text-decoration: none;
	white-space: nowrap;
	/* A blurred tint alone never reads as GLASS — over a flat page it's
	   just a grey shape, since there's nothing behind it to distort. What
	   sells it is the EDGE: a bright top rim where light catches, a darker
	   bottom rim, and a soft shadow lifting it off the page. That reads as
	   a physical pane at any background, which the tint alone didn't. */
	border: 1rem solid rgba(255, 255, 255, 0.7);
	box-shadow:
		inset 0 1rem 1rem rgba(255, 255, 255, 0.95),
		inset 0 -1rem 1rem rgba(0, 0, 0, 0.04),
		0 2rem 12rem rgba(0, 0, 0, 0.07);
}

.flow-nav__pills {
	/* Figma Rectangle 24 (891 → 1543, 652 wide) holds: the "projects view"
	   label at 208, then three 142-wide tabs at 6rem intervals, with 6rem
	   of padding on the right. The label sits FLUSH to the container's left
	   edge and butts straight against the first tab — hence no left padding
	   and no blanket gap; the 6rem intervals come from the sibling rule
	   under .flow-nav__item below. */
	gap: 0;
	padding: 6rem 6rem 6rem 0;
	/* This is the actual element compressing (default flex-shrink:1) —
	   flex-shrink:0 on ancestors (.flow-nav, .header__left) stops THEM from
	   being squeezed by what's further out, but doesn't stop their own
	   children from shrinking internally, which is what was truncating
	   RANDOM to "RAN" and clipping GRID/List via this element's own
	   overflow:hidden. */
	flex-shrink: 0;
}

.flow-page .brand,
.flow-nav__pill {
	padding: 0 32rem;
	font-size: 20rem;
	line-height: 30rem;
	letter-spacing: 0.06em;
	text-transform: uppercase;
}

/* Extended-pseudo-element technique (joshwcomeau.com/css/backdrop-filter):
   blur() only samples pixels directly behind the filtered element, and
   these pills are short, so doubling the height gives it more to sample
   from, then the mask fades the extra half back out. Shared across all 4
   pills rather than repeated per-selector. */
.flow-nav__pills::before,
.flow-page .brand::before,
.flow-nav__pill::before {
	content: '';
	position: absolute;
	inset: 0;
	height: 200%;
	/* A semi-transparent WHITE tint reads as invisible over a page that's
	   already white — there's no color difference to reveal. Figma's own
	   fill is #f8f8f8 (barely different from white on its own too), so the
	   tint needs to actually BE gray, and mostly opaque, to always read as
	   that flat pill color; backdrop-filter still processes whatever real
	   contrast is behind it, which is what adds the glass depth on top. */
	/* Now that the blur actually samples (see transform-style on .nav), the
	   tint can be light enough to read as glass instead of paint — it only
	   needs to keep the label legible over whatever passes underneath. */
	background-color: rgba(250, 250, 250, 0.55);
	backdrop-filter: blur(20px) brightness(1.06) saturate(1.8);
	-webkit-backdrop-filter: blur(20px) brightness(1.06) saturate(1.8);
	mask-image: linear-gradient(to bottom, black 0%, black 50%, transparent 50%, transparent 100%);
	-webkit-mask-image: linear-gradient(to bottom, black 0%, black 50%, transparent 50%, transparent 100%);
	pointer-events: none;
	z-index: -1;
}

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
	.flow-nav__pills,
	.flow-page .brand,
	.flow-nav__pill {
		background-color: rgba(255, 255, 255, 0.92);
	}
}

.flow-nav__item {
	display: inline-flex;
	align-items: center;
	height: 45rem;
	padding: 0 24rem;
	border: 0;
	border-radius: 28.5rem;
	background: transparent;
	color: #000;
	font-family: inherit;
	font-size: 20rem;
	line-height: 30rem;
	letter-spacing: 0.06em;
	text-decoration: none;
	text-transform: uppercase;
	white-space: nowrap;
}

/* Figma sizes every tab identically (RANDOM 1099–1241, GRID 1247–1389,
   List 1395–1537 — all exactly 142) and the label at 208, rather than
   letting each one size to its own text. Content-sized tabs were what made
   the intervals read as uneven ("следить за расстоянием"): "∷ GRID" is a
   good deal shorter than "♺ RANDOM", so the gaps between the active pill
   and its neighbours never matched the design. Scoped to .flow-nav__pills
   so the same classes reused in the mobile burger menu (.mob-link
   .flow-nav__item--btn, see header.php) keep sizing to their content. */
.flow-nav__pills .flow-nav__item {
	justify-content: center;
	/* Measured from rendered ink at 1456px: 4rem top padding shifts only the
	   flex content by half that amount, producing equal 16px top/bottom ink
	   space while the 45rem selected-tab background stays centred. */
	padding: 4rem 0 0;
}

.flow-nav__pills .flow-nav__label {
	width: 208rem;
}

.flow-nav__pills .flow-nav__item--btn {
	width: 142rem;
}

/* 6rem between tabs, but none between the label and the first tab — the
   label butts straight against RANDOM in the frame. Keying off a preceding
   BUTTON gives exactly that: RANDOM follows the label (a span) and gets 0,
   GRID and List each follow a button and get 6. */
.flow-nav__pills .flow-nav__item--btn + .flow-nav__item {
	margin-left: 6rem;
}

/* "projects view" is a plain label (see header.php) — pointer cursor and
   hover background only belong on the actual tabs (RANDOM / GRID). */
.flow-nav__item--btn {
	cursor: pointer;
	transition: background .3s ease;
}

/* Figma Rectangle 25 is the selected-tab fill: #f2f2f2 against the
   #f8f8f8 nav container. Keeping that slightly darker fill means the active
   Random/Grid/List tab remains visible even when the page behind the glass
   nav is white. */
.flow-nav__item--btn:hover,
.flow-nav__item--btn[aria-pressed="true"] {
	background: #f2f2f2;
}

/* Dim while a reshuffle is in flight so the click clearly registered. */
.flow-nav__item--btn.is-loading {
	pointer-events: none;
	opacity: .5;
}

/* Buttons repeated inside the mobile burger menu — inherit .mob-link
   typography, just strip the native button chrome. */
.mob-link.flow-nav__item--btn {
	border: 0;
	background: transparent;
	font-family: inherit;
	text-align: left;
	padding: 0;
	cursor: pointer;
}

/* Standalone pill used by the statement CTA. */
.flow-pill__link {
	display: inline-flex;
	align-items: center;
	height: 57rem;
	padding: 0 32rem;
	border-radius: 28.5rem;
	background: #f8f8f8;
	color: #000;
	font-size: 20rem;
	line-height: 30rem;
	letter-spacing: 0.06em;
	text-decoration: none;
	text-transform: uppercase;
	white-space: nowrap;
	transition: background .3s ease;
}

.flow-pill__link:hover {
	background: #f2f2f2;
}

/* ---------- The grid ---------- */

.flow-section {
	padding-bottom: 120rem;
}

.flow-grid {
	display: grid;
	grid-template-columns: repeat(12, 1fr);
	/* Grid stretches items to the row's tallest by default, so a short cell
	   beside a tall one grows invisible empty space below its image — and the
	   hover caption, anchored to the cell, ends up floating well under the
	   picture it labels. Size every cell to its own content instead. */
	align-items: start;
	column-gap: 68rem;
	/* Rows are meant to interlock, not stack — the overlap offsets do the
	   spacing. A 68rem row-gap on top of that pushed the median cell-to-cell
	   distance positive, so nothing nested. */
	row-gap: 24rem;
	width: 1780rem;
	max-width: 100%;
	margin: 0 auto;
	/* No top padding needed — combine_flow_layout() guarantees row 0 never
	   gets a negative v_offset (nothing sits above it to overlap into), so
	   there's nothing here that can clip. This used to carry padding-top:
	   60rem as a workaround for a generator bug that let a SECOND cell in
	   row 0 shift upward "over" its own row-mate; fixing that made this
	   match GRID mode's padding (0) instead of visibly jumping between the
	   two on toggle. */
}

.flow-cell {
	position: relative;
	grid-column: var(--flow-col) / span var(--flow-span);
	/* --flow-shift is a % of the cell's OWN height, so it scales with the
	   image rather than being a fixed distance. */
	transform: translateY(var(--flow-shift, 0%));
	/* translateY is visual only — it doesn't shrink the space the cell
	   occupies, so a pulled-up cell would leave a hole and the next row
	   would sit too low. --flow-pull converts that height-relative shift
	   into the width-relative % a margin understands (a % margin resolves
	   against the container WIDTH), closing the gap. It's computed per cell
	   in combine_flow_layout() because it depends on the asset's aspect. */
	margin-bottom: calc(-1 * var(--flow-pull, 0%));
	text-decoration: none;
	color: inherit;
}

/* --flow-aspect is the asset's true ratio, emitted per cell. Reserving the
   box up front means no layout shift as images stream in — which matters a
   lot here, because cells overlap and a late reflow would visibly jump the
   whole composition. */
.flow-cell__media {
	position: relative;
	overflow: hidden;
	background: #f4f4f4;
	line-height: 0;
	aspect-ratio: var(--flow-aspect, 16 / 9);
}

/* Nothing is cropped and nothing is letterboxed: the media box is built
   from the asset's OWN aspect ratio (--flow-aspect, emitted per cell), so
   the box is already exactly the right shape and the image just scales to
   fill it. `contain` rather than `cover` so that if a ratio is ever
   slightly off (e.g. a source whose real dimensions weren't readable and
   fell back to 16/9), the image letterboxes instead of silently cutting
   pieces off — visible imperfection beats invisible data loss. */
.flow-cell__media img,
.flow-cell__media video {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: contain;
}

/* SVG icon/logo graphics (the about-us gallery) aren't photos — show them
   whole instead of cropping to the fixed 9:16/1:1/16:9 box, and don't let
   the placeholder grey show through their transparent areas. */
.flow-cell--graphic .flow-cell__media {
	background: transparent;
}

/* Pinned to row 0 (page-flow.php's $pinned_url), which gets the LOWEST
   z-index from combine_flow_layout()'s per-cell counter — any later row
   that overlaps upward over it (the whole point of the overlap mechanic)
   would otherwise cover it. !important beats the inline z-index style the
   same way --flow-aspect overrides do elsewhere in this file. */
.flow-cell--graphic {
	z-index: 999 !important;
	/* The SIGN never scales with its column span — it's a fixed-size mark
	   that only moves around the composition ("скейлить не надо, пусть
	   большая всегда будет, просто по позиции ездит"). 327rem is its size
	   in the design frame (Group 2087329654, 327×327), which matches how
	   big it renders on the homepage. */
	width: 327rem;
	max-width: 100%;
}

.flow-cell--graphic .flow-cell__media {
	aspect-ratio: 1 !important;
}

.flow-cell--graphic .flow-cell__media img {
	object-fit: contain;
}

.flow-cell__lottie {
	width: 100%;
	aspect-ratio: 1 / 1;
}

/* ---------- Load reveal ----------
 *
 * A horizontal wipe rather than a fade: the veil clips away to the right
 * while the asset clips in from the left, so the two edges travel together
 * and the swap reads as one gesture. Same technique and easing as
 * superdesigners.co (0.9s, cubic-bezier(0,0,.2,1)).
 *
 * The veil carries the video poster where we have one, so the reveal comes
 * off the real first frame instead of flat grey.
 */

/* Everything below is gated on `html.w-mod-js`, which header_block.php sets
   synchronously in <head>. Without it the assets simply render — a clip-path
   that only JS can release would otherwise hide the entire page if a script
   fails to load. */

.flow-cell__veil {
	display: none;
}

/* Two elements, not one. The OUTER box carries the wipe and must stay
   exactly the size of the media box it covers — clip-path percentages
   resolve against an element's own border box, so an oversized veil (an
   earlier version used inset:-20rem to give the blur overscan) wipes across
   a different physical distance than the area it's meant to uncover, and
   leaves a sliver of #f4f4f4 showing at the edge. A `transform: scale()`
   doesn't fix that either — a transform applies to the ALREADY-clipped
   shape, so it drags the reveal edge somewhere else again.
   The INNER layer is where the blur lives and is free to be oversized,
   because it's cropped by the outer's plain overflow:hidden rather than by
   any clip-path maths of its own. */

.w-mod-js .flow-cell__veil {
	display: block;
	position: absolute;
	inset: 0;
	overflow: hidden;
	background-color: #f4f4f4;
	/* Clips from the LEFT edge inward, travelling right. */
	clip-path: inset(0 0 0 0);
	transition: clip-path .9s cubic-bezier(0, 0, .2, 1);
	pointer-events: none;
	z-index: 1;
}

.w-mod-js .flow-cell__veil-bg {
	position: absolute;
	/* Overscan so the blur has real pixels to soften into instead of
	   fading into transparent right at its own edge. */
	inset: -20rem;
	background-size: cover;
	background-position: center;
	/* Same technique as superdesigners.co's `loading-layer-bg`: a low-res
	   thumbnail blurred to hide its low resolution, standing in for the
	   full asset until it's ready. */
	filter: blur(30rem);
}

/* Only the VEIL animates. The asset underneath is never clipped.
 *
 * An earlier version also clipped the image from inset(0 100% 0 0) to
 * inset(0), mirroring superdesigners.co. Visually that's indistinguishable
 * from wiping the veil alone — as the veil's left edge travels right, the
 * asset behind it is revealed left-to-right either way — but clipping the
 * image gives it ZERO visible area until revealed, and a zero-area image is
 * precisely what a browser's lazy-load heuristic treats as "nowhere near the
 * viewport". Below-the-fold images could then sit deferred indefinitely,
 * showing the blurred placeholder forever. Not worth the risk for no visual
 * difference. */

.w-mod-js .flow-cell.is-revealed .flow-cell__veil {
	clip-path: inset(0 0 0 100%);
}

@media (prefers-reduced-motion: reduce) {
	.flow-cell__veil {
		transition: none;
	}
}

/* ---------- View switching (RANDOM vs GRID vs LIST) ---------- */

/* The three views are separate sections with DIFFERENT CONTENT, not one
   grid restyled: RANDOM is the shuffled image pool, GRID is the real
   project list, LIST is the "Index" table. flow.js puts .is-grid-view or
   .is-list-view on .flow-page to switch. Both of the non-random views drop
   everything above their own heading ("в грид верх надо отрезать весь до
   заголовка") — showreel/teasers/statement are RANDOM-only. */
.flow-view--grid,
.flow-view--list {
	display: none;
}

.flow-page.is-grid-view .flow-view--random,
.flow-page.is-grid-view .flow-teaser,
.flow-page.is-grid-view .flow-statement,
.flow-page.is-grid-view .flow-showreel,
.flow-page.is-list-view .flow-view--random,
.flow-page.is-list-view .flow-teaser,
.flow-page.is-list-view .flow-statement,
.flow-page.is-list-view .flow-showreel {
	display: none;
}

.flow-page.is-grid-view .flow-view--grid,
.flow-page.is-list-view .flow-view--list {
	display: block;
}

/* ---------- GRID mode ---------- */

/* Metrics from the design's own "Recent work" node (51:68): 135 / 125 /
   -1%, same type as the statement, NOT a small section label. */
/* "расстояние от верха как в макете" — the frame puts "Recent work" at
   y:264. .flow-page already carries 120rem of top padding to clear the
   fixed nav, so this makes up the remaining 144rem. (The nav really ends
   at 117 — 30 + 57 + 30 — and .flow-page rounds that to 120; subtracting
   from 264 gives 144, not the 147 an exact 117 would imply. Measured on
   the live page the old value put the first image at 434 design units
   against the frame's 431.)

   Both headings then sit at 264 and, with the 125rem line box and 42rem
   margin below, the first image lands at 431 exactly.

   .flow-section only ever carried padding-bottom, which left this gap to
   whatever margin happened to be around. */
.flow-view--grid,
.flow-view--list {
	padding-top: 144rem;
}

.flow-recent-heading {
	/* Keep the same 1780rem centred box as the content below it, then let
	   the display type optically overhang that edge. In the design both
	   heading nodes start at x:61 while the grid/table starts at x:70. */
	width: 1780rem;
	max-width: 100%;
	text-indent: -9rem;
	/* Heading box ends y:389, first image starts y:431. */
	margin: 0 auto 42rem;
	font-size: 135rem;
	line-height: 125rem;
	letter-spacing: -0.01em;
	font-weight: 500;
}

/* Same 12-column geometry as the random grid, but nothing overlaps: rows
   are explicit and every cell is top-aligned. Row shapes are planned in
   page-flow.php from the design frame's own rectangles — small 16:9
   (span 4, 547 wide) + big 16:9 (span 8, 1163 wide), or three squares. */
.flow-projects-grid {
	display: grid;
	grid-template-columns: repeat(12, 1fr);
	align-items: start;
	column-gap: 68rem;
	/* The rebuilt frame runs a constant 235rem from one row's image bottom
	   to the next row's image top (1441→1676, 2336→2572, 3119→3354). A grid
	   item here is image + caption, so the gap between ITEMS is that 235
	   less the caption block (16rem offset + 32rem line) = 187rem. The old
	   141rem came from measuring 189rem on the previous version of this
	   frame, which the rebuild widened.
	   Titles that wrap to two lines eat into the following gap rather than
	   pushing the row down — the frame does the same thing (its 2-line
	   "Sber Conference…" captions sit closer to the next row than the
	   1-line ones do), so this matches the design rather than fighting it. */
	row-gap: 187rem;
	width: 1780rem;
	max-width: 100%;
	margin: 0 auto;
}

.flow-project {
	grid-row: var(--flow-grid-row, auto);
	grid-column: var(--flow-grid-col, auto) / span var(--flow-grid-span, 4);
	text-decoration: none;
	color: #000;
}

/* Fixed per-shape ratios, straight from the frame: 547×310 and 1163×660
   are both 16:9; the squares are 547×547. Covers are videos and ARE
   allowed to crop here ("кавер это видос, пусть кропаются") — unlike the
   random pool, where nothing may be cut. */
.flow-project__media {
	position: relative;
	overflow: hidden;
	background: #f4f4f4;
	background-position: center;
	background-repeat: no-repeat;
	background-size: cover;
	line-height: 0;
}

.flow-project--wide .flow-project__media {
	aspect-ratio: 16 / 9;
}

.flow-project--square .flow-project__media {
	aspect-ratio: 1 / 1;
}

.flow-project__media img,
.flow-project__media video {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* GRID rests on the exact image export from Figma. Its matching video is
   kept as a hover-only layer, so an MP4's arbitrary first frame cannot
   replace the designed artwork on initial paint. */
.flow-project__media.has-figma-artwork video {
	opacity: 0;
}

.flow-project__media.has-figma-artwork.is-video-hovering video {
	opacity: 1;
}

/* Design node 51:48 — 27/32, no letter-spacing, 16rem under the image. */
.flow-project__caption {
	margin-top: 16rem;
	font-size: 27rem;
	line-height: 32rem;
	letter-spacing: 0;
}

/* ---------- Showreel (block 1) ---------- */

/* The front page's own hero video, reused here rather than re-uploaded —
   see $flow_showreel in page-flow.php. Rendered through the same
   combine_video()/vp="any" path as every other cell so it gets the same
   mobile/desktop source switching and lazy-activation behaviour. */
.flow-showreel {
	/* First block of the random view. Figma 6270:150 puts Rectangle 18 at
	   y:292; .flow-page already spends 120rem clearing the nav, so this is
	   the remaining 172rem. */
	padding-top: 172rem;
	/* The gap down to the first teaser row is only 54rem in the frame
	   (showreel ends 1293, row starts 1347) — far tighter than the space
	   above it. .flow-teaser owns that gap; see the sibling rule below. */
	padding-bottom: 0;
}

.flow-showreel__media {
	position: relative;
	/* The SAME 1780rem box as the grid and every other block, not
	   .container's full width. Inheriting the container made this one block
	   1880rem wide — measured 1058rem tall against the frame's 1001, so the
	   page's one full-bleed-looking element was the only thing not aligned
	   to the 12-column geometry. */
	width: 1780rem;
	max-width: 100%;
	margin: 0 auto;
	aspect-ratio: 16 / 9;
	overflow: hidden;
	border-radius: 8rem;
	background: #f4f4f4;
}

/* Figma: showreel bottom 1293 → first teaser row 1347. */
.flow-showreel + .flow-teaser {
	padding-top: 54rem;
}

.flow-showreel__media video {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* ---------- Random teaser bursts (blocks 2 and 4) ---------- */

/* A SMALL instance of the same overlapping random composition as the main
   grid (checked directly against Figma: these images overlap and vary in
   size around the "We combine" statement, not a neat uniform row) —
   .flow-teaser-grid reuses .flow-grid/.flow-cell wholesale (see
   combine_flow_teaser_row() in page-flow.php), this just gives the section
   its own vertical rhythm since it's much shorter than the main grid. */
.flow-teaser {
	padding-top: 60rem;
	padding-bottom: 60rem;
}

.flow-teaser-grid {
	padding-top: 0;
}

/* ---------- Statement ("We combine …", block 3) ---------- */

.flow-statement {
	position: relative;
	padding-top: 120rem;
	padding-bottom: 0;
}

/* "текущий сайт" (the live homepage) keeps this same slider image snug
   against the "We combine" text — both are flex children of one card
   (.div-block-24) with no gap between them. The default 20+60rem here put
   much more air between them than that. Scoped to the statement→teaser
   pair specifically, not .flow-teaser generally, so block 2 (after the
   showreel) keeps its own normal spacing. */
.flow-statement + .flow-teaser {
	padding-top: 20rem;
}

/* The same 1780rem box every other block on the page uses. Without it the
   statement sat on .container's 20rem padding alone — starting at x:20
   against its neighbours' x:70, i.e. 50rem further out on both sides, which
   is the "less margin" it read as. Constraining this wrapper rather than
   .container itself leaves the container's padding doing its real job:
   holding text off the screen edge once the viewport is narrower than the
   box. max-width keeps it from overflowing there. */
.flow-statement__inner {
	width: 1780rem;
	max-width: 100%;
	margin: 0 auto;
}

/* Plain text, no card (Figma #1118). main.css's shared .h1 is 135rem but
   with line-height 130 / letter-spacing 0 — the design's own statement
   (node 51:210) is 135 / 125 / -1%, so those two need restating here. */
.flow-statement .h1.topz {
	font-size: 135rem;
	line-height: 125rem;
	letter-spacing: -0.01em;
	/* 420rem matches the homepage's own instance of this rotating heading
	   (.div-block-25's min-height) — "text block on main page has its
	   height fixed and it's not fixed here". JS (tuckStatement in flow.js)
	   still overrides this via inline style once it can measure the actual
	   tallest phrase at THIS box's width, which may wrap differently than
	   the homepage's narrower card — inline style beats this rule
	   regardless of specificity, so this is purely the pre-JS floor: no
	   flash of a shorter box before the real reserve applies, and no gap
	   if JS is ever slow, blocked, or disabled. */
	min-height: 420rem;
}

/* Block-level, below the heading — not inline with the rotating text (see
   the markup note in page-flow.php for why: a pill mixed into wrapping
   text broke badly on mobile). .flow-pill__link already has its own
   correct type (20rem/30rem/0.06em) matching Figma's Rectangle 29; this
   just adds the gap under the statement. */
.flow-statement__cta {
	margin-top: 40rem;
}

/* ---------- LIST view ("Index", Figma 6447:40) ---------- */

/* Four columns on the same 1780rem box as everything else. The frame puts
   client at x:70, type-of-work at 523, industry at 995 and year hard right
   (right-aligned, ending at 1850) — as fractions of the 1779 content width
   that lands on 25.4% / 26.5% / 40.7% / the rest, which these fr units
   reproduce without pinning anything to absolute pixels. */
.flow-index {
	position: relative;
	width: 1780rem;
	max-width: 100%;
	margin: 0 auto;
}

.flow-index__head,
.flow-index__row {
	display: grid;
	grid-template-columns: 452fr 472fr 724fr 131fr;
	align-items: center;
	/* Figma rules sit 59rem apart (550, 610, 669, 727 …). */
	min-height: 59rem;
	font-size: 20rem;
	line-height: 30rem;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: #000;
	text-decoration: none;
	/* The hairline between rows. The hovered row promotes its own rule and
	   the one under it to solid black — see the is-hovered rules below. */
	border-bottom: 1rem solid rgba(0, 0, 0, 0.2);
}

.flow-index__head {
	border-bottom-color: rgba(0, 0, 0, 0.2);
}

/* One blank row's worth of height, no border/content — see the markup
   note in page-flow.php. */
.flow-index__spacer {
	height: 59rem;
}

.flow-index__year {
	text-align: right;
	/* "трекинг 0 — yes, year values" — every other column keeps the
	   table's 0.06em uppercase tracking; year values don't. */
	letter-spacing: 0;
}

/* Rows dim while another row is hovered, so the active one reads as the
   only live line in the table — the frame greys every other row's type. */
.flow-index.is-hovering .flow-index__row {
	color: rgba(0, 0, 0, 0.35);
	transition: color .25s ease;
}

.flow-index.is-hovering .flow-index__row.is-hovered {
	color: #000;
}

/* Solid rule under the hovered row, and under the row above it — that pair
   is what the frame draws at full opacity around the active line. The head
   needs naming too: it is the previous sibling of the FIRST row, so it owns
   that row's top rule. */
.flow-index__row.is-hovered,
.flow-index__row.is-before-hovered,
.flow-index__head.is-before-hovered {
	border-bottom-color: #000;
}

/* The shared square preview: 547×547 in the frame, at x:1238 — 1168rem
   from the table's own left edge. JS moves it vertically to the hovered
   row and swaps its source; it never takes pointer events, so it can sit
   over the year column without blocking the row link underneath. */
.flow-index__preview {
	position: absolute;
	left: 1168rem;
	top: 0;
	width: 547rem;
	height: 547rem;
	overflow: hidden;
	pointer-events: none;
	opacity: 0;
	visibility: hidden;
	transition: opacity .25s ease, transform .35s cubic-bezier(.22, .61, .36, 1);
	z-index: 5;
}

.flow-index__preview.is-visible {
	opacity: 1;
	visibility: visible;
}

/* Square crop — the cover is 16:9, so it IS cut here, same licence GRID's
   covers have ("кавер это видос, пусть кропаются"). */
.flow-index__preview-poster,
.flow-index__preview video {
	position: absolute;
	inset: 0;
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* The poster is a separately loaded image rather than relying on the
   video's poster attribute: it paints before the MP4 request begins. Once
   the video has a renderable frame, it takes over the same square. */
.flow-index__preview-poster {
	background: #f4f4f4;
}

.flow-index__preview video {
	opacity: 0;
	background: #f4f4f4;
}

.flow-index__preview.is-video-ready video {
	opacity: 1;
}

@media screen and (max-width: 992px) {
	/* No room for a 547rem square beside the table at this width, and no
	   hover to open it with on most of these devices — the rows stay plain
	   links. */
	.flow-index__preview {
		display: none;
	}

	.flow-index__head,
	.flow-index__row {
		font-size: 14rem;
		min-height: 44rem;
	}
}

@media screen and (max-width: 767px) {
	/* Four columns don't survive a phone. Drop industry (the least load-
	   bearing of the three text columns) and stack the rest as client +
	   year on one line, type of work under it. */
	.flow-index__head {
		display: none;
	}

	.flow-index__row {
		grid-template-columns: 1fr auto;
		gap: 0 12rem;
		padding: 12rem 0;
	}

	.flow-index__row > span:nth-child(3) {
		display: none;
	}

	.flow-index__row > span:nth-child(2) {
		grid-column: 1 / -1;
		opacity: .5;
	}
}

/* ---------- Featured-project interstitials ---------- */

/* The big full-width 16:9 blocks that break up the random feed after 7–10
   media cells — see combine_flow_feature_block() in page-flow.php. A
   grid-column: 1 / -1 child of .flow-grid, so it
   claims its own full row and the overlapping cells around it keep
   interlocking normally. The generous vertical margin is deliberate: the
   cells above it can carry a negative v_offset of up to 32% of their own
   height, and without room to absorb that a tall neighbour would ride up
   over the video. */
.flow-feature {
	grid-column: 1 / -1;
	display: block;
	/* Even margins, and generous: a full-width video reads as a hard stop in
	   the feed, so it needs more air around it than two overlapping cells
	   need from each other. The old 80/40 left the following row crowding
	   the caption — made worse by that row's own upward pull, which
	   page-flow.php now cancels for the row directly after a feature. */
	margin: 100rem 0;
	text-decoration: none;
	color: inherit;
	/* Above the flow cells' own z-index ladder (they count up from 1), so
	   an overlapping neighbour can never sit on top of the feature. */
	position: relative;
	z-index: 200;
}

.flow-feature__media {
	position: relative;
	width: 100%;
	aspect-ratio: 16 / 9;
	overflow: hidden;
	background: #f4f4f4;
}

.flow-feature__media video,
.flow-feature__media img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* Title and CTA sit on one baseline under the video, as in the review
   frame ("Combine blocks movie" with its SEE PROJECT pill trailing it). */
.flow-feature__foot {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 24rem;
	margin-top: 24rem;
}

/* "размер шрифта надо крупнее, такой же как сверху" — matches
   .flow-statement .h1.topz ("We combine") exactly: 135rem / 125rem. */
.flow-feature__title {
	font-size: 135rem;
	line-height: 125rem;
	letter-spacing: -0.01em;
}

@media screen and (max-width: 767px) {
	.flow-feature {
		margin: 56rem 0;
	}

	.flow-feature__foot {
		gap: 16rem;
		margin-top: 16rem;
	}

	.flow-feature__title {
		font-size: 40rem;
		line-height: 46rem;
	}
}

/* ---------- Load more (block 4 pagination) ---------- */

.flow-cell--paged,
.flow-feature--paged {
	display: none;
}

/* Invisible trigger, not a control — flow.js's IntersectionObserver loads
   the next batch once this scrolls near the viewport (rootMargin does the
   "before you'd notice" work), no button or click involved
   ("а мы же можем так 13 блоков просто грузить?"). A real height, even
   a small one, rather than 0 — some browsers don't reliably fire
   intersection on a truly zero-size target. */
.flow-load-sentinel {
	height: 4rem;
}

/* ---------- Burger-menu tier ---------- */

/* main.css hides .header__left entirely at 991px — below this the burger
   menu takes over and already carries these links (see .menu-block in
   header.php). Studio/Get-in-touch are SIBLINGS of .header__left on this
   template, not children, so that hide rule never reached them: they kept
   rendering as pills and collided with the burger button. Same breakpoint
   as main.css's own rule, deliberately, so they disappear together. */
@media screen and (max-width: 991px) {
	.flow-nav__pill {
		display: none;
	}
}

/* ---------- Tablet ---------- */

@media screen and (max-width: 992px) {

	/* html font-size rebases to 100vw/992 here, so these rem values are
	   read against a 992 frame — they are NOT the 1920 numbers halved. */
	.flow-nav__item,
	.flow-pill__link {
		height: 40rem;
		padding: 0 16rem;
		font-size: 16rem;
	}

	/* .flow-statement .h1.topz (135rem) outranks main.css's own responsive
	   .h1.topz rules on specificity, so without an override here the
	   statement stayed at full desktop size all the way down — which is
	   why it rendered enormous on phones. */
	.flow-statement .h1.topz {
		font-size: 70rem;
		line-height: 66rem;
	}

	.flow-grid {
		width: 100%;
		column-gap: 30rem;
		row-gap: 40rem;
	}

	/* Halve the overlap — at this width full-strength pulls collide. */
	.flow-cell {
		transform: translateY(calc(var(--flow-shift, 0%) * .5));
		margin-bottom: calc(-.5 * var(--flow-pull, 0%));
	}

	.flow-grid.is-uniform .flow-cell {
		/* Desktop's explicit --flow-grid-row plans rows of 2 OR 3 items —
		   forcing every cell to span 6 here means a former 3-item row would
		   overflow its pinned row (3 × 6 = 18 of 12 columns). Auto-flow
		   instead, so the browser wraps naturally to fit 2-per-row. */
		grid-row: auto;
		grid-column: auto / span 6;
	}

	/* These blocks never got their own tablet treatment — reduce padding to
	   match the mobile tier below. Block 3 needs nothing here: it reuses the
	   homepage's own div-block-24/25 markup, which already has its own
	   responsive rules in main.css. */
	.flow-showreel,
	.flow-teaser {
		padding-top: 40rem;
		padding-bottom: 40rem;
	}

	/* The nav tab widths above are literal Figma numbers measured against
	   the 1920 frame. html rebases to 100vw/992 here, so holding them would
	   make the tab group proportionally twice as wide and overflow the bar
	   — back to content sizing, matching the height/padding reset above. */
	.flow-nav__pills .flow-nav__item {
		padding: 0 16rem;
	}

	.flow-nav__pills .flow-nav__label,
	.flow-nav__pills .flow-nav__item--btn {
		width: auto;
	}

	/* Same rebasing problem for the grid's own desktop-frame spacing: 147
	   and 187 are ~8-10% of a 1920 frame but nearly half a 992 one. */
	.flow-view--grid,
	.flow-view--list {
		padding-top: 60rem;
	}

	/* Desktop's 9rem optical overhang is measured in the 1920 frame. Keep
	   the responsive heading inside the narrower container instead of
	   rebasing that desktop value against the 992 frame. */
	.flow-recent-heading {
		text-indent: 0;
	}

	.flow-projects-grid {
		row-gap: 72rem;
	}
}

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

@media screen and (max-width: 767px) {

	/* ONE column on mobile, both List and Grid — at phone width a 2-up grid
	   left each tile too small to read, and the cells keep their own
	   (sometimes very tall) ratios now, so pairing them side by side put
	   wildly mismatched heights next to each other. A real mobile design is
	   coming separately; this is the interim, robust fallback. */
	.flow-grid {
		grid-template-columns: 1fr;
		column-gap: 0;
		row-gap: 16rem;
		padding-top: 0;
	}

	.flow-cell {
		grid-column: 1 / -1;
		transform: none;
		margin-bottom: 0;
		z-index: auto !important;
	}

	/* GRID mode's desktop rows carry an explicit --flow-grid-row (see
	   $flow_grid_plan in page-flow.php) sized for a 12-column layout — reset
	   it here so cells just stack in source order like the base rule above
	   already does for List mode. */
	.flow-grid.is-uniform .flow-cell {
		grid-row: auto;
		grid-column: 1 / -1;
	}

	/* Matches main.css's own .h1.topz mobile size — see the tablet-tier
	   note above for why an explicit override is needed at all. */
	.flow-statement .h1.topz {
		font-size: 30rem;
		line-height: 32rem;
		letter-spacing: 0;
	}

	.flow-showreel,
	.flow-teaser {
		padding-top: 24rem;
		padding-bottom: 24rem;
	}

	/* No teaser-specific override needed here — .flow-teaser-grid IS
	   .flow-grid, so it already gets the same square-tile mobile treatment
	   as the main grid above, for free. */

	/* Same trap as .flow-statement .h1.topz: .flow-page .brand's pill
	   sizing (57rem tall, 20rem type) outranks main.css's own responsive
	   .brand rules, so it never scaled down. Worse, those rem values GROW
	   here — html font-size rebases from 100vw/1920 to 100vw/992, and to
	   100vw/375 below 495px — so an untouched 57rem pill is physically
	   BIGGER on a phone than on a desktop. */
	.flow-page .brand {
		height: 40rem;
		padding: 0 16rem;
		font-size: 16rem;
	}
}

/* Smallest tier — main.css rebases html to 100vw/375 at 495px and drops
   .brand to 14rem type at 479px; match that rather than let the pill keep
   growing against the narrower frame. */
@media screen and (max-width: 479px) {
	.flow-page .brand {
		height: 34rem;
		padding: 0 14rem;
		font-size: 14rem;
	}
}
