/* MR NOH FOOD INDUSTRIES (M) SDN. BHD
   Single page landing build, sections in the order of the company profile.

   One theme, locked: near black surfaces, brand yellow as the only accent,
   off white type. Yellow takes over a whole surface exactly twice, the
   tagline ticker under the hero and the Financial Projection band.
   Corner radius is 0 everywhere except the donut chart, which is a chart.

   Typography is a closed system. Every role below has one rule and every
   element of that role uses it. Long headings get a wider container, never
   a smaller size. */

:root {
  color-scheme: dark;

  /* Palette (approved) */
  --bg: #0b0a09;
  --bg-soft: #121110;
  --panel: #191715;
  --panel-2: #211e1b;
  --ink: #f5f3ee;
  --muted: #9b958b;
  --line: rgba(255,255,255,.12);
  --line-strong: rgba(255,255,255,.26);
  --yellow: #f7d417;
  --yellow-deep: #e2c000;
  --on-yellow: #100f0d;
  --on-yellow-muted: rgba(16,15,13,.7);
  --on-yellow-line: rgba(16,15,13,.24);
  /* Eyebrows are yellow on dark surfaces; a yellow surface flips this token. */
  --eyebrow: var(--yellow);

  /* Type roles */
  --font-body: "Inter", system-ui, -apple-system, sans-serif;
  --font-display: "Inter Tight", "Inter", system-ui, sans-serif;
  --fs-h1: clamp(42px, 6vw, 86px);
  --fs-h2: clamp(28px, 3.25vw, 46px);
  --fs-h3: clamp(19px, 1.65vw, 23px);
  --fs-quote: clamp(22px, 2.4vw, 34px);
  --fs-stat: clamp(30px, 3vw, 46px);
  --fs-stat-lg: clamp(44px, 5vw, 76px);
  --fs-lede: clamp(16px, 1.2vw, 18px);
  --fs-body: 16px;
  --fs-small: 14px;
  --fs-caption: 13px;
  --fs-label: 12px;
  --fs-eyebrow: 11px;
  --fs-button: 14px;

  /* Layout */
  --shell: 1440px;
  --gutter: clamp(20px, 5vw, 72px);
  --section: clamp(80px, 9vw, 140px);
  --gap: clamp(28px, 4vw, 64px);
  --gap-sm: clamp(20px, 2.4vw, 36px);
  --header-h: 74px;

  /* Motion */
  --ease: cubic-bezier(.16,1,.3,1);
  --dur: .45s;
}

