/* ==========================================================================
   duduk by EcoWorld — homepage styles
   Design basis: reference/page1.png at 1920px. Layout measurements are
   expressed as calc(N * var(--u)) so the whole composition scales
   proportionally between the 1320 / 1140 / 960 content widths; below 992px
   every section switches to its own stacked layout.
   ========================================================================== */

/* ---------- Brand fonts ---------- */
@font-face { font-family: 'EcoWorldSerif'; src: url('../assets/fonts/EcoWorldSerif-Regular.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'EcoWorldSerif'; src: url('../assets/fonts/EcoWorldSerif-Bold.woff2')    format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }
@font-face { font-family: 'EcoWorldSans';  src: url('../assets/fonts/EcoWorldSans-Regular.woff2')  format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'EcoWorldSans';  src: url('../assets/fonts/EcoWorldSans-Bold.woff2')     format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }

/* ---------- Tokens ---------- */
:root {
  /* Design unit: the 1920px mockup scales fluidly with the viewport, so the
     composition is identical at any window width or browser zoom level
     (1u = 1px at 1920px wide). Below 992px the stacked layouts take over. */
  --u: calc(100vw / 1920);
  --wrap: calc(1320 * var(--u));   /* content width — 1320px in the mockup */
  --nav-h: 57px;        /* live nav height; refined at runtime by main.js */

  --gray-heading: #58595B;
  --gray-footer:  #5A5A5A;
  --input-bg:     #F2F2F2;
  --purple:       #7F59C0;
  --yellow:       #FFE66E;

  /* the core brand rainbow, left → right */
  --grad-brand: linear-gradient(90deg,
    #6A72C2 0%, #7F59C0 8%, #A41CC4 22%, #C020A7 36%, #E44461 52%,
    #FF462F 66%, #FF4334 74%, #F28730 88%, #FFA215 100%);
  /* "Who Dis" panel — angle and stops sampled off the mockup's own background
     (135deg exactly; measured every 5% along the gradient axis) */
  --grad-brand-diag: linear-gradient(135deg,
    #6F86C3 0%, #8171BA 10%, #9559AF 20%, #AA3FA3 30%, #BE2798 40%, #CD1588 50%,
    #DD2576 60%, #E3455F 70%, #EB6548 80%, #F18431 90%, #F79F1E 100%);
  /* "Is Duduk Untuk You" panel */
  --grad-teal-panel: linear-gradient(180deg, #0D2F3B 0%, #164C59 55%, #1F5E6B 100%);
  --grad-sun:  linear-gradient(90deg, #FFCB3D 0%, #D9DE8F 45%, #4FD0C5 100%);
  --grad-sun-b: linear-gradient(90deg, #FFB13D 0%, #E8D989 40%, #5ED3C6 100%);
  /* "Suka What You See" — heading ramp, sampled off the mockup's own letters */
  --grad-suka: linear-gradient(90deg,
    #7F59C0 0%, #6577C3 22%, #4C95C5 40%, #3BB4C0 63%, #33C4BA 80%, #2CD3B6 100%);
  /* Its frame is ONE purple→teal ramp on a 135° axis spanning the whole frame box,
     so each of the four rules only shows the slice of that ramp its own span covers —
     giving every rule its own copy of the full ramp is what made the right edge run
     cyan→purple→cyan.  Measured off page1.png: colour is a function of (x + y) alone,
     over t = 425..2598, and these are that ramp resampled along each rule. */
  --grad-suka-top: linear-gradient(90deg, #6874C2 0%, #6479C3 10%, #5F7FC3 20%, #5B84C4 30%, #5789C4 40%, #528EC5 50%, #4E93C5 60%, #4A98C6 70%, #459DC6 80%, #43A2C5 90%, #42A6C4 100%);
  --grad-suka-right: linear-gradient(180deg, #42A5C4 0%, #3FAAC2 10%, #3DAFC1 20%, #3BB4C0 30%, #39B8BE 40%, #37BDBD 50%, #35C2BC 60%, #33C7BA 70%, #30CBB9 80%, #2ED0B7 90%, #2BD3B4 100%);
  --grad-suka-bottom: linear-gradient(90deg, #5986C4 0%, #518FC5 10%, #4A98C6 20%, #44A1C5 30%, #41A8C3 40%, #3DAFC1 50%, #3AB7BF 60%, #36BEBD 70%, #33C6BA 80%, #2FCDB8 90%, #2BD3B4 100%);
  --grad-suka-left: linear-gradient(180deg, #7F59C0 0%, #7B5EC0 10%, #7763C1 20%, #7367C1 30%, #6F6CC2 40%, #6C70C2 50%, #6875C2 60%, #6479C3 70%, #607EC3 80%, #5C83C4 90%, #5887C4 100%);

  /* Thank-you frame — page 2 of the .ai. Same construction as the others: ONE 135deg
     ramp over the whole frame box, proved by colour being a function of (x + y) alone
     (top rule at x307,y250 and left edge at x301,y257 both give t~558 and both read
     #A41CC4). These are that ramp resampled along each of the five segments. */
  --grad-thanks-top: linear-gradient(90deg, #A21CC6 0%, #B51EB4 8.333%, #C921A1 16.67%, #DC248F 25%, #EF267D 33.33%, #FF2A6B 41.67%, #FF3258 50%, #FF3B46 58.33%, #FF4335 66.67%, #FF4C23 75%, #FF5718 83.33%, #FF6419 91.67%, #FF6419 100%);
  --grad-thanks-left: linear-gradient(180deg, #A21CC6 0%, #A41CC4 12.5%, #A61CC2 25%, #A81DC0 37.5%, #AA1DBE 50%, #AC1DBD 62.5%, #AE1EBB 75%, #B01EB9 87.5%, #B11EB8 100%);
  --grad-thanks-left2: linear-gradient(180deg, #FE286F 0%, #FE296C 12.5%, #FF2A6A 25%, #FF2B67 37.5%, #FF2C65 50%, #FF2D62 62.5%, #FF2F60 75%, #FF305D 87.5%, #FF315A 100%);
  --grad-thanks-bottom: linear-gradient(90deg, #FF305D 0%, #FF374F 12.5%, #FF3D43 25%, #FF4336 37.5%, #FF4929 50%, #FF4F1B 62.5%, #FF5818 75%, #FF6319 87.5%, #FF6419 100%);

  /* "Who Dis" frame — it is NOT a translucent white: proof is that frame colours at
     equal (x+y) are identical (bottom x1000 == right y130), i.e. it is its own 135deg
     gradient, parallel to the panel behind it. Sampled around the whole perimeter. */
  --grad-frame-whodis: linear-gradient(135deg,
    #BD9DD5 0%, #C592D1 10%, #CE81CC 20%, #D76EC7 30%, #E054C1 40%, #E82ABC 50%,
    #EC53B1 60%, #EE73A5 70%, #F18A98 80%, #F49D89 90%, #F6AD7A 100%);

  /* "DUDUK" in section 4 — starts pink, not purple. Sampled off the mockup's letters. */
  --grad-duduk: linear-gradient(90deg,
    #FF286E 0%, #FF2F5E 10%, #FF3E40 30%, #FF4530 40%, #FF4C21 50%,
    #FF5A18 60%, #FF731A 70%, #FF8B1D 80%, #FF9C14 90%, #FFAF0B 100%);

  /* hero headline: sampled every 10% off the mockup's own letters. SWIMMING and POOL
     share ONE gradient across the block, so POOL (shorter) only shows its left half. */
  --grad-hero-text: linear-gradient(90deg,
    #A11CC7 0%, #C220A8 10%, #E82583 20%, #FF2F5F 30%, #FF3E40 40%, #FF4E1E 50%,
    #FF6619 60%, #FF811C 70%, #FF9A1B 80%, #FFAB0E 90%, #FFBD00 100%);

  --serif: 'EcoWorldSerif', Georgia, 'Times New Roman', serif;
  --sans:  'EcoWorldSans', system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif;
}

/* ---------- Base ---------- */
html { scroll-behavior: smooth; scroll-padding-top: var(--nav-h); }
body {
  font-family: 'EcoWorldSerif';   /* as live */
  font-weight: 400;
  color: var(--gray-heading);
  background: #fff;
  overflow-x: hidden;
  padding-top: var(--nav-h);      /* clear the fixed nav */
}
img { max-width: 100%; }
.wrap { position: relative; width: var(--wrap); margin: 0 auto; }
.gtext {
  background-image: var(--grad-brand);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
}
.visually-hidden { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }

/* ==========================================================================
   HEADER + FOOTER — verbatim clone of https://www.duduk.my (style.css v3.13)
   Do not restyle: the user requires these to match the live site exactly.
   ========================================================================== */
nav {
  position: fixed; top: 0; left: 0; width: 100%;
  background: white; z-index: 99999; color: black;
  box-shadow: 1px 0px 11px -2px rgba(0,0,0,0.53);
  -webkit-box-shadow: 1px 0px 11px -2px rgba(0,0,0,0.53);
  -moz-box-shadow: 1px 0px 11px -2px rgba(0,0,0,0.53);
}
nav ul { padding-left: 0; margin-bottom: 0; }
nav ul li { padding: 10px 15px 10px 0px; display: inline-block; }
.logo { width: 100px; position: fixed; top: 10px; left: 50%; transform: translateX(-50%); }
.navigation { margin: auto; font-size: 14px; }
.navigation a { color: #5a5a5a; text-decoration: none; }
.topright img { height: 20px; width: auto; margin-right: 3px; }
.topright img:nth-child(5) { margin-right: 0; }
.logo-grey { height: 15px !important; }

footer { background: #5a5a5a; width: 100%; }
.footercontent { padding-left: 40px; padding-right: 45px; font-size: 12px; height: 45px; color: white; }
.logo-white { height: 15px; }
footer a { color: #fff; text-decoration: none; }
footer a:hover { text-decoration: none; color: white; }

@media (max-width: 767.98px) {
  .offcanvas-backdrop { position: fixed; top: 0; left: 0; z-index: 999999; width: 100vw; height: 100vh; background-color: #000; }
  .navigation { width: 100%; height: 62px; }
  .logo { width: 98px; }
  .footercontent { padding-left: 20px; padding-right: 20px; font-size: 11px; height: 48px; color: white; }
  .mobilemenubutton { position: fixed; right: 20px; top: 20px; }
  .mobilemenubutton img { width: 40px; }
  .offcanvas { z-index: 9999999; max-width: 80%; }
  .mobilemenu li { list-style-type: none; }
  .mobilemenu li a { color: #5a5a5a; font-size: 8vw; margin-bottom: 2vh; display: block; }
  .offcanvas { background: transparent url(../assets/images/live/mobilemenubg.png); border-left: 0 !important; background-size: 100% 100%; }
  .offcanvas .btn-close { position: absolute; left: 20vw; top: 20px; }
  .offcanvas-body { padding-right: 10vw; }
  .offcanvas-body .logo-grey { width: 34vw !important; height: auto !important; margin-bottom: 28px; }
  .mobilemenubottom { position: absolute; bottom: 0; width: 100%; right: 10vw; bottom: 30px; }
  .mobilemenusocial { margin-right: -5px; }
  .mobilemenusocial img { height: 6vw; margin-right: 3vw; }
  .mobilemenusocial img.tiktok { margin-right: 0; }
}
/* end live clone */

/* ==========================================================================
   Shared section furniture
   ========================================================================== */
.reveal { opacity: 0; transform: translateY(26px); transition: opacity .75s ease, transform .75s ease; }
.reveal.is-visible { opacity: 1; transform: none; }
.reveal-d1 { transition-delay: .12s; }
.reveal-d2 { transition-delay: .24s; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal { opacity: 1; transform: none; transition: none; }
}

/* gradient rule segments used to build the open frames */
.rule { position: absolute; }

/* ==========================================================================
   1. HERO
   ========================================================================== */
.hero {
  position: relative;
  height: calc(826 * var(--u));
  /* Photo positioned so the unicorn sits left of the headline, as in the mockup.
     Sourced from the 10195x5212 original inside reference/Landing Page_FA.ai, so a
     true 2x variant is served to HiDPI screens via image-set(). */
  background-color: #a9dcea;
  background-image: url(../assets/images/duduk-swimming-pool-full.webp);
  background-image: -webkit-image-set(
    url(../assets/images/duduk-swimming-pool-full.webp) 1x,
    url(../assets/images/duduk-swimming-pool-full@2x.webp) 2x);
  background-image: image-set(
    url(../assets/images/duduk-swimming-pool-full.webp) 1x,
    url(../assets/images/duduk-swimming-pool-full@2x.webp) 2x);
  background-repeat: no-repeat;
  /* canvas placed so the float sits at x 246–926u, horizon at 464u — as in the mockup */
  background-size: calc(2624 * var(--u)) auto;
  background-position: calc(-688 * var(--u)) calc(-455 * var(--u));
  overflow: hidden;
}
.hero .wrap { height: 100%; }
/* Water darkens toward the bottom exactly as in the mockup (sampled: #B2E9EA at the
   horizon → #639299 mid → #122F37 at the bottom edge). The float's silhouette —
   the float sits on top of this layer, so it stays bright as in the design. */
.hero__shade {
  position: absolute; inset: 0;
  /* alpha profile solved from mockup-vs-photo at nine depths: the design fades
     rgb(10,33,41) in from just below the horizon to fully opaque at the bottom edge */
  background: linear-gradient(180deg,
    rgba(10,33,41,0) 58.1%, rgba(10,33,41,.128) 63%, rgba(10,33,41,.255) 67.8%,
    rgba(10,33,41,.355) 72.6%, rgba(10,33,41,.495) 78.7%, rgba(10,33,41,.652) 84.7%,
    rgba(10,33,41,.794) 90.8%, rgba(10,33,41,.90) 95.6%, rgba(10,33,41,1) 99.3%);
  pointer-events: none;
}
/* Frame: 12u stroke, colours sampled from the mockup along a 135° gradient.
   Its right edge is open beside SWIMMING (164–295u below the frame top). */
.hero__frame {
  position: absolute; left: 0; right: 0;
  top: calc(117 * var(--u)); height: calc(590 * var(--u));
  border: calc(12 * var(--u)) solid transparent;
  border-image: linear-gradient(135deg,
    #A31CC5 0%, #C220A8 8.6%, #E0248B 17.3%, #FF286E 25.9%, #FF2F5F 30.9%, #FF3651 34.6%,
    #FF3D42 39.5%, #FF4334 43.2%, #FF4A25 48.2%, #FF5117 51.8%, #FF5D18 56.8%, #FF6819 60.5%,
    #FF741B 65.4%, #FF7F1C 69.1%, #FF8B1D 74.1%, #FF9E18 82.7%, #FFAD0C 91.4%, #FFBC01 100%) 1;
  clip-path: polygon(
    0 0, 100% 0,
    100% calc(164 * var(--u)), calc(100% - 12 * var(--u)) calc(164 * var(--u)),
    calc(100% - 12 * var(--u)) calc(295 * var(--u)), 100% calc(295 * var(--u)),
    100% 100%, 0 100%);
  pointer-events: none;
}
/* The float, cut out of the background photo itself (identical pixels, identical
   placement) and drawn OVER the frame — so the tail and horn occlude the frame line
   along the photo's own edge. No mask can do this cleanly: any silhouette that isn't
   the photo's exact edge leaves a sliver or bites into the float. */
.hero__float {
  position: absolute; left: calc(228.3 * var(--u)); top: calc(80.4 * var(--u));
  width: calc(715.5 * var(--u)); height: auto; max-width: none;
  pointer-events: none;
}
.hero__title {
  position: absolute; left: calc(678 * var(--u)); top: calc(212 * var(--u));
  margin: 0;
  font-family: var(--serif); font-weight: 700; text-transform: uppercase;
  font-size: calc(78 * var(--u)); line-height: 1;
  color: var(--gray-heading);
  text-align: left; white-space: nowrap;
}
.hero__title span { display: block; }
/* one gradient box holding both SWIMMING and POOL, as in the mockup */
.hero__title .gtext {
  background-image: var(--grad-hero-text);
  font-family: var(--sans); font-weight: 700; letter-spacing: .03em;
  font-size: calc(113 * var(--u)); line-height: .92;
  margin: calc(18 * var(--u)) 0 calc(4 * var(--u));
}
.hero__title .gtext span { display: block; }

/* ==========================================================================
   2. WHO DIS?
   ========================================================================== */
.whodis {
  position: relative;
  height: calc(843 * var(--u));   /* measured off the mockup */
  background: var(--grad-brand-diag);
  color: #fff; overflow: hidden;
}
.whodis .wrap { height: 100%; }
/* Measured off the mockup: 12u stroke (25px at 2x), and NOT solid white — fitting
   overlay colour + alpha over 98 samples (left stroke at 58 heights, bottom rule at 40
   widths) gives a pale magenta at 41%. Red and blue match white, but green is
   consistently lower, which is what makes solid white read as the wrong colour.
   NB height is border-box (Bootstrap's reboot), so it spans top 107u → bottom 756u,
   putting the bottom rule at 744–756u as measured. */
.whodis__frame {
  /* measured outer edges: 297u → 1626u, i.e. 3u outside the wrap on the left and 6u on
     the right, so the box is 1329u wide */
  position: absolute; left: calc(-3 * var(--u)); right: calc(-6 * var(--u));
  top: calc(107 * var(--u)); height: calc(649 * var(--u));
  border: calc(12 * var(--u)) solid transparent; border-top: 0;
  border-image: var(--grad-frame-whodis) 1;
  pointer-events: none;
}
/* the top rule is split so the "WHO DIS?" heading sits in the gap (measured: the line
   runs 297→360u, breaks, and resumes 728→1626u) */
.whodis__frame::before, .whodis__frame::after {
  /* the same gradient, sized to the frame box and offset so it stays continuous
     with the border-image on the sides */
  content: ""; position: absolute; top: 0; height: calc(12 * var(--u));
  background-image: var(--grad-frame-whodis);
  background-size: calc(1329 * var(--u)) calc(649 * var(--u));
  background-repeat: no-repeat;
}
/* start/end at the padding box, NOT the border box: the side borders already cover the
   corners, and overlapping them stacked two translucent whites into visible bright squares */
.whodis__frame::before { left: 0; width: calc(51 * var(--u)); background-position: calc(-12 * var(--u)) 0; }
.whodis__frame::after  { left: calc(419 * var(--u)); right: 0;  background-position: calc(-431 * var(--u)) 0; }

.whodis__text { position: absolute; left: calc(76 * var(--u)); top: calc(90 * var(--u)); width: calc(720 * var(--u)); }
.whodis__h1 { margin: 0; font-family: var(--serif); font-weight: 700; font-size: calc(66 * var(--u)); line-height: 1; text-transform: uppercase; }
.whodis__h2 { margin: calc(14 * var(--u)) 0 0; font-family: var(--sans);  font-weight: 700; font-size: calc(90 * var(--u)); line-height: 1; text-transform: uppercase; white-space: nowrap; }
.whodis__h3 { margin: calc(14 * var(--u)) 0 0; font-family: var(--serif); font-weight: 700; font-size: calc(56 * var(--u)); line-height: 1; text-transform: uppercase; white-space: nowrap; }
/* 24u to sit level with the Is Duduk body copy (17.06px at a 1365px viewport).
   NB the mockup has this at 26u — see the note in the plan. */
.whodis__p { margin: calc(34 * var(--u)) 0 0; font-family: var(--serif); font-size: calc(24 * var(--u)); line-height: 1.36; }
.whodis__p + .whodis__p { margin-top: calc(26 * var(--u)); }
/* Full-body cut-out from the .ai original. Placement solved by fitting her silhouette
   width against the mockup at nine heights: scale ≈ 1:1 with the asset (1538u tall),
   head 32u below the section top, legs cropped by the 843u section edge. Predicted
   edges match the mockup within ~10u at every sampled height. */
.whodis__model {
  position: absolute; top: calc(-52 * var(--u)); left: calc(512 * var(--u));
  height: calc(1538 * var(--u)); width: auto; max-width: none;
  pointer-events: none;
}

/* ==========================================================================
   3. VIDEO
   ========================================================================== */
/* section measures 883u in the mockup; a 16:9 player in the 1320u column is 742.5u,
   so 70u of padding top and bottom */
.video { background: #fff; padding: calc(70 * var(--u)) 0; }
.video__player {
  position: relative; width: 100%; aspect-ratio: 16 / 9;
  background: #000; overflow: hidden; cursor: pointer;
  border-radius: calc(4 * var(--u));
}
.video__poster { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .6s ease; }
.video__player:hover .video__poster { transform: scale(1.02); }
.video__chrome {
  position: absolute; left: 0; right: 0; top: 0;
  padding: calc(18 * var(--u)) calc(22 * var(--u));
  display: flex; align-items: center; gap: calc(14 * var(--u));
  background: linear-gradient(180deg, rgba(0,0,0,.55), rgba(0,0,0,0));
  color: #fff; font-family: var(--sans); pointer-events: none;
}
.video__chrome img { width: calc(46 * var(--u)); height: calc(46 * var(--u)); border-radius: 50%; background: #fff; object-fit: contain; padding: 4px; }
.video__chrome strong { display: block; font-size: calc(22 * var(--u)); line-height: 1.15; }
.video__chrome small  { display: block; font-size: calc(14 * var(--u)); opacity: .85; }
.video__play {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: calc(96 * var(--u)); height: calc(68 * var(--u));
  background: rgba(33,33,33,.82); border: 0; border-radius: calc(16 * var(--u));
  display: grid; place-items: center; cursor: pointer;
  transition: background .25s ease, transform .25s ease;
}
.video__player:hover .video__play { background: #ff0000; transform: translate(-50%, -50%) scale(1.06); }
.video__play svg { width: calc(34 * var(--u)); height: calc(34 * var(--u)); fill: #fff; margin-left: 4px; }
.video__player iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.video__player.is-playing .video__poster,
.video__player.is-playing .video__play,
.video__player.is-playing .video__chrome { display: none; }

/* ==========================================================================
   4. IS DUDUK UNTUK YOU?
   ========================================================================== */
/* The panel is a purely HORIZONTAL gradient — sampled at six different heights it is
   identical at every one, and it lightens to a pale cyan before the photo takes over.
   (It was previously a vertical gradient, which is what made the light cyan look
   missing.) Stops measured every 100u across the mockup. */
.isduduk {
  position: relative;
  height: calc(983 * var(--u));           /* measured: page1 y5520–7568 */
  background: linear-gradient(90deg,
    #071B23 0%, #0A242E 5.2%, #0C2D39 10.4%, #0F3644 15.6%, #12404F 20.8%,
    #184959 26%, #215263 31.3%, #2A5C6C 36.5%, #336576 41.7%, #3B6F7F 46.9%,
    #437788 52.1%, #4E8091 57.3%, #5A8996 62.5%, #6C949E 67.7%,
    #86A5AC 80%, #9FB3B6 100%);
  color: #fff; overflow: hidden;
}
/* designed backdrop from the .ai original — it carries its own soft left fade */
.isduduk__photo {
  position: absolute; right: 0; bottom: 0;
  height: 100%; width: auto; max-width: none;
}
.isduduk .wrap { height: 100%; }
/* Frame: top-left stub, top-right run, right edge, bottom rule — and deliberately NO
   left edge, as in the design. Positioned against the section (viewport u), since the
   rules run to the viewport edge rather than the content column. Each carries its own
   gradient, sampled along its length. */
.isduduk > .rule { position: absolute; }
/* rule ends chosen so the whitespace either side of the heading reads as balanced
   (~30u each); the design's own gaps are 37u and 29u */
.isduduk__ruleTL {
  left: 0; width: calc(295 * var(--u)); top: calc(175 * var(--u)); height: calc(12 * var(--u));
  background: linear-gradient(90deg, #9074B4, #C968A8);
}
.isduduk__ruleTR {
  left: calc(901 * var(--u)); width: calc(653 * var(--u)); top: calc(175 * var(--u)); height: calc(12 * var(--u));
  background: linear-gradient(90deg, #FFB728 0%, #F3BA3B 13%, #E9BC48 22%, #E0BE56 32%,
    #D7C164 41%, #C9C57F 55%, #B1C99B 79%, #A8CBA9 88%, #9CCEB9 100%);
}
.isduduk__edgeR {
  left: calc(1542 * var(--u)); width: calc(12 * var(--u)); top: calc(175 * var(--u)); height: calc(691 * var(--u));
  background: linear-gradient(180deg, #9CCEB9 0%, #67CAD9 62%, #48C3DF 100%);
}
.isduduk__ruleB {
  left: 0; width: calc(1554 * var(--u)); top: calc(854 * var(--u)); height: calc(12 * var(--u));
  background: linear-gradient(90deg, #F1896C 0%, #F59B54 6.4%, #F9AD3C 12.9%, #F6B936 19.3%,
    #E6BD4D 25.7%, #D7C164 32.2%, #C7C47B 38.6%, #B8C892 45%, #A8CBA9 51.5%,
    #98CFC0 57.9%, #89D2D3 64.4%, #7BCFD6 71%, #73C7D0 77.2%, #65CADA 83.7%, #55C6DD 100%);
}

.isduduk__title { position: absolute; left: calc(23 * var(--u)); top: calc(108 * var(--u)); margin: 0; text-transform: uppercase; line-height: 1; }
.isduduk__title .line1 { display: flex; align-items: baseline; gap: calc(24 * var(--u)); }
.isduduk__title .is    { font-family: var(--serif); font-weight: 700; font-size: calc(71 * var(--u)); }
/* DUDUK starts PINK, not purple — its own ramp, sampled off the mockup's letters */
/* our EcoWorld Sans is a narrower cut than the mockup's: DUDUK renders 423u where the
   design is 449u, which is what threw the right-hand gap out. Tracked out to match. */
.isduduk__title .gtext { font-family: var(--sans); font-weight: 700; font-size: calc(122 * var(--u)); line-height: .9;
  letter-spacing: .053em; background-image: var(--grad-duduk); }
.isduduk__title .line2 { display: block; font-family: var(--serif); font-weight: 700; font-size: calc(74 * var(--u)); margin-top: calc(20 * var(--u)); }

/* top/padding solved so the dividers land on the design's 470u and 641u — with those
   right, each icon's own offset also reads as centred within its row */
.isduduk__list { position: absolute; left: calc(24 * var(--u)); top: calc(332 * var(--u)); width: calc(697 * var(--u)); margin: 0; padding: 0; list-style: none; }
.isduduk__item {
  display: grid; grid-template-columns: calc(140 * var(--u)) 1fr; column-gap: calc(22 * var(--u));
  align-items: start;
  padding: calc(19 * var(--u)) 0 calc(25 * var(--u));
  border-bottom: 1px solid rgba(255,255,255,.5);
}
.isduduk__item:last-child { border-bottom: 0; }
/* The three icons are the designer's own vector artwork, extracted from the .ai's
   content stream (they are vector, so they never appeared in the image extraction).
   Each carries its own fill/stroke: 1 and 3 are filled outlines (expanded strokes),
   2 is a 3pt stroke. Sizes are the measured originals, all different. */
/* each icon sits at its own vertical offset against the text, as in the design */
.isduduk__item svg { justify-self: center; height: auto; }
.isduduk__item .ic1 { width: calc(56.3 * var(--u));  margin-top: calc(-3 * var(--u)); }
.isduduk__item .ic2 { width: calc(69.1 * var(--u));  margin-top: calc(26 * var(--u)); }
.isduduk__item .ic3 { width: calc(101.8 * var(--u)); margin-top: calc(19 * var(--u)); }
.isduduk__item p { margin: 0; font-family: var(--serif); font-size: calc(24 * var(--u)); line-height: 1.3; }
.isduduk__item .then { display: block; font-family: var(--sans); font-weight: 700; color: var(--yellow); font-size: calc(25 * var(--u)); line-height: 1.3; }
.isduduk__boy {
  position: absolute; left: calc(575 * var(--u)); top: calc(80 * var(--u));
  height: calc(1043 * var(--u)); width: auto; max-width: none;
  pointer-events: none;
}

/* ==========================================================================
   5. KOLEKSI — Designed untuk you
   ========================================================================== */
.koleksi { background: #fff; color: var(--gray-heading); text-align: center; padding: calc(84 * var(--u)) 0 calc(72 * var(--u)); }
.koleksi__title { margin: 0; font-family: var(--serif); font-weight: 700; font-size: calc(96 * var(--u)); line-height: 1; text-transform: uppercase; }
.koleksi__title .gtext { font-family: var(--sans); font-size: calc(94 * var(--u)); }
.koleksi__sub { margin: calc(22 * var(--u)) 0 calc(54 * var(--u)); font-family: var(--serif); font-size: calc(38 * var(--u)); line-height: 1.2; }

.carousel { --per-view: 3; --gap: calc(24 * var(--u)); position: relative; width: calc(1256 * var(--u)); margin: 0 auto; }
.carousel__viewport { overflow: hidden; }
.carousel__track { display: flex; gap: var(--gap); transition: transform .55s cubic-bezier(.22,.61,.36,1); will-change: transform; touch-action: pan-y; }
.carousel.is-dragging .carousel__track { transition: none; }
.project {
  flex: 0 0 calc((100% - (var(--per-view) - 1) * var(--gap)) / var(--per-view));
  display: block; text-decoration: none; color: inherit; user-select: none;
  -webkit-user-drag: none;
}
.project__media { position: relative; aspect-ratio: 1 / 1; overflow: hidden; background: #e6e6e6; }
.project__media img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .6s ease; -webkit-user-drag: none; }
a.project:hover .project__media img { transform: scale(1.04); }
.project__strip { position: absolute; left: 0; right: 0; bottom: 0; height: calc(11 * var(--u)); background: var(--accent, var(--grad-brand)); }
.project__badge {
  position: absolute; inset: 0 0 calc(11 * var(--u)) 0;
  display: flex; align-items: center; justify-content: center;
  background: rgba(38,42,56,.62); color: #fff;
  font-family: var(--sans); font-weight: 700; text-transform: uppercase;
  font-size: calc(52 * var(--u)); line-height: 1.05; text-align: center;
}
/* Bumi Lot Only wears the same type as Sold Out, but with no scrim: it sits on one
   line along the bottom of the photo, the way the live site's baked-in version did. */
.project__badge--bumi {
  inset: auto 0 calc(24 * var(--u)) 0;
  background: none; font-size: calc(36 * var(--u)); white-space: nowrap;
  text-shadow: 0 calc(2 * var(--u)) calc(12 * var(--u)) rgba(0,0,0,.55);
}
.project__logo { height: calc(96 * var(--u)); margin-top: calc(26 * var(--u)); display: flex; align-items: center; justify-content: center; }
.project__logo img { max-height: 100%; max-width: 78%; width: auto; height: auto; -webkit-user-drag: none; }
.project__logo span { font-family: var(--serif); font-weight: 700; font-size: calc(34 * var(--u)); letter-spacing: .12em; text-transform: uppercase; }
.project.is-unlinked { cursor: default; }

.carousel__arrow {
  position: absolute; top: calc(190 * var(--u));
  width: calc(44 * var(--u)); height: calc(64 * var(--u));
  background: none; border: 0; padding: 0; cursor: pointer; color: #b9b9b9;
  transition: color .2s ease, transform .2s ease;
}
.carousel__arrow:hover { color: var(--gray-heading); }
.carousel__arrow:disabled { opacity: .3; cursor: default; }
.carousel__arrow svg { width: 100%; height: 100%; fill: none; stroke: currentColor; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.carousel__arrow--prev { left: calc(-66 * var(--u)); }
.carousel__arrow--next { right: calc(-66 * var(--u)); }
.carousel__dots { display: flex; justify-content: center; gap: calc(20 * var(--u)); margin-top: calc(74 * var(--u)); }
.carousel__dot { width: calc(20 * var(--u)); height: calc(20 * var(--u)); border-radius: 50%; border: 2px solid #9d9d9d; background: #fff; padding: 0; cursor: pointer; transition: background .2s ease; }
.carousel__dot:hover { background: #dcdcdc; }
.carousel__dot.is-active { background: #9d9d9d; }

/* ==========================================================================
   6. SUKA WHAT YOU SEE? — registration
   ========================================================================== */
/* Section is 1152u per the .ai (was 1046u). The background photo is placed at its
   NATURAL size — 2126x1246u at (−103, −47) — which is why the design shows the whole
   room; `cover` was cropping in far too tight. */
.suka { position: relative; height: calc(1078 * var(--u)); background: #26262a; color: #fff; overflow: hidden; }
.suka__bg {
  position: absolute; inset: 0;
  background: url(../assets/images/luxury-living-room.webp) no-repeat;
  background-size: calc(2126 * var(--u)) calc(1246 * var(--u));
  background-position: calc(-103 * var(--u)) calc(-47 * var(--u));
  filter: blur(6px) brightness(.66);
}
.suka .wrap { height: 100%; }
/* Frame: like the other sections it is one 135° gradient, purple → teal, sampled
   around the perimeter. Rules are positioned against the section because they run
   past the content column. Top rule starts after the heading; the left edge starts
   below it; no rule closes the top-left corner — as designed. */
.suka > .rule { position: absolute; }
.suka__ruleT { left: calc(864 * var(--u));  width: calc(761 * var(--u));  top: calc(129 * var(--u)); height: calc(12 * var(--u)); background: var(--grad-suka-top); }
.suka__edgeR { left: calc(1613 * var(--u)); width: calc(12 * var(--u));   top: calc(129 * var(--u)); height: calc(844 * var(--u)); background: var(--grad-suka-right); }
.suka__ruleB { left: calc(296 * var(--u));  width: calc(1329 * var(--u)); top: calc(961 * var(--u)); height: calc(12 * var(--u)); background: var(--grad-suka-bottom); }
.suka__edgeL { left: calc(296 * var(--u));  width: calc(12 * var(--u));   top: calc(301 * var(--u)); height: calc(672 * var(--u)); background: var(--grad-suka-left); }

.suka__title {
  position: absolute; left: calc(-9 * var(--u)); top: calc(96 * var(--u)); margin: 0;
  font-family: var(--sans); font-weight: 700; text-transform: uppercase;
  font-size: calc(84 * var(--u)); line-height: 1.12;
  background-image: var(--grad-suka);
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; color: transparent;
}
/* placed exactly as the .ai does: 870.3 x 1656.3u at x 19.8 — she was ~90u too far
   right, which is what covered the "?" */
/* placed from the .ai CTM: the artwork is rotated 5.356deg clockwise.
   The rotation lives on the inner <img> so .reveal can still animate the wrapper. */
.suka__girl {
  position: absolute; display: block; left: calc(175.04 * var(--u)); top: calc(131.1 * var(--u));
  width: calc(874.11 * var(--u)); height: calc(1663.58 * var(--u));
  pointer-events: none;
}
.suka__girl img {
  display: block; width: 100%; height: 100%; max-width: none;
  transform: rotate(5.356deg); transform-origin: 0 0;
}
.suka__form { position: absolute; left: calc(651 * var(--u)); top: calc(183 * var(--u)); width: calc(609 * var(--u)); }
.suka__h2 { margin: 0 0 calc(22 * var(--u)); text-align: center; font-family: var(--serif); font-weight: 700; font-size: calc(50 * var(--u)); line-height: 1.1; text-transform: uppercase; white-space: nowrap; }

.form-card { background: #fff; border-radius: calc(20 * var(--u)); padding: calc(28 * var(--u)) calc(32 * var(--u)) calc(30 * var(--u)); color: var(--gray-heading); }
.field + .field { margin-top: calc(20 * var(--u)); }
.field label { display: block; margin: 0 0 calc(7 * var(--u)); font-family: var(--serif); font-size: calc(25 * var(--u)); line-height: 1.2; color: var(--gray-heading); }
.input {
  display: block; width: 100%; height: calc(46 * var(--u));
  padding: 0 calc(18 * var(--u));
  background: var(--input-bg); border: 0; border-radius: calc(10 * var(--u));
  font-family: var(--sans); font-size: calc(17 * var(--u)); color: #333;
  outline: none; transition: box-shadow .2s ease;
  -webkit-appearance: none; appearance: none;
}
.input:focus { box-shadow: 0 0 0 2px var(--purple); }
.field.is-invalid .input { box-shadow: inset 0 0 0 2px #E44461; }
.field__error { display: none; margin-top: calc(6 * var(--u)); font-family: var(--sans); font-size: calc(13 * var(--u)); color: #D6335F; }
.field.is-invalid .field__error { display: block; }

/* custom grouped dropdown */
.dd { position: relative; }
.dd__btn { text-align: left; display: flex; align-items: center; justify-content: space-between; gap: 12px; cursor: pointer; }
.dd__btn .dd__label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: #8a8a8a; }
.dd__btn.has-value .dd__label { color: #333; }
.dd__btn svg { width: 16px; height: 16px; flex: 0 0 16px; stroke: #777; fill: none; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; transition: transform .2s ease; }
.dd.is-open .dd__btn svg { transform: rotate(180deg); }
.dd__list {
  position: absolute; left: 0; right: 0; top: calc(100% + 6px); z-index: 30;
  margin: 0; padding: 8px 0; list-style: none;
  background: #fff; border-radius: 12px; box-shadow: 0 14px 36px rgba(0,0,0,.24);
  max-height: 300px; overflow: auto; color: #333;
}
.dd__list--up { top: auto; bottom: calc(100% + 6px); }
.dd__group { padding: 12px 18px 5px; font-family: var(--sans); font-size: 12px; letter-spacing: .06em; text-transform: uppercase; color: #9a9a9a; }
.dd__group + .dd__group { border-top: 1px solid #f0f0f0; }
.dd__opt { position: relative; padding: 9px 18px 9px 42px; font-family: var(--sans); font-size: 15px; line-height: 1.3; cursor: pointer; }
.dd__opt:hover, .dd__opt.is-focus { background: var(--input-bg); }
.dd__opt[aria-selected="true"] { color: var(--purple); font-weight: 700; }
.dd__opt[aria-selected="true"]::before { content: ""; position: absolute; left: 18px; top: 13px; width: 8px; height: 13px; border: solid var(--purple); border-width: 0 2px 2px 0; transform: rotate(45deg); }

.checks { margin: calc(20 * var(--u)) 0 0 calc(24 * var(--u)); }
.check { display: flex; align-items: flex-start; gap: calc(14 * var(--u)); cursor: pointer; font-family: var(--sans); font-size: calc(17 * var(--u)); line-height: 1.25; color: #fff; margin: 0; }
.check + .check { margin-top: calc(14 * var(--u)); }
.check input { position: absolute; opacity: 0; width: 0; height: 0; }
.check__box { flex: 0 0 calc(24 * var(--u)); width: calc(24 * var(--u)); height: calc(24 * var(--u)); background: #fff; border-radius: calc(3 * var(--u)); position: relative; margin-top: calc(-1 * var(--u)); transition: box-shadow .2s ease; }
.check input:focus-visible + .check__box { box-shadow: 0 0 0 3px rgba(127,89,192,.7); }
.check input:checked + .check__box::after { content: ""; position: absolute; left: 35%; top: 12%; width: 30%; height: 58%; border: solid var(--purple); border-width: 0 3px 3px 0; transform: rotate(45deg); }
.check.is-invalid .check__box { box-shadow: 0 0 0 2px #E44461; }
.check a { color: #fff; text-decoration: underline; text-underline-offset: 2px; }
.check a:hover { color: var(--yellow); }

.form__status { min-height: calc(20 * var(--u)); margin: calc(12 * var(--u)) 0 0; font-family: var(--sans); font-size: calc(15 * var(--u)); line-height: 1.3; color: #ffb3c1; }
.form__status:empty { display: none; }
.btn-register {
  display: block; width: 100%; height: calc(62 * var(--u)); margin-top: calc(28 * var(--u));
  background: var(--purple); color: #fff; border: 0; border-radius: 999px;
  font-family: var(--sans); font-weight: 700; font-size: calc(30 * var(--u)); letter-spacing: .02em; text-transform: uppercase;
  cursor: pointer; transition: background .2s ease, transform .2s ease, box-shadow .2s ease;
}
.btn-register:hover { background: #6d47b3; transform: translateY(-2px); box-shadow: 0 10px 24px rgba(0,0,0,.28); }
.btn-register:active { transform: none; }
.btn-register:disabled { opacity: .7; cursor: progress; transform: none; box-shadow: none; }

/* ==========================================================================
   7. THANK YOU state (reference/page2.png)
   ========================================================================== */
/* page 2 of the .ai is 1920x1050; the grey bar from y 974.9 is the mockup's stand-in
   footer, which the real cloned footer replaces — so the panel itself is 974.9u. */
.thanks {
  display: none;
  position: relative; height: calc(974.9 * var(--u));
  background: #6d6a63;
  color: #fff; overflow: hidden; outline: none;
}
/* The photo is MIRRORED in the design — its placement matrix is
   [-2138.64 0 0 1170.89 2129.92 68.34], and a negative `a` is a horizontal flip.
   The mirror is baked into the ASSET, not done with `transform: scaleX(-1)`.  A CSS flip
   pivots on the element's own box, and the photo layer (the section, which is 100vw MINUS
   the scrollbar) and the cut-out layer (2138.6u wide) have different boxes — so the two
   flips landed one scrollbar-width apart and every person appeared twice.  With the
   mirror baked in, both layers are plain placements at the design's own x = -8.7u and
   register exactly at any viewport. */
.thanks::before {
  content: ""; position: absolute; inset: 0;
  background: url(../assets/images/thankyou-cafe.webp) no-repeat;
  background-size: calc(2138.6 * var(--u)) calc(1170.9 * var(--u));
  background-position: calc(-8.7 * var(--u)) calc(-189.2 * var(--u));
  z-index: 0;
}
.thanks::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(90deg,
    rgba(0,0,0,.547) 0%,   rgba(0,0,0,.489) 5.2%,  rgba(0,0,0,.461) 10.4%,
    rgba(0,0,0,.398) 15.6%, rgba(0,0,0,.339) 20.8%, rgba(0,0,0,.293) 26%,
    rgba(0,0,0,.240) 31.3%, rgba(0,0,0,.181) 36.5%, rgba(0,0,0,.133) 41.7%,
    rgba(0,0,0,.106) 46.9%, rgba(0,0,0,.037) 52.1%, rgba(0,0,0,.021) 57.3%,
    rgba(0,0,0,0)    65.1%);
}
body.is-thanks .page-main { display: none; }
body.is-thanks .thanks { display: block; }
/* deliberately no z-index here: with `z-index: auto` .wrap does not create a stacking
   context, so its children stack against the section and the cut-out can slide between
   the frame and the copy */
.thanks .wrap { height: 100%; }
.thanks .rule { z-index: 2; }
.thanks__fg {
  position: absolute; z-index: 3; pointer-events: none;
  left: calc(-8.7 * var(--u)); top: calc(-189.2 * var(--u));
  width: calc(2138.6 * var(--u)); height: calc(1170.9 * var(--u)); max-width: none;
}
/* 12u stroke like every other frame on the site (was 8u), and positioned against the
   wrap, whose left edge sits 4.3u right of the frame's. Both breaks are measured:
   the top rule stops at 1014u and resumes at 1177u, and the left edge stops at 330u
   and resumes at 742u — that lower gap is the space the five lines of copy sit in. */
/* ONE continuous run: what looked like a gap at 1014-1177u is the dark-haired woman's
   head in front of it, and the right-hand end is tucked behind the hijab. Both ends and
   the middle are occluded by .thanks__fg, so nothing is cut short in the markup. */
.thanks__ruleT  { left: calc(-4.3 * var(--u)); width: calc(1254.3 * var(--u)); top: calc(244.8 * var(--u)); height: calc(11.6 * var(--u)); background: var(--grad-thanks-top); }
.thanks__edgeL  { left: calc(-4.3 * var(--u)); width: calc(11.6 * var(--u));  top: calc(244.8 * var(--u)); height: calc(85.2 * var(--u));  background: var(--grad-thanks-left); }
.thanks__edgeL2 { left: calc(-4.3 * var(--u)); width: calc(11.6 * var(--u));  top: calc(742.1 * var(--u)); height: calc(118.1 * var(--u)); background: var(--grad-thanks-left2); }
.thanks__ruleB  { left: calc(-4.3 * var(--u)); width: calc(604.3 * var(--u)); top: calc(848.6 * var(--u)); height: calc(11.6 * var(--u)); background: var(--grad-thanks-bottom); }
/* measured off page2.png: five lines on a 79.2u pitch, cap height 40.3u */
.thanks__text {
  position: absolute; z-index: 4; left: calc(-7 * var(--u)); top: calc(330 * var(--u)); margin: 0;
  font-family: var(--serif); font-weight: 700; text-transform: uppercase;
  font-size: calc(58 * var(--u)); line-height: 1.366; text-shadow: 0 2px 18px rgba(0,0,0,.25);
}
/* THANKS is the hero's own ramp, not --grad-brand: sampled across the word it runs
   #A11CC7 → #FFBB02, matching --grad-hero-text stop for stop */
/* our EcoWorld Sans is a narrower cut than the mockup's — THANKS set solid comes out
   310u where the design is 360u, so it is tracked out and the trailing space
   cancelled with a negative margin, exactly as DUDUK is in the Is Duduk heading */
.thanks__text .gtext { font-family: var(--sans); font-size: calc(80 * var(--u)); line-height: 1.2; vertical-align: -0.02em;
  letter-spacing: .104em; background-image: var(--grad-hero-text); }

/* ==========================================================================
   RESPONSIVE — tablet & phone (< 992px)
   --------------------------------------------------------------------------
   The mockup is desktop-only, so below 992px every section re-flows into a
   single column.  The point of this layer is that it re-flows *as the same
   design*: the gradient frames, the gradient headlines, the photo treatments
   and the colours are all the desktop's, only re-cut for a portrait canvas.
   `--u` still resolves down here (100vw/1920) but is deliberately unused —
   at phone widths it shrinks the design to nothing — so sizes are px and
   clamp(), which lets 576→991px grow into the space on its own.
   Nothing above this comment is touched by these rules.
   ========================================================================== */
@media (max-width: 991.98px) {
  :root { --fs: 5px; }            /* frame stroke; the phone block drops it to 4px */
  .wrap { width: auto; margin: 0 20px; }
  .rule { display: none; }        /* re-enabled per section below, where it still reads */

  /* ---- 1. HERO ----------------------------------------------------------
     The photo already contains the unicorn, and .hero__float is that same
     unicorn cut out of the photo and drawn back over it — so a `cover`
     background renders the float twice.  Instead the photo is parked on its
     float-free right-hand water and the cut-out becomes the hero's subject,
     which also keeps it crisp (2200px asset) at any width. */
  /* The photo holds the float at x 34.9%–62.2% of its own width, so the crop is
     pinned to the water to the RIGHT of that and sized in vw — a viewport-relative
     zoom keeps the visible window at ~36% of the image at every width, which is
     what stops the photo's float reappearing beside the cut-out on wider screens. */
  .hero {
    height: auto; padding: clamp(40px, 9vw, 70px) 0 0;
    background-size: 280vw auto; background-position: 100% 24%;
  }
  /* static so .hero__frame resolves against the section and can frame the
     float too — the float sits outside .wrap */
  .hero .wrap { position: static; height: auto; }
  /* only the bottom fifth darkens here — the desktop's long fade swallowed the
     whole photo once the section became portrait */
  .hero__shade {
    background: linear-gradient(180deg,
      rgba(10,33,41,0) 80%, rgba(10,33,41,.26) 87%, rgba(10,33,41,.60) 94%,
      rgba(10,33,41,.88) 100%);
  }
  .hero__frame {
    left: 16px; right: 16px; top: 16px; bottom: 16px; height: auto;
    border-width: var(--fs); clip-path: none;
  }
  .hero__title {
    position: static; margin: 0 clamp(32px, 9vw, 56px);
    font-size: clamp(26px, 5.6vw, 46px);
  }
  .hero__title .gtext {
    font-size: clamp(38px, 8.4vw, 68px);
    margin: clamp(4px, 1vw, 10px) 0 clamp(2px, .6vw, 6px);
  }
  /* overlaps the frame's left and bottom edges, as it does on desktop */
  /* the asset is trimmed to its own edges (2.4% padding), so the width is set to
     clear the frame's right edge while still crossing its left one */
  /* positioned + z-index so it paints over BOTH the shade and the frame: the tail
     crosses the frame's left edge and the boat crosses its bottom edge, the way the
     float breaks the frame on desktop.  -2% keeps the tail inside the section, since
     the asset is trimmed to within 2.4% of its own edges. */
  /* `left: auto` matters: the desktop rule sets `left: calc(228.3 * var(--u))` for its
     absolute placement, and switching to `position: relative` turned that into a
     ~47px relative shove to the right — which is what pushed the head off-screen. */
  .hero__float {
    position: relative; z-index: 3; left: auto; top: auto;
    display: block; width: min(94%, 680px); max-width: none;
    margin: clamp(4px, 3vw, 22px) auto clamp(-30px, -6vw, -16px);
  }

  /* ---- 2. WHO DIS -------------------------------------------------------
     The desktop's translucent gradient frame, re-cut as a closed box around
     the copy: the desktop breaks its top rule so "WHO DIS?" can sit in the
     gap, and a portrait column has no room for that. */
  .whodis { height: auto; padding: clamp(34px, 6vw, 60px) 0 0; }
  .whodis .wrap { height: auto; }
  .whodis__frame { display: none; }
  .whodis__text {
    position: static; width: auto; text-align: center;
    border: var(--fs) solid transparent; border-image: var(--grad-frame-whodis) 1;
    padding: clamp(20px, 4vw, 34px) clamp(18px, 3.6vw, 30px) clamp(22px, 4vw, 34px);
  }
  /* justified so the copy's left and right edges line up under the centred headings */
  .whodis__p { text-align: justify; text-justify: inter-word; hyphens: none; }
  .whodis__h1 { font-size: clamp(28px, 5.6vw, 46px); }
  .whodis__h2 { font-size: clamp(32px, 7.2vw, 62px); margin-top: 8px; white-space: normal; }
  .whodis__h3 { font-size: clamp(22px, 4.8vw, 40px); margin-top: 8px; white-space: normal; }
  .whodis__p  { font-size: clamp(14px, 2.1vw, 19px); margin-top: clamp(18px, 2.6vw, 26px); }   /* matches .isduduk__item p */
  .whodis__p + .whodis__p { margin-top: clamp(14px, 2vw, 20px); }
  /* She is scaled off the ARTWORK, not the column: the asset carries ~25% empty
     canvas each side, so the element runs wider than the column and the section
     trims the overflow.  The negative top margin is a percentage, which resolves
     against the column width and so tracks the viewport — it lifts her head through
     the frame's bottom rule, and z-index puts it in front.  height + object-fit
     keeps the design's crop of her legs. */
  .whodis__model {
    position: relative; z-index: 2; display: block; left: auto; top: auto;
    width: 152%; max-width: none; margin: -17% -26% 0;
    height: clamp(360px, 92vw, 640px);
    object-fit: cover; object-position: top center;
  }

  /* ---- 3. VIDEO --------------------------------------------------------- */
  .video { padding: clamp(26px, 4.5vw, 46px) 0; }
  .video__player { border-radius: 4px; }
  .video__chrome { padding: clamp(10px, 2vw, 18px) clamp(12px, 2.4vw, 22px); gap: clamp(9px, 1.6vw, 14px); }
  .video__chrome img { width: clamp(28px, 5vw, 44px); height: clamp(28px, 5vw, 44px); }
  .video__chrome strong { font-size: clamp(14px, 2.2vw, 20px); }
  .video__chrome small { font-size: clamp(11px, 1.5vw, 13px); }
  .video__play { width: clamp(58px, 10vw, 90px); height: clamp(41px, 7vw, 64px); border-radius: clamp(10px, 1.8vw, 16px); }
  .video__play svg { width: clamp(22px, 3.6vw, 32px); height: clamp(22px, 3.6vw, 32px); }

  /* ---- 4. IS DUDUK ------------------------------------------------------ */
  .isduduk { height: auto; padding: clamp(38px, 6.5vw, 62px) 0 0; }
  .isduduk .wrap { height: auto; }
  /* the backdrop keeps to the bottom band, behind the boy, as it does on desktop */
  .isduduk__photo {
    left: auto; right: 0; top: auto; bottom: 0;
    width: 100%; height: auto; max-height: 46%; object-fit: cover;
    object-position: right bottom; opacity: .55;
  }
  /* the heading keeps the desktop's split rule: a purple stub, the words, then
     the orange→teal run out to the edge.  Built off the heading itself so the
     gap tracks the type at any width. */
  /* both rules flex equally, so the words sit centred with the same gap either side */
  .isduduk__title { position: static; text-align: center; margin: 0 clamp(-20px, -2vw, -14px); padding: 0 clamp(14px, 2vw, 20px); }
  .isduduk__title .line1 { align-items: center; justify-content: center; gap: clamp(10px, 2.4vw, 18px); }
  .isduduk__title .line1::before,
  .isduduk__title .line1::after { content: ""; height: var(--fs); align-self: center; flex: 1 1 0; }
  .isduduk__title .line1::before { background: linear-gradient(90deg, #9074B4, #C968A8); }
  .isduduk__title .line1::after {
    background: linear-gradient(90deg, #FFB728 0%, #D7C164 41%, #A8CBA9 78%, #9CCEB9 100%);
  }
  .isduduk__title .is { font-size: clamp(26px, 5.2vw, 44px); }
  .isduduk__title .gtext { font-size: clamp(44px, 9.2vw, 78px); letter-spacing: .04em; }
  .isduduk__title .line2 { font-size: clamp(26px, 5.6vw, 48px); margin-top: clamp(8px, 1.4vw, 16px); }
  /* the desktop frame's bottom rule, kept as the list's own base line */
  .isduduk__list {
    position: static; width: auto; margin-top: clamp(20px, 3.4vw, 32px);
    border: 0 solid transparent; border-bottom-width: var(--fs);
    border-image: linear-gradient(90deg, #F1896C 0%, #F9AD3C 13%, #D7C164 32%,
      #A8CBA9 51%, #89D2D3 64%, #55C6DD 100%) 1;
  }
  .isduduk__item {
    grid-template-columns: clamp(56px, 11vw, 96px) 1fr; column-gap: clamp(12px, 2.4vw, 22px);
    padding: clamp(14px, 2.4vw, 20px) 0 clamp(16px, 2.8vw, 24px);
  }
  .isduduk__item .ic1 { width: clamp(26px, 5vw, 44px);  margin-top: 0; }
  .isduduk__item .ic2 { width: clamp(32px, 6.2vw, 54px); margin-top: clamp(4px, 1vw, 10px); }
  .isduduk__item .ic3 { width: clamp(46px, 9vw, 80px);  margin-top: clamp(3px, .8vw, 8px); }
  .isduduk__item p { font-size: clamp(14px, 2.1vw, 19px); }
  .isduduk__item .then { font-size: clamp(15px, 2.2vw, 20px); }
  /* Lifted just enough for his hat to break the list's base line.  The asset has
     3.15% empty canvas above his head, so the lift only has to cover that plus a
     few px — more than that and the hat reaches the third item's copy. */
  .isduduk__boy {
    position: relative; z-index: 2; display: block; left: auto; top: auto;
    height: auto; width: min(84%, 480px); max-width: none;
    margin: clamp(-20px, -3.6vw, -10px) auto 0;
  }

  /* ---- 5. KOLEKSI ------------------------------------------------------- */
  .koleksi { padding: clamp(44px, 7vw, 70px) 0 clamp(38px, 6vw, 60px); }
  .koleksi__title { font-size: clamp(32px, 6.6vw, 58px); }
  .koleksi__title .gtext { font-size: clamp(32px, 6.5vw, 57px); }
  .koleksi__sub { font-size: clamp(17px, 3vw, 26px); margin: clamp(10px, 1.6vw, 18px) 0 clamp(24px, 4vw, 40px); }
  .carousel { --per-view: 2; --gap: clamp(14px, 2.4vw, 22px); width: auto; margin: 0 clamp(40px, 7vw, 62px); }
  .project__strip { height: clamp(5px, .9vw, 8px); }
  .project__badge { font-size: clamp(26px, 5.4vw, 46px); }
  .project__badge--bumi { inset: auto 0 clamp(12px, 2vw, 20px) 0; font-size: clamp(15px, 3vw, 26px); }
  .project__logo { height: clamp(52px, 9vw, 78px); margin-top: clamp(12px, 2vw, 20px); }
  .project__logo span { font-size: clamp(17px, 3vw, 26px); }
  .carousel__arrow { top: calc(50% - 46px); width: clamp(26px, 4.4vw, 38px); height: clamp(38px, 6.6vw, 56px); }
  .carousel__arrow--prev { left: clamp(-52px, -5vw, -34px); }
  .carousel__arrow--next { right: clamp(-52px, -5vw, -34px); }
  .carousel__dots { gap: clamp(6px, 1.2vw, 12px); margin-top: clamp(20px, 3.4vw, 32px); flex-wrap: wrap; }
  .carousel__dot { width: clamp(9px, 1.4vw, 13px); height: clamp(9px, 1.4vw, 13px); }

  /* ---- 6. SUKA ----------------------------------------------------------
     The desktop's four open rules collapse into one framed box: at this width
     the frame has nothing to open onto, and the girl still breaks its bottom
     edge the way she breaks the frame on desktop. */
  .suka { height: auto; padding: clamp(38px, 6.5vw, 62px) 0 0; }
  /* the form card ran almost into the frame — the column is inset instead of the
     frame moving, so the frame's own placement and size are untouched */
  .suka .wrap { height: auto; margin: 0 clamp(30px, 8vw, 52px); }
  .suka__bg { background-size: cover; background-position: 50% 42%; }
  .suka > .suka__ruleT {
    display: block; left: 14px; right: 14px; top: 14px; bottom: 14px;
    width: auto; height: auto; background: none;
    border: var(--fs) solid transparent;
    border-image: linear-gradient(135deg, #854EBE 0%, #6379C3 30%, #4A96C5 50%,
      #37BCBD 80%, #2CD3B6 100%) 1;
  }
  .suka__title { position: static; text-align: center; font-size: clamp(32px, 7.4vw, 60px); margin-bottom: clamp(18px, 3vw, 28px); }
  .suka__form { position: static; width: auto; }
  .suka__h2 { font-size: clamp(24px, 4.8vw, 42px); margin-bottom: clamp(14px, 2.2vw, 22px); }
  .form-card { border-radius: 16px; padding: clamp(18px, 3.4vw, 30px) clamp(16px, 3vw, 26px) clamp(20px, 3.6vw, 32px); }
  .field + .field { margin-top: clamp(13px, 2.2vw, 20px); }
  .field label { font-size: clamp(15px, 2.4vw, 21px); margin-bottom: 6px; }
  .input { height: clamp(44px, 7vw, 58px); padding: 0 16px; border-radius: 10px; font-size: clamp(15px, 2.2vw, 19px); }
  .field__error { font-size: clamp(12px, 1.7vw, 15px); margin-top: 5px; }
  .checks { margin: clamp(14px, 2.4vw, 22px) 0 0 4px; }
  .check { font-size: clamp(13px, 1.9vw, 17px); gap: clamp(10px, 1.6vw, 14px); }
  .check + .check { margin-top: clamp(10px, 1.6vw, 14px); }
  .check__box { flex-basis: clamp(20px, 3vw, 26px); width: clamp(20px, 3vw, 26px); height: clamp(20px, 3vw, 26px); border-radius: 3px; }
  .form__status { font-size: clamp(13px, 1.9vw, 16px); margin-top: 12px; }
  .btn-register { height: clamp(50px, 8vw, 66px); font-size: clamp(18px, 3vw, 26px); margin-top: clamp(18px, 3vw, 26px); }
  /* the wrapper clips her legs the way the section edge crops her on desktop */
  .suka__girl {
    position: relative; display: block; left: auto; top: auto; overflow: hidden;
    width: min(68%, 360px); height: clamp(340px, 66vw, 600px); transform: none;
    margin: clamp(20px, 3.4vw, 32px) auto 0;
  }
  .suka__girl img { width: 100%; height: auto; transform: none; }

  /* ---- 7. THANK YOU ----------------------------------------------------- */
  .thanks {
    height: auto; min-height: 60vh;
    padding: clamp(54px, 9vw, 92px) 0 clamp(60px, 10vw, 100px);
  }
  /* the mirror lives in the asset now, so `cover` keeps it; the u-based placement is
     desktop-only.  The cut-out cannot stay in register with a `cover` photo at arbitrary
     aspect ratios, and the mobile frame is a plain box nothing passes behind. */
  .thanks::before { background-size: cover; background-position: 62% center; }
  .thanks__fg { display: none; }
  .thanks .wrap { height: auto; }
  .thanks__text {
    position: static; background: rgba(0,0,0,.30);
    padding: clamp(20px, 4vw, 34px) clamp(18px, 3.4vw, 30px);
    border: var(--fs) solid transparent;
    border-image: linear-gradient(135deg, #A21CC6 0%, #E42588 40%, #FF3B47 65%, #FF6419 100%) 1;
    font-size: clamp(22px, 4.6vw, 40px); line-height: 1.3;
  }
  .thanks__text .gtext { font-size: clamp(32px, 6.8vw, 58px); }
}

/* ==========================================================================
   TABLET (768–991px) — enough width to keep the desktop's two-column pairings
   ========================================================================== */
@media (min-width: 768px) and (max-width: 991.98px) {
  /* Who Dis: copy left, model right, as on desktop */
  .whodis .wrap { display: grid; grid-template-columns: minmax(0, 1fr) 30%; column-gap: clamp(18px, 3vw, 30px); align-items: end; }
  .whodis__text { grid-column: 1; grid-row: 1; }
  /* taller than the column is wide, so object-fit: cover trims the asset's empty
     side canvas instead of scaling the figure down with it */
  .whodis__model { grid-column: 2; grid-row: 1; width: 100%; height: clamp(420px, 60vw, 580px); margin: 0; align-self: end; }
  /* Is Duduk: list left, boy right, heading across both */
  .isduduk .wrap { display: grid; grid-template-columns: minmax(0, 1fr) 34%; column-gap: clamp(16px, 2.6vw, 26px); align-items: end; }
  .isduduk__title { grid-column: 1 / -1; grid-row: 1; }
  .isduduk__list { grid-column: 1; grid-row: 2; }
  .isduduk__boy { grid-column: 2; grid-row: 2; width: 100%; margin: 0; align-self: end; }
}

/* three cards across only once they are wide enough to read */
@media (min-width: 880px) and (max-width: 991.98px) {
  .carousel { --per-view: 3; }
}

/* ==========================================================================
   PHONE (< 576px)
   ========================================================================== */
@media (max-width: 575.98px) {
  :root { --fs: 4px; }
  .wrap { margin: 0 16px; }
  .hero { background-position: 96% 0; }
  .hero__frame { left: 12px; right: 12px; top: 12px; bottom: 12px; }
  .hero__float { margin-left: -1%; margin-right: auto; }
  .carousel { --per-view: 1; margin: 0 38px; }
  .carousel__arrow--prev { left: -36px; }
  .carousel__arrow--next { right: -36px; }
  /* 17 single-card pages means 17 dots — they have to stay small to hold one row */
  .carousel__dots { gap: 5px; }
  .carousel__dot { width: 8px; height: 8px; }
  .project__logo { height: 74px; }
  .suka > .suka__ruleT { left: 10px; right: 10px; top: 10px; bottom: 10px; }
}
