/* ==========================================================================
   PROJECTS PAGES  (projects.html, project-single.html)

   All CSS for the projects pages lives in this file (team decision; the only
   exception to README rule 1). Every other README rule applies here too:
   color / font tokens, calc(N * var(--u)) sizes, README breakpoints, .btn-default.

   MERGE NOTE: this file will later be merged into the Cubix files.
     - each "Pxx" block            -> cubix-style.css (as its own section)
     - each "Pxx ... RESPONSIVE"   -> cubix-responsive.css (same section)

   Contents
   P00. Products showcase   (older code, not yet moved to the tokens)
   P01. Projects – Hero
   P02. Products showcase – Card logos   (old carousel, no longer used)
   P03. Products showcase – White watermark cards
   P04. Products page – Hero
   P05. Products page – Banner (title + breadcrumb)
   P06. Products page – Side decorations
   P07. Products page – Picture gallery   (every product except Cubix PMS)
   ========================================================================== */

/* ==========================================================================
   P00. Products showcase                       page: projects.html
   Older code, kept as it was. Still uses its own colors (--ink, --acc);
   move them to the site tokens before merging. Font: the site body font
   (--font-body, same as the home page); headings stay on --font-heading.
   ========================================================================== */
:root{--ink:#0d0d10;--mut:#6c7280;--faint:#a3a8b3;--line:rgba(13,13,16,.09);--acc:#2f5bff;
--font:var(--font-body)}
*{box-sizing:border-box;margin:0}
html,body{overflow-x:clip}
body{font-family:var(--font);color:var(--ink);background:#fff;-webkit-font-smoothing:antialiased}
button{font:inherit;color:inherit;cursor:pointer;background:none;border:0}
button:focus-visible{outline:2px solid var(--acc);outline-offset:3px}

/* ---------- Site integration ----------
   projects.html also loads bootstrap.min.css + custom.css for the site footer.
   These rules stop their global element styles leaking into the showcase.
   Kept near the top so the showcase rules below still take priority. */
.show{font-size:16px;line-height:normal}
.show *{margin:0}
.show :is(h1,h2,h3,h4,h5,h6){color:inherit;line-height:inherit}
.show p{line-height:inherit}
.show dt{font-weight:inherit}
/* keep the site's own look (font, text colour) in the top bar, header, home-page banner and footer */
.topbar,.main-header,.hero_rev,.main-footer{font-family:var(--default-font);-webkit-font-smoothing:auto}
.topbar,.main-header,.hero_rev{color:var(--text-color)}


/* ---------- Hero: home-page banner (.hero_rev in custom.css) with an image instead of the video ---------- */
/* Same position / size / fit as custom.css ".hero_rev video". On the home page the video is centred in the
   slider wrapper, which the slider script sizes to (viewport height - 60px), hence top: 50vh - 30px. */
.hero_rev .hero-banner-img{position:absolute;top:calc(50vh - 30px);left:50%;transform:translate(-50%,-50%);width:100vw;height:100vh;object-fit:cover;z-index:0}

/* ---------- Showcase ---------- */
.show{position:relative;padding-bottom:0;overflow:hidden;background:var(--color-white)}
.show>*{position:relative}
/* Tabs + screen mockup (.pp-show): plain white, so it reads as its own part between the hero
   (pink wash at its bottom) and the secondary images (pink wash at their top).
   Spacing = home page sections: 80 top / bottom (60 below 992, 50 below 768). */
.pp-show{
	padding: calc(80 * var(--u)) 0;
	background: var(--color-white);
}
.pp-show .tabs{margin-top: 0}
.pp-show + .band{margin-top: 0}

/* Heading: normal flow, NOT sticky. Scrolls away with the page; JS adds shrink/fade/parallax. */
.heading{text-align:center;padding:0;transform-origin:50% 0;will-change:transform,opacity}
.eyebrow{display:block;font-size:.72rem;letter-spacing:.2em;text-transform:uppercase;color:var(--mut);margin-bottom:2.2vh}
.heading h2{font-size:clamp(2.1rem,6vw,5.2rem);font-weight:500;letter-spacing:-.045em;line-height:1.02}

/* Level 1: products */
/* Product carousel: tall portrait cards, active one in the centre and larger */
.pcar{--dist:205px;position:relative;max-width:1180px;height:400px;margin:0 auto}
.ptrack{position:absolute;inset:0}
.pcard{--x:0;--s:1;--br:1;position:absolute;left:50%;top:50%;width:240px;height:350px;border-radius:22px;overflow:hidden;text-align:left;padding:0;
background:linear-gradient(180deg,var(--c1),var(--c2));
transform:translate(-50%,-50%) translateX(calc(var(--x)*var(--dist))) scale(var(--s));filter:brightness(var(--br));
transition:transform .7s cubic-bezier(.2,.7,.2,1),opacity .5s,filter .5s,box-shadow .4s;will-change:transform;box-shadow:0 14px 30px -18px rgba(40,32,20,.45)}
.pcard[data-id=smb]{--c1:#b9b4a6;--c2:#8d8879}
.pcard[data-id=hotel]{--c1:#d8ccba;--c2:#a89a82}
.pcard[data-id=cudine]{--c1:#cc8d69;--c2:#93573e}
.pcard[data-id=clinic]{--c1:#b4cdd4;--c2:#6b8f99}
.pcard[data-id=retail]{--c1:#dccb9f;--c2:#a58a4c}
.pcard[data-id=campus]{--c1:#cbc3dc;--c2:#857a9f}
.pcard::after{content:"";position:absolute;inset:0;background:linear-gradient(to top,rgba(28,24,18,.86) 0,rgba(28,24,18,.3) 42%,transparent 62%)}
.pcard.on{box-shadow:0 34px 60px -26px rgba(40,32,20,.6)}
.pc-t{position:absolute;left:20px;right:20px;bottom:20px;z-index:1;color:#fff;display:block}
.pc-t small{display:block;font-size:.62rem;letter-spacing:.08em;text-transform:uppercase;opacity:.85;margin-bottom:5px}
.pc-t b{display:block;font-size:1.15rem;font-weight:600;letter-spacing:-.01em;line-height:1.2}
.pnav{position:absolute;top:50%;margin-top:-19px;z-index:5;width:38px;height:38px;border-radius:50%;background:#fff;display:grid;place-items:center;
font-size:1.1rem;line-height:1;box-shadow:0 6px 18px -6px rgba(13,13,16,.3);transition:transform .2s}
.pnav:hover{transform:scale(1.08)}.pnav.prev{left:0}.pnav.next{right:0}   /* arrows sit at the far ends, clear of the outermost cards */

/* Level 2: features */
.tabs{display:flex;justify-content:center;flex-wrap:wrap;gap:8px;margin:44px auto 14px;padding:0 20px;max-width:var(--container-w)}
.tab{padding:9px 18px;border-radius:999px;border:1px solid var(--line);background:#fff;font-size:.85rem;color:var(--mut);
display:inline-flex;align-items:center;gap:8px;transition:all .3s}
.tab::before{content:"";width:0;height:6px;border-radius:50%;background:var(--acc);transition:width .3s}
.tab:hover{color:var(--ink)}
.tab.on{background:var(--ink);border-color:var(--ink);color:#fff;transform:scale(1.03)}
.tab.on::before{width:6px}
.tabs:not(.open) .tab.extra{display:none}
/* "10 More" / "Show Less" pill: same size as the tabs, with the home page button look
   (cubix-style.css "01. Global -> Button"): blue -> pink -> blue gradient that slides on hover, pink glow */
.show .tab.tab-more{
	border-color: transparent;
	background: linear-gradient(to right, var(--color-accent) 0%, var(--color-accent-2) 50%, var(--color-accent) 100%);
	background-size: 200% auto;
	box-shadow: 0 8px 24px rgba(var(--color-accent-2-rgb), 0.25);
	color: var(--color-white);
	font-weight: 600;
	transition: background-position 0.4s ease-in-out, box-shadow 0.4s ease-in-out;
}
.show .tab.tab-more:hover,
.show .tab.tab-more:focus-visible{
	background-position: right center;
	box-shadow: 0 10px 30px rgba(var(--color-accent-2-rgb), 0.4);
	color: var(--color-white);
}
.tab.tab-more::before{display:none}
.tabs-bar{display:none}                                   /* phones only (P-mobile below) */
/* Feature tabs: soft navy shadow so the pills look raised; stronger on hover and on the selected tab.
   (New code: README tokens + --u sizes, scoped to the showcase section .show) */
.show .tab{box-shadow: 0 calc(8 * var(--u)) calc(22 * var(--u)) rgba(var(--color-primary-rgb), 0.16)}
.show .tab:hover{box-shadow: 0 calc(12 * var(--u)) calc(28 * var(--u)) rgba(var(--color-primary-rgb), 0.24)}
.show .tab.on{box-shadow: 0 calc(12 * var(--u)) calc(28 * var(--u)) rgba(var(--color-primary-rgb), 0.35)}
/* description line: same box as the window below it (.stage), so its text lines up with the container */
.fdesc{text-align:center;font-size:.9rem;color:var(--mut);min-height:1.4em;max-width:var(--container-w);margin:0 auto 34px;padding:0 15px}
.fdesc b{color:var(--ink);font-weight:600}

/* Stage: left editorial | main image | right meta. Same box as the header container
   (.main-header .container in cubix-style.css) and the hero (P04), so the left text starts under
   the Cubix logo and the right meta ends under the "Book Demo" button. The side texts only fit
   beside the image from 1700px, below that the right meta moves under the image */
.stage{display:grid;grid-template-columns:calc(150 * var(--u)) minmax(0,1fr) calc(150 * var(--u));gap:calc(28 * var(--u));align-items:center;max-width:var(--container-w);margin:0 auto;padding:0 15px}
.side{font-size:.78rem;color:var(--mut);line-height:1.5}
.side.l p{font-size:1.02rem;font-weight:500;color:var(--ink);letter-spacing:-.01em;line-height:1.35}
.side.l i{display:block;width:32px;height:1px;background:var(--ink);margin-bottom:14px}
.side.r{padding-left:16px;border-left:1px solid var(--line)}
.side.r b{display:block;font-size:1.5rem;font-weight:500;color:var(--ink);letter-spacing:-.03em;font-variant-numeric:tabular-nums}
.side.r span{display:block;font-size:.66rem;letter-spacing:.14em;text-transform:uppercase;margin:4px 0 14px}
.side.r em{font-style:normal;color:var(--ink);font-weight:500}
/* right meta: big faint feature number behind 01 / 15, like the hero product info (P04 .pp-hero-num) */
.side.r{position:relative}
.side.r b,.side.r span,.side.r em{position:relative}
.side.r .side-num{
	position: absolute;
	top: calc(-120 * var(--u));
	left: calc(-14 * var(--u));
	margin: 0;
	font-family: var(--font-display);
	font-size: calc(160 * var(--u));
	font-weight: 600;
	line-height: 1;
	letter-spacing: 0;
	color: color-mix(in srgb, var(--acc) 5%, transparent);
	pointer-events: none;
}
/* Black display texts (editorial, counter, row headings): the big cursor circle (data-cursor="-opaque")
   replaces the arrow on hover, like the hero title "Powering Your Business" */
.side.l p,.side.r b,.det h4{cursor:none}
/* side text, counter and product name: same font, size and weight as the home Products side info
   (cubix-style.css "07. Products": .side p / dd = display font, 24 design px, 600) */
.side.l p,
.side.r b,
.side.r em{
	font-family: var(--font-display);
	font-size: calc(24 * var(--u));
	font-weight: 600;
	line-height: 1.25;
	letter-spacing: 0;
}
@media (max-width: 767.98px){
	.side.r b,
	.side.r em{font-size: 20px}
}
/* product name in the brand gradient (like the gradient part of the section titles) */
.side.r em{
	display: inline-block;               /* gradient spans the name only, not the whole column */
	padding-right: 0.08em;               /* stops the gradient clipping the last letter */
	background: var(--gradient-brand);
	-webkit-background-clip: text;
	background-clip: text;
	-webkit-text-fill-color: transparent;
}
.cap{text-align:center;font-size:.66rem;letter-spacing:.1em;color:var(--faint);margin-top:14px;text-transform:uppercase}

/* Main image: mock app window */
.frame{background:#f4f5f8;border:1px solid var(--line);border-radius:18px;overflow:hidden;box-shadow:0 40px 80px -40px rgba(13,13,16,.35),0 2px 6px rgba(13,13,16,.05)}
.chrome{display:flex;align-items:center;gap:6px;padding:10px 14px;background:#fff;border-bottom:1px solid var(--line)}
.chrome i{width:8px;height:8px;border-radius:50%;background:var(--gradient-brand)}
.chrome span{margin:0 auto;font-size:10px;color:var(--mut);background:#f1f2f6;border-radius:6px;padding:3px 40px}
.app{display:flex;min-height:480px}
.app nav{width:140px;flex:none;background:#fff;border-right:1px solid var(--line);padding:14px 8px;display:flex;flex-direction:column;gap:2px}
.app nav em{font-style:normal;font-weight:700;font-size:12px;padding:0 8px 10px;letter-spacing:-.01em}
.app nav em img{display:block;width:24px;height:auto}
/* every sidebar item is always visible: one line each, and the items share the window's height
   (up to 30px each) instead of scrolling */
.app nav b{font-weight:500;font-size:10.5px;color:var(--mut);padding:0 8px;border-radius:7px;white-space:nowrap;flex:1 1 30px;min-height:16px;max-height:30px;display:flex;align-items:center}
.app nav b.on{background:color-mix(in srgb,var(--acc) 10%,#fff);color:var(--acc)}
.app nav b{cursor:pointer;transition:color .2s}
.app nav b:hover{color:var(--acc)}
/* shows the sidebar items can be clicked: on hover (or keyboard focus) a soft pill, the text
   moves right a little and a small arrow slides in on the right */
.app nav b{position:relative;transition:color .25s,background-color .25s,padding-left .25s cubic-bezier(.22,1,.36,1)}
.app nav b::after{content:"\203A";position:absolute;right:8px;top:50%;font-size:13px;line-height:1;color:var(--acc);opacity:0;transform:translate(-6px,-55%);transition:opacity .25s,transform .25s cubic-bezier(.22,1,.36,1)}
.app nav b:not(.on):hover,.app nav b:not(.on):focus-visible{color:var(--acc);background:color-mix(in srgb,var(--acc) 6%,#fff);padding-left:12px;outline:0}
.app nav b:not(.on):hover::after,.app nav b:not(.on):focus-visible::after{opacity:1;transform:translate(0,-55%)}
/* first-view intro (js/product.js navGlide): a soft box glides down the sidebar and back up, then a
   small "Click" tag blinks on the open name; it never blocks clicks */
.app nav{position:relative}
.app nav .nav-glide{position:absolute;top:0;z-index:2;border-radius:7px;pointer-events:none;background:color-mix(in srgb,var(--acc) 10%,transparent);transition:background-color .3s}
.app nav.is-gliding b.on{background:transparent}
.app nav.is-gliding b{transform-origin:8px 50%;transition:color .25s,transform .3s cubic-bezier(.34,1.56,.64,1)}
.app nav.is-gliding b.is-pop{color:var(--acc);transform:scale(1.14)}
.app nav .nav-glide.is-hint{background:transparent}
.app nav .nav-glide span{position:absolute;right:5px;top:50%;display:flex;align-items:center;gap:3px;font-style:normal;font-size:8px;font-weight:600;line-height:1;color:#fff;background:var(--acc);border-radius:20px;padding:3px 6px;opacity:0;transform:translateY(-50%)}
.app nav .nav-glide span i{font-size:8px}
.app nav .nav-glide.is-hint span{animation:navClick .7s ease-in-out 8 alternate}
@keyframes navClick{from{opacity:0}to{opacity:1}}
.body{flex:1;min-width:0;padding:14px;display:flex}
/* single-image slot in the middle of the app window: rounded, fills all the space */
.shot{position:relative;flex:1;border-radius:16px;overflow:hidden;background:#e9ecf3;border:1.5px dashed #c3c9d8;display:grid;place-items:center;text-align:center}
.shot .ph{display:grid;gap:6px;color:var(--mut);padding:20px}.shot .ph b{font-size:.9rem;font-weight:600;color:var(--ink)}.shot .ph span{font-size:.72rem;word-break:break-all}
.shot.has{border:0;background:none}.shot.has .ph{display:none}
.shot img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:top left;border-radius:inherit}
/* While a picture loads (.is-loading: nothing yet · .is-wait: switching on a slow network, the old picture dims)
   a soft shimmer shows instead of the "Upload image" box */
.shot.is-loading,.shot.is-wait{border:0;background:linear-gradient(100deg,#eef0f6 30%,#f7f8fb 50%,#eef0f6 70%) 0 0/300% 100%;animation:shot-shimmer 1.4s linear infinite}
.shot.is-loading .ph{visibility:hidden}
.shot.is-wait img{opacity:.35;transition:opacity .3s}
@keyframes shot-shimmer{to{background-position:-150% 0}}
@media (prefers-reduced-motion:reduce){.shot.is-loading,.shot.is-wait{animation:none}}
/* With a real screenshot (.is-shot, set by js/product.js): the window's height comes from the picture,
   not from the sidebar. The sidebar is laid over the left edge at the same height and scrolls if longer. */
.app.is-shot{position:relative;min-height:0}
.app.is-shot nav{position:absolute;top:0;bottom:0;left:0;padding-bottom:8px;overflow:hidden}
.app.is-shot .body{margin-left:140px;align-items:flex-start}
.app.is-shot .shot{border-radius:10px;box-shadow:0 1px 3px rgba(var(--color-primary-rgb), .08)}

/* Picture zoom (js/product.js "PICTURE ZOOM"), PMS window and product sliders: a small hint on the picture,
   the round lens that follows the mouse while Ctrl is held (computers), and the full-screen view (click / tap) */
.shot-hint{position:absolute;right:10px;bottom:10px;z-index:2;display:flex;align-items:center;gap:6px;padding:5px 11px;border-radius:999px;
	background:rgba(17,20,33,.66);color:#fff;font-size:12px;font-weight:500;line-height:1.2;pointer-events:none;opacity:0;transition:opacity .3s}
.shot.has .shot-hint{opacity:1}                      /* phones / tablets: always shown ("Tap to zoom") */
@media (hover:hover) and (pointer:fine){              /* computers: only while the mouse is on the picture */
	.shot.has .shot-hint{opacity:0}
	.shot.has:hover .shot-hint{opacity:1}
}
.app .shot.has,.pp-gal .shot.has{cursor:zoom-in}
.lens-on .shot.has{cursor:none}                      /* while Ctrl is held the lens is the pointer */
.lens-on .shot-hint,.lens-on .cb-cursor{opacity:0!important}
.shot-lens{position:fixed;left:0;top:0;z-index:1000;width:130px;height:130px;border-radius:50%;pointer-events:none;
	background-color:#fff;background-repeat:no-repeat;border:3px solid #fff;box-shadow:0 14px 40px rgba(13,13,16,.28),0 0 0 1px rgba(13,13,16,.08);
	opacity:0;transition:opacity .18s;will-change:transform}
.shot-lens.on{opacity:1}

.shot-view{position:fixed;inset:0;z-index:10000;display:flex;flex-direction:column;background:#0c0e16;
	opacity:0;visibility:hidden;transition:opacity .22s,visibility 0s .22s}
.shot-view.on{opacity:1;visibility:visible;transition:opacity .22s}
.sv-bar{display:flex;align-items:center;gap:10px;padding:12px 16px;color:#fff;flex:none}
.sv-bar b{flex:1;min-width:0;font-size:15px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sv-bar button{width:42px;height:42px;flex:none;border:0;border-radius:50%;background:rgba(255,255,255,.12);color:#fff;font-size:16px;display:grid;place-items:center;cursor:pointer;transition:background-color .2s}
.sv-bar button:hover{background:rgba(255,255,255,.24)}
.sv-bar button:focus-visible{outline:2px solid #fff;outline-offset:2px}
.shot-view.is-zoomed .sv-zoom i::before{content:"\f010"}   /* magnifying-glass-minus */
.sv-sc{flex:1;min-height:0;overflow:auto;touch-action:pan-x pan-y;overscroll-behavior:contain;cursor:zoom-in;scrollbar-width:none}
.sv-sc::-webkit-scrollbar{display:none}
.shot-view.is-zoomed .sv-sc{cursor:grab}
.shot-view.is-drag .sv-sc{cursor:grabbing}
.sv-in{display:flex;width:max-content;min-width:100%;min-height:100%}
.sv-in img{display:block;flex:none;margin:auto;height:auto;max-width:none;border-radius:6px;box-shadow:0 20px 60px rgba(0,0,0,.45);user-select:none;-webkit-user-drag:none}
.shot-view.on .sv-in{animation:sv-in .28s cubic-bezier(.2,.7,.2,1)}
@keyframes sv-in{from{opacity:0;transform:scale(.97)}}
.sv-tip{position:absolute;left:50%;bottom:18px;transform:translateX(-50%);margin:0;padding:7px 14px;border-radius:999px;background:rgba(255,255,255,.14);
	color:#fff;font-size:13px;white-space:nowrap;pointer-events:none;transition:opacity .4s}
.shot-view.tip-off .sv-tip{opacity:0}
html.sv-lock,html.sv-lock body{overflow:hidden}
@media (prefers-reduced-motion:reduce){.shot-view.on .sv-in{animation:none}}

/* Secondary images */
/* Light band: white with the home page's soft pink wash coming down from the top (one glow from each
   top corner, like the home Products section), light mini app windows next to plain text, in a zig-zag.
   Spacing = home page sections: 80 top / bottom (60 below 992, 50 below 768). */
.band{position:relative;overflow:hidden;margin-top:70px;padding:calc(80 * var(--u)) 0;
background:
	radial-gradient(100% calc(445 * var(--u)) at 0% 0%,   rgba(var(--color-accent-2-rgb), 0.08) 0%, transparent 90%),
	radial-gradient(100% calc(445 * var(--u)) at 100% 0%, rgba(var(--color-accent-2-rgb), 0.08) 0%, transparent 90%),
	var(--color-white)}
/* Same box as the header container (.main-header .container) */
.secs{display:flex;flex-direction:column;gap:calc(80 * var(--u));max-width:var(--container-w);margin:0 auto;padding:0 15px}
/* Zig-zag rows: picture on one side, its text on the other. space-between puts the left item on the
   container's left edge (under the logo) and the right item on its right edge (under "Book Demo") */
.zz{display:flex;align-items:center;justify-content:space-between;gap:calc(90 * var(--u))}
.zz.r{flex-direction:row-reverse}
.zz .sec{flex:0 1 calc(560 * var(--u))}
/* Text: no card, just number, label, heading and description */
.det{flex:0 1 calc(420 * var(--u));color:var(--color-primary)}
.det small{display:flex;align-items:center;gap:calc(14 * var(--u));margin-bottom:calc(16 * var(--u))}
.det small b{font-family:var(--font-display);font-size:calc(56 * var(--u));font-weight:600;line-height:1;
	background:var(--gradient-brand);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}
.det small span{font-size:calc(12 * var(--u));font-weight:600;letter-spacing:.16em;color:var(--color-text)}
.det h4{font-family:var(--font-heading);font-size:calc(34 * var(--u));font-weight:600;line-height:1.2;margin-bottom:calc(12 * var(--u))}
.det p{font-size:calc(17 * var(--u));line-height:1.65;color:var(--color-text)}
/* Picture: a light mini app window (same look as the big one above): rounded, soft shadow, gradient dots */
.sec{background:var(--color-light);border:1px solid var(--line);border-radius:calc(18 * var(--u));overflow:hidden;
box-shadow:0 30px 60px -30px rgba(var(--color-primary-rgb), .3),0 2px 6px rgba(var(--color-primary-rgb), .04)}
.sec .chrome{padding:calc(10 * var(--u)) calc(14 * var(--u))}
.sec-body{display:flex;min-height:calc(250 * var(--u));padding:calc(14 * var(--u))}
.sec .sec-body>*{flex:1;height:auto}   /* the widget fills the window (no grey strip under short widgets) */
.sec:hover{box-shadow:0 36px 70px -30px rgba(var(--color-primary-rgb), .4),0 2px 6px rgba(var(--color-primary-rgb), .05)}

/* ---- AOS-style "animate on scroll" (same data-aos API as michalsnik.github.io/aos, written in vanilla JS) ---- */
[data-aos]{opacity:0;transition-property:opacity,transform,box-shadow;transition-duration:.4s;transition-timing-function:ease}
[data-aos=fade]{transform:none}
[data-aos=fade-up]{transform:translate3d(0,100px,0)}
[data-aos=fade-down]{transform:translate3d(0,-100px,0)}
[data-aos=fade-left]{transform:translate3d(100px,0,0)}
[data-aos=fade-right]{transform:translate3d(-100px,0,0)}
[data-aos=zoom-in]{transform:scale(.6)}
[data-aos].aos-animate{opacity:1;transform:none}

/* ---------- Mock UI widgets (all generated from data) ---------- */
.w{background:#fff;border:1px solid var(--line);border-radius:10px;padding:10px;display:flex;flex-direction:column;gap:9px;min-width:0;height:100%;font-size:10px}
.w h4{font-size:9.5px;font-weight:600;color:var(--mut)}
.kp{grid-column:1/-1;display:grid;grid-template-columns:repeat(4,1fr);gap:8px}
.kp div{background:#fff;border:1px solid var(--line);border-radius:10px;padding:9px 10px}
.kp small{display:block;font-size:9px;color:var(--mut)}.kp b{font-size:16px;font-weight:600;letter-spacing:-.02em}
.kp em{font-style:normal;font-size:9px;margin-left:5px;color:var(--faint)}.kp em.up{color:var(--acc)}
.bars{flex:1;display:flex;align-items:flex-end;gap:6%;min-height:64px}.bars i{flex:1;background:#e3e6ee;border-radius:3px 3px 0 0}.bars i.hi{background:var(--acc)}
.ln{flex:1;width:100%;min-height:64px}
.dn{--p:50;width:74px;height:74px;border-radius:50%;margin:auto;position:relative;display:grid;place-items:center;background:conic-gradient(var(--acc) calc(var(--p)*1%),#e8ebf1 0)}
.dn::before{content:"";position:absolute;inset:11px;background:#fff;border-radius:50%}.dn b{position:relative;font-size:14px;font-weight:600}
.w>small{text-align:center;color:var(--mut);font-size:9px}
table{width:100%;border-collapse:collapse}th{text-align:left;font-weight:500;color:var(--faint);padding-bottom:4px;font-size:9px}
td{padding:5px 0;border-top:1px solid #eff0f4}td:last-child,th:last-child{text-align:right}
.pill{display:inline-block;padding:1px 7px;border-radius:99px;background:#eef0f5;font-size:8.5px;color:var(--mut)}
.pill.a{background:color-mix(in srgb,var(--acc) 12%,#fff);color:var(--acc)}
.ls{display:grid;gap:7px}.ls div{display:flex;align-items:center;gap:8px}
.ls i{width:20px;height:20px;border-radius:50%;background:#eceef3;flex:none;display:grid;place-items:center;font-style:normal;font-size:8px;font-weight:600;color:var(--mut)}
.ls p{flex:1;min-width:0}.ls b{display:block;font-weight:600;font-size:10px}.ls span{color:var(--mut);font-size:9px}
.pg{display:grid;gap:9px}.pg div{display:grid;gap:4px}.pg span{display:flex;justify-content:space-between;color:var(--mut)}
.pg u{display:block;height:5px;border-radius:3px;background:#e8ebf1;overflow:hidden}.pg u i{display:block;height:100%;background:var(--acc);border-radius:3px}
.iv{display:grid;gap:6px}.iv div{display:flex;justify-content:space-between;color:var(--mut)}
.iv .t{border-top:1px solid var(--line);padding-top:7px;color:var(--ink);font-weight:700;font-size:12px}
.pf{display:grid;gap:8px;justify-items:center;text-align:center}
.pf i{width:34px;height:34px;border-radius:50%;background:linear-gradient(135deg,var(--acc),color-mix(in srgb,var(--acc) 40%,#fff))}
.pf b{font-size:11px}.pf span{color:var(--mut)}
.pf dl{display:grid;grid-template-columns:repeat(3,1fr);gap:6px;width:100%;margin-top:2px}
.pf dl div{background:#f5f6f9;border-radius:7px;padding:5px}.pf dt{font-size:8px;color:var(--faint)}.pf dd{font-weight:600}
.gd{display:grid;grid-template-columns:repeat(6,1fr);gap:5px}
.gd i{aspect-ratio:1.5;border-radius:5px;border:1px solid #e3e6ee;background:#f7f8fa}
.gd i.o{background:var(--acc);border-color:var(--acc)}.gd i.c{background:repeating-linear-gradient(45deg,#e3e6ee 0 3px,#f7f8fa 3px 6px)}
.cal{display:grid;grid-template-columns:repeat(7,1fr);gap:3px;text-align:center}
.cal i{font-style:normal;padding:4px 0;border-radius:5px;color:var(--mut);font-size:9px}.cal i.h{color:var(--faint);font-size:8px}
.cal i.m{background:color-mix(in srgb,var(--acc) 13%,#fff);color:var(--ink)}.cal i.s{background:var(--acc);color:#fff}

/* ---------- Responsive ----------
   Same steps as the home page (cubix-responsive.css): 1199.98 small laptop, 991.98 tablet,
   767.98 mobile, 575.98 small mobile, 900 for the layout switch and 699.98 for left-aligned text.
   Between 1200 and 1919px nothing changes here: the whole part shrinks evenly with --u, like the home page. */

/* Below 1700px: the side texts no longer fit next to the picture (it would get so small that the
   15 sidebar items no longer fit beside it), so the left text hides and the right meta moves
   under the picture, in one line */
@media (max-width: 1699.98px){
	.stage{grid-template-columns: minmax(0, 1fr)}
	.side.l{display: none}
	.side.r{order: 2; display: flex; align-items: baseline; gap: 16px; border: 0; padding: 0; justify-content: center; flex-wrap: wrap}
	.side.r span{margin: 0}
	.side.r .side-num{display: none}
}

/* Small laptop (992px – 1199px): fixed sizes, a little smaller than the 1920 design */
@media (max-width: 1199.98px){
	.zz{gap: 60px}
	.det small b{font-size: 48px}
	.det h4{font-size: 28px}
	.det p{font-size: 16px}
}

/* Tablet (below 992px): home page section spacing */
@media (max-width: 991.98px){
	.pp-show,
	.band{padding: 60px 0}
	.secs{gap: 60px}
	.det small b{font-size: 44px}
	.det h4{font-size: 24px}
}

/* Below 901px (home page layout switch): no sidebar in the big window (the tabs above do the same
   job), and the picture rows stack: picture on top, its text under it */
@media (max-width: 900px){
	.app nav{display: none}
	.app{min-height: 380px}
	.app.is-shot .body{margin-left: 0}
	.kp{grid-template-columns: repeat(2, 1fr)}
	.zz,
	.zz.r{flex-direction: column; align-items: stretch; gap: 20px}
	.zz .sec{flex: none; width: 100%}
	.det{flex: none}
	.sec-body{min-height: 200px}
}

/* Mobile (below 768px) */
@media (max-width: 767.98px){
	.pp-show,
	.band{padding: 50px 0}
	.secs{gap: 50px}

	/* tabs: one row you can swipe; the right edge fades out to show there are more */
	.tabs{
		flex-wrap: nowrap;
		overflow-x: auto;
		justify-content: flex-start;
		padding: 6px 40px 16px 15px;
		scrollbar-width: none;
		-webkit-mask-image: linear-gradient(90deg, var(--color-black) 0, var(--color-black) calc(100% - 40px), transparent 100%);
		mask-image: linear-gradient(90deg, var(--color-black) 0, var(--color-black) calc(100% - 40px), transparent 100%);
	}
	.tabs::-webkit-scrollbar{display: none}
	.tab{flex: none}

	/* thin bar under the row: the thumb shows there are more tabs and how far the row is swiped
	   (js/product.js tabsBar; iPhone Safari ignores styled scrollbars, so this is a plain element) */
	.tabs-bar{
		display: block;
		position: relative;
		height: 3px;
		margin: -6px 15px 14px;
		border-radius: 3px;
		background: rgba(var(--color-primary-rgb), 0.1);
		opacity: 0;
		transition: opacity 0.3s ease;
	}
	.tabs-bar.on{opacity: 1}
	.tabs-bar i{
		position: absolute;
		top: 0;
		bottom: 0;
		left: 0;
		border-radius: inherit;
		background: var(--gradient-brand);
	}
	.fdesc{padding: 0 15px}

	/* corners like the home page cards on phones */
	.frame{border-radius: 12px}
	.sec{border-radius: 10px}

	.det small b{font-size: 40px}
	.det small span{font-size: 11px}
	.det h4{font-size: 22px}
	.det p{font-size: 15px}
}

/* Below 700px: text on the left, like the home page section titles */
@media (max-width: 699.98px){
	.fdesc{text-align: left}
	.side.r{justify-content: flex-start; padding: 0 15px}
	.cap{text-align: left; padding: 0 15px}
}

/* Old card carousel (P00 .pcar / .pcard, not used on the page any more): kept as it was */
@media (max-width:1100px){
.pcar{--dist:170px;height:370px}.pcard{width:210px;height:310px}}
@media (max-width:860px){
.pcar{--dist:140px;height:340px}.pcard{width:190px;height:280px}.pnav{left:4px}.pnav.next{right:4px;left:auto}}
@media (max-width:560px){
.pcar{--dist:104px;height:310px}.pcard{width:170px;height:250px}.pc-t{left:14px;right:14px;bottom:14px}.pc-t b{font-size:1rem}}
@media (prefers-reduced-motion:reduce){*{transition:none!important}}

/* ==========================================================================
   P01. Projects – Hero                         page: projects.html
   HTML: <section class="rev-slider hero_rev projects-hero">
   Same height as the page banner on about.html (.page-header in custom.css),
   which is a fixed 400px on every screen. A fixed px value is used on purpose
   (instead of calc(N * var(--u))) so both pages always match exactly.
   The banner image already fills the box (object-fit: cover), so it is cropped.
   ========================================================================== */

/* Banner height: drop the homepage hero's 21:9 shape and 420px minimum (custom.css .hero_rev) */
.projects-hero{
	aspect-ratio: auto;
	height: 400px;
	min-height: 0;
}

/* --------------------------------------------------------------------------
   P01. Projects – Hero · RESPONSIVE  -> move to cubix-responsive.css
   None needed: like about.html, the banner stays 400px on every screen.
   -------------------------------------------------------------------------- */

/* ==========================================================================
   P02. Products showcase – Card logos          page: projects.html
   HTML (built by js/product.js):
     <button class="pcard" aria-label="Product name"><span class="pc-t"> <small>category</small>
       <span class="pc-logo"><span class="pc-logo-box"><img></span></span> </span></button>
   Every card shows its product logo under the category. The logo already contains the product
   name, so the name is not written as text (if a product has no logo, its name shows instead).
   Logo files: images/logo/cubix-*.svg, set per product in js/product.js ("logo").
   ========================================================================== */

/* Logo slot under the category */
.show .pc-logo{
	display: block;
	margin-top: calc(8 * var(--u));
}

/* Logo box: kept smaller than the card's text width so the logo looks neat, left-aligned with the
   category; no background, the logo sits straight on the card's dark lower part */
.show .pc-logo-box{
	display: flex;
	align-items: center;
	justify-content: flex-start;
	width: 70%;
	aspect-ratio: 3 / 1;
}

/* The logo itself: as big as the box allows, never stretched */
.show .pc-logo-box img{
	display: block;
	max-width: 100%;
	max-height: 100%;
	object-fit: contain;
}

/* --------------------------------------------------------------------------
   P02. Products showcase – Card logos · RESPONSIVE  -> move to cubix-responsive.css
   None needed: the logo box is a % of the card's text area, so it follows the card's own
   breakpoints (P00).
   -------------------------------------------------------------------------- */

/* ==========================================================================
   P03. Products showcase – White watermark cards   page: projects.html
   HTML: <section class="cxw-section"> inside the hero (P04), cards built by js/white-cards.js
   Replaces the old card carousel (P00 .pcar / .pcard and P02, both no longer used on the page).
   All classes start with .cxw- so nothing clashes with other CSS.
   --cxw-gap is the distance between cards as a share of the card width (js/white-cards.js
   multiplies it by the card's width), so every size here can use calc(N * var(--u)).
   ========================================================================== */

/* Section: local names for the colors and card sizes used below */
.cxw-section{
	--cxw-ink: var(--color-primary);
	--cxw-muted: var(--color-text);
	--cxw-line: rgba(var(--color-black-rgb), 0.1);
	--cxw-pink: var(--color-accent-2);
	--cxw-grad: var(--gradient-brand);
	--cxw-s: .92;                    /* card scale: the hero's middle column is the header container minus the
	                                    two side columns, so the cards are 92% size on desktop (1.15 below 1200px) */
	--cxw-w: calc(270 * var(--u) * var(--cxw-s));   /* card width  */
	--cxw-h: calc(380 * var(--u) * var(--cxw-s));   /* card height */
	--cxw-gap: .8;                   /* distance between cards = 0.8 x card width (read by js/white-cards.js) */
	padding: calc(10 * var(--u)) 0;
	font-family: var(--font-body);
}

/* Stage: holds the cards in 3D; side cards fan out to the left and right */
.cxw-stage{
	position: relative;
	height: calc(500 * var(--u) * var(--cxw-s));
	perspective: calc(1400 * var(--u));
	overflow: hidden;
	touch-action: pan-y;             /* sideways swipe changes the card (js/white-cards.js); up / down scrolls the page */
	user-select: none;               /* PC: a mouse drag does not select text */
	-webkit-user-select: none;
	/* soft left / right edges: the side cards and their shadows fade out instead of being cut
	   in a hard vertical line */
	-webkit-mask-image: linear-gradient(90deg, transparent 0, var(--color-black) calc(48 * var(--u)), var(--color-black) calc(100% - 48 * var(--u)), transparent 100%);
	mask-image: linear-gradient(90deg, transparent 0, var(--color-black) calc(48 * var(--u)), var(--color-black) calc(100% - 48 * var(--u)), transparent 100%);
}

/* Frame around the stage (same size): holds the arrows, which stay sharp outside the stage's fade */
.cxw-frame{
	position: relative;
}

/* ---------- Card ---------- */
.cxw-card{
	position: absolute;
	left: 50%;
	top: 50%;
	width: var(--cxw-w);
	height: var(--cxw-h);
	margin: calc(var(--cxw-h) / -2) 0 0 calc(var(--cxw-w) / -2);
	border-radius: calc(22 * var(--u) * var(--cxw-s));
	overflow: hidden;
	cursor: pointer;
	background: var(--color-white);
	box-shadow: 0 calc(20 * var(--u)) calc(40 * var(--u)) rgba(var(--color-primary-rgb), 0.10), 0 0 0 1px rgba(var(--color-primary-rgb), 0.05);
	transition: transform .7s cubic-bezier(.22,1,.36,1), opacity .7s ease, filter .7s ease;
	will-change: transform;
}

/* Intro: the first spread out of the stack (js/white-cards.js spread()) is a little slower */
.cxw-stage.is-intro .cxw-card{transition-duration: 1.1s}

/* Gradient line along the bottom (full strength on the middle card) */
.cxw-card::after{
	content: "";
	position: absolute;
	left: 0; right: 0; bottom: 0;
	height: calc(4 * var(--u));
	background: var(--cxw-grad);
	opacity: .35;
	transition: opacity .7s;
}
.cxw-card.is-center::after{opacity: 1}

/* Big faint logo in the corner (the "watermark") */
.cxw-mark{
	position: absolute;
	right: calc(-48 * var(--u) * var(--cxw-s));
	bottom: calc(-30 * var(--u) * var(--cxw-s));
	width: calc(250 * var(--u) * var(--cxw-s));
	height: calc(250 * var(--u) * var(--cxw-s));
	opacity: .07;
	background-repeat: no-repeat;
	background-position: left center;
	background-size: auto 100%;
	pointer-events: none;
	transition: opacity .7s;
}
.cxw-card.is-center .cxw-mark{opacity: .13}

/* Card content: category chip, logo, description and "Explore" link */
.cxw-inner{
	position: absolute;
	inset: 0;
	display: flex;
	flex-direction: column;
	gap: calc(14 * var(--u) * var(--cxw-s));
	padding: calc(22 * var(--u) * var(--cxw-s));
}
.cxw-chip{
	align-self: flex-start;
	font-size: calc(11 * var(--u));
	font-weight: 700;
	letter-spacing: .12em;
	text-transform: uppercase;
	padding: calc(6 * var(--u)) calc(10 * var(--u));
	border-radius: 999px;
	background: var(--color-light);
	color: var(--color-text);
}
.cxw-logo{
	display: block;
	width: 82%;
	height: auto;
	margin-top: calc(6 * var(--u));
}
.cxw-desc{
	margin: auto 0 0;
	font-size: calc(13 * var(--u));
	line-height: 1.5;
	color: var(--cxw-muted);
}
.cxw-go{
	display: inline-flex;
	align-items: center;
	gap: calc(6 * var(--u));
	font-size: calc(13 * var(--u));
	font-weight: 700;
	color: var(--cxw-pink);
	text-decoration: none;
}
.cxw-go svg{width: calc(14 * var(--u)); height: calc(14 * var(--u)); fill: none; stroke: currentColor; stroke-width: 2.2}

/* ---------- Arrows & dots ---------- */
.cxw-arrow{
	position: absolute;
	top: 50%;
	translate: 0 -50%;
	z-index: 50;
	width: calc(44 * var(--u));
	height: calc(44 * var(--u));
	border-radius: 50%;
	border: 1px solid var(--cxw-line);
	background: var(--color-white);
	cursor: pointer;
	display: grid;
	place-items: center;
	box-shadow: 0 calc(6 * var(--u)) calc(16 * var(--u)) rgba(var(--color-primary-rgb), 0.08);
	/* subtle pop: "scale" is separate from the centring "translate", so the button never moves out of place.
	   The springy curve gives a small overshoot when it grows back after a click. */
	transition: scale .35s cubic-bezier(.34, 1.56, .64, 1), box-shadow .3s ease;
}
.cxw-arrow svg{width: calc(18 * var(--u)); height: calc(18 * var(--u)); stroke: var(--cxw-ink); fill: none; stroke-width: 2; transition: translate .3s ease}

/* hover: grows a little, slightly deeper shadow, the arrow nudges toward its direction */
.cxw-arrow:hover{
	scale: 1.08;
	box-shadow: 0 calc(10 * var(--u)) calc(22 * var(--u)) rgba(var(--color-primary-rgb), 0.14);
}
.cxw-prev:hover svg{translate: calc(-2 * var(--u)) 0}
.cxw-next:hover svg{translate: calc(2 * var(--u)) 0}

/* click: quick press in, then pops back (spring curve above) */
.cxw-arrow:active{
	scale: .92;
	transition-duration: .1s;
}
.cxw-prev{left: 0}
.cxw-next{right: 0}
.cxw-dots{display: flex; justify-content: center; gap: calc(8 * var(--u)); margin-top: calc(4 * var(--u))}
/* PC: the dots sit up in the empty band under the cards, so they stay on the first screen */
@media (min-width: 1200px){
	.cxw-dots{margin-top: calc(-30 * var(--u) * var(--cxw-s))}
}
.cxw-dots button{
	width: calc(8 * var(--u)); height: calc(8 * var(--u)); border-radius: 50%;
	border: 0; padding: 0; background: rgba(var(--color-black-rgb), 0.18); cursor: pointer;
	transition: width .3s;
}
.cxw-dots button.is-on{width: calc(24 * var(--u)); border-radius: calc(6 * var(--u)); background: var(--cxw-grad)}
.cxw-arrow:focus-visible, .cxw-card:focus-visible, .cxw-dots button:focus-visible, .cxw-filter button:focus-visible{
	outline: 2px solid var(--color-accent); outline-offset: 3px;
}

/* ---------- Group filter above the cards (js/white-cards.js builds the buttons) ----------
   All / Hospitality / Business / Digital, each with its number of products;
   the chosen one in the brand gradient (like the active dot).
   It sits in the empty band at the top of the card stage (the stage is taller than the cards),
   so adding it does not move anything on the page. */
.cxw-section{
	position: relative;
}
.cxw-filter{
	position: absolute;
	top: calc(10 * var(--u));            /* = the section's top padding: the top of the stage */
	left: 0;
	right: 0;
	z-index: 20;                         /* above the stage and its cards */
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: calc(8 * var(--u));
	pointer-events: none;                /* only the buttons take clicks, not the band around them */
}
.cxw-filter button{
	pointer-events: auto;
}
.cxw-filter button{
	padding: calc(8 * var(--u)) calc(16 * var(--u));
	border: 1px solid rgba(var(--color-primary-rgb), 0.12);
	border-radius: 100px;
	background: var(--color-white);
	color: var(--cxw-ink);
	font-family: var(--font-body);
	font-size: calc(15 * var(--u));
	font-weight: 600;
	line-height: 1.2;
	cursor: pointer;
	transition: background .3s ease, color .3s ease, border-color .3s ease, box-shadow .3s ease;
}
.cxw-filter button span{
	margin-left: calc(5 * var(--u));
	font-weight: 500;
	opacity: .5;
}
.cxw-filter button:hover{
	border-color: var(--cxw-pink);
}
.cxw-filter button.is-on{
	border-color: transparent;
	background: var(--cxw-grad);
	background-origin: border-box;   /* gradient spans the 1px transparent border too, so no pink/blue slivers repeat at the edges */
	color: var(--color-white);
	box-shadow: 0 calc(6 * var(--u)) calc(16 * var(--u)) rgba(var(--color-accent-2-rgb), 0.2);
}
.cxw-filter button.is-on span{
	opacity: .85;
}
@media (prefers-reduced-motion: reduce){
	.cxw-card{transition: none}
	.cxw-arrow, .cxw-arrow svg{transition: none}
}

/* --------------------------------------------------------------------------
   P03. Products showcase – White watermark cards · RESPONSIVE  -> move to cubix-responsive.css
   -------------------------------------------------------------------------- */

/* Small laptop / tablet: the hero is one column, so the cards are full size again */
@media (max-width: 1199.98px){
	.cxw-section{--cxw-s: 1.15; --cxw-gap: .8}
	.cxw-frame{max-width: 860px; margin: 0 auto}   /* arrows stay close to the cards on wide tablets */
	.cxw-filter{top: 10px}
	.cxw-filter button{padding: 8px 16px; font-size: 14px}
}

/* Mobile: smaller cards, closer together (README mobile breakpoint) */
@media (max-width: 767.98px){
	.cxw-section{--cxw-s: 1.15; --cxw-w: 240px; --cxw-h: 344px; --cxw-gap: .8}
	.cxw-stage{height: 500px}
	.cxw-prev{left: 4px}
	.cxw-next{right: 4px}
	.cxw-filter{gap: 6px}
	.cxw-filter button{padding: 7px 12px; font-size: 13px}
}

/* Small mobile: the four filter buttons stay on one line */
@media (max-width: 575.98px){
	.cxw-filter{gap: 5px}
	.cxw-filter button{padding: 6px 10px; font-size: 12px}
	.cxw-filter button span{margin-left: 3px}
}

/* ==========================================================================
   P04. Products page – Hero                     page: projects.html
   HTML: <div class="pp-hero"> at the top of <section class="show">
     intro copy | product cards (P03) | product in the middle (filled by js/product.js)
   The hero has its own white base, grid and glow; the showcase below it keeps the
   P00 background.
   ========================================================================== */

/* Hero band: white with a soft pink wash rising from the bottom, fading toward the top
   (same as the home Clients section, cubix-style.css "04. Clients": one glow from each
   bottom corner, wide enough to meet in the middle). No grid. */
.pp-hero{
	position: relative;
	overflow: hidden;
	background:
		radial-gradient(100% calc(445 * var(--u)) at 0% 100%,   rgba(var(--color-accent-2-rgb), 0.075) 0%, transparent 90%),
		radial-gradient(100% calc(445 * var(--u)) at 100% 100%, rgba(var(--color-accent-2-rgb), 0.075) 0%, transparent 90%),
		var(--color-white);
}
/* Three columns: intro | cards | product info.
   Same box as the header container (.main-header .container in cubix-style.css), so the intro
   starts under the logo and the product info ends under the "Book Demo" button. */
.pp-hero-in{
	position: relative;
	width: 100%;
	max-width: var(--container-w);
	margin: 0 auto;
	padding: calc(40 * var(--u)) 15px calc(80 * var(--u));   /* less on top: the dots under the cards stay on the first screen */
	display: grid;
	grid-template-columns: calc(360 * var(--u)) minmax(0, 1fr) calc(240 * var(--u));
	gap: calc(32 * var(--u));
	align-items: center;
}

/* Intro copy: same title design as the home page sections
   (cubix-style.css "09. Home section titles" + About text in "05. About") */

/* small title, with the sub-heading icon in front */
.pp-hero .pp-eyebrow{
	position: relative;
	display: inline-block;
	padding-left: calc(30 * var(--u));
	margin-bottom: 6px;
	font-family: var(--font-heading);
	font-size: calc(15 * var(--u));
	font-weight: 600;
	line-height: normal;
	letter-spacing: 0.2em;
	text-transform: uppercase;
	color: var(--color-primary);
}
.pp-hero .pp-eyebrow::before{
	content: '';
	position: absolute;
	top: 50%;
	left: 0;
	width: calc(20 * var(--u));
	height: calc(20 * var(--u));
	transform: translateY(-50%);
	background: url('../images/icon-sub-heading.svg') no-repeat left center / cover;
}

/* big title: dark, the <span> part in the brand gradient */
.pp-hero .pp-hero-title.nm-heading{
	margin: 0;
	font-family: var(--font-display);
	font-size: calc(46 * var(--u));
	font-weight: 700;
	font-style: normal;
	line-height: 1.2;
	letter-spacing: 0;
	color: var(--color-primary);
	cursor: none;                        /* the big cursor circle (data-cursor="-opaque") replaces the arrow, like "Our Products" */
}
.pp-hero .pp-hero-title span{
	padding-right: 0.08em;               /* stops the gradient clipping the last letter */
	background: var(--gradient-brand);
	-webkit-background-clip: text;
	background-clip: text;
	-webkit-text-fill-color: transparent;
}

/* text: same as the home About text */
.pp-hero .pp-hero-text{
	margin: calc(20 * var(--u)) 0 calc(36 * var(--u));
	max-width: calc(340 * var(--u));
	font-family: var(--font-body);
	font-size: calc(18 * var(--u));
	line-height: 1.7;
	color: rgba(var(--color-primary-rgb), 0.7);
}
.pp-hero .pp-hero-link{
	display: inline-flex;
	align-items: center;
	gap: calc(10 * var(--u));
	font-family: var(--font-body);
	font-size: calc(14 * var(--u));
	font-weight: 700;
	color: var(--color-primary);
	text-decoration: none;
}
.pp-hero .pp-hero-link svg{
	width: calc(34 * var(--u)); height: calc(34 * var(--u));
	padding: calc(8 * var(--u));
	border-radius: 50%;
	border: 1px solid rgba(var(--color-primary-rgb), 0.15);
	fill: none; stroke: var(--color-accent-2); stroke-width: 2;
	transition: transform .3s;
}
.pp-hero .pp-hero-link:hover svg{transform: translateY(calc(3 * var(--u)))}

/* "Scroll drop": the arrow slides down out of the circle, comes back in from the top,
   and a soft pink ring pings out from the circle as it settles. Loops every 2.4s. */
.pp-hero .pp-hero-link svg{
	overflow: hidden;                    /* the arrow disappears at the circle's edge */
	animation: ppScrollPing 2.4s ease-out infinite;
}
.pp-hero .pp-hero-link svg path{
	animation: ppScrollDrop 2.4s cubic-bezier(.22, 1, .36, 1) infinite;
}
@keyframes ppScrollDrop{                 /* units = the 24 x 24 icon box */
	0%, 12%  { translate: 0 0;    opacity: 1 }
	34%      { translate: 0 16px; opacity: 0 }   /* out through the bottom */
	35%      { translate: 0 -16px; opacity: 0 }  /* jump to above the top, unseen */
	60%,100% { translate: 0 0;    opacity: 1 }   /* back in the middle */
}
@keyframes ppScrollPing{
	0%, 55%  { box-shadow: 0 0 0 0 rgba(var(--color-accent-2-rgb), 0.35) }
	90%,100% { box-shadow: 0 0 0 calc(10 * var(--u)) rgba(var(--color-accent-2-rgb), 0) }
}
@media (prefers-reduced-motion: reduce){
	.pp-hero .pp-hero-link svg,
	.pp-hero .pp-hero-link svg path{animation: none}
}

/* Product in the middle of the cards: big faint number + 02 / 06, category, name */
.pp-hero .pp-hero-info{
	position: relative;
	font-family: var(--font-body);
	padding-top: calc(70 * var(--u));
}
.pp-hero .pp-hero-num{
	position: absolute;
	top: calc(-40 * var(--u));
	left: calc(-30 * var(--u));
	font-family: var(--font-display);
	font-size: calc(220 * var(--u));
	font-weight: 600;
	line-height: 1;
	color: color-mix(in srgb, var(--acc) 4%, transparent);
	transition: color .6s;
	pointer-events: none;
}
.pp-hero .pp-hero-count{
	position: relative;
	font-family: var(--font-body);
	font-size: calc(13 * var(--u));
	color: var(--color-text);
	margin-bottom: calc(10 * var(--u));
}
.pp-hero .pp-hero-count b{
	font-family: var(--font-display);
	font-size: calc(24 * var(--u));
	font-weight: 500;
	color: var(--color-primary);
	margin-right: calc(4 * var(--u));
}
.pp-hero .pp-hero-cat{
	position: relative;
	display: block;
	font-family: var(--font-body);
	font-size: calc(11 * var(--u));
	font-weight: 700;
	letter-spacing: .2em;
	text-transform: uppercase;
	color: var(--color-text);
	margin-bottom: calc(10 * var(--u));
}
.pp-hero .pp-hero-name{
	position: relative;
	font-family: var(--font-heading);
	font-size: calc(26 * var(--u));
	font-weight: 500;
	line-height: 1.2;
	color: var(--color-primary);
	margin-bottom: calc(22 * var(--u));
	/* product name in the brand gradient (like the gradient part of the section titles) */
	width: fit-content;                  /* gradient spans the name only, not the whole column */
	padding-right: 0.08em;               /* stops the gradient clipping the last letter */
	background: var(--gradient-brand);
	-webkit-background-clip: text;
	background-clip: text;
	-webkit-text-fill-color: transparent;
}
.pp-hero .pp-hero-line{
	display: block;
	width: calc(36 * var(--u));
	height: 2px;
	background: var(--gradient-brand);
}

/* --------------------------------------------------------------------------
   P04. Products page – Hero · RESPONSIVE  -> move to cubix-responsive.css
   -------------------------------------------------------------------------- */

/* Small laptop / tablet: intro on top (centred), cards full width, product info in one line under the dots */
@media (max-width: 1199.98px){
	.pp-hero-in{
		grid-template-columns: minmax(0, 1fr);
		gap: 24px;
		padding: 80px 15px;
		text-align: center;
	}
	.pp-hero .pp-hero-text{max-width: 560px; margin-left: auto; margin-right: auto}
	.pp-hero .pp-hero-info{
		display: flex;
		flex-wrap: wrap;
		justify-content: center;
		align-items: baseline;
		gap: 6px 16px;
		padding-top: 0;
	}
	.pp-hero .pp-hero-num,
	.pp-hero .pp-hero-line{display: none}
	.pp-hero .pp-hero-count,
	.pp-hero .pp-hero-cat,
	.pp-hero .pp-hero-name{margin: 0}
}
/* Title + text sizes: same steps as the home section titles and About text */
@media (max-width: 991.98px){
	.pp-hero-in{padding: 60px 15px}
	.pp-hero .pp-hero-title.nm-heading{font-size: 36px}
	.pp-hero .pp-hero-text{font-size: 17px}
}
@media (max-width: 767.98px){
	.pp-hero-in{padding: 50px 15px}
	.pp-hero .pp-hero-title.nm-heading{font-size: 26px}
	.pp-hero .pp-hero-text{font-size: 16px}
	.pp-hero .pp-hero-name{font-size: 22px}
}
/* Below 700px: intro and product info on the left, like the home page section titles */
@media (max-width: 699.98px){
	.pp-hero-in{text-align: left}
	.pp-hero .pp-hero-text{margin-left: 0; margin-right: 0}
	.pp-hero .pp-hero-info{justify-content: flex-start}
}

/* ==========================================================================
   P05. Products page – Banner (title + breadcrumb)     page: projects.html
   HTML: <div class="page-header"> (base styles: custom.css "Page Header")
   Same container as the header (.main-header .container in cubix-style.css) and the
   hero intro (P04), so "Our Products" starts under the Cubix logo and above
   "Powering Your Business" on every screen. custom.css keeps it at a fixed 1300px.
   ========================================================================== */

.page-header .container{
	max-width: var(--container-w);
}

/* breadcrumb in the site body font */
.page-header-box{
	font-family: var(--font-body);
}

/* title: display font like the home hero heading (custom.css asks for 800, which Oswald doesn't have) */
.page-header-box h1{
	font-family: var(--font-display);
	font-weight: 700;
}

/* ==========================================================================
   P06. Products page – Side decorations           page: projects.html
   Same look as the home page side decorations (cubix-style.css "06. Home side decorations"):
   they fill the empty space beside the container on wide screens (1200px+, hidden below).
     Left:  <span class="pp-side-word"><span class="home-side-words" data-words="A|B">A</span></span>
            big outline word, bottom to top
     Right: <div class="pp-side-label"><b>01</b><i></i><span class="home-side-words" data-words="...">..</span></div>
            section number + line + name, bottom to top
   The words change one after another (js/home-about.js, the same script as the home page).
   Used in the hero (01) and the tabs part (02), centred in their part like the home page.
   Purely decorative (aria-hidden).
   ========================================================================== */

.pp-side-word,
.pp-side-label{
	--side-gap: calc((100% - var(--container-w)) / 2);   /* width of one empty side */
	position: absolute;
	z-index: 0;
	pointer-events: none;
	user-select: none;
	overflow-anchor: none;               /* the changing words resize: never let them shift the scroll */
}

/* ---------- Left: big outline word (reads bottom to top) ---------- */
.pp-side-word{
	top: 50%;
	left: calc(var(--side-gap) / 2);     /* middle of the left gap */
	writing-mode: vertical-rl;
	transform: translate(-50%, -50%) rotate(180deg);
	font-family: var(--font-display);
	font-size: calc(90 * var(--u));
	font-weight: 700;
	line-height: 1;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	white-space: nowrap;
	color: transparent;                  /* outline only */
	-webkit-text-stroke: 1.5px rgba(var(--color-accent-rgb), 0.35);
}

/* the word changes one after another; the parent is turned 180deg, so +Y moves it up on screen */
.pp-side-word .home-side-words{
	display: inline-block;
	transition: opacity 0.45s ease, transform 0.45s ease, filter 0.45s ease;   /* 0.45s = FADE_MS in js/home-about.js */
}
.pp-side-word .home-side-words.is-leaving{
	opacity: 0;
	transform: translateY(calc(30 * var(--u)));
	filter: blur(6px);
}
.pp-side-word .home-side-words.is-entering{
	opacity: 0;
	transform: translateY(calc(-30 * var(--u)));
	filter: blur(6px);
	transition: none;
}

/* ---------- Right: section number + line + name ---------- */
.pp-side-label{
	top: 50%;
	right: calc(var(--side-gap) / 2);    /* middle of the right gap */
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: calc(14 * var(--u));
	transform: translate(50%, -50%);
}
.pp-side-label b{
	font-family: var(--font-display);
	font-size: calc(28 * var(--u));
	font-weight: 700;
	line-height: 1;
	background: var(--gradient-brand);
	-webkit-background-clip: text;
	background-clip: text;
	-webkit-text-fill-color: transparent;
}
.pp-side-label i{
	display: block;
	width: 1px;
	height: calc(70 * var(--u));
	background: linear-gradient(180deg, var(--color-accent), var(--color-accent-2));
}
.pp-side-label span{
	writing-mode: vertical-rl;
	height: calc(200 * var(--u));        /* fixed: a longer or shorter name never moves the number and the line */
	font-family: var(--font-heading);
	font-size: calc(13 * var(--u));
	font-weight: 600;
	letter-spacing: 0.3em;
	text-transform: uppercase;
	white-space: nowrap;
	text-align: end;
	color: rgba(var(--color-primary-rgb), 0.45);
	transform: rotate(180deg);           /* reads bottom to top, like the big word */
	transition: opacity 0.45s ease, transform 0.45s ease, filter 0.45s ease;
}
.pp-side-label span.is-leaving{
	opacity: 0;
	transform: rotate(180deg) translateY(calc(14 * var(--u)));
	filter: blur(4px);
}
.pp-side-label span.is-entering{
	opacity: 0;
	transform: rotate(180deg) translateY(calc(-14 * var(--u)));
	filter: blur(4px);
	transition: none;
}

/* --------------------------------------------------------------------------
   P06. Products page – Side decorations · RESPONSIVE
   -------------------------------------------------------------------------- */

/* Below 1200px the container fills the screen: no side space, so no decorations (like the home page) */
@media (max-width: 1199.98px){
	.pp-side-word,
	.pp-side-label{display: none}
}


/* ==========================================================================
   P07. Products page – Picture gallery            page: projects.html
   HTML (built by js/product.js renderGallery): <div class="pp-gal"> inside #main.
   Every product except Cubix PMS: no tab row and no app sidebar, only the P00 window
   (.frame + .chrome) with a Swiper slider of 3 pictures inside, sliding on every 3 s,
   and gradient dots under it. Cubix PMS keeps its tabs + sidebar (P00).
   A picture that is not uploaded yet shows the P00 "Upload image" placeholder (.shot .ph).
   ========================================================================== */

/* no tab row for gallery products (js/product.js adds .is-off) */
.pp-show .tabs.is-off{display: none}

/* the slider fills the window under its address bar */
.pp-gal .swiper{width: 100%}
.pp-gal .swiper-slide{padding: calc(14 * var(--u))}

/* one picture: every picture gets the same wide shape (2:1, e.g. 1920 x 960 screenshots),
   so the window does not jump between pictures and is about as tall as the Cubix PMS window */
.pp-gal .shot{
	aspect-ratio: 2 / 1;
	border-radius: calc(10 * var(--u));
}
.pp-gal .shot.has{box-shadow: 0 1px 3px rgba(var(--color-primary-rgb), .08)}
.pp-gal .shot img{object-position: top left}

/* dots under the window: faint navy, the active one a wide pill in the brand gradient */
.pp-gal-dots{
	display: flex;
	justify-content: center;
	align-items: center;
	margin-top: calc(22 * var(--u));
	--swiper-pagination-bullet-horizontal-gap: calc(5 * var(--u));
}
.pp-gal-dots .swiper-pagination-bullet{
	width: calc(10 * var(--u));
	height: calc(10 * var(--u));
	border-radius: calc(10 * var(--u));
	background: rgba(var(--color-primary-rgb), .18);
	opacity: 1;
	transition: width .35s ease, background-color .35s ease;
}
.pp-gal-dots .swiper-pagination-bullet:hover{background-color: rgba(var(--color-primary-rgb), .35)}
.pp-gal-dots .swiper-pagination-bullet-active,
.pp-gal-dots .swiper-pagination-bullet-active:hover{
	width: calc(32 * var(--u));
	background: var(--gradient-brand);
}

/* --------------------------------------------------------------------------
   P07. Products page – Picture gallery · RESPONSIVE  -> move to cubix-responsive.css
   Below 1200px --u is 1px, so the sizes above are already right; only the
   space above the dots gets smaller with the rest of the section.
   -------------------------------------------------------------------------- */
@media (max-width: 767.98px){
	.pp-gal .swiper-slide{padding: 10px}
	.pp-gal-dots{margin-top: 16px}
}

/* ==========================================================================
   Full-screen Menu Contact Column Sizing (Balanced & No scrollbar)
   ========================================================================== */
.cx-menu--split .cx-menu__contact{
	padding: calc(14 * var(--u)) calc(50 * var(--u)) calc(30 * var(--u)) calc(20 * var(--u));
}

.cx-menu--split .cx-menu__contact h4{
	margin-top: calc(22 * var(--u));
	font-family: var(--font-heading);
	font-size: calc(28 * var(--u));
	font-weight: 500;
	letter-spacing: 0.5px;
	color: rgba(var(--color-white-rgb), 0.85);
}

.cx-menu--split .cx-menu__contact h4:first-child{
	margin-top: 0;
}

.cx-menu--split .cx-menu__contact p,
.cx-menu--split .cx-menu__contact > a:not(.btn-default){
	margin-top: calc(5 * var(--u));
	font-size: calc(19.5 * var(--u));
	font-weight: 500;
	line-height: 1.45;
	color: var(--color-white);
}

.cx-menu--split .cx-menu__contact > a:not(.btn-default){
	display: block;
	width: -webkit-fit-content;
	width: -moz-fit-content;
	width: fit-content;
	margin: calc(5 * var(--u)) 0 0 auto;
	font-size: calc(20 * var(--u));
	font-weight: 600;
	text-decoration: underline;
	text-underline-offset: 4px;
	text-align: right;
}

.cx-menu--split .cx-menu__contact > br{
	display: none;
}

.cx-menu--split .cx-menu__social{
	margin-top: calc(24 * var(--u));
	gap: calc(12 * var(--u));
}

.cx-menu--split .cx-menu__social a{
	width: calc(44 * var(--u));
	height: calc(44 * var(--u));
	font-size: calc(18 * var(--u));
}

.cx-menu--split .cx-menu__contact .btn-default{
	margin-top: calc(24 * var(--u));
}