/* ---------- Base ---------- */
*, *::before, *::after { box-sizing: border-box }
html { background: var(--bg); scroll-padding-top: var(--header-h) }
body { margin: 0; overflow-x: clip; background: var(--bg); color: var(--ink); font-family: var(--font-body); font-size: var(--fs-body); line-height: 1.65; -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility }
img { display: block; width: 100%; height: auto }
a { color: inherit; text-decoration: none }
button, input, textarea, select { font: inherit }
button { color: inherit; cursor: pointer }
h1, h2, h3, h4, p, ul, ol, dl, dd, figure { margin: 0 }
ul { padding: 0; list-style: none }
::selection { background: var(--yellow); color: var(--on-yellow) }
:focus-visible { outline: 2px solid var(--yellow); outline-offset: 4px }
::-webkit-scrollbar { width: 10px }
::-webkit-scrollbar-track { background: var(--bg) }
::-webkit-scrollbar-thumb { border: 3px solid var(--bg); background: #3c3833 }

/* Lenis owns the scroll position once it boots. */
html.lenis, html.lenis body { height: auto }
.lenis.lenis-smooth { scroll-behavior: auto !important }
.lenis.lenis-stopped { overflow: hidden }

.skip-link { position: fixed; z-index: 1000; top: 12px; left: 12px; padding: 10px 14px; background: var(--yellow); color: var(--on-yellow); font-weight: 500; transform: translateY(-180%); transition: transform .25s var(--ease) }
.skip-link:focus { transform: none }

.shell { width: min(var(--shell), calc(100% - var(--gutter) * 2)); margin-inline: auto }

/* ---------- Type roles ---------- */
.hero__title { font-family: var(--font-display); font-size: var(--fs-h1); font-weight: 600; letter-spacing: -.05em; line-height: .94; color: #fff }
.display-title { font-family: var(--font-display); font-size: var(--fs-h2); font-weight: 600; letter-spacing: -.04em; line-height: 1.02; text-wrap: balance }
main h3, .site-footer h3 { font-family: var(--font-display); font-size: var(--fs-h3); font-weight: 600; letter-spacing: -.025em; line-height: 1.2 }
.label, main h4 { font-family: var(--font-body); font-size: var(--fs-label); font-weight: 600; letter-spacing: .12em; line-height: 1.3; text-transform: uppercase }
.eyebrow { margin-bottom: 18px; color: var(--eyebrow); font-size: var(--fs-eyebrow); font-weight: 600; letter-spacing: .2em; text-transform: uppercase }
.lede { max-width: 60ch; margin-top: var(--gap-sm); color: var(--muted); font-size: var(--fs-lede); line-height: 1.6 }
.stat { font-family: var(--font-display); font-size: var(--fs-stat); font-weight: 700; letter-spacing: -.05em; line-height: 1; font-variant-numeric: tabular-nums }
.stat--lg { font-size: var(--fs-stat-lg) }
.quote { font-family: var(--font-display); font-size: var(--fs-quote); font-weight: 500; letter-spacing: -.03em; line-height: 1.25 }
.small { color: var(--muted); font-size: var(--fs-small); line-height: 1.55 }
.caption { color: var(--muted); font-size: var(--fs-caption); line-height: 1.5 }

/* SplitText writes these. Declared so an unsplit heading still renders. */
.split-line { display: block }
/* SplitText masks clip at the line box; a little slack keeps descenders whole. */
.split-mask-line-mask, [data-mask] [class$="-mask"] { padding-bottom: .1em; margin-bottom: -.1em }
.hero__line { display: block }

/* ---------- Buttons.
   One shape, two fills. Hover in and out share the same curve so a fast
   pointer never leaves a half state behind. ---------- */
.button { position: relative; display: inline-flex; min-height: 52px; padding: 0 26px; align-items: center; justify-content: center; gap: 14px; border: 1px solid transparent; font-size: var(--fs-button); font-weight: 500; letter-spacing: -.01em; line-height: 1; white-space: nowrap; transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease), color var(--dur) var(--ease) }
.button i { font-size: 16px; transition: transform var(--dur) var(--ease) }
.button:hover i { transform: translate(3px, -3px) }
.button--ghost:hover i { transform: translateY(3px) }
.button--primary { border-color: var(--yellow); background: var(--yellow); color: var(--on-yellow) }
.button--primary:hover { border-color: var(--yellow-deep); background: var(--yellow-deep) }
.button--ghost { border-color: rgba(255,255,255,.42); background: rgba(11,10,9,.32); color: #fff }
.button--ghost:hover { border-color: #fff; background: #fff; color: var(--on-yellow) }
.button--header { min-height: 42px; padding-inline: 18px; gap: 10px; border-color: rgba(255,255,255,.4); color: #fff }
.button--header:hover { border-color: var(--yellow); background: var(--yellow); color: var(--on-yellow) }
[data-magnetic] { will-change: transform }

/* Text links share one underline that grows in from the left and leaves to
   the right, so every link on the page answers the pointer the same way. */
.text-link { background: linear-gradient(currentColor, currentColor) no-repeat 100% 100% / 0 1px; transition: background-size var(--dur) var(--ease), color var(--dur) var(--ease) }
.text-link:hover { background-position: 0 100%; background-size: 100% 1px }

/* ---------- Header ---------- */
.site-header { position: fixed; z-index: 90; top: 0; right: 0; left: 0; border-bottom: 1px solid var(--line); background: rgba(11,10,9,.82); -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px); transition: background .4s var(--ease), border-color .4s var(--ease), transform .45s var(--ease) }
.site-header.is-scrolled { border-color: var(--line); background: rgba(11,10,9,.82); -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px) }
.header__inner { display: flex; height: var(--header-h); align-items: center; justify-content: space-between; gap: 30px }
.brand { display: block; width: 118px; flex: 0 0 auto }
.desktop-nav { display: flex; align-items: center; gap: clamp(18px, 2.2vw, 34px) }
.desktop-nav a { position: relative; padding: 26px 0; color: rgba(255,255,255,.72); font-size: var(--fs-button); letter-spacing: -.01em; white-space: nowrap; transition: color var(--dur) var(--ease) }
.desktop-nav a::after { content: ""; position: absolute; right: 0; bottom: 20px; left: 0; height: 2px; background: var(--yellow); transform: scaleX(0); transform-origin: right center; transition: transform .38s var(--ease) }
.desktop-nav a:hover, .desktop-nav a.is-active { color: #fff }
.desktop-nav a:hover::after, .desktop-nav a.is-active::after { transform: scaleX(1); transform-origin: left center }
.menu-button { display: none; align-items: center; gap: 9px; border: 0; background: transparent; color: #fff; font-size: var(--fs-button) }
.menu-button i { font-size: 22px }
.mobile-menu { display: none }

/* ---------- 01 Hero ---------- */
.hero { position: relative; display: flex; min-height: 100svh; align-items: flex-end; overflow: hidden; background: var(--bg) }
.hero__media { position: absolute; inset: -10% 0; will-change: transform }
.hero__media img { width: 100%; height: 100%; object-fit: cover; object-position: center }
.hero__scrim { position: absolute; inset: 0; background: linear-gradient(100deg, rgba(8,7,6,.9) 0%, rgba(8,7,6,.52) 34%, rgba(8,7,6,0) 68%), linear-gradient(0deg, var(--bg) 0%, rgba(8,7,6,.34) 26%, rgba(8,7,6,0) 52%), linear-gradient(180deg, rgba(8,7,6,.62) 0%, rgba(8,7,6,0) 17%) }
.hero__inner { position: relative; z-index: 1; padding-top: calc(var(--header-h) + 56px); padding-bottom: clamp(60px, 8vw, 104px) }
.hero__content { width: min(980px, 94%) }
/* Direct children only: the script wraps each line's text in an inner span
   that must stay free of the mask and of the motion gate below. */
.hero__title > span { display: block; overflow: hidden; padding-bottom: .06em; margin-bottom: -.06em }
.hero__title > span:last-child { color: var(--yellow) }
.hero__copy { max-width: 44ch; margin-top: 30px; color: rgba(255,255,255,.8); font-size: var(--fs-lede); line-height: 1.6 }
.hero__actions { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 36px }

/* ---------- Tagline ticker. The one marquee, speed follows the scroll. ---------- */
/* A slim credential band, set in the shared .label role rather than a heading
   size, so it reads as supporting information and not a statement.

   Spacing is one variable. The gap sits between items inside a group and is
   repeated as the group's own trailing padding, which makes "one group plus
   one gap" the repeating unit. The track is exactly two of those, so the
   -50% loop lands group two where group one started and the seam is spaced
   identically to every other gap. Changing --ticker-gap keeps that true. */
.ticker { --ticker-gap: clamp(44px, 5.2vw, 92px); position: relative; z-index: 2; overflow: hidden; background: var(--yellow); color: var(--on-yellow) }
.ticker__track { display: flex; width: max-content; will-change: transform }
.ticker__group { display: flex; align-items: center; gap: var(--ticker-gap); padding-right: var(--ticker-gap) }
.ticker__group li { display: flex; padding-block: 16px; align-items: center; font-family: var(--font-body); font-size: var(--fs-label); font-weight: 600; letter-spacing: .12em; line-height: 1.3; text-transform: uppercase; white-space: nowrap }

/* ---------- 02 About Us ---------- */
/* The About section follows the homepage pattern from the PSB theme: one
   centred column, a short rule under the heading, and the photograph breaking
   out of the shell to the full viewport width. The script grows it in from
   70%, so the band arrives at full width on its own. No bottom padding: the
   band is the section's own edge.

   .entities / .entity below are unused here; they still describe the
   scannable group-structure block kept for the About page. */
.group { padding-block: var(--section) 0 }
.group__inner { display: grid; grid-template-columns: minmax(0, 1fr); justify-items: center; align-content: center; gap: clamp(34px, 4.4vw, 62px); text-align: center }
.group__story { width: min(100%, 1100px) }
/* Wide enough that the paragraph sets in three full lines. At 68ch the last
   line was left holding "convenient for all." on its own. text-wrap: pretty
   keeps it that way if the copy is ever edited. */
.group__story .lede { max-width: 76ch; margin-inline: auto; text-wrap: pretty }
.group__rule { display: block; width: 54px; height: 1px; margin: clamp(20px, 2.2vw, 28px) auto 0; background: var(--yellow) }
/* The three companies, one card each, written to one format: name, then a
   sentence that opens with the year. Same card language as .doing__item so
   the two three-up blocks on the page read as a pair. Left-aligned inside a
   centred section: the heading is the poster, these are the detail. */
.entities { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(14px, 1.4vw, 20px); width: min(100%, 1240px); text-align: left; align-items: stretch }
.entity { display: flex; flex-direction: column; padding: clamp(26px, 2.6vw, 36px); border: 1px solid var(--line); background: var(--bg-soft); transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease) }
.entity:hover { border-color: var(--yellow); background: var(--panel) }
/* The yellow marker the profile puts beside each company name. */
.entity__rule { display: block; width: 28px; height: 2px; margin-bottom: clamp(18px, 2vw, 26px); background: var(--yellow) }
/* The longest name wraps to two lines, so two is what the row reserves: the
   descriptions still start level across all three cards, with no dead line
   under the shorter names. */
.entities h3 { min-height: 2.4em; min-height: 2lh }
.entity__meta { display: flex; flex-wrap: wrap; gap: 10px 18px; margin-top: 10px; color: var(--yellow); font-size: var(--fs-label); font-weight: 600; letter-spacing: .1em; text-transform: uppercase }
.entity__meta span + span { position: relative; padding-left: 19px }
.entity__meta span + span::before { content: ""; position: absolute; top: 50%; left: 0; width: 11px; height: 1px; background: currentColor }
.entity__role { flex: 1; margin-top: 12px; color: var(--muted); font-size: var(--fs-small); line-height: 1.6 }
/* 100vw counts the scrollbar, so subtract the measured gutter to land on the
   visible width exactly. */
/* The video is held to the section's own measure rather than run to the
   viewport edges, so it lines up with the words above it. */
.group__figure { position: relative; width: 100%; margin: 0; justify-self: stretch; overflow: hidden; background: var(--bg-soft) }
/* At full scale the band is exactly one viewport: 100vw by 100svh. */
/* A cinematic band rather than the clip's own 16:9: shorter on the page, and
   the crop it costs is off the top and bottom, where this footage carries the
   least. A fixed viewport height would instead leave a frame taller than it is
   wide on a narrow screen. */
.group__figure { aspect-ratio: 21 / 9 }
.group__figure img, .group__figure video { display: block; width: 100%; height: 100%; object-fit: cover; object-position: center; background: var(--bg-soft) }

/* ---------- 03 Mission and Vision ---------- */
.mv { padding-block: var(--section); background: var(--bg-soft) }
.mv__inner { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(14px, 1.4vw, 20px) }
.mv__block { position: relative; padding: clamp(30px, 3.4vw, 52px); border: 1px solid var(--line); background: var(--bg) }
.mv__block--vision { border-color: var(--yellow) }
.mv__icon { display: grid; width: 56px; height: 56px; margin-bottom: var(--gap-sm); place-items: center; border: 1px solid var(--line); color: var(--yellow); font-size: 26px }
.mv__block--vision .mv__icon { border-color: var(--yellow) }
.mv__copy { max-width: 46ch; margin-top: var(--gap-sm); color: var(--muted); font-size: var(--fs-lede); line-height: 1.6 }
.mv__list { margin-top: var(--gap-sm); border-top: 1px solid var(--line) }
.mv__list li { padding: 16px 0 16px 22px; border-bottom: 1px solid var(--line); position: relative; color: var(--muted); font-size: var(--fs-body); line-height: 1.6 }
.mv__list li::before { content: ""; position: absolute; top: 26px; left: 0; width: 10px; height: 1px; background: var(--yellow) }

/* ---------- 04 Our Core Values ---------- */
.values { padding-block: var(--section) }
.values__grid { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); margin-top: var(--gap); border: 1px solid var(--line) }
.value { padding: clamp(24px, 2.4vw, 36px) clamp(20px, 2vw, 30px) }
.value + .value { border-left: 1px solid var(--line) }
.value i { display: block; color: var(--yellow); font-size: 30px }
.value h3 { margin-top: clamp(24px, 3vw, 48px) }
.value p { margin-top: 10px; color: var(--muted); font-size: var(--fs-small); line-height: 1.55 }

/* ---------- 05 Our Team ---------- */
.leader { padding-block: var(--section); background: var(--bg-soft) }
.leader__inner { display: grid; grid-template-columns: minmax(0, .42fr) minmax(0, 1fr); gap: var(--gap); align-items: center }
.leader__portrait { overflow: hidden; background: var(--panel) }
.leader__portrait img { aspect-ratio: 3 / 4; object-fit: cover; filter: grayscale(1) contrast(1.05); transition: filter .7s var(--ease) }
.leader__portrait:hover img { filter: none }
.leader__statement { max-width: 40ch; margin-top: var(--gap-sm); font-family: var(--font-display); font-size: var(--fs-quote); font-weight: 500; letter-spacing: -.03em; line-height: 1.25 }
.leader__copy { max-width: 56ch; margin-top: var(--gap-sm); color: var(--muted); font-size: var(--fs-body); line-height: 1.65 }
.leader__name { margin-top: var(--gap-sm); font-size: var(--fs-small); font-weight: 600 }
.leader__role { margin-top: 4px; color: var(--muted); font-size: var(--fs-small) }

/* ---------- 06 What We Do ---------- */
/* The pinned panel below is a full screen of its own, so this section closes
   with a shorter gap than the standard rhythm. */
.doing { padding-block: var(--section) 0 }
/* Three equal cards on one line. The grid stretches them and the copy takes
   the leftover height, so the three bottoms align no matter how the text
   wraps. The image is flush to the card edge and the card clips it. */
.doing__grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(16px, 1.8vw, 28px); margin-top: var(--gap); align-items: stretch }
.doing__item { display: flex; flex-direction: column; overflow: hidden; border: 1px solid var(--line); background: var(--bg-soft); transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease) }
.doing__item:hover { border-color: var(--yellow); background: var(--panel) }
.doing__item figure { overflow: hidden; background: var(--panel) }
.doing__item img { aspect-ratio: 4 / 3; object-fit: cover; transition: transform .9s var(--ease) }
.doing__item:hover img { transform: scale(1.04) }
.doing__item p { flex: 1; padding: clamp(20px, 2vw, 28px); font-size: var(--fs-body); line-height: 1.55 }

/* ---------- 07 Our Product.
   Default is a swipeable rail, which is also the fallback for reduced motion
   and narrow screens. On desktop the script pins the section and pans the
   track sideways as the page scrolls. ---------- */
.products { padding-block: var(--section) 0; background: var(--bg-soft) }
/* The whole head is a centred block: label, title and description on one axis. */
.products__head { text-align: center }
.products__head h2 { max-width: 20ch; margin-inline: auto }
.products__head .lede { margin-inline: auto }
.pan { --rail-inset: max(var(--gutter), calc((100% - var(--shell)) / 2)); --rail-gap: clamp(12px, 1.2vw, 20px); margin-top: var(--gap); padding-bottom: var(--section); overflow-x: auto; scroll-snap-type: x proximity; scroll-padding-inline: var(--rail-inset); scrollbar-width: none; -webkit-overflow-scrolling: touch }
.pan::-webkit-scrollbar { display: none }
.pan__track { display: flex; gap: var(--rail-gap); padding-inline: var(--rail-inset) }
.product { flex: 0 0 clamp(230px, 24vw, 330px); scroll-snap-align: start }
.product__media { overflow: hidden; background: var(--bg) }
.product__media img { aspect-ratio: 1 / 1; object-fit: cover; transition: transform .9s var(--ease) }
.product:hover .product__media img { transform: scale(1.05) }
.product h3 { margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--line); text-align: center }
/* Pinned mode, added by the script on desktop only. */
/* Pinned, the section is exactly one viewport. The header clearance is the
   section's own padding so it takes part in the centring, instead of being a
   second offset on the heading that stacks on top of it. */
/* Pinned, the panel is one viewport and its content is centred in the whole of
   it. No allowance for the header: it hides on the way down, which is the only
   direction you can arrive from, and reserving its height would push the block
   off centre and cost the photographs the space. The padding is symmetric and
   small, just so nothing touches the screen edge. */
.products.has-rail { display: flex; flex-direction: column }
.products.has-rail .products__head { padding-top: 0 }
.products.has-rail .pan { margin-top: clamp(24px, 2.6vw, 40px); padding-bottom: 0; overflow: hidden; scroll-snap-type: none }
.products.has-rail .pan__track { will-change: transform }
/* Cards are sized so five span the viewport, and the rail opens with the first
   one dead centre: the left half of the screen is empty, and the pan fills it.
   The same offset sits on both ends, so the rail opens with the first card
   centred and closes with the last one centred.

   Everything is written in vw, never %, because a percentage inside a custom
   property resolves against whatever box the property is finally used on, and
   that is the pan on the track but the max-content track on a card. */
.products.has-rail .pan { --rail-card: calc((100vw - var(--sbw, 0px) - 4 * var(--rail-gap)) / 5); --rail-offset: calc((100vw - var(--sbw, 0px)) / 2 - var(--rail-card) / 2) }
.products.has-rail .pan__track { padding-inline: var(--rail-offset) }
.products.has-rail .product { flex-basis: var(--rail-card) }

/* ---------- 08 Products Packaging ---------- */
.packs { padding-block: var(--section) }
.packs__grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); grid-auto-rows: clamp(160px, 15vw, 230px); gap: clamp(12px, 1.2vw, 18px); margin-top: var(--gap) }
.pack { position: relative; overflow: hidden; background: var(--panel) }
.pack img { width: 100%; height: 100%; object-fit: cover; transition: transform .9s var(--ease) }
.pack:hover img { transform: scale(1.05) }
.pack figcaption { position: absolute; right: 0; bottom: 0; left: 0; padding: 32px 18px 14px; background: linear-gradient(0deg, rgba(8,7,6,.9) 0%, rgba(8,7,6,.5) 48%, transparent); color: #fff; font-size: var(--fs-caption); font-weight: 500 }
.pack--lead { grid-column: span 2; grid-row: span 2 }

/* ---------- 09 Our Kiosk ---------- */
.kiosk { padding-block: var(--section); background: var(--panel) }
.kiosk__inner { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: var(--gap); align-items: start }
.kiosk__media { overflow: hidden; background: var(--panel-2) }
.kiosk__media img { aspect-ratio: 5 / 4; object-fit: cover; will-change: transform }
.kiosk__copy { max-width: 46ch; margin-top: var(--gap-sm); color: var(--muted); font-size: var(--fs-lede); line-height: 1.6 }
.specs { margin-top: var(--gap-sm); border-top: 1px solid var(--line) }
.spec { padding-block: 20px; border-bottom: 1px solid var(--line) }
.spec dt { font-family: var(--font-display); font-size: var(--fs-h3); font-weight: 600; letter-spacing: -.025em; line-height: 1.2 }
.spec dd { margin-top: 6px; color: var(--muted); font-size: var(--fs-small) }

/* ---------- 10 Franchise Plan ---------- */
.plan { padding-block: var(--section) }
/* Each card takes the height its own rows need. Stretched to match, the
   shorter one carries a block of dead space at the bottom, which reads as a
   mistake rather than as breathing room. */
.plan__grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(14px, 1.4vw, 20px); margin-top: var(--gap); align-items: start }
.plan__block { padding: clamp(30px, 3.4vw, 52px); border: 1px solid var(--line) }
.plan__block ul { margin-top: var(--gap-sm); border-top: 1px solid var(--line) }
.plan__block li { position: relative; padding: 16px 0 16px 22px; border-bottom: 1px solid var(--line); color: var(--muted); font-size: var(--fs-body); line-height: 1.6 }
.plan__block li::before { content: ""; position: absolute; top: 26px; left: 0; width: 10px; height: 1px; background: var(--yellow) }

/* ---------- 11 Brand Overview ---------- */
.brand-overview { padding-block: var(--section); background: var(--bg-soft) }
.brand-overview__inner { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--gap); margin-top: var(--gap) }
.audience__chart { display: flex; gap: var(--gap-sm); align-items: center; margin-top: var(--gap-sm); padding: clamp(22px, 2.4vw, 36px); border: 1px solid var(--line) }
/* Two conic layers: the data underneath, a same colour wipe on top that the
   script pulls back from 0% to 100% so the ring draws itself. */
.donut { --r: 100%; flex: 0 0 auto; width: clamp(150px, 14vw, 210px); aspect-ratio: 1; border-radius: 50%; background: conic-gradient(transparent 0 var(--r), var(--bg-soft) var(--r) 100%), conic-gradient(var(--yellow) 0 60%, var(--ink) 60% 90%, #5a5550 90% 100%); -webkit-mask: radial-gradient(circle, transparent 0 60%, #000 60.5%); mask: radial-gradient(circle, transparent 0 60%, #000 60.5%) }
.donut__key li { display: flex; gap: 12px; align-items: baseline; padding-block: 9px; color: var(--muted); font-size: var(--fs-small) }
.donut__key li + li { border-top: 1px solid var(--line) }
.donut__key b { min-width: 3.2ch; color: var(--ink); font-family: var(--font-display); font-size: var(--fs-h3); font-weight: 600; letter-spacing: -.02em; font-variant-numeric: tabular-nums }
.donut__swatch { width: 10px; height: 10px; flex: 0 0 auto; align-self: center }
.donut__swatch--johor { background: var(--yellow) }
.donut__swatch--klang { background: var(--ink) }
.donut__swatch--other { background: #5a5550 }
.audience__facts { display: grid; grid-template-columns: 1fr 1fr; margin-top: clamp(14px, 1.4vw, 20px); border: 1px solid var(--line) }
.audience__facts > div { padding: clamp(18px, 2vw, 26px) }
.audience__facts > div + div { border-left: 1px solid var(--line) }
.audience__facts dt { color: var(--muted); font-size: var(--fs-label); font-weight: 600; letter-spacing: .12em; text-transform: uppercase }
.audience__facts dd { margin-top: 10px; font-family: var(--font-display); font-size: var(--fs-h3); font-weight: 600; letter-spacing: -.025em; line-height: 1.2 }
.brand-values { display: grid; gap: clamp(14px, 1.4vw, 20px); align-content: start }
.brand-values article { padding: clamp(22px, 2.4vw, 36px); border: 1px solid var(--line) }
.brand-values ul { margin-top: var(--gap-sm); border-top: 1px solid var(--line) }
.brand-values li { position: relative; padding: 13px 0 13px 22px; border-bottom: 1px solid var(--line); color: var(--muted); font-size: var(--fs-body); line-height: 1.55 }
.brand-values li::before { content: ""; position: absolute; top: 24px; left: 0; width: 10px; height: 1px; background: var(--yellow) }

/* ---------- 12 Franchise Cost Information ---------- */
.cost { padding-block: var(--section) }
.tiles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); margin-top: var(--gap); border: 1px solid var(--line) }
.tile { padding: clamp(24px, 2.6vw, 38px) }
.tile + .tile { border-left: 1px solid var(--line) }
.tile__value { color: var(--yellow); font-family: var(--font-display); font-size: var(--fs-stat); font-weight: 700; letter-spacing: -.05em; line-height: 1; font-variant-numeric: tabular-nums }
.tile__label { margin-top: 12px; color: var(--muted); font-size: var(--fs-small) }
.cost__caption { margin-top: var(--gap) }
.costs { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--gap); margin-top: var(--gap-sm) }
.costs__group h4 { padding-bottom: 14px; border-bottom: 1px solid var(--line-strong); color: var(--muted) }
.costs__group li { display: grid; grid-template-columns: 1fr auto auto; gap: 6px 16px; padding-block: 13px; align-items: baseline }
.costs__group li + li { border-top: 1px solid var(--line) }
.costs__item { font-size: var(--fs-small) }
.costs__pct { color: var(--muted); font-size: var(--fs-caption); font-variant-numeric: tabular-nums }
.costs__amt { min-width: 92px; font-size: var(--fs-small); font-weight: 600; text-align: right; font-variant-numeric: tabular-nums }
.costs__foot { margin-top: 14px; color: var(--muted); font-size: var(--fs-caption) }
.costs__total { display: flex; margin-top: var(--gap); padding: 24px clamp(18px, 2vw, 30px); align-items: baseline; justify-content: space-between; background: var(--yellow); color: var(--on-yellow); font-family: var(--font-display); font-size: var(--fs-stat); font-weight: 700; letter-spacing: -.045em; line-height: 1; font-variant-numeric: tabular-nums; transform-origin: left center }
.cost__panels { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(14px, 1.4vw, 20px); margin-top: clamp(14px, 1.4vw, 20px) }
.cost__panel { padding: clamp(24px, 2.6vw, 38px); border: 1px solid var(--line) }
.cost__panel--alt { background: var(--bg-soft) }
.cost__panel dl { margin-top: var(--gap-sm); border-top: 1px solid var(--line) }
.cost__panel dl > div { display: flex; justify-content: space-between; gap: 16px; padding-block: 13px; border-bottom: 1px solid var(--line) }
.cost__panel dt { color: var(--muted); font-size: var(--fs-small) }
.cost__panel dd { font-size: var(--fs-small); font-weight: 600; text-align: right; font-variant-numeric: tabular-nums }
.cost__cta, .plan__cta { margin-top: var(--gap) }

/* ---------- 13 Types of Franchise Facilities ---------- */
.facilities { padding-block: var(--section); background: var(--bg-soft) }
/* Accordion. Without the script every panel is open, so the text is always
   reachable; the script collapses all but the first and animates the rest. */
.facilities__list { max-width: 960px; margin-top: var(--gap); border-top: 1px solid var(--line) }
.facility { border-bottom: 1px solid var(--line) }
.facility__toggle { display: flex; width: 100%; padding: clamp(20px, 2.2vw, 28px) 0; align-items: center; justify-content: space-between; gap: 24px; border: 0; background: none; color: inherit; font: inherit; text-align: left; cursor: pointer; transition: color var(--dur) var(--ease) }
.facility__toggle:hover { color: var(--yellow) }
.facility__toggle i { flex: 0 0 auto; color: var(--yellow); font-size: 20px; transition: transform .45s var(--ease) }
.facility.is-open .facility__toggle i { transform: rotate(45deg) }
.facility__panel { overflow: hidden }
html.js-accordion .facility:not(.is-open) .facility__panel { height: 0 }
.facility__panel p { max-width: 60ch; padding-bottom: clamp(20px, 2.2vw, 28px); color: var(--muted); font-size: var(--fs-body); line-height: 1.65 }

/* ---------- 14 Why Choose Us ---------- */
.why { padding-block: var(--section) }
.why__list { counter-reset: why; margin-top: var(--gap); border-top: 1px solid var(--line) }
.why__row { position: relative; isolation: isolate; overflow: hidden; display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: clamp(18px, 3.4vw, 60px); align-items: center; padding: clamp(24px, 3.2vw, 46px) clamp(14px, 1.8vw, 26px); border-bottom: 1px solid var(--line); counter-increment: why }
.why__row::before { content: counter(why, decimal-leading-zero); color: var(--muted); font-family: var(--font-display); font-size: var(--fs-caption); font-weight: 600; letter-spacing: .1em }
.why__claim { max-width: 34ch; font-family: var(--font-display); font-size: clamp(19px, 2.1vw, 31px); font-weight: 600; letter-spacing: -.03em; line-height: 1.2; text-wrap: balance }
.why__row i { color: var(--yellow); font-size: clamp(25px, 2.3vw, 34px) }

/* ---------- 15 Business Model and Financial Base ---------- */
.model-section { padding-block: var(--section); background: var(--bg-soft) }
.model-section__inner { display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, .8fr); gap: var(--gap); align-items: start }
.model { display: grid; gap: clamp(22px, 2.6vw, 36px); margin-top: var(--gap) }
.model__row { display: flex; gap: var(--gap-sm); align-items: baseline }
.model__num { flex: 0 0 auto; width: clamp(120px, 11vw, 168px); color: var(--yellow); font-family: var(--font-display); font-size: var(--fs-stat-lg); font-weight: 700; letter-spacing: -.05em; line-height: 1; font-variant-numeric: tabular-nums }
.model p { max-width: 40ch; margin-top: 6px; color: var(--muted); font-size: var(--fs-small); line-height: 1.55 }
.revenue { padding: clamp(24px, 2.6vw, 38px); border: 1px solid var(--yellow) }
.revenue ul { margin-top: var(--gap-sm); border-top: 1px solid var(--line) }
.revenue li { position: relative; padding: 14px 0 14px 22px; border-bottom: 1px solid var(--line); font-size: var(--fs-body); line-height: 1.55 }
.revenue li::before { content: ""; position: absolute; top: 25px; left: 0; width: 10px; height: 1px; background: var(--yellow) }

/* ---------- 16 Financial Projection. The yellow takeover. ---------- */
.projection { --eyebrow: var(--on-yellow); padding-block: var(--section); background: var(--yellow); color: var(--on-yellow) }
.projection__inner { display: grid; grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr); gap: var(--gap); align-items: start }
.projection__head h3 { margin-top: var(--gap) }
.projection__points { margin-top: var(--gap-sm); border-top: 1px solid var(--on-yellow-line) }
.projection__points li { position: relative; padding: 14px 0 14px 22px; border-bottom: 1px solid var(--on-yellow-line); color: var(--on-yellow-muted); font-size: var(--fs-body); line-height: 1.6 }
.projection__points li::before { content: ""; position: absolute; top: 25px; left: 0; width: 10px; height: 1px; background: var(--on-yellow) }
.chart { display: grid; gap: var(--gap-sm) }
.chart figcaption { color: var(--on-yellow-muted); font-size: var(--fs-caption) }
.chart__plot { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(18px, 2.4vw, 44px); height: clamp(240px, 28vw, 400px); border-bottom: 1px solid rgba(16,15,13,.4) }
.chart__group { display: grid; grid-template-rows: minmax(0, 1fr) auto; height: 100% }
.chart__bars { display: flex; gap: clamp(8px, 1vw, 14px); align-items: stretch; min-height: 0 }
.bar-col { display: flex; flex: 1; flex-direction: column; justify-content: flex-end; height: 100% }
.bar__value { margin-bottom: 8px; color: var(--on-yellow); font-family: var(--font-display); font-size: var(--fs-small); font-weight: 600; letter-spacing: -.02em; text-align: center; font-variant-numeric: tabular-nums }
.bar { height: calc(var(--v) / 1200 * 100%); transform-origin: bottom center; will-change: transform }
.bar--my { background: var(--on-yellow) }
.bar--sg { background: var(--ink) }
.chart__label { padding-top: 12px; color: var(--on-yellow-muted); font-size: var(--fs-label); font-weight: 600; letter-spacing: .12em; text-transform: uppercase }
.chart__key { display: flex; flex-wrap: wrap; gap: 8px 28px }
.chart__key li { display: flex; gap: 10px; align-items: center; color: var(--on-yellow-muted); font-size: var(--fs-small) }
.chart__swatch { width: 12px; height: 12px }
.chart__swatch--my { background: var(--on-yellow) }
.chart__swatch--sg { background: var(--ink) }

/* ---------- Weekly calendar (the one section not in the profile) ---------- */
.events { padding-block: var(--section) }
.events__inner { display: grid; grid-template-columns: minmax(0, .72fr) minmax(0, 1.25fr); gap: var(--gap); align-items: center }
.events__note { max-width: 34ch; margin-top: var(--gap-sm); color: var(--muted); font-size: var(--fs-lede); line-height: 1.6 }
.events__figure { display: flex; justify-content: center; padding: clamp(14px, 1.4vw, 22px); background: var(--bg-soft); border: 1px solid var(--line) }
.events__figure img { width: auto; max-width: 100%; height: auto; max-height: 720px; object-fit: contain }

/* ---------- 17 Contact ---------- */
.site-footer { background: var(--bg-soft) }
.footer__grid { display: grid; grid-template-columns: 1.25fr .7fr 1.05fr 1.05fr; gap: clamp(34px, 4.4vw, 84px); padding-block: var(--section) clamp(46px, 5vw, 68px) }
.brand--footer { width: 150px }
.footer__brand > p { max-width: 34ch; margin-top: 26px; color: var(--muted); font-size: var(--fs-small); line-height: 1.7 }
.footer__social { display: flex; gap: 10px; margin-top: 26px }
.footer__social a { display: grid; width: 38px; height: 38px; place-items: center; border: 1px solid var(--line); border-radius: 50%; color: var(--muted); font-size: 17px; transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease), color var(--dur) var(--ease) }
.footer__social a:hover { border-color: var(--yellow); background: var(--yellow); color: var(--on-yellow) }
.site-footer h4 { margin-bottom: 26px; font-family: var(--font-display); font-size: var(--fs-h3); font-weight: 600; letter-spacing: -.025em; line-height: 1.2 }
.footer__links { display: flex; align-items: flex-start; flex-direction: column; gap: 13px }
.footer__links h4 { margin-bottom: 13px }
.footer__links a, .footer__contact a { color: var(--muted); font-size: var(--fs-small); line-height: 1.6; transition: color var(--dur) var(--ease) }
.footer__links a:hover, .footer__contact a:hover { color: var(--yellow) }
.footer__contact { font-style: normal }
.footer__contact > a { display: flex; align-items: center; gap: 13px; margin-bottom: 20px }
.footer__contact > a:last-child { margin-bottom: 0 }
.footer__contact i { display: grid; flex: 0 0 auto; margin-block: -5px; width: 30px; height: 30px; place-items: center; border-radius: 50%; background: var(--yellow); color: var(--on-yellow); font-size: 16px }
.footer__signup > p { color: var(--muted); font-size: var(--fs-small); line-height: 1.7 }
.signup { display: flex; margin-top: 22px; align-items: center; gap: 8px; padding: 5px 5px 5px 15px; border: 1px solid var(--line); border-radius: 4px; transition: border-color var(--dur) var(--ease) }
.signup:focus-within { border-color: var(--yellow) }
.signup__input { flex: 1 1 auto; min-width: 0; border: 0; background: transparent; color: var(--ink); font: inherit; font-size: var(--fs-small) }
.signup__input::placeholder { color: var(--muted) }
.signup__input:focus { outline: none }
.signup__button { display: grid; flex: 0 0 auto; width: 40px; height: 40px; place-items: center; border: 0; border-radius: 4px; background: var(--yellow); color: var(--on-yellow); font-size: 17px; cursor: pointer; transition: background var(--dur) var(--ease) }
.signup__button:hover { background: var(--yellow-deep) }
.signup__note { margin-top: 12px; min-height: 2lh; color: var(--yellow); font-size: var(--fs-caption); line-height: 1.6 }
.footer__bar { border-top: 1px solid var(--line) }
.footer__bottom { display: flex; padding-block: 22px; align-items: center; justify-content: space-between; gap: 16px; color: var(--muted); font-size: var(--fs-caption); line-height: 1.7 }
.footer__bottom a { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; transition: color var(--dur) var(--ease) }
.footer__bottom a:hover { color: var(--yellow) }

/* ---------- Motion gate.
   The inline head script adds .motion-ready before first paint when the
   visitor allows motion. The script removes it again if GSAP never arrives,
   and the timed keyframe below is the last resort if the script itself
   fails, so content can never stay hidden. ---------- */
html.motion-ready [data-reveal], html.motion-ready [data-mask] { opacity: 0; animation: unhide 0s 3s forwards }
html.motion-ready .hero__title > span, html.motion-ready .hero__copy, html.motion-ready .hero__actions { opacity: 0; animation: unhide 0s 3s forwards }
html.motion-ready.motion-live [data-reveal], html.motion-ready.motion-live [data-mask],
html.motion-ready.motion-live .hero__title > span, html.motion-ready.motion-live .hero__copy, html.motion-ready.motion-live .hero__actions { animation: none }
@keyframes unhide { to { opacity: 1 } }

/* ---------- Responsive ---------- */
@media (max-width: 1180px) {
  .values__grid { grid-template-columns: repeat(3, minmax(0, 1fr)) }
  .value:nth-child(4) { border-left: 0 }
  .value:nth-child(n+4) { border-top: 1px solid var(--line) }
}

@media (max-width: 1023px) {
  .kiosk__inner, .events__inner, .leader__inner, .brand-overview__inner, .model-section__inner, .projection__inner { grid-template-columns: minmax(0, 1fr) }
  .footer__grid { grid-template-columns: 1fr 1fr }
  .footer__brand, .footer__signup { grid-column: 1 / -1 }
  .footer__bottom { align-items: flex-start; flex-direction: column; gap: 12px }
  .entities { grid-template-columns: repeat(2, minmax(0, 1fr)) }

  .leader__portrait { max-width: 320px }
  .costs { grid-template-columns: minmax(0, 1fr) }
  .tiles { grid-template-columns: repeat(2, minmax(0, 1fr)) }
  .tile:nth-child(3) { border-left: 0 }
  .tile:nth-child(n+3) { border-top: 1px solid var(--line) }
}

@media (max-width: 900px) {
  .desktop-nav, .site-header .button--header { display: none }
  .menu-button { display: inline-flex }
  .mobile-menu { display: grid; gap: 24px; padding: 8px var(--gutter) 30px; border-top: 1px solid var(--line); background: var(--bg) }
  .mobile-menu[hidden] { display: none }
  .site-header:has(.mobile-menu:not([hidden])) { border-color: var(--line); background: var(--bg) }
  .mobile-menu__nav { display: grid; gap: 2px }
  .mobile-menu__nav a { padding-block: 14px; border-bottom: 1px solid var(--line); font-family: var(--font-display); font-size: var(--fs-h3); font-weight: 600; letter-spacing: -.025em }
  .mobile-menu .button { width: 100% }
  .mv__inner, .plan__grid, .cost__panels { grid-template-columns: minmax(0, 1fr) }
  .doing__grid { grid-template-columns: minmax(0, 1fr) }
  .doing__item img { aspect-ratio: 16 / 10 }
  .packs__grid { grid-template-columns: repeat(2, minmax(0, 1fr)) }
  .pack--lead { grid-column: span 2; grid-row: span 1 }
  .audience__chart { flex-direction: column; align-items: flex-start }
}

@media (max-width: 640px) {
  .footer__grid { grid-template-columns: 1fr }
  .footer__brand, .footer__signup { grid-column: auto }
  /* The logo box is 71px tall and the artwork carries ~5px of its own
     transparent margin, so a 64px bar left the mark almost touching
     both edges. 88px gives it about 14px of visible air each side. */
  :root { --header-h: 88px }
  .hero__actions .button { flex: 1 1 auto }
  .entities { grid-template-columns: minmax(0, 1fr) }
  .entities h3 { min-height: 0 }
  .values__grid { grid-template-columns: minmax(0, 1fr) }
  .value + .value { border-left: 0; border-top: 1px solid var(--line) }
  .why__row { grid-template-columns: auto minmax(0, 1fr); gap: 18px }
  .why__row i { display: none }
  .model__row { flex-direction: column; gap: 8px }
  .model__num { width: auto }
  .tiles { grid-template-columns: minmax(0, 1fr) }
  .tile + .tile { border-top: 1px solid var(--line); border-left: 0 }
  .audience__facts { grid-template-columns: minmax(0, 1fr) }
  .audience__facts > div + div { border-left: 0; border-top: 1px solid var(--line) }
  .events__figure img { max-height: 62vh }
  .costs__group li { grid-template-columns: 1fr auto }
  .costs__pct { grid-column: 1 }
  .costs__amt { grid-row: 1; grid-column: 2 }
  .costs__total { flex-direction: column; gap: 8px }
  .chart__plot { gap: 14px; height: 240px }
}

/* ---------- Reduced motion.
   Everything collapses to a static, fully readable page. The pin is never
   built, so the rail keeps its native swipe. ---------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important }
  .ticker { overflow-x: auto }
  .hero__media { inset: 0 }
  .donut { --r: 100% }
}
