:root{
    --white:#FFFFFF;
    --grayBg:#F5F5F7;
    --ink:#1D1D1F;
    --gray600:#6E6E73;
    --gray300:rgba(0,0,0,0.12);
    /* เส้นขนหนู — เดิมมี 0.05 0.06 0.07 0.08 0.1 กระจายอยู่ 35 จุด
       ต่างกันไม่ถึงระดับที่ตาแยกออก แต่ทำให้ไม่มีใครรู้ว่าควรใช้ค่าไหน */
    --line:rgba(0,0,0,0.08);
    --line-strong:rgba(0,0,0,0.18);

    /* สีระดับสมาชิก — ไม่ได้คิดเอง เอามาจาก TIER_TONE ในโค้ด POS
       (src/data/membersMock.ts) เพื่อให้หน้าเว็บกับตัวแอปเรียกสีเดียวกัน
       ระดับสูงสุดใช้ brand-700 · วัดแล้วผ่านทั้งสามด่าน ไอคอนบนจานอ่อน /
       ไอคอนขาวบนจานทึบ / จานตัดกับพื้นเทา ทุกตัว ≥ 3 */
    --tier-member:#525252;    /* neutral-600 · 6.50 · 7.81 · 7.18 */
    --tier-silver:#475569;    /* slate-600   · 6.34 · 7.58 · 6.96 */
    --tier-gold:#B45309;      /* amber-700   · 4.25 · 5.02 · 4.61 */
    --tier-platinum:#327D08;  /* brand-700   · 4.37 · 5.16 · 4.74 */
    /* ── เขียวแบรนด์ ────────────────────────────────────────────────────────
       ยึดตามแอปจริงแล้ว 2 ก.ย. 2569 ตามที่เจ้าของตัดสิน

       ประวัติ — เดิมหน้านี้ใช้ #3F9B0B ซึ่งตรงกับแอป แล้ววันที่ 31 ส.ค.
       เปลี่ยนไปเป็น #55AA0F ตามสีในไฟล์โลโก้ ตอนนั้นยังไม่มีใครเปิดโค้ดแอปดู
       พอเปิดดูจริงพบว่า src/index.css:20 เขียนกำกับไว้ตรงๆ ว่า
         --color-brand-600: #3f9b0b;  /* ← CI base / accent (#3F9B0B) *​/
       และเป็นสีเดียวกับ --color-seated ที่ทาโต๊ะมีลูกค้าทั้งแอป
       สองสีนั้น hue ต่างกัน 5.4° ซึ่งเกินระดับที่ตาแยกออก คือเขียวคนละตัว
       ไม่ใช่เฉดเดียวกันคนละความสว่าง

       บันไดชุดนี้ไม่ได้คำนวณเอง — ยกมาจาก --color-brand-* ของแอปทั้งสิบขั้น
       (src/index.css:14-23) แล้วเลือกขั้นที่ผ่านเกณฑ์ของแต่ละงาน
       เขียวบนหน้าเว็บกับบนแอปจึงเป็นค่าเดียวกันจริงๆ ไม่ใช่แค่ใกล้เคียง

         โทเคน           ขั้นในแอป    ค่า        วัดได้
         --green         brand-600   #3F9B0B   ขาวทับ 3.56 · เทียบพื้นขาว 3.56
         --green-ui      brand-600   #3F9B0B   3.56 ผ่านเกณฑ์ 3 ของ UI
         --green-strong  brand-700   #327D08   ขาวทับ 5.16
         --green-dark    brand-800   #276006   ขาวทับ 7.60 · ตอนชี้/กด
         --green-text    brand-700   #327D08   5.16 บนพื้นขาว
         --green-tint    brand-50    #F2F9EC   หมึกบนพื้นนี้ 15.66

       ที่ต่างจากรอบก่อน — ไม่ต้องแยก --green กับ --green-ui อีกแล้ว
       #55AA0F ได้ 2.94 บนขาว ตกเกณฑ์ 3 ของ UI ที่ไม่ใช่ตัวหนังสือ จึงเคยต้อง
       มีสองตัว · #3F9B0B ได้ 3.56 ทำได้ทั้งสองงาน เก็บสองชื่อไว้เพราะโค้ด
       เรียกใช้อยู่ 40 กว่าจุด และชื่อมันบอกเจตนาต่างกัน */
    --green:#3F9B0B;
    /* เขียวเดียวกันในรูปแบบ channel สำหรับพื้นโปร่ง มีกฎ 13 ที่เคยฝัง hex ไว้
       ตรงๆ ทำให้ตอนเปลี่ยนสีแบรนด์แล้วตกหล่น */
    --green-rgb:63,155,11;
    --green-ui:#3F9B0B;        /* เขียวที่ต้องมองเห็นบนพื้นขาว */
    --green-strong:#327D08;
    --green-dark:#276006;      /* pressed / hover on --green-strong */
    --green-text:#327D08;
    --green-tint:#F2F9EC;

    /* ── สีสถานะโต๊ะ ยกมาจากแอปจริง (2 ก.ย. 2569) ──────────────────────────
       ที่มา ~/Documents/NubTang POS/
         src/types.ts:109                    ชนิด TableStatus ห้าค่า
         src/pages/selling/sessionUtils.ts:49 STATUS_LABEL ชื่อไทยของแต่ละค่า
         src/pages/selling/SellingPage.tsx:837 TILE_TONE สีของไทล์
         src/index.css:26,31-40               ค่าสีที่ชื่อเหล่านั้นชี้ไป

       ของเดิมในหน้านี้เป็นสีพาสเทลที่คิดขึ้นเอง ไม่ตรงกับที่ลูกค้าจะเห็นจริง
       สักสีเดียว — เขียวเป็น --green-tint เหลืองเป็น #FDF4E3 แดงเป็น #FCEBE8
       และไม่มีสีเทาของสถานะ "รอเคลียร์" เลย ทั้งที่แอปมี */
    --tbl-free:#FFFFFF;        /* available · ว่าง        app: bg-white */
    --tbl-free-line:#E5E5E7;   /*                        app: neutral-200 */
    /* --color-seated ในแอปคือค่าเดียวกับ --color-brand-600 เป๊ะ
       ชี้มาที่ --green ไปเลย จะได้ไม่มีวันหลุดจากกันอีก */
    --tbl-busy:var(--green);   /* occupied · มีลูกค้า     app: --color-seated */
    --tbl-warn:#F4C430;        /* warning · ใกล้หมดเวลา  app: bg-[#f4c430] */
    --tbl-over:#E8615C;        /* overtime · เกินเวลา    app: bg-[#e8615c] */
    --tbl-clean:#D2D2D6;       /* cleaning · รอเคลียร์   app: neutral-300 */
    --tbl-clean-ink:#3F3F46;   /*                        app: neutral-700 */
    /* พื้นเข้มสำหรับบล็อกที่กลับสี — ฟุตเตอร์ (1 ก.ย. 2569)
       #55AA0F ของ CI ใช้เป็นพื้นตรงๆ ไม่ได้ ตัวหนังสือขาวบนมันได้ 2.94
       ซึ่งตกเกณฑ์ 4.5 ไปครึ่งหนึ่ง · สองค่านี้เป็นขั้นในบันไดของแอป
       ขาวบนพื้นนี้ได้ 7.60 · เขียวอ่อนรองได้ 5.54 ซึ่งดีกว่าเทาบนพื้นเทาเดิม
       ที่ได้ 4.66 คือฟุตเตอร์อ่านง่ายขึ้นกว่าเดิม ไม่ใช่แลกความชัดกับสี */
    --green-deep:#276006;        /* brand-800 · ขาวบนพื้นนี้ 7.60 */
    --green-deep-soft:#C6E6AB;   /* brand-200 · 5.54 บน --green-deep */
    --green-deep-line:rgba(255,255,255,0.18);   /* pale fill behind green text — 6.08 with --green-text */
    --red:#D14C3D;         /* พื้น ไอคอน เส้น — 4.36 บนขาว ใช้เป็นตัวหนังสือไม่ผ่าน */
    --red-text:#BE3A2C;    /* แดงที่ใช้เป็นตัวหนังสือได้ทั้งบนขาวและบนเทา */
    --amber:#E3A83B;       /* พื้น ไอคอน เส้น — ไม่ใช่ตัวหนังสือ */
    --amber-text:#8A5300;  /* อำพันที่ใช้เป็นตัวหนังสือได้ — 4.96 บนขาว */
    --display:'Prompt', sans-serif;
    --body:'IBM Plex Sans Thai', sans-serif;
    /* ฟอนต์ตัวเลข — เดิมเป็น IBM Plex Mono เปลี่ยน 28 ส.ค. 2569
       เหตุผลสามข้อ วัดมาแล้วทั้งหมด ดูบันทึกใน DECISIONS.md
         1 Plex Mono ไม่มีตัว ฿ สัญลักษณ์บาทจึงตกไปใช้ฟอนต์เนื้อความ
           ราคาบนหน้าประกอบจากสองแบบอักษรโดยไม่มีใครตั้งใจ
         2 monospace ให้ลูกน้ำกินที่เต็มตัว ฿1,900 อ่านเป็น ฿1 , 900
         3 ศูนย์มีจุดของ Plex Mono มีไว้แยก 0 จาก O ในโค้ด
           หน้านี้ไม่มีปัญหานั้น จุดจึงรบกวนเปล่าๆ ที่ขนาดใหญ่
       ชื่อ token เปลี่ยนจาก --mono เป็น --num ด้วย เพราะ Bai Jamjuree
       ไม่ใช่ monospace การเรียกมันว่า mono จะหลอกคนอ่านโค้ดคนต่อไป */
    --num:'Bai Jamjuree', 'IBM Plex Sans Thai', sans-serif;

    /* ── สูตรลอย ─────────────────────────────────────────────────────────
       ถอดจาก idle.space (ดู design-system-reference.md A5.3) เว็บนั้นใช้
       สามอย่างนี้คู่กันเสมอ นับได้ 12/12/13 — เงาใหญ่นุ่มข้างล่าง
       แสงขาวเรืองข้างใน และเส้นขอบขาวครึ่งพิกเซลข้างบน วัตถุจึงดูเหมือน
       ถูกแสงส่องจากด้านบน นี่คือกลไกของความรู้สึกจับต้องได้ ไม่ใช่มุมโค้ง

       สีเงาเป็น rgba(10,10,10,…) ไม่ใช่ดำสนิท — ตามต้นฉบับ */
    --lift-1:0 10px 40px -10px rgba(10,10,10,0.15);   /* แผงทั่วไป */
    --lift-2:0 7px 30px -7px rgba(10,10,10,0.30);     /* ตอนชี้ · ของเด่น */
    --lift-glow:inset 0 0 12px rgba(255,255,255,0.5); /* แสงในขาว */
    --lift-edge:0.5px solid rgba(255,255,255,0.9);    /* เส้นขอบขาว */

    /* สเกลเดิม map มาที่สูตรใหม่ จึงไม่ต้องไล่แก้ 16 จุดที่อ้างมัน */
    --elevation-1:var(--lift-1);
    --elevation-2:var(--lift-1);
    --elevation-3:var(--lift-2);
    --elevation-4:var(--lift-2);
    --elevation-hover:var(--lift-2);   /* การ์ดตอนชี้ */
    --elevation-float:var(--lift-1);   /* แผงที่ลอยเหนือพื้น */
    --shadow-xs:0 1px 2px rgba(16,24,40,0.04);            /* เคยถูกอ้างโดยไม่เคยประกาศ */

    /* z-index scale — documented ranges; existing numeric z-indexes already
       fall inside these bands, kept as plain numbers to avoid a risky sweep */
    /* One ladder, lowest first. Add a rung rather than picking a number:
       a raw z-index in a rule is a guess about everything else on the page. */
    --z-raised:10;        /* lifted within its own section */
    --z-sticky-bar:40;    /* the CTA bar pinned to the bottom on phones */
    --z-sticky-nav:50;    /* the header */
    --z-overlay:100;      /* the dim behind a drawer */
    --z-drawer:110;       /* the drawer itself */
    --z-modal:200;        /* the registration wizard */
    --z-toast:300;
    --z-skip:400;         /* the bypass link, reachable over everything */

    /* ── Type scale ───────────────────────────────────────────────────────
       Ten steps, extracted from what the page actually sets rather than
       invented. The first version of this scale carried a 28 and a 44 that no
       rule used, and left out the 26 that twelve elements did — a scale that
       describes nothing is just a second opinion.

       Anything new picks a step. Two things sit outside on purpose:
       `h2` is fluid (see --text-display), and the fake POS screen uses 9-10px
       because it is a picture of an interface, not an interface. */
    /* ── Four sizes. That is the whole scale. ──────────────────────────────
       11px is for eyebrows and labels ONLY. Nothing that is read as a
       sentence goes below 16px.

       The ten old step names are kept as aliases so the 53 rules that
       reference them do not each have to be rewritten — every one of them now
       lands on one of the four. Reading a rule tells you which of the four it
       gets; the old name no longer promises its old number. */
    --text-label:11px;    /* eyebrow · chip · table header · meta */
    --text-body:16px;     /* everything read as a sentence, and every control */
    --text-head:26px;     /* card titles, sub-headings, figures */
    --text-display:48px;  /* section headings and the hero */

    --text-2xs:var(--text-label);
    --text-xs:var(--text-label);
    --text-sm:var(--text-body);
    --text-base:var(--text-body);
    --text-lg:var(--text-body);
    --text-xl:var(--text-head);
    --text-2xl:var(--text-head);
    --text-3xl:var(--text-display);
    --text-4xl:var(--text-display);
    --text-5xl:var(--text-display);

    /* Weights: four, and each one has a job. Thai text at 300 gets fragile
       below 16px, so Light is for large text only. */
    /* 300 ถูกถอดออกทั้งหมด — เคยใช้บนเมนูหลักกับรายการฟีเจอร์รวม 27 จุด
       ไทยน้ำหนักบางที่ 16px เส้นจะเรียวจนอ่านยาก และการเลิกใช้ทำให้ไม่ต้อง
       โหลดไฟล์ฟอนต์ไทยอีกชุด (~21KB จากทั้งหมด 188KB) */
    --w-regular:400;
    --w-medium:500;   /* labels, nav, buttons */
    --w-semibold:600; /* card and section headings */
    --w-bold:700;     /* display only */

    /* Display type tightens as it grows; body type never does. */
    /* ระยะตัวอักษร — เดิมมี 13 ค่าจาก 21 จุด แทบหนึ่งค่าต่อหนึ่งการใช้
       ค่าลบห้าตัว (-0.015 -0.02 -0.022 -0.025 -0.03) ทำงานเดียวกันคือ
       บีบตัวอักษรใหญ่ให้แน่นขึ้น ซึ่งตาแยกไม่ออกว่าต่างกัน */
    --track-tight:-0.022em;   /* หัวข้อและตัวเลขขนาดใหญ่ */
    --track-normal:0;
    --track-wide:0.14em;      /* ป้ายตัวพิมพ์ใหญ่ขนาดเล็ก */

    /* ความสูงบรรทัด — เดิมมี 12 ค่า โดยหกตัว (1.5 1.55 1.6 1.65 1.7 1.75)
       ทำงานเดียวกันคือเนื้อความที่ต้องอ่าน และสี่ตัว (1.14 1.16 1.2 1.25)
       ทำงานเดียวกันคือหัวข้อ */
    --lh-tight:1.15;   /* หัวข้อ 26px ขึ้นไป */
    --lh-body:1.55;    /* เนื้อความ — ค่าที่หน้าใช้อยู่แล้ว 419 จุด */
    --lh-loose:1.7;    /* หมายเหตุและตัวเล็ก */
    --track-display:var(--track-tight);  /* ชื่อเดิม */

    /* ── Spacing ──────────────────────────────────────────────────────────
       4px grid. Section rhythm is the last three. */
    /* ── ความกว้างเนื้อหา ────────────────────────────────────────────
       17 ค่าที่ไม่ซ้ำกันถูกใช้อยู่ (620–1500) ซึ่งทำให้ขอบซ้ายของแต่ละเซ็กชัน
       ไม่ตรงกันถึง 13 ตำแหน่งบนจอ 1440 — บางอันยื่นเลยขอบ บางอันหดเข้า
       ห้าขั้นนี้ตั้งชื่อตามหน้าที่ ไม่ใช่ตามตัวเลข */
    --w-wide:1180px;    /* เท่ากับ .wrap — เส้นขอบหลักของทั้งหน้า */
    --w-mid:960px;      /* ตาราง กริดแน่นๆ */
    --w-narrow:820px;   /* การ์ดราคา ใบเสร็จ ฟอร์ม */
    --w-text:660px;     /* ความยาวบรรทัดสำหรับอ่าน */
    --w-tight:480px;    /* ข้อความสั้นจัดกลาง */
    --space-0:2px;
    --space-1:4px;   --space-2:8px;   --space-3:12px;  --space-4:16px;
    --space-5:20px;  --space-6:24px;  --space-8:32px;  --space-10:40px;
    --space-12:48px; --space-16:64px; --space-20:80px; --space-25:100px;
    --space-36:144px;

    /* ── Radius ───────────────────────────────────────────────────────────
       Five steps. The page was using sixteen, including 11/12/13/14 and
       18/19/20, which no eye can tell apart but which stack up as noise when
       cards sit side by side. */
    /* ขยับขึ้นทั้งสเกลตามทิศ idle.space ซึ่งใช้ 24px เป็นค่าหลัก
       ค่าเดิม 8px ครองหน้าอยู่ 487 จุด ทำให้ทุกอย่างดูเหลี่ยมและแบน */
    --radius-sm:10px;   /* chips, tags, small controls */
    --radius-md:14px;   /* buttons, inputs */
    --radius-lg:20px;   /* cards */
    --radius-xl:24px;   /* panels, image frames */
    --radius-full:999px;

    /* ── Motion ───────────────────────────────────────────────────────────
       Entering eases out, leaving eases in, and leaving is quicker. */
    /* Durations, by how the interaction should feel rather than by a number
       someone picked at the time. 21 distinct values were in use. */
    --dur-fast:150ms;      /* a hover, a colour change */
    --dur-base:220ms;      /* the default for anything that moves */
    --dur-slow:320ms;      /* something with distance to travel */
    /* ตัวอักษรม้วนในปุ่ม — ค่าจาก iux-landing-v3 ตรงๆ ทั้งเวลาและเส้นโค้ง
       เส้นโค้งนี้ออกตัวช้าแล้วเบรกยาว ต่างจาก --ease-lift ที่พุ่งออกทันที
       ซึ่งเหมาะกับของที่เดินทางเป็นระลอกมากกว่า */
    --dur-roll:240ms;
    --stagger-roll:14ms;   /* หน่วงต่อหนึ่งตัวอักษร */
    --dur-slower:400ms;    /* a panel opening or closing */
    --dur-reveal:700ms;    /* scroll reveal */
    --dur-cover:900ms;     /* the cover fade, the longest thing on the page */
    /* กฎเดียวที่ถอดจาก idle.space: สีเปลี่ยนเร็ว การเคลื่อนที่ช้า
       เว็บนั้นแยกชัด transform 0.7s easeOutQuart · สี 0.15s
       --dur-fast 150ms ของเราตรงกับฝั่งสีอยู่แล้ว ขาดแต่ฝั่งการเคลื่อนที่ */
    --dur-lift:700ms;      /* การ์ดยกตอนชี้ */

    /* Curves are NOT collapsed to one. Each of these governs a specific
       interaction and the pairs are deliberate — a panel that opens on one
       curve and closes on another is a decision, not drift. Naming them makes
       that decision visible instead of leaving four bezier tuples in the file. */
    --ease-out:cubic-bezier(.2,.8,.2,1);
    --ease-in:cubic-bezier(.4,0,1,1);
    --ease-in-out:cubic-bezier(.65,0,.35,1);      /* drawer, segmented toggle */
    --ease-expand:cubic-bezier(0.33,1,0.68,1);    /* an accordion opening */
    --ease-collapse:cubic-bezier(0.7,0,0.84,0);   /* the same one closing */
    --ease-enter:cubic-bezier(.22,1,.36,1);       /* something arriving from off-screen */
    --ease-back:cubic-bezier(.34,1.56,.64,1);     /* overshoots past its mark, then settles */
    --ease-lift:cubic-bezier(.25,1,.5,1);         /* easeOutQuart — คู่กับ --dur-lift */
    --ease-roll:cubic-bezier(.5,0,.2,1);          /* คู่กับ --dur-roll */
  

  }
  *{box-sizing:border-box; margin:0; padding:0;}
  body{
    background:var(--white); color:var(--ink); font-family:var(--body);
    font-weight:var(--w-regular); line-height:var(--lh-body); -webkit-font-smoothing:antialiased;
  }
  a{color:inherit; text-decoration:none; -webkit-tap-highlight-color:transparent;}
  img,svg{display:block; max-width:100%;}
  ul,ol{list-style:none;}
  button,input,select,textarea{font:inherit; color:inherit; background:none; border:none; appearance:none; -webkit-appearance:none;}
  button{cursor:pointer;}
  button:disabled{cursor:not-allowed;}

  /* custom focus ring — replaces the browser's default outline everywhere,
     but only shows for keyboard navigation (not on mouse click) */
  :focus{ outline:none; }
  /* กรอบโฟกัสคือ UI ที่ต้องเห็นบนพื้นขาว ต้องได้ 3:1 (WCAG 2.4.11)
     สีแบรนด์ใหม่ได้ 2.94 จึงใช้ไม่ได้ ต้องใช้ --green-ui ที่ 3.40 */
  :focus-visible{ outline:2px solid var(--green-ui); outline-offset:2px; border-radius:var(--radius-sm); }

  /* custom scrollbar (webkit + firefox) */
  *{ scrollbar-width:thin; scrollbar-color:rgba(0,0,0,0.25) transparent; }
  *::-webkit-scrollbar{ width:10px; height:10px; }
  *::-webkit-scrollbar-track{ background:transparent; }
  *::-webkit-scrollbar-thumb{
    background:rgba(0,0,0,0.25); border-radius:var(--radius-full);
    border:2px solid transparent; background-clip:content-box;
  }
  *::-webkit-scrollbar-thumb:hover{ background:rgba(0,0,0,0.4); }

  /* custom text selection */
  ::selection{ background:var(--green); color:var(--white); }

  /* ทางที่ไม่ผ่าน Lenis (เปิดลิงก์ #… ตรงๆ หรือกดปุ่มย้อนกลับ) เบราว์เซอร์
     เลื่อนเอง จึงต้องบอกมันว่าเหนือหัวข้อมีแถบลอยกินที่อยู่เท่าไร */
  section[id], main[id], div[id]{ scroll-margin-top:var(--space-20); }

  .wrap{max-width:var(--w-wide); margin:0 auto; padding:0 var(--space-6);}
  .wrap-narrow{max-width:var(--w-narrow); margin:0 auto; padding:0 var(--space-6);}

  /* ---------- nav ---------- */
  /* ── แถบเมนูลอย ──────────────────────────────────────────────────────────
     เดิมเป็นแถบเต็มจอติดขอบบน มีเส้นคั่นข้างล่าง ซึ่งเป็นทรงของเว็บทั่วไป
     ทิศที่เจ้าของเลือก (idle.space) วางแถบเป็นแผ่นลอยที่เว้นจากขอบทุกด้าน
     ใช้สูตรลอยชุดเดียวกับการ์ดในระลอก 1 กระจกฝ้ามีอยู่แล้ว เหลือทำให้ลอย

     margin-top เท่ากับ top พอดี — sticky กินที่ในสายธรรมดาตอนยังไม่เลื่อน
     ถ้าใส่แต่ top แถบจะติดขอบตอนอยู่บนสุดแล้วกระโดดลง 16px ตอนเริ่มเลื่อน

     เส้นคั่นล่างถอดออก เพราะแผ่นลอยแยกตัวด้วยเงา ไม่ใช่ด้วยเส้น
     เส้นขอบขาวที่ใส่แทนคือแสงสะท้อนด้านบน ไม่ได้ทำหน้าที่แบ่งเขต

     ความกว้างสูงสุดเท่า .wrap และ padding ของ nav เท่า padding ของ .wrap
     ที่จอตั้งแต่ 1212px ขึ้นไปโลโก้จึงตรงกับขอบเนื้อหาพอดี ต่ำกว่านั้น
     แถบเว้นเข้ามา 16px ตามระยะขอบของมันเอง */
  header{
    position:sticky; top:var(--space-4); z-index:var(--z-sticky-nav);
    width:calc(100% - var(--space-8)); max-width:var(--w-wide);
    margin:var(--space-4) auto 0;
    border-radius:var(--radius-xl);
    /* ความทึบ 0.8 -> 0.65 (28 ส.ค. 2569) พร้อมเพิ่ม blur 14 -> 20
       เพราะพอพื้นจางลง ถ้า blur เท่าเดิมมันจะอ่านเป็น "สีขาวจางๆ"
       ไม่ใช่กระจก การเบลอแรงขึ้นยังช่วยให้อ่านง่ายขึ้นด้วย เพราะมันกลบ
       รายละเอียดถี่ๆ ของรูปที่เลื่อนผ่านข้างหลัง

       0.65 ไม่ได้เดา — ของที่เลื่อนผ่านใต้แถบเข้มที่สุดคือรูปห้องอาหาร
       (img-09 สว่าง 0.071 และมีพิกเซลดำสนิท) คำนวณกรณีแย่ที่สุดคือดำสนิท
       ได้คอนทราสต์ 5.96 กับตัวหนังสือเมนู เพดานจริงอยู่ที่ 0.57
       ซึ่งได้ 4.64 ต่ำกว่านั้นตกเกณฑ์ 4.5 — เหลือระยะไว้เผื่อรูปที่จะ
       เปลี่ยนทีหลัง อย่าลดต่ำกว่า 0.60 โดยไม่วัดใหม่ */
    background:rgba(255,255,255,0.65); backdrop-filter:saturate(180%) blur(20px);
    border:var(--lift-edge);
    box-shadow:var(--lift-1), var(--lift-glow);
  }
  nav{ display:flex; align-items:center; justify-content:space-between; padding:var(--space-3) var(--space-6); }
  /* ── โลโก้ ──────────────────────────────────────────────────────────────
     เดิมเป็นสี่เหลี่ยมเขียว + ตัวอักษร "NubTang POS" ที่เป็น placeholder
     รอไฟล์จริง ตอนนี้เจ้าของส่งไฟล์มาแล้ว (30 ส.ค. 2569) จึงใช้ของจริง

     คุมด้วย "ความสูง" ไม่ใช่ความกว้าง เพราะโลโก้ต้องสูงเท่ากันกับของอื่น
     ในแถวเดียวกันเสมอ ส่วนความกว้างปล่อยให้เป็นไปตามสัดส่วน 3360:1028
     width:auto จำเป็น ไม่งั้น width/height ใน HTML จะบังคับให้กว้าง 3360 */
  .logo{ display:flex; align-items:center; }
  .logo img{ height:34px; width:auto; display:block; }
  .navlinks{ display:flex; gap:var(--space-6); font-size:var(--text-base); font-weight:var(--w-regular); color:var(--ink); align-items:center; }
  .navlinks a{ transition:color var(--dur-fast); padding-bottom:var(--space-0); }
  .navlinks a:hover{ color:var(--ink); }
  .navlinks a.nav-active{ font-weight:var(--w-medium); border-bottom:1.5px solid var(--ink); }
  .nav-lang{ display:flex; align-items:center; gap:var(--space-1); font-size:var(--text-base); color:var(--ink); margin-right:var(--space-0); }
  .nav-lang svg{ width:16px; height:16px; }
  .navcta{ display:flex; align-items:center; gap:var(--space-3); }
  .navcta .btn{ border-radius:var(--radius-md); padding:var(--space-2) var(--space-4); font-weight:var(--w-medium); font-size:var(--text-base); }
  .navcta .btn-outline{ border-color:var(--ink); color:var(--ink); }
  .navcta .btn-dark{ background:var(--ink); }
  .btn{
    font-family:var(--body); font-weight:var(--w-medium); font-size:var(--text-sm); padding:var(--space-2) var(--space-4);
    border-radius:var(--radius-md); border:1px solid transparent; cursor:pointer; display:inline-block;
    transition:opacity var(--dur-fast), transform var(--dur-fast), background var(--dur-fast);
  }
  .btn:active{ transform:scale(0.97); }
  .btn-dark{ background:var(--ink); color:var(--white); }
  .btn-dark:hover{ opacity:0.82; }
  .btn-outline{ border-color:var(--line-strong); color:var(--ink); }
  .btn-outline:hover{ background:rgba(0,0,0,0.04); }
  /* ปุ่มเขียวคือการกระทำหลักของหน้า หนากว่าปุ่มอื่นทุกที่ที่มันปรากฏ
     เดิมน้ำหนัก 600 ผูกอยู่กับ .hero-actions อย่างเดียว ปุ่มเดียวกันที่แถบ
     ปิดท้ายจึงบางกว่า ทั้งที่ชวนทำสิ่งเดียวกัน */
  /* ── ปุ่มหลัก เขียว ตัวหนังสือขาว ไม่มีขอบ ────────────────────────────
     ตัวหนังสือขาวบังคับว่าพื้นต้องเข้มกว่า CI base #3F9B0B ซึ่งขาวบนมัน
     ได้แค่ 3.56 · brand-700 #327D08 คือขั้นถัดไปในบันไดของแอป ได้ 5.16

     ไม่ต้องมีขอบ — brand-700 เทียบพื้นขาวได้ 5.16 ซึ่งเกิน 3 ที่ WCAG 1.4.11
     ขอสำหรับขอบเขตของส่วนควบคุมอยู่แล้ว ตัวพื้นทำหน้าที่นั้นเองได้ */
  .btn-green{ background:var(--green-strong); color:var(--white); font-weight:var(--w-semibold); }
  .btn-green:hover, .btn-green:focus-visible{ background:var(--green-dark); }
  .btn-lg{ padding:var(--space-4) var(--space-8); font-size:var(--text-base); border-radius:var(--radius-lg); }

  /* ปุ่มบนพื้นเขียวเข้ม — ฟุตเตอร์ (1 ก.ย. 2569)
     พื้นขาวเต็มแทนที่จะเป็นขอบโปร่ง เพราะบนพื้นเข้มขอบบางอ่านเป็นปุ่มยาก
     ขาวบน --green-deep ได้ 7.94 (ต้อง 3 สำหรับสิ่งที่ไม่ใช่ตัวอักษร)
     --green-text บนขาวได้ 6.35 (ต้อง 4.5) */
  .btn-on-deep{ background:var(--white); color:var(--green-text); font-weight:var(--w-semibold); }
  .btn-on-deep:hover, .btn-on-deep:focus-visible{ background:var(--green-tint); }

  /* ── ตัวอักษรม้วนขึ้นตอนชี้ ทีละตัว ────────────────────────────────────
     ถอดกลไกจาก iux-landing-v3.vercel.app ตามที่เจ้าของชี้ให้ดู (1 ก.ย. 2569)
     ต้นฉบับใช้ .cascade-char ครอบทีละตัวอักษร ข้างในมีสำเนาสองชั้น
     ชั้นล่างวางที่ top:100% แล้วทั้งคู่เลื่อนขึ้น 100% พร้อมกัน
     ตัวถัดไปหน่วงทีละ 14ms ตัวอักษรจึงไล่กันขึ้นเป็นระลอก

     ที่ต้องต่างจากต้นฉบับเพราะเป็นภาษาไทย
     1 ต้นฉบับตัดทีละตัวอักษรได้เพราะเป็นอังกฤษ ภาษาไทยตัดแบบนั้นไม่ได้
       สระกับวรรณยุกต์จะหลุดจากพยัญชนะที่มันเกาะอยู่ ต้องตัดเป็น
       grapheme cluster ดูสคริปต์ท้าย index.html
     2 ต้นฉบับตั้งความสูงกล่อง 20px ทั้งที่ line-height 21px คือยอมให้ตัด
       นิดหน่อย ภาษาอังกฤษไม่มีอะไรอยู่เหนือตัวพิมพ์ใหญ่จึงไม่มีใครเห็น
       ของเราตั้ง 1.7 ตามที่วัดมาแล้วว่าไม้โทบน "นี้" ต้องการเท่านี้ */
  .btn-roll{ display:inline-flex; white-space:nowrap; }
  .btn-char{
    display:flex; position:relative; overflow:hidden;
    line-height:1.7; white-space:pre;   /* pre เพื่อให้ช่องว่างไม่ยุบหาย */
  }
  .btn-char > span{
    display:block;
    transition:transform var(--dur-roll) var(--ease-roll);
  }
  .btn-char > .dup{ position:absolute; top:100%; left:0; }
  .btn:hover .btn-char > span,
  .btn:focus-visible .btn-char > span{ transform:translateY(-100%); }
  .hero{ padding:var(--space-20) 0 0; text-align:center; }
  /* ---------------------------------------------------------------------
     Kitchen-ticket identity
     ---------------------------------------------------------------------
     The page used to look like any SaaS: centred headings, a success-green,
     nothing that said "restaurant". The motif now comes from the thing every
     one of these shops already handles a hundred times a night — the printed
     kitchen ticket. A separate face for anything a machine would print (labels,
     numbers, table codes), section numbers running down the page like line
     items, and a perforated edge where the page changes register.
     Light mode only, by design. */
  /* ฟอนต์ตัวเลขคือ Bai Jamjuree ซึ่งมีทั้งไทยและ ฿ ครบ ป้ายกับตัวเลขจึงเป็น
     แบบอักษรเดียวกันทั้งบรรทัด ไม่ต้องพึ่งการตกไปหาฟอนต์สำรองเหมือนตอนใช้
     Plex Mono ที่วาดไทยและ ฿ ไม่ได้ */
  .eyebrow{
    /* The label itself is Thai, which IBM Plex Mono cannot draw. It is set in
       the text face on purpose; the section number in ::after is the mono part. */
    font-family:var(--body); font-size:var(--text-xs); font-weight:var(--w-medium);
    letter-spacing:var(--track-wide); text-transform:uppercase;
    color:var(--gray600); margin-bottom:var(--space-3);
    display:inline-flex; align-items:center; gap:var(--space-2);
  }
  /* จุดสี่เหลี่ยมเขียวหน้าป้ายถูกถอดออก 28 ส.ค. 2569 ตามที่เจ้าของสั่ง
     พร้อมกับเปลี่ยนสีตัวอักษรจากเขียวเป็นเทาเข้ม

     ป้ายนี้เป็นข้อมูลกำกับ ไม่ใช่สิ่งที่ต้องแย่งสายตากับหัวข้อที่อยู่ใต้มัน
     พอถอดทั้งจุดและสีเขียวออก มันถอยไปเป็นชั้นรองอย่างที่ควรเป็น และ
     สีเขียวเหลือไว้ทำหน้าที่เดียวคือบอกว่ากดได้ ซึ่งเป็นงานที่มันควรทำ

     --gray600 ไม่ใช่การเดา วัดแล้วบนพื้นทั้งสองแบบที่ป้ายนี้วางอยู่จริง
     ขาว 5.07 · เทาอ่อน #F5F5F7 4.66 ผ่านเกณฑ์ 4.5 ทั้งคู่
     ป้ายนี้ 11px จึงต้องใช้เกณฑ์ตัวอักษรปกติ ไม่ใช่เกณฑ์ตัวใหญ่ */

  /* Section number, printed like a ticket line item. Set per section with
     `style="--n:'03'"` so the markup stays declarative. */
  .eyebrow[data-n]::after,
  .tag[data-n]::after{
    font-family:var(--num); font-size:var(--text-xs); letter-spacing:var(--track-wide);
    color:var(--gray600); opacity:0.6;
  }
  .eyebrow[data-n]::after,
  .tag[data-n]::after{ content:'/ ' attr(data-n); }

  /* Perforated edge — the tear line on a printed ticket. The scallops are
     painted in the colour of the section on the OTHER side, so the band looks
     torn away from its neighbour rather than merely bordered. */
  .perf-top, .perf-bottom{ position:relative; }
  .perf-top::before, .perf-bottom::after{
    content:''; position:absolute; left:0; right:0; height:11px;
    background-size:14px 14px; background-repeat:repeat-x;
    pointer-events:none; z-index:2;
  }
  .perf-top::before{
    top:-1px;
    background-image:radial-gradient(circle at 7px 0, var(--perf-color, var(--white)) 6px, transparent 6.5px);
  }
  .perf-bottom::after{
    bottom:-1px;
    background-image:radial-gradient(circle at 7px 11px, var(--perf-color-b, var(--grayBg)) 6px, transparent 6.5px);
  }

  /* ---------- soft band ----------
     The "protect your money" chapter — shift close, cash count, audit trail —
     plus the comparison table and the closing CTA. These four used to run on
     ink. They are light now, and the page reads as one continuous document
     rather than a light one with dark chapters cut into it.

     Separation comes from a tint and a hairline instead of from inverting,
     which is a quieter device and survives being printed or screenshotted. */
  /* สองกลไกให้สีพื้นเทาเหมือนกัน แต่คนละหน้าที่ — เลือกจากสิ่งที่ต้องการ ไม่ใช่จากสี
       · section.alt — เปลี่ยนสีพื้นอย่างเดียว และใช้ได้กับ <section> เท่านั้น
                       (ตัวเลือกคือ section.alt) นี่คือตัวปกติ
       · .band-soft  — พ่วงมาสามอย่าง: สีพื้น · ปรับสีตัวอักษรข้างใน (ย่อหน้าเป็น
                       --gray600) · และตัวแปร --perf-color ที่บอกรอยปรุว่าทาสีอะไร
                       ใช้ได้กับ element ใดก็ได้ ตอนนี้อยู่บนบทเงินสองอันที่มี
                       รอยฉีกคร่อม และบนแถบ CTA ปิดท้ายซึ่งใช้เพราะการปรับตัวอักษร
     .is-white กลับสีเป็นขาว พร้อมสลับสีรอยปรุให้เป็นเทาตาม */
  .band-soft{
    background:var(--grayBg); color:var(--ink);
    --perf-color:var(--white); --perf-color-b:var(--white);
  }
  .band-soft.is-white{ background:var(--white); --perf-color:var(--grayBg); --perf-color-b:var(--grayBg); }
  .band-soft h2, .band-soft h3, .band-soft strong{ color:var(--ink); }
  .band-soft p, .band-soft .s-head p{ color:var(--gray600); }
  .band-soft .eyebrow{ color:var(--gray600); }   /* ตามกฎหลัก — วัดแล้ว 4.66/5.07 */
  .band-soft .eyebrow[data-n]::after{ color:var(--gray600); opacity:1; }
  .band-soft .mf-pts li{ color:var(--ink); }
  .band-soft .mf-pts li svg{ color:var(--green-ui); }
  .band-soft .mf-imgslot{
    background:var(--white); border-color:var(--line);
  }
  .band-soft .mf-imgslot-hint{ color:var(--gray600); }

  /* ---------- 06 · the slip ----------
     Every other feature section on this page put text on one side and a picture
     on the other. That reads as a template by the third repeat, and it tells
     the reader nothing. Here the layout IS the feature: closing a shift ends
     with a printed slip, so the section centres on one. */
  /* สองคอลัมน์ แบบเดียวกับ #featured-menu และ #membership
     เดิมเรียงลงมาและจัดกึ่งกลาง ทำให้ section เดียวมีขอบซ้ายสี่ค่า
     (หัวข้อ 310 · ใบเสร็จ 460 · บรรทัดคำอธิบาย 230 · กล่องวันทำการ 230)
     ทั้งที่ขอบของหน้าคือ 74 — ตอนนี้ทุกชิ้นเริ่มที่ 74 เหมือนกันหมด
     คอลัมน์ซ้ายกว้างเท่าความยาวบรรทัดที่อ่านสบาย ใบเสร็จอยู่ข้างข้อความที่อธิบายมัน */
  .slip-layout{
    display:grid;
    grid-template-columns:minmax(0, var(--w-text)) 1fr;
    column-gap:var(--space-12); row-gap:var(--space-10);
    align-items:start;
  }
  .slip-lead{ grid-column:1; grid-row:1; text-align:left; max-width:none; margin-bottom:0; }

  .slip{
    grid-column:2; grid-row:1 / span 2; justify-self:end;
    width:min(360px, 100%); background:#FBFAF7; color:var(--ink);
    padding:var(--space-6) var(--space-6) var(--space-5); position:relative;
    font-family:var(--num);
    box-shadow:var(--elevation-3); border:1px solid var(--line);
    border-radius:var(--radius-md);
  }
  .slip-head{ text-align:center; padding:var(--space-2) 0 var(--space-4); border-bottom:1px dashed rgba(0,0,0,0.28); }
  .slip-brand{ display:block; font-family:var(--display); font-weight:var(--w-semibold); font-size:var(--text-lg); letter-spacing:0.04em; }
  .slip-kind{ display:block; font-size:var(--text-xs); letter-spacing:0.18em; margin-top:var(--space-1); color:var(--gray600); }
  .slip-meta{ display:block; font-size:var(--text-2xs); margin-top:var(--space-2); color:var(--gray600); }

  .slip-rows{ padding:var(--space-3) 0; font-size:var(--text-sm); }
  .slip-rows > div{ display:flex; justify-content:space-between; gap:var(--space-3); padding:3.var(--space-1) 0; }
  .slip-rows dt{ color:var(--gray600); }
  .slip-rows dd{ font-variant-numeric:tabular-nums; }
  .slip-rows-total{ border-top:1px dashed rgba(0,0,0,0.28); font-weight:var(--w-semibold); }

  .slip-diff{
    display:flex; justify-content:space-between; align-items:baseline;
    border-top:2px solid var(--ink); border-bottom:2px solid var(--ink);
    padding:var(--space-3) 0; font-weight:var(--w-semibold); font-size:var(--text-sm);
  }
  .slip-diff-num{ font-size:var(--text-xl); letter-spacing:-0.02em; color:#B4471B; font-variant-numeric:tabular-nums; }
  .slip-flag{
    display:flex; align-items:flex-start; gap:var(--space-2); margin-top:var(--space-3);
    font-size:var(--text-xs); line-height:var(--lh-body); color:#B4471B;
  }
  .slip-flag svg{ margin-top:var(--space-0); }

  /* the four supporting points sit under the slip as a keyed list, not as
     another bullet column beside a picture */
  .slip-pts{
    grid-column:1; grid-row:2;
    display:grid; grid-template-columns:1fr;
    gap:var(--space-4); margin-top:0; max-width:none; width:100%;
  }
  .slip-pts li{
    display:flex; gap:var(--space-3); align-items:baseline;
    /* This section used to be a dark band, where white at 0.9 read as the
       dimmed state. It is .band-soft now, and white on #F5F5F7 scores 1.08 —
       four of these lines were invisible on the page. Dimming on a light
       ground has to come down towards the ink, not up towards the paper. */
    font-size:var(--text-base); line-height:var(--lh-body); color:var(--gray600);
  }
  .slip-pt-k{
    /* ป้ายและเนื้อความในบรรทัดเดียวกันใช้ขนาดเดียวกัน ต่างกันที่สีอย่างเดียว
       ทั้งสี่บรรทัดจึงอ่านเป็นรายการเดียว ไม่ใช่หัวข้อย่อยกับคำอธิบาย
       ป้ายเป็นภาษาไทยซึ่ง IBM Plex Mono วาดไม่ได้ จึงตั้งเป็นฟอนต์เนื้อความตรงๆ
       และเลิก uppercase เพราะไม่มีผลกับอักษรไทย */
    flex-shrink:0; width:96px; font-family:var(--body);
    font-size:var(--text-base); letter-spacing:var(--track-normal);
    color:var(--gray600); padding-top:0;
  }

  /* ---------- 07 · the log ----------
     เดิมเป็นรายการเปล่าเต็มความกว้าง มีแต่เส้นขนหนู อ่านเป็นเนื้อหาบนหน้าเว็บ
     ไม่ใช่ภาพหน้าจอของผลิตภัณฑ์ เจ้าของขอให้ดูเป็น mockup มากกว่านี้

     โครงทั้งหมดถอดมาจาก src/pages/activity/ActivityPage.tsx ของโปรเจกต์ POS
     ไม่ได้ออกแบบขึ้นใหม่ — แถบหัวเรื่องพร้อมคำบรรยาย แท็บสองอัน กล่องขาว
     มีขอบและมุมโค้ง หัวตารางห้าคอลัมน์ จุดสีบอกประเภท และเหตุผลที่ขึ้น
     บรรทัดที่สองใต้รายละเอียด */
  .log-lead{ max-width:var(--w-text); margin-bottom:var(--space-10); }

  /* กล่องที่ทำให้มันอ่านเป็น "หน้าจอ" ไม่ใช่ "รายการบนหน้าเว็บ"
     ใช้สูตรเดียวกับแผงอื่นในหน้า จะได้ไม่เป็นของนอกชุด */
  /* ── container query ────────────────────────────────────────────────────
     แผงนี้กว้าง 1132px บนคอมแต่ 343px บนมือถือ การยุบคอลัมน์จึงควรขึ้นกับ
     ความกว้างของ "แผง" ไม่ใช่ของ "หน้าต่าง" — ถ้าวันหนึ่งเอาแผงนี้ไปวางใน
     คอลัมน์แคบบนจอคอม media query จะยังคิดว่าเป็นจอกว้างแล้วอัดห้าคอลัมน์
     ลงในที่ที่ไม่พอ

     เขียนแบบ mobile-first ตั้งใจ — ค่าตั้งต้นคือแบบแคบ แล้วค่อยขยายด้วย
     min-width เบราว์เซอร์ที่ไม่รองรับ container query จะข้ามบล็อก @container
     ไปทั้งก้อน แล้วได้แบบแคบซึ่งอ่านได้ทุกความกว้าง ไม่ต้องมี @supports */
  .logscreen{
    background:var(--white); border:1px solid var(--line);
    border-radius:var(--radius-xl); overflow:hidden;
    box-shadow:var(--lift-1), var(--lift-glow);
    container-type:inline-size; container-name:logscreen;
  }
  .logscreen-bar{
    display:flex; align-items:center; justify-content:space-between; gap:var(--space-4);
    flex-wrap:wrap; padding:var(--space-4); border-bottom:1px solid var(--line);
  }
  .logscreen-title strong{
    display:block; font-family:var(--display); font-weight:var(--w-semibold);
    font-size:var(--text-base); color:var(--ink);
  }
  .logscreen-title span{ display:block; font-size:var(--text-sm); color:var(--gray600); }

  /* แท็บสองอันนี้มีจริงในหน้าจอ (รายการสำคัญ / ทั้งหมด) แต่บนเว็บกดไม่ได้
     จึงเป็น span ไม่ใช่ button — ไม่อยู่ในลำดับ Tab ไม่มี role
     screen reader จะอ่านเป็นข้อความธรรมดา ซึ่งตรงกับสิ่งที่มันเป็นจริง */
  .logscreen-seg{
    display:inline-flex; gap:var(--space-1); padding:var(--space-1);
    background:var(--grayBg); border:1px solid var(--line); border-radius:var(--radius-md);
  }
  .logscreen-seg span{
    padding:var(--space-2) var(--space-4); border-radius:var(--radius-sm);
    font-size:var(--text-sm); color:var(--gray600);
  }
  .logscreen-seg .is-on{
    background:var(--ink); color:var(--white); font-weight:var(--w-medium);
  }

  .log{ font-size:var(--text-sm); }

  /* ค่าตั้งต้น = แผงแคบ · เวลาอยู่ซ้ายกินสี่บรรทัด ที่เหลือเรียงลงมา */
  .log-row{
    display:grid; grid-template-columns:52px 1fr;
    gap:var(--space-1) var(--space-3); align-items:baseline;
    padding:var(--space-4) var(--space-4) var(--space-4) var(--space-3);
    position:relative; border-bottom:1px solid var(--line);
  }
  .log-row:last-child{ border-bottom:0; }
  .log-row time{ grid-row:span 4; }
  .log-head{ display:none; }          /* ไม่มีคอลัมน์ให้กำกับตอนแคบ */
  .log-amt:empty{ display:none; }     /* ไม่งั้นเหลือช่องว่างลอย */

  /* แผงกว้างพอค่อยกางเป็นห้าคอลัมน์ตามหน้าจอจริง
     590px คือความกว้างที่ห้าคอลัมน์ต้องการ (64+132+150+92 + gap 4x16) บวกที่ให้
     คอลัมน์รายละเอียดหายใจ ตั้ง 640 เผื่อไว้ */
  @container logscreen (min-width: 640px){
    .log-row{
      grid-template-columns:64px 132px 150px 1fr 92px;
      gap:var(--space-4); padding:var(--space-3) var(--space-5);
    }
    .log-row time{ grid-row:auto; }
    .log-head{
      display:grid; background:var(--grayBg); color:var(--gray600);
      font-weight:var(--w-medium); padding-top:var(--space-2); padding-bottom:var(--space-2);
    }
    .log-head > span:last-child{ text-align:right; }
    .log-amt{ text-align:right; }
    .logscreen-bar{ padding:var(--space-5); }
  }

  .log-row time{
    font-family:var(--num); font-size:var(--text-sm);
    color:var(--gray600); font-variant-numeric:tabular-nums;
  }
  .log-who{ color:var(--gray600); }

  /* ประเภท พร้อมจุดสี — สีมาจาก dotTone() ในโค้ด POS
     ยกเลิกบิลแดง · เงินเข้าออกและยกเลิกรายการเหลือง · เปิดปิดกะฟ้า · ที่เหลือเทา */
  .log-kind{ color:var(--gray600); display:flex; align-items:baseline; gap:var(--space-2); }
  .log-kind .dot{
    width:8px; height:8px; border-radius:var(--radius-full);
    background:var(--gray300); flex-shrink:0; align-self:center;
  }
  .log-kind .dot-red{ background:var(--red); }
  .log-kind .dot-amber{ background:var(--amber); }
  .log-kind .dot-sky{ background:#0284C7; }

  .log-what{ color:var(--ink); }
  /* เหตุผลอยู่บรรทัดที่สองใต้รายละเอียด เหมือนหน้าจอจริง
     ไม่เอียง ถึงจะเป็น <em> — ตัวไทยเอียงคือการเอียงด้วยเครื่อง ไม่ใช่แบบอักษรจริง */
  .log-what em{
    display:block; margin-top:var(--space-1); font-style:normal;
    font-size:var(--text-sm); color:var(--gray600);
  }
  .log-amt{
    font-family:var(--num); font-variant-numeric:tabular-nums; color:var(--ink);
  }

  /* แถบเหลืองซ้ายมือ = รายการที่เจ้าของควรเปิดดู ตรงกับ IMPORTANT_KINDS
     ในระบบจริง ซึ่งเป็นเกณฑ์เดียวกับที่แท็บ "รายการสำคัญ" ใช้กรอง */
  .log-flag::before{
    content:''; position:absolute; left:0; top:10px; bottom:10px; width:3px;
    border-radius:var(--radius-sm); background:var(--amber);
  }
  .log-flag .log-what{ font-weight:var(--w-medium); }

  .log-note{
    display:flex; align-items:center; gap:var(--space-2); margin-top:var(--space-5);
    font-size:var(--text-sm); color:rgba(255,255,255,0.5);
  }
  .log-dot{ width:3px; height:15px; border-radius:var(--radius-sm); background:var(--amber); flex-shrink:0; }

  @media (max-width:860px){
    /* จอแคบ: ยุบเป็นคอลัมน์เดียว ใบเสร็จลงมาอยู่ใต้หัวข้อตามลำดับที่อ่าน */
    .slip-layout{ grid-template-columns:1fr; row-gap:var(--space-8); }
    .slip-lead, .slip, .slip-pts{ grid-column:1; grid-row:auto; }
    .slip-pts{ gap:var(--space-3); }
    .slip-pt-k{ width:88px; }
    /* กฎของ .logscreen ย้ายไปเป็น container query แล้ว — มันขึ้นกับความกว้าง
       ของแผง ไม่ใช่ของหน้าต่าง */
  }


  /* ---------- 05 · the floor ----------
     Table chips carry the four states and the timer the real screen shows, so
     the reader recognises their own floor rather than a stock illustration. */
  .floor-lead{ max-width:var(--w-text); }
  .floor{ display:grid; grid-template-columns:1fr 300px; gap:var(--space-8); align-items:start; }
  .floor-grid{
    display:grid; grid-template-columns:repeat(4, 1fr); gap:var(--space-2);
    padding:var(--space-5); border-radius:var(--radius-lg); background:var(--grayBg);
    border:1px solid var(--line);
  }
  .tbl{
    display:flex; flex-direction:column; justify-content:center; gap:var(--space-1);
    min-height:74px; padding:var(--space-2) var(--space-3); border-radius:var(--radius-md);
    font-family:var(--num); font-size:var(--text-sm); font-weight:var(--w-semibold);
    background:var(--white); border:1px solid var(--line); color:var(--ink);
  }
  .tbl em{ font-style:normal; font-size:var(--text-xs); font-weight:var(--w-regular); }
  /* ── ไทล์โต๊ะ ใช้สีเดียวกับแอปจริง ──────────────────────────────────────
     พื้นยกมาตรงๆ ทุกสี · ตัวหนังสือเป็นสีหมึกทุกไทล์ ซึ่งต่างจากแอป
     ที่ใช้ตัวขาวบนเขียวกับแดง เหตุผล — แอปเขียนป้ายโต๊ะที่ 24px น้ำหนัก 800
     ซึ่งเข้าเกณฑ์ตัวใหญ่ที่ WCAG ผ่อนให้เหลือ 3:1 ตัวขาวบนเขียวได้ 3.56
     บนแดงได้ 3.34 จึงผ่านในแอป
     ไทล์จำลองในหน้านี้เล็กกว่ามาก ป้ายอยู่ที่ 14px จึงต้องใช้เกณฑ์ 4.5
     ตัวขาวตกทั้งสองสี ส่วนหมึกได้ 4.53 กับ 4.83 ผ่านทั้งคู่ */
  .tbl.is-free{ background:var(--tbl-free); border-color:var(--tbl-free-line); color:var(--ink); }
  .tbl.is-busy{ background:var(--tbl-busy); border-color:var(--tbl-busy); }
  .tbl.is-warn{ background:var(--tbl-warn); border-color:var(--tbl-warn); }
  .tbl.is-over{ background:var(--tbl-over); border-color:var(--tbl-over); }
  .tbl.is-clean{ background:var(--tbl-clean); border-color:var(--tbl-clean); color:var(--tbl-clean-ink); }

  /* โต๊ะที่กดเรียกพนักงาน และโต๊ะที่ถูกรวม — แอปไม่มีสีเฉพาะให้ทั้งสองอย่าง
     โต๊ะที่ถูกรวมนับเป็น occupied ตรงๆ (SellingPage.tsx:95-97)
     ส่วนสายเรียกไปโผล่ในรายการแจ้งเตือน ไม่ได้ย้อมไทล์
     ทั้งคู่จึงเป็นสีเดียวกับ "มีลูกค้า" ตามของจริง */
  .tbl.is-call, .tbl.is-merged{ background:var(--tbl-busy); border-color:var(--tbl-busy); }

  /* ตัวเวลาจางได้เฉพาะบนพื้นสว่างที่มีที่เหลือพอ
     บนเขียว แดง และเทา หมึกเต็มสีได้ 4.73 / 5.05 / 6.93 ซึ่งเฉียดอยู่แล้ว
     จางลงอีกตกทันที (วัดที่ opacity 0.7 ได้ 3.10 · 3.14 · 3.51)
     เขียนเป็นรายการที่ "จางได้" แทนรายการที่ "ห้ามจาง" เพราะถ้ามีสถานะใหม่
     เพิ่มมาแล้วลืมแก้ ค่าตั้งต้นจะเป็นแบบที่ปลอดภัย ไม่ใช่แบบที่ตก */
  .tbl.is-free em, .tbl.is-warn em{ opacity:0.7; }
  .tbl-wide{ grid-column:span 2; }
  /* เดิมเป็นตัวขาวจางเพราะไทล์รวมโต๊ะเคยเป็นพื้นสีหมึก ตอนนี้เป็นพื้นเขียว
     ตามแอปจริง ตัวขาวจางจึงตกคอนทราสต์ — ใช้สีหมึกเหมือนตัวหนังสืออื่นในไทล์ */
  .tbl-join{
    display:inline-flex; align-items:center; gap:var(--space-1); font-size:var(--text-2xs);
    font-weight:var(--w-medium); color:var(--ink);
  }

  .floor-calls{ display:flex; flex-direction:column; gap:var(--space-2); }
  .call{
    display:flex; gap:var(--space-3); align-items:flex-start;
    padding:var(--space-3) var(--space-4); border-radius:var(--radius-md); background:var(--white);
    border:1px solid var(--line); box-shadow:var(--elevation-2);
  }
  .call svg{ margin-top:var(--space-0); font-size:var(--text-sm); }
  .call span{ display:flex; flex-direction:column; gap:var(--space-0); font-size:var(--text-sm); color:var(--gray600); }
  .call strong{ font-size:var(--text-sm); font-weight:var(--w-semibold); color:var(--ink); }
  .call-staff svg{ color:var(--green-ui); }
  .call-bill svg{ color:var(--ink); }
  .call-over svg{ color:var(--red); }

  .floor-legend{
    display:flex; flex-wrap:wrap; gap:var(--space-2) var(--space-5); margin-top:var(--space-5);
    font-size:var(--text-sm); color:var(--gray600);
  }
  .floor-legend li{ display:flex; align-items:center; gap:var(--space-2); }
  .floor-legend .dot{ width:11px; height:11px; border-radius:var(--radius-sm); border:1px solid rgba(0,0,0,0.12); }
  .floor-legend .dot.is-free{ background:var(--tbl-free); }
  .floor-legend .dot.is-busy{ background:var(--tbl-busy); }
  .floor-legend .dot.is-warn{ background:var(--tbl-warn); }
  .floor-legend .dot.is-over{ background:var(--tbl-over); }
  .floor-legend .dot.is-clean{ background:var(--tbl-clean); }

  @media (max-width:980px){
    .floor{ grid-template-columns:1fr; gap:var(--space-5); }
    .floor-grid{ grid-template-columns:repeat(3, 1fr); }
  }
  @media (max-width:620px){
    .floor-grid{ grid-template-columns:repeat(2, 1fr); }
  }

  /* ---------- client logo marquee ---------- */
  #clients{ padding:var(--space-16) 0; overflow:hidden; }
  .client-marquee{
    display:flex; flex-direction:column; gap:var(--space-5);
  }
  .client-track{
    display:flex; gap:var(--space-5); width:max-content;
    animation-duration:32s; animation-timing-function:linear; animation-iteration-count:infinite;
  }
  /* The marquee used to scroll customer logos. There are no customers yet, so
     it scrolls the kinds of restaurant the system is built for instead — same
     motion, nothing claimed that isn't true. */
  .type-chip{
    flex-shrink:0; display:inline-flex; align-items:center; height:46px; padding:0 var(--space-5);
    border-radius:var(--radius-full); border:1px solid var(--gray300); background:var(--white);
    font-size:var(--text-base); font-weight:var(--w-medium); color:var(--gray600); white-space:nowrap;
  }
  .client-track.scroll-left{ animation-name:marqueeLeft; }
  .client-track.scroll-right{ animation-name:marqueeRight; }
  @keyframes marqueeLeft{ from{ transform:translateX(0); } to{ transform:translateX(-50%); } }
  @keyframes marqueeRight{ from{ transform:translateX(-50%); } to{ transform:translateX(0); } }
  .client-logo{
    flex:0 0 auto; width:120px; height:120px; border-radius:var(--radius-xl);
    background:var(--white); border:1px solid var(--line);
    box-shadow:var(--elevation-2);
    display:flex; align-items:center; justify-content:center; padding:var(--space-3);
  }
  .client-logo img{ width:100%; height:100%; object-fit:contain; }
  @media (max-width:860px){
    .client-logo{ width:88px; height:88px; padding:var(--space-2); }
    .client-track{ gap:var(--space-3); }
    .client-marquee{ gap:var(--space-3); }
  }
  h1{
    font-family:var(--display); font-weight:var(--w-medium); font-size:var(--text-5xl); line-height:var(--lh-tight);
    letter-spacing:var(--track-normal); margin:0 auto var(--space-6); white-space:nowrap; color:var(--ink);
    /* ข้อความในฮีโร่ทุกชิ้นอยู่บนความกว้างเดียว เดิมสลับ 1132/660/1132
       ทำให้ห้าบล็อกจัดกึ่งกลางแต่ไม่มีชิ้นไหนแชร์ขอบกับชิ้นไหนเลย */
    max-width:var(--w-text);
  }
  .hero-sub{ font-family:var(--body); font-size:var(--text-xl); color:var(--gray600); max-width:var(--w-text); margin:0 auto var(--space-6); }
  .hero-actions{ display:flex; justify-content:center; gap:var(--space-4); margin-bottom:var(--space-12); }
  .hero-actions .btn{
    border-radius:var(--radius-lg); padding:var(--space-4) var(--space-6); font-size:var(--text-lg); font-weight:var(--w-semibold);
    transition:background var(--dur-base) ease, color var(--dur-base) ease, transform var(--dur-base) ease, box-shadow var(--dur-base) ease, border-color var(--dur-base) ease;
  }
  .hero-cta-primary{
    background:var(--green-strong); color:var(--white); box-shadow:0 0 0 0 rgba(var(--green-rgb), 0);
  }
  .hero-cta-primary:hover{
    background:var(--green-dark); transform:translateY(-3px);
    box-shadow:0 14px 24px -10px rgba(var(--green-rgb), 0.5);
  }
  /* เดิมเป็นปุ่มขอบหนาขนาดเท่าปุ่มหลัก สองปุ่มจึงแย่งน้ำหนักกันเอง
     ทั้งที่มันแค่พาเลื่อนลงไปในหน้าเดียวกัน — ลดเป็นลิงก์ข้อความ */
  .hero-cta-text{
    display:inline-flex; align-items:center; gap:var(--space-2);
    color:var(--gray600); font-size:var(--text-base); font-weight:var(--w-medium);
    padding:var(--space-3) var(--space-2);
    border-bottom:1px solid transparent;
    transition:color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
  }
  .hero-cta-text:hover{ color:var(--ink); border-bottom-color:var(--line-strong); }
  /* ลูกศรเส้นคุมได้ทั้งความหนาและตำแหน่ง ต่างจากอักขระ → ที่ได้อะไรก็ตาม
     ที่ฟอนต์ตัวนั้นวาดไว้ · ตั้งขนาดเป็น px ไม่ใช่ 1em เพราะ 1em ของลิงก์นี้
     คือ 16px ซึ่งทำให้เส้นหนา 2 หน่วยบน viewBox 16 กลายเป็นหนา 2px เท่าตัวอักษร
     ที่น้ำหนัก 500 — ลูกศรจะเด่นกว่าคำที่มันตามอยู่ */
  svg.icon.link-arrow, .hero-cta-text .cta-arrow{
    width:15px; height:15px; vertical-align:-0.15em;
    transition:transform var(--dur-base) var(--ease-lift);
  }
  .hero-cta-text:hover .cta-arrow{ transform:translateX(4px); }

  /* segmented control (iOS style) */
  .seg{
    display:inline-flex; position:relative; background:var(--grayBg); border-radius:var(--radius-full);
    padding:var(--space-1); margin:0 auto var(--space-6); gap:var(--space-0);
  }
  .seg button{
    position:relative; z-index:1; border:none; background:transparent; font-family:var(--body);
    font-weight:var(--w-medium); font-size:var(--text-sm); padding:var(--space-2) var(--space-5); border-radius:var(--radius-full); cursor:pointer; color:var(--gray600);
    transition:color var(--dur-slow) ease;
  }
  .seg button.active{ color:var(--ink); }
  .seg-highlight{
    position:absolute; top:4px; bottom:4px; left:4px;
    background:var(--white); border-radius:var(--radius-full); box-shadow:var(--elevation-1);
    transition:transform var(--dur-slower) var(--ease-in-out), width var(--dur-slower) var(--ease-in-out);
  }
  .block-alacarte, .block-buffet{
    opacity:1; transform:translateY(0); transition:opacity var(--dur-base) ease, transform var(--dur-base) ease;
  }
  .block-alacarte.mode-fade, .block-buffet.mode-fade{
    opacity:0; transform:translateY(8px);
  }
  body[data-mode="alacarte"] .alacarte-only{ display:inline; }
  body[data-mode="alacarte"] .buffet-only{ display:none; }
  body[data-mode="buffet"] .buffet-only{ display:inline; }
  body[data-mode="buffet"] .alacarte-only{ display:none; }
  span.buffet-only, span.alacarte-only{ display:none; }
  body[data-mode="alacarte"] span.alacarte-only{ display:inline; }
  body[data-mode="buffet"] span.buffet-only{ display:inline; }
  block.alacarte-only, block.buffet-only{ display:none; }
  body[data-mode="alacarte"] .block-alacarte{ display:block; }
  body[data-mode="buffet"] .block-alacarte{ display:none; }
  body[data-mode="buffet"] .block-buffet{ display:block; }
  body[data-mode="alacarte"] .block-buffet{ display:none; }

  /* ---------- device: tablet (realistic) ---------- */
  /* ระยะรอบแท็บเล็ตถูกหั่นลง 31 ส.ค. 2569 เพื่อดันตัวสินค้าขึ้นและดึงปุ่ม
     กลับขึ้นมาใกล้จอ  บน 48 -> 24  ล่าง 64 -> 8
     เงาใต้เครื่อง (.device-shadow) ทำหน้าที่เว้นระยะให้อยู่แล้ว
     ระยะล่างเดิม 64 จึงเป็นที่ว่างซ้อนที่ว่าง */
  .device-stage{ padding:var(--space-6) var(--space-6) var(--space-2); display:flex; justify-content:center; position:relative; }
  .device-stage-inner{ position:relative; width:100%; max-width:var(--w-mid); }
  .device-shadow{
    position:absolute; left:50%; bottom:-36px; transform:translateX(-50%);
    width:70%; height:56px; border-radius:50%; filter:blur(26px);
    background:radial-gradient(ellipse at center, rgba(0,0,0,0.4), rgba(0,0,0,0) 72%);
    z-index:0;
  }
  .ipad-frame{
    width:100%; position:relative; aspect-ratio:1600/1027;
    filter:drop-shadow(0 45px 60px rgba(0,0,0,0.35));
    opacity:0; transform:translateY(40px) scale(0.97);
    transition:opacity var(--dur-cover) ease, transform var(--dur-cover) var(--ease-out);
  }
  .ipad-frame.in{ opacity:1; transform:translateY(0) scale(1); }
  .ipad-screen{
    position:absolute; left:2.46%; right:2.25%; top:3.70%; bottom:3.51%;
    background:var(--grayBg); overflow:hidden;
    font-family:var(--body); z-index:1;
  }
  .hero-slide{
    position:absolute; inset:0; width:100%; height:100%; object-fit:cover; object-position:top;
    opacity:0; transition:opacity var(--dur-cover) ease;
  }
  .hero-slide.active{ opacity:1; }
  .ipad-overlay{
    position:absolute; inset:0; width:100%; height:100%; z-index:5; pointer-events:none;
  }
  .d-rail{ background:var(--white); border-right:1px solid var(--line); display:flex; flex-direction:column; align-items:center; padding:var(--space-4) 0; gap:var(--space-5); }
  .d-rail .ic{ width:20px; height:20px; border-radius:5px; background:rgba(0,0,0,0.12); }
  .d-rail .ic.active{ background:var(--ink); }
  .d-main{ padding:var(--space-4) var(--space-5); }
  .d-tabs{ display:flex; gap:var(--space-2); margin-bottom:var(--space-3); }
  .d-tab{ font-size:var(--text-xs); font-weight:var(--w-medium); padding:var(--space-2) var(--space-4); border-radius:var(--radius-sm); color:var(--gray600); }
  .d-tab.active{ background:var(--ink); color:var(--white); }
  .d-stats{ display:flex; gap:var(--space-4); font-size:var(--text-2xs); color:var(--gray600); margin-bottom:var(--space-3); flex-wrap:wrap; }
  .d-stats b{ color:var(--ink); }
  .d-grid{ display:grid; grid-template-columns:repeat(5,1fr); gap:var(--space-2); }
  .d-table{
    border-radius:var(--radius-sm); padding:var(--space-2); font-size:var(--text-2xs); color:var(--ink); min-height:64px;
    display:flex; flex-direction:column; justify-content:space-between; background:var(--white); border:1px solid var(--line);
  }
  .d-table.free{ background:var(--green); color:var(--white); border:none; }
  .d-table.mid{ background:var(--amber); color:var(--ink); border:none; }
  .d-table.hot{ background:var(--red); color:var(--white); border:none; }
  .d-table .tn{ font-weight:var(--w-semibold); font-size:var(--text-xs); }
  .d-side{ background:var(--white); border-left:1px solid var(--line); padding:var(--space-4); display:flex; flex-direction:column; }
  .d-side h4{ font-size:var(--text-sm); font-weight:var(--w-semibold); margin-bottom:var(--space-3); }
  .d-side .row{ display:flex; justify-content:space-between; font-size:var(--text-2xs); color:var(--gray600); margin-bottom:var(--space-1); }
  .d-side .empty{ flex:1; display:flex; align-items:center; justify-content:center; flex-direction:column; gap:var(--space-2); color:var(--gray600); font-size:var(--text-2xs); }
  .d-side .circ{ width:44px; height:44px; border-radius:50%; background:var(--grayBg); }
  .d-side .actions{ display:flex; gap:var(--space-2); }
  .d-side .actions .a1{ flex:1; background:var(--green); color:var(--white); border-radius:9px; padding:var(--space-2); text-align:center; font-size:var(--text-xs); font-weight:var(--w-medium); }
  .d-side .actions .a2{ flex:1.4; background:var(--ink); color:var(--white); border-radius:9px; padding:var(--space-2); text-align:center; font-size:var(--text-xs); font-weight:var(--w-medium); display:flex; justify-content:space-between; padding-left:var(--space-3); padding-right:var(--space-3); }



  /* ---------- bypass block (WCAG 2.4.1) ----------
     Two navs and a header sit above the content, so a keyboard user meets all
     of them on the way in. This is the way out. */
  /* ── strong ที่ไม่มีกฎรับ ────────────────────────────────────────────────
     <strong> ที่ไม่ถูกกฎไหนจับ ตกไปใช้ค่าเริ่มต้นของเบราว์เซอร์ซึ่งคือ 700
     สแกนหน้าที่เรนเดอร์แล้วเจอสี่จุด — สองจุดใน .flist สองจุดในย่อหน้านำ
     ของ #pricing ทั้งสี่เป็นการเน้นคำในประโยค ไม่ใช่หัวข้อ จึงควรเป็น 600
     เท่ากับ <strong> อื่นทั้งหน้า ไม่ใช่หนากว่าเพราะบังเอิญไม่มีใครสั่ง

     ประกาศเป็นฐานให้ <strong> ทุกตัวในเนื้อหา แล้วกฎที่เจาะจงกว่าทับได้ตามเดิม
     เว้นข้างในภาพประกอบไว้ เพราะพวกนั้นมีสเกลของตัวเอง */
  strong{ font-weight:var(--w-semibold); }

  .skip-link{
    position:absolute; left:12px; top:-64px; z-index:var(--z-skip);
    padding:var(--space-3) var(--space-4); border-radius:var(--radius-md);
    background:var(--ink); color:var(--white);
    font-size:var(--text-base); font-weight:var(--w-medium);
    text-decoration:none; transition:top var(--dur-fast) ease;
  }
  .skip-link:focus{ top:12px; }


  /* ---------- pictures of an interface ----------
     A mock POS screen, a phone, a floor plan, a printed slip and a log row are
     pictures of a product, not reading copy. The four-size rule governs what a
     visitor reads; forcing 16px inside these would blow the illustrations up
     and stop them looking like the screens they depict. Custom properties
     inherit, so redeclaring the old steps here restores them inside these
     containers and nowhere else. */
  .demo-stage, .pin-demo, .floor, .floor-legend, .slip-layout,
  .log-row, .member-card-wrap, .demo-stat, .menu-card, .tbl{
    --text-2xs:11px;
    --text-xs:12px;
    --text-sm:14px;
    --text-lg:18px;
  }


  /* ── ราคาและปุ่ม ใต้แท็บเล็ต ─────────────────────────────────────────────
     ย้ายลงมาจากเหนือแท็บเล็ต 31 ส.ค. 2569 เพื่อให้เห็นตัวสินค้าเร็วขึ้น

     เดิมกลุ่มนี้อยู่กลางกองข้อความ ระยะห่างจึงมาจากตัวที่อยู่เหนือมัน
     ตอนนี้อยู่ใต้ภาพ ต้องมีระยะของตัวเองเพื่อไม่ให้ดูเหมือนคำบรรยายภาพ */
  /* 40 -> 12 · ยังพอให้อ่านเป็นคนละกลุ่มกับคำบรรยายภาพ แต่ไม่เสียที่เปล่า

     ต้องเขียนเป็น .wrap.hero-below ไม่ใช่ .hero-below เฉยๆ เพราะบล็อก
     max-width 480 มีกฎ .wrap{ padding:0 var(--space-4) } ซึ่งเป็นตัวย่อ
     มันจึงรีเซ็ต padding-top ทิ้ง ทำให้ราคาไปติดคำบรรยายภาพเฉพาะบนมือถือ
     specificity (0,2,0) ของสองคลาสชนะ (0,1,0) ของคลาสเดียว */
  .wrap.hero-below{ padding-top:var(--space-3); }

  /* ตัวเลขราคาเป็นฟอนต์ตัวเลขของแบรนด์ เพราะยอดบาทคือสิ่งที่คนมาอ่าน */
  .hero-price{
    max-width:var(--w-text); margin:0 auto var(--space-6); text-align:center;
    font-size:var(--text-base); color:var(--gray600);
  }
  .hero-price b{
    font-family:var(--num); font-variant-numeric:tabular-nums;
    font-size:var(--text-2xl); font-weight:var(--w-semibold); color:var(--ink);
  }
  .hero-price span{ display:block; margin-top:var(--space-1); font-size:var(--text-base); }

  /* ── พื้นผิวที่ลอย ──────────────────────────────────────────────────────
     ประกาศครั้งเดียวแทนการไล่แก้ทีละกฎ — ทุกใบในลิสต์นี้เป็น "แผง" ที่ควรลอย

     เก็บเส้น --line ไว้ ไม่เปลี่ยนเป็นขอบขาวตามต้นฉบับ เพราะการ์ดของเรา
     หลายใบ (.switch-table .tiers-scroll .bizday) ไม่มีเงาเลย ใช้เส้นแยกอย่างเดียว
     ถ้าเปลี่ยนเป็นขาวจะกลืนหายไปกับพื้น — ที่ idle.space ทำได้เพราะเงาเป็นตัวแยก
     ส่วนขอบขาวเป็นแค่แสงสะท้อนด้านบน ไม่ใช่เส้นแบ่ง

     แสงในขาวใส่ได้ทุกใบ เพราะมันอยู่ข้างใน ไม่ไปแตะการแยกตัวจากพื้น */
  .price-card,
  .testi-card,
  .checklist-card,
  .faq-item,
  .switch-table,
  .tiers-scroll,
  .bizday,
  .included-list li,
  .addon-list li{
    box-shadow:var(--lift-1), var(--lift-glow);
  }

  /* ── การตอบสนองตอนชี้และตอนโฟกัส ────────────────────────────────────────
     รวมไว้ที่เดียวต่อจากกฎพื้นผิว เพราะมันคือพื้นผิวเดียวกันตอนถูกแตะ

     แยกสองกลุ่มตามว่า "กดได้จริงไหม" ไม่ใช่ตามว่าเป็นการ์ดหรือเปล่า
     ตรวจ DOM แล้วพบว่ามีแค่สองตัวที่มีของกดได้ข้างใน — .price-card มี <a>
     และ .faq-item มี <summary> ส่วน .testi-card .checklist-card .photo-slot
     .included-list li .addon-list li .tier-step ไม่มีอะไรให้กดเลยสักตัว
     ของเดิมยกสามตัวแรกขึ้นตอนชี้ ซึ่งเป็นการบอกว่ากดได้ทั้งที่กดไม่ได้
     กลุ่มนี้จึงเหลือแค่เงาลึกขึ้น ไม่ขยับ — ยังรู้สึกมีชีวิต แต่ไม่โกหก

     :focus-within คู่กับ :hover ทุกกฎ การ์ดพวกนี้ไม่ได้โฟกัสเอง แต่ของ
     ข้างในโฟกัสได้ คนที่กด Tab จึงเห็นเท่ากับคนที่ใช้เมาส์ */

  /* กดได้จริง — ยกขึ้นและเงาลึกขึ้น

     .faq-item ถูกถอดออกจากกลุ่มนี้ 1 ก.ย. 2569 ตามที่เจ้าของสั่ง
     เหตุผลที่ฟังขึ้น: การ์ด FAQ เปลี่ยนสถานะอยู่แล้วตอนกด (เส้นขอบเขียว
     เงาลึกขึ้น ลูกศรหมุน แผงกางออก) การยกขึ้นตอนชี้จึงเป็นสัญญาณซ้ำซ้อน
     และมันขยับกล่องที่คนกำลังจะกดพอดี ซึ่งเป็นการเลื่อนเป้าหมายใต้เมาส์ */
  .price-card{
    transition:transform var(--dur-lift) var(--ease-lift),
               box-shadow var(--dur-lift) var(--ease-lift),
               border-color var(--dur-base) ease;
  }
  .price-card:hover, .price-card:focus-within{
    transform:translateY(-8px);
    box-shadow:var(--lift-2), var(--lift-glow);
  }
  /* ยุบตอนกด ค้างตำแหน่งที่ยกไว้ ไม่ให้ตกลงมาแล้วเด้งขึ้นใหม่ */
  .price-card:active{
    transform:translateY(-8px) scale(0.98);
    transition-duration:var(--dur-fast);
  }

  /* อ่านอย่างเดียว — เงาลึกขึ้นอย่างเดียว ไม่ขยับ */
  .testi-card, .checklist-card, .included-list li, .addon-list li{
    transition:box-shadow var(--dur-lift) var(--ease-lift);
  }
  .testi-card:hover,        .testi-card:focus-within,
  .checklist-card:hover,    .checklist-card:focus-within,
  .included-list li:hover,  .included-list li:focus-within,
  .addon-list li:hover,     .addon-list li:focus-within{
    box-shadow:var(--lift-2), var(--lift-glow);
  }

  /* ── คู่ :focus-visible ของ hover ที่มีอยู่แล้ว ──────────────────────────
     ของเดิมสามจุดนี้ขยับเฉพาะตอนเอาเมาส์ไปชี้ คนใช้คีย์บอร์ดได้แค่กรอบโฟกัส */
  .hero-cta-text:focus-visible{ color:var(--ink); border-bottom-color:var(--line-strong); }
  .hero-cta-text:focus-visible .cta-arrow{ transform:translateX(4px); }
  .faq-contact a:focus-visible svg{ transform:translateX(3px); }
  .drawer-links a:focus-visible{ color:var(--ink); padding-left:var(--space-2); }

  /* ── ลิงก์ในแถบเมนู ─────────────────────────────────────────────────────
     กฎเดิมคือ a:hover{color:var(--ink)} ซึ่งเป็นสีเดียวกับตอนไม่ชี้พอดี
     — ชี้แล้วไม่มีอะไรเกิดขึ้นเลย ใช้เส้นใต้ที่วิ่งออกมาจากซ้ายแทน
     เว้นลิงก์หน้าปัจจุบันไว้ เพราะมันมีเส้นใต้ถาวรของตัวเองอยู่แล้ว
     ไม่ใช้ opacity ตามต้นฉบับ เพราะ --ink ที่ 60% เหลือคอนทราสต์ราว 3.5
     ซึ่งตกเกณฑ์ 4.5 ของตัวหนังสือขนาดนี้ */
  .navlinks a:not(.nav-active){ position:relative; }
  .navlinks a:not(.nav-active)::after{
    content:''; position:absolute; left:0; right:0; bottom:-3px; height:1.5px;
    background:var(--ink); transform:scaleX(0); transform-origin:left;
    transition:transform var(--dur-base) var(--ease-lift);
  }
  .navlinks a:not(.nav-active):hover::after,
  .navlinks a:not(.nav-active):focus-visible::after{ transform:scaleX(1); }

  /* ---------- scroll reveal ---------- */
  /* เนื้อหาเห็นได้เป็นค่าตั้งต้น — สถานะซ่อนมีผลเฉพาะตอนที่ .js ติดอยู่บน <html>
     ซึ่งแปลว่า JS ยืนยันแล้วว่ามันจะมาเปิดให้เอง ดูเหตุผลเต็มที่สคริปต์ใน <head> */
  .reveal{ transition:opacity var(--dur-reveal) ease, transform var(--dur-reveal) ease; }
  html.js .reveal:not(.in){ opacity:0; transform:translateY(24px); }
  .reveal.in{ opacity:1; transform:translateY(0); }
  .caption-pop{ opacity:0; transform:translateY(14px) scale(0.8); transition:opacity var(--dur-slower) ease, transform var(--dur-slower) var(--ease-back); }
  .caption-pop.in{ opacity:1; transform:translateY(0) scale(1); }

  /* ---------- full-screen sequential scrolling showcase ---------- */
  /* layer 0 = full-bleed parallax photo; layers 1-4 = framed feature cards sliding over it */
  .stack-wrap{ position:relative; height:300vh; }
  .stack-inner{ position:sticky; top:0; height:100vh; overflow:hidden; }
  .stack-safe{ position:relative; width:100%; height:100%; }
  .stack-card{
    position:absolute; inset:0;
    display:flex; align-items:center; justify-content:center;
    background:var(--white);
    will-change:transform; transform:translateY(100%);
    transform-origin:top center;
  }
  .stack-card[data-idx="0"]{
    background:none;
  }
  .stack-card:not([data-idx="0"]){
    inset:3vh 1.5vw;
    border-radius:var(--radius-xl); overflow:hidden;
    box-shadow: 0 30px 70px -30px rgba(0,0,0,0.35);
  }
  .stack-card[data-idx="1"], .stack-card[data-idx="3"]{ background:var(--white); }
  .stack-card[data-idx="2"], .stack-card[data-idx="4"]{ background:#F7F8FB; }
  .cover-photo{
    position:absolute; inset:0; z-index:0;
    /* รูปใหม่ 3 ก.ย. 2569 · 1916x821 เป็นภาพแนวนอนกว้าง ต่างจากใบเดิม
       จึงจัดกึ่งกลางแนวตั้ง ไม่ใช่ 30% ที่เคยตั้งไว้ให้ใบเดิม */
    background-image:image-set(url("../assets/img/img-22-1dad36cdc7.webp") type("image/webp"),
                            url("../assets/img/img-22-1dad36cdc7.jpg") type("image/jpeg"));
    background-size:cover; background-position:center center;
  }
  .cover-photo::after{
    content:""; position:absolute; inset:0;
    /* The scrim used to be darkest at the top and bottom and thinnest at 45%,
       which is exactly where the overlaid heading sits (measured: the white
       text occupies 40.3%-56.4% of the photo). Against the brightest pixel
       under that text, rgb(251,241,227), the old 0.35-0.40 gave white 2.90 —
       below the 4.5 the 22px line needs. 0.62 across the text band gives 5.76,
       and the edges stay lighter so the photograph still reads as one. */
    background:linear-gradient(180deg,
      rgba(20,15,10,0.42) 0%,
      rgba(20,15,10,0.62) 32%,
      rgba(20,15,10,0.62) 68%,
      rgba(20,15,10,0.58) 100%);
  }
  .cover-whiteout{
    position:absolute; inset:0; z-index:1; background:var(--white); opacity:0; pointer-events:none;
  }
  .cover-content{
    position:relative; z-index:2; height:100%; display:flex; flex-direction:column;
    align-items:center; justify-content:center; text-align:center; padding:0 var(--space-6); color:var(--white);
    will-change:transform;
  }
  .cover-eyebrow{
    font-family:var(--num); font-size:var(--text-xl); letter-spacing:var(--track-wide); text-transform:uppercase;
    opacity:0.8; margin-bottom:var(--space-5);
  }
  .cover-heading{
    font-family:var(--display); font-weight:var(--w-medium); font-size:var(--text-5xl); line-height:var(--lh-tight);
    letter-spacing:var(--track-tight); max-width:var(--w-mid);
  }
  /* คำโปรยใต้หัวเรื่อง ไม่ใช่หัวเรื่อง — เดิมอยู่ที่ --text-3xl ซึ่งเป็นชื่อพ้อง
     ของ --text-display จึงโตตามหัวเรื่องไปด้วย พอ display เป็น 48px ข้อความ
     กว้าง 1273px ในการ์ด 1280px แล้วดัน .stack-card ล้นออกไป 20px
     ใช้ขนาดเดียวกับ .hero-sub ซึ่งเป็นคำโปรยเหมือนกัน */
  .cover-sub{ font-size:var(--text-head); opacity:0.85; margin-top:var(--space-6); white-space:nowrap; }

  @media (max-width:860px){
    .stack-wrap{ height:340vh; }
    .stack-card:not([data-idx="0"]){ inset:1.5vh 1vw; }
    .cover-heading{ font-size:var(--text-3xl); }
    .cover-sub{ font-size:var(--text-xl); }
  }
  section{ padding:var(--space-25) 0; }
  section.alt{ background:var(--grayBg); }
  /* Left-aligned by default. Twelve consecutive centred section heads read as
     one undifferentiated column; ranging them left gives the page a spine and
     lets the eye find each new heading without re-centring. Centring is now
     opt-in, for the two moments that earn it — the hero and the closing CTA. */
  .s-head{ text-align:left; max-width:var(--w-text); margin:0 0 var(--space-16); }
  .s-head.s-head-center{ text-align:center; max-width:var(--w-text); margin:0 auto var(--space-16); }
  h2{ font-family:var(--display); font-weight:var(--w-medium); font-size:var(--text-display); letter-spacing:var(--track-tight); line-height:var(--lh-tight); }
  .s-head p{ font-size:var(--text-lg); color:var(--gray600); margin-top:var(--space-6); }

  /* ---------- feature block ---------- */
  .feat{ display:grid; grid-template-columns:1fr 1fr; gap:clamp(40px, 5vw, 72px); align-items:center; margin-bottom:var(--space-20); }
  .feat:last-child{ margin-bottom:0; }

  .stack-card-inner{
    display:grid; grid-template-columns:460px minmax(300px,680px); gap:var(--space-25); align-items:center;
    justify-content:center; max-width:var(--w-wide); width:100%; padding:clamp(40px, 8vh, 145px) 24px;
  }
  .stack-card .f-visual .shot-frame-mock{
    background:var(--grayBg); display:flex; align-items:center; justify-content:center;
  }

  .feat.rev .f-visual{ order:2; }
  .feat.rev .f-text{ order:1; }
  /* the feature-card label is the same object as .eyebrow — give it the same
     printed-label treatment so the motif holds across every section */
  .f-text .tag{
    font-family:var(--num); font-size:var(--text-xs); font-weight:var(--w-medium);
    letter-spacing:var(--track-wide); text-transform:uppercase;
    color:var(--gray600); margin-bottom:var(--space-3);
    display:inline-flex; align-items:center; gap:var(--space-2);
  }
  .f-text h2, .f-text h3{ font-family:var(--display); font-weight:var(--w-medium); font-size:var(--text-3xl); letter-spacing:var(--track-tight); line-height:var(--lh-tight); margin-bottom:var(--space-5); }
  .f-text p{ font-size:var(--text-lg); color:var(--ink); margin-bottom:var(--space-5); }
  .flist{ list-style:none; }
  .flist li{ font-size:var(--text-base); font-weight:var(--w-regular); padding:var(--space-2) 0 var(--space-2) var(--space-6); position:relative; color:#585858; }
  .flist li::before{
    content:""; position:absolute; left:0; top:7px;
    width:16px; height:16px; background:var(--green);
    -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M2.5 8.5l3.5 3.5 7.5-8' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat center / contain;
            mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M2.5 8.5l3.5 3.5 7.5-8' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat center / contain;
  }

  /* small device frame reused inside feature blocks */
  .mini-tablet{ background:linear-gradient(180deg,#2b2b2d,#0c0c0d); border-radius:22px; padding:var(--space-2); box-shadow:0 30px 60px -30px rgba(0,0,0,0.35); }
  .mini-tablet .screen{ background:var(--white); border-radius:16px; padding:var(--space-4); min-height:280px; }

  .mini-phone{ width:230px; margin:0 auto; background:linear-gradient(180deg,#2b2b2d,#0c0c0d); border-radius:38px; padding:var(--space-2); box-shadow:0 30px 60px -30px rgba(0,0,0,0.35); position:relative; }
  .mini-phone::before{ content:""; position:absolute; top:16px; left:50%; transform:translateX(-50%); width:70px; height:18px; background:#0c0c0d; border-radius:12px; z-index:2; }
  .mini-phone .screen{ background:var(--white); border-radius:28px; padding:var(--space-5) var(--space-4); min-height:400px; }

  .iphone-frame{
    position:relative; width:230px; margin:0 auto; aspect-ratio:572/1163;
    filter:drop-shadow(0 30px 50px rgba(0,0,0,0.3));
  }
  .iphone-screen{
    position:absolute; left:5.24%; right:5.42%; top:2.24%; bottom:2.41%;
    border-radius:32px; overflow:hidden; background:var(--white); z-index:1;
  }
  .iphone-overlay{
    position:absolute; inset:0; width:100%; height:100%; z-index:5; pointer-events:none;
  }

  .bar{ height:9px; background:var(--line); border-radius:var(--radius-sm); margin-bottom:var(--space-2); }
  .bar.w60{width:60%;} .bar.w40{width:40%;} .bar.w80{width:80%;}
  .pill-btn{ background:var(--green-strong); color:var(--white); font-size:var(--text-xs); font-weight:var(--w-medium); text-align:center; padding:var(--space-2); border-radius:9px; margin-top:var(--space-3); }

  .receipt-mini{ font-size:var(--text-xs); }
  .receipt-mini .r{ display:flex; justify-content:space-between; padding:var(--space-1) 0; border-bottom:1px dashed var(--line); color:var(--gray600); }
  .receipt-mini .total{ display:flex; justify-content:space-between; padding-top:var(--space-2); font-weight:var(--w-semibold); color:var(--ink); font-size:var(--text-sm); }

  .dash-row{ display:flex; justify-content:space-between; margin-bottom:var(--space-4); }
  .dash-num{ font-family:var(--display); font-weight:var(--w-semibold); font-size:var(--text-xl); }
  .dash-label{ font-size:var(--text-2xs); color:var(--gray600); }
  .dash-bars{ display:flex; align-items:flex-end; gap:var(--space-1); height:100px; }
  .dash-bars div{ flex:1; background:var(--green); border-radius:var(--radius-sm) 3px 0 0; opacity:0.85; }

  /* ---------- photo placeholders ---------- */
  .gallery{ display:grid; grid-template-columns:1.3fr 1fr 1fr; grid-template-rows:1fr 1fr; gap:var(--space-4); height:440px; }
  .gallery .g1{ grid-row:1/3; }
  .photo-slot{
    position:relative; border-radius:var(--radius-xl); overflow:hidden; border:1.5px dashed var(--gray300);
    background:repeating-linear-gradient(135deg, var(--grayBg), var(--grayBg) 10px, var(--white) 10px, var(--white) 20px);
    display:flex; align-items:flex-end; padding:var(--space-4);
  }
  .photo-slot .cap{ font-size:var(--text-xs); color:var(--gray600); background:rgba(255,255,255,0.97); padding:var(--space-1) var(--space-3); border-radius:var(--radius-sm); }
  .photo-slot.has-photo{ border:none; background-size:cover; background-position:center; }
  .photo-slot.has-photo .cap{ color:var(--ink); }

  /* ---------- membership ---------- */
  #membership{ padding:var(--space-25) 0; }
  .membership-grid{ display:grid; grid-template-columns:1fr 1fr; gap:clamp(40px, 5vw, 72px); align-items:center; }
  .member-stage{ display:flex; flex-direction:column; align-items:center; gap:var(--space-12); }
  .member-card-wrap{ perspective:1400px; width:100%; max-width:420px; }
  .member-card{
    position:relative; width:100%; aspect-ratio:1.586; border-radius:var(--radius-xl); padding:var(--space-6) var(--space-6);
    background:linear-gradient(135deg, #1D1D1F 0%, #2b2b2f 45%, #14161a 100%);
    box-shadow:0 30px 60px -25px rgba(0,0,0,0.5); color:var(--white); overflow:hidden;
    transform-style:preserve-3d; transition:transform var(--dur-cover) var(--ease-out);
    display:flex; flex-direction:column; justify-content:space-between;
  }
  .mc-top{ display:flex; align-items:center; justify-content:space-between; }
  .mc-brand{ display:flex; align-items:center; gap:var(--space-2); font-family:var(--display); font-weight:var(--w-semibold); font-size:var(--text-base); }
  .mc-brand-dot{ width:10px; height:10px; border-radius:var(--radius-sm); background:var(--green); display:inline-block; }
  .mc-badge{
    display:flex; align-items:center; gap:var(--space-1); font-size:var(--text-xs); font-weight:var(--w-bold); letter-spacing:0.04em;
    color:#1D1D1F; background:linear-gradient(135deg, #F3D27A, #C9962B); padding:var(--space-1) var(--space-3); border-radius:var(--radius-full);
  }
  .mc-name{ font-size:var(--text-lg); font-weight:var(--w-medium); letter-spacing:0.02em; opacity:0.92; }
  .mc-bottom{ display:flex; align-items:flex-end; justify-content:space-between; }
  .mc-points-label{ font-size:var(--text-2xs); color:rgba(255,255,255,0.55); margin-bottom:var(--space-1); }
  .mc-points{ font-size:var(--text-xl); font-weight:var(--w-semibold); letter-spacing:-0.02em; }
  .mc-points .count-num{ font-family:var(--num); font-variant-numeric:tabular-nums; }
  /* เดิมเป็นกล่องเปล่าลายตารางเส้นตรง ตั้งใจให้เป็น QR แต่ QR จริงเป็นลาย
     ไม่สม่ำเสมอและมีสี่เหลี่ยมจับมุมสามมุม อันนั้นจึงอ่านเป็นกระดาษกราฟ
     และที่สำคัญกว่า — ระบบไม่มีบัตรสมาชิกแบบสแกนเลย */
  .mc-id{ text-align:right; flex-shrink:0; }
  .mc-id-label{ font-size:var(--text-2xs); color:rgba(255,255,255,0.55); margin-bottom:var(--space-1); }
  .mc-id-num{
    font-family:var(--num); font-variant-numeric:tabular-nums;
    font-size:var(--text-sm); letter-spacing:0.04em; color:rgba(255,255,255,0.88);
  }
  .mc-sheen{
    position:absolute; inset:0; pointer-events:none;
    background:linear-gradient(115deg, rgba(255,255,255,0.16) 0%, rgba(255,255,255,0) 30%, rgba(255,255,255,0) 100%);
  }

  /* ── แถบระดับสมาชิก ──────────────────────────────────────────────────
     เดิมตั้งขนาดวงกลมไว้ที่ตัว <svg> เอง ซึ่งไม่เคยมีผล เพราะ svg.icon
     ประกาศ width:1em ไว้ทีหลังในไฟล์และชนะ วงกลมที่ตั้งใจให้ 36px
     จึงเรนเดอร์จริงแค่ 16px แล้วขอบ 3px กินจนเหลือที่ว่างข้างใน 10px
     ซึ่งพอดีกับตัว glyph เป๊ะ — ไอคอนชนขอบทุกด้าน
     ตอนนี้เหรียญเป็น element ของตัวเอง ขนาดไอคอนคุมแยกจากขนาดเหรียญ */
  .tier-bar{ width:100%; max-width:420px; position:relative; display:flex; justify-content:space-between; }
  .tier-track{
    position:absolute; top:21px; left:22px; right:22px; height:3px;
    background:var(--grayBg); border-radius:var(--radius-full); overflow:hidden;
  }
  .tier-fill{
    position:absolute; left:0; top:0; height:100%; width:66.67%;
    border-radius:var(--radius-full);
    /* ไล่จากทองแดงไปเงินไปทอง คือเส้นทางที่เดินมาแล้วจริงๆ */
    background:linear-gradient(90deg, var(--tier-member), var(--tier-silver) 52%, var(--tier-gold));
  }
  .tier-step{
    position:relative; z-index:1; display:flex; flex-direction:column; align-items:center;
    gap:var(--space-2); font-size:var(--text-xs); color:var(--gray600); font-weight:var(--w-medium);
  }
  .tier-medal{
    width:44px; height:44px; border-radius:50%; box-sizing:border-box;
    display:flex; align-items:center; justify-content:center;
    background:var(--white); border:2px solid var(--gray300); color:var(--gray600);
    box-shadow:0 0 0 4px var(--grayBg);   /* เว้นวงรอบให้เส้นทางลอดผ่านไม่ชนเหรียญ */
    transition:transform var(--dur-fast) var(--ease-out);
  }
  /* ต้องชนะ svg.icon{width:1em} ที่ประกาศไว้ทีหลังในไฟล์ — สองคลาสจึงพอ */
  .tier-medal .icon{ width:20px; height:20px; }

  /* ผ่านมาแล้ว: พื้นอ่อนสีโลหะ ขอบและไอคอนเป็นสีโลหะเต็ม */
  .tier-step.is-done .tier-medal{ border-color:currentColor; }
  .tier-step[data-tier="member"]  { --metal:var(--tier-member);   }
  .tier-step[data-tier="silver"]  { --metal:var(--tier-silver);   }
  .tier-step[data-tier="gold"]    { --metal:var(--tier-gold);     }
  .tier-step[data-tier="platinum"]{ --metal:var(--tier-platinum); }
  .tier-step.is-done .tier-medal{
    color:var(--metal); border-color:var(--metal);
    background:color-mix(in srgb, var(--metal) 12%, var(--white));
  }
  /* อยู่ตรงนี้: เหรียญทึบ ไอคอนขาว และใหญ่กว่าเพื่อนเล็กน้อย */
  .tier-step.is-current .tier-medal{
    background:var(--metal); border-color:var(--metal); color:var(--white);
    transform:scale(1.14); box-shadow:0 0 0 4px var(--grayBg), var(--elevation-2);
  }
  .tier-step.is-current .tier-name{ color:var(--ink); font-weight:var(--w-semibold); }
  /* ยังไม่ถึง: เงียบที่สุด ไม่มีสีโลหะ */
  .tier-step.is-locked .tier-medal{ border-style:dashed; }

  @media (prefers-reduced-motion: reduce){
    .tier-step.is-current .tier-medal{ transform:none; }
  }

  @media (max-width:860px){
    .membership-grid{ grid-template-columns:1fr; gap:var(--space-10); }
  }

  /* ---------- trust stats ---------- */
  #trust-stats{ padding:var(--space-12) 0; border-bottom:1px solid var(--line); }
  .trust-grid{ display:grid; grid-template-columns:repeat(auto-fit, minmax(160px, 1fr)); gap:clamp(16px, 2vw, 24px); text-align:center; }
  .trust-item + .trust-item{ border-left:1px solid var(--line); }
  /* Figures a machine would print — counts, prices, points — are set in mono.
     It is the clearest carrier of the ticket motif and it makes the numbers
     line up in a column the way a receipt does. */
  .trust-num{ font-weight:var(--w-semibold); font-size:var(--text-4xl); letter-spacing:var(--track-tight); color:var(--ink); margin-bottom:var(--space-1); }
  .trust-num .count-num{ font-family:var(--num); font-variant-numeric:tabular-nums; }
  .trust-label{ font-size:var(--text-sm); color:var(--gray600); }
  @media (max-width:860px){
    .trust-grid{ grid-template-columns:1fr 1fr; gap:var(--space-6) 0; }
    .trust-item + .trust-item{ border-left:none; }
    .trust-item:nth-child(odd){ border-right:1px solid var(--line); }
  }

  /* ---------- testimonials ---------- */
  .testi-grid{ display:grid; grid-template-columns:repeat(auto-fit, minmax(300px, 1fr)); gap:clamp(16px, 2vw, 24px); }
  .testi-card{
    background:var(--white); border:1px solid var(--line); border-radius:var(--radius-xl); padding:var(--space-8);
    display:flex; flex-direction:column;
  }
  /* takes the place of the star row in the pioneer cards */
  .pioneer-icon{
    width:44px; height:44px; margin-bottom:var(--space-4); border-radius:var(--radius-md);
    display:flex; align-items:center; justify-content:center;
    background:rgba(var(--green-rgb), 0.10); color:var(--green-text); font-size:var(--text-lg);
  }
  .testi-quote{ font-size:var(--text-base); line-height:var(--lh-loose); color:var(--ink); margin-bottom:var(--space-6); flex:1; }
  .testi-person{ display:flex; align-items:center; gap:var(--space-3); padding-top:var(--space-5); border-top:1px solid var(--line); }
  .testi-avatar{
    width:42px; height:42px; border-radius:50%; background:var(--green); color:var(--white);
    display:flex; align-items:center; justify-content:center; font-weight:var(--w-semibold); font-size:var(--text-base); flex-shrink:0;
  }
  .testi-name{ font-weight:var(--w-semibold); font-size:var(--text-sm); }
  .testi-role{ font-size:var(--text-xs); color:var(--gray600); }

  /* ---------- why switch ---------- */
  /* หัวข้อของเซ็กชันนี้ชิดซ้าย ตารางจึงชิดซ้ายด้วย ไม่ใช่จัดกลาง */
  /* ตามแบบตารางที่หน้านี้มีอยู่แล้วที่ .tiers-scroll — กล่องขาว เส้นขนหนู
     มุม xl · เดิมกล่องนี้เป็นเทาทั้งแผงบน section ขาว ซึ่งกลับด้านกับ
     แผงอื่นทุกอันในหน้าที่เป็นขาววางบนเทา มันเลยดูเป็นของนอกชุด */
  .switch-table{ margin:0; border-radius:var(--radius-xl); overflow:hidden; border:1px solid var(--line);
    background:var(--white); container-type:inline-size; container-name:switch; }

  /* ค่าตั้งต้น = แผงแคบ · คอลัมน์เดียว ไม่มีเส้นตั้ง หัวตารางซ่อน
     สามคอลัมน์เป็นสถานะที่ต้อง "ขอ" ด้วยความกว้าง ไม่ใช่ค่าเริ่มต้น */
  .switch-row{ display:grid; grid-template-columns:1fr; }

  /* เส้นแบ่งแถว ลากครบทั้งสามคอลัมน์ (แก้ 30 ส.ค. 2569)
     ก่อนหน้านี้กฎนี้เขียนถึงแค่ .switch-label กับ .switch-old คอลัมน์เขียว
     จึงเป็นแถบเดียวต่อเนื่องลงมาทั้งคอลัมน์ พอสองคอลัมน์ซ้ายมีเส้นแต่
     คอลัมน์ขวาไม่มี สายตาจึงไม่เชื่อมว่าข้อความฝั่งขวาเป็นแถวเดียวกับ
     หัวข้อฝั่งซ้าย

     บันทึกเดิมตรงนี้บอกว่าเคยลองใส่เส้น "เขียวจาง" แล้ววัดได้ 1.184 เทียบ
     เส้นเทา 1.199 แล้วสรุปว่าไม่ต้องใส่ — แต่ตัวเลขนั้นแปลว่ามันเห็นพอกัน
     ซึ่งเป็นเหตุผลให้ใส่ ไม่ใช่ไม่ใส่ และไม่ต้องใช้สีเขียวด้วย
     --line เป็นดำ 8% ทำงานได้บนพื้นเขียวจาง 4% เหมือนที่ทำงานบนพื้นขาว */
  .switch-row + .switch-row > .switch-label{ border-top:1px solid var(--line); }

  /* เส้นแบ่งคอลัมน์ ประกาศเป็น border-left บนช่องที่ไม่ใช่ช่องแรก
     จึงไม่มีเส้นเกินที่ขอบขวาสุด เหมือนที่ทำกับ .tiers-table
     จางกว่าเส้นนอนหนึ่งขั้น เพราะแถวคือหน่วยที่คนอ่าน */
  .switch-row > div{ padding:var(--space-5) var(--space-5); font-size:var(--text-sm); }
  .switch-label{ font-weight:var(--w-bold); }
  .switch-head{ display:none; }

  /* แผงกว้างพอค่อยกางเป็นสามคอลัมน์ — 200px ของคอลัมน์หัวข้อ บวกอีกสองคอลัมน์
     ที่ต้องมีที่พอให้ประโยคไม่ตัดคำทุกบรรทัด */
  @container switch (min-width: 720px){
    .switch-row{ grid-template-columns:200px 1fr 1fr; }
    .switch-label{ font-weight:var(--w-medium); }
    .switch-head{ display:grid; }
    .switch-row + .switch-row > div{ border-top:1px solid var(--line); }
    .switch-row > div:not(:first-child){ border-left:1px solid rgba(0,0,0,0.05); }
  }
  /* หัวคอลัมน์กลับมาเป็น 16px (30 ส.ค. 2569) — 11px เล็กเกินไปจนอ่านยาก
     เจ้าของทัก และตอนนี้ไม่ต้องพึ่งขนาดเล็กเพื่อบอกว่ามันคือหัวตารางแล้ว
     เพราะมีพื้นเทาและเส้นคั่นใต้หัวทำหน้าที่นั้นอยู่

     ถอด letter-spacing กว้างกับ uppercase ออกด้วย — "แบบเดิม" เป็นภาษาไทย
     ซึ่ง uppercase ไม่มีผล และการกางตัวอักษรไทยทำให้สระกับวรรณยุกต์
     ดูหลุดออกจากพยัญชนะ อ่านยากขึ้น ไม่ได้ช่วยอะไร */
  .switch-head{ background:var(--grayBg); }
  .switch-head > div{
    font-size:var(--text-body); font-weight:var(--w-medium);
    color:var(--gray600); padding:var(--space-3) var(--space-5);
  }
  .switch-head .switch-col-old{ color:var(--gray600); }
  .switch-head .switch-col-new{ color:var(--green-text); }
  .switch-label{ color:var(--ink); }   /* น้ำหนักคุมที่กฎ container query ข้างบน */
  .switch-old{ color:var(--gray600); display:flex; gap:var(--space-2); align-items:flex-start; }
  .switch-new{ color:var(--ink); display:flex; gap:var(--space-2); align-items:flex-start; background:rgba(var(--green-rgb), 0.04); }
  .switch-old svg{ color:var(--red); margin-top:var(--space-0); flex-shrink:0; }
  .switch-new svg{ color:var(--green-text); margin-top:var(--space-0); flex-shrink:0; }
  /* กฎการยุบคอลัมน์ย้ายไปเป็น container query ข้างบนแล้ว */

  /* ---------- self-assessment checklist (vertical stepper) ---------- */
  .checklist-grid{ position:relative; max-width:var(--w-text); margin:0; display:flex; flex-direction:column; gap:var(--space-3); }
  .checklist-grid::before{ content:""; position:absolute; left:21px; top:28px; bottom:28px; width:2px; background:linear-gradient(var(--green), rgba(21,198,74,0.12)); border-radius:var(--radius-sm); }
  .checklist-item{ position:relative; display:flex; gap:var(--space-4); padding:0; align-items:flex-start; }
  .checklist-num{
    position:relative; z-index:1; flex-shrink:0; width:44px; height:44px; border-radius:50%;
    background:linear-gradient(135deg, var(--green), var(--green-dark)); color:var(--white);
    display:flex; align-items:center; justify-content:center; font-family:var(--display); font-weight:var(--w-semibold); font-size:var(--text-lg);
    box-shadow:0 4px 12px rgba(var(--green-rgb), 0.32), 0 0 0 5px var(--white);
  }
  .checklist-card{
    flex:1; background:var(--grayBg); border:1px solid var(--line); border-radius:var(--radius-lg); padding:var(--space-4) var(--space-4);
    transition:background var(--dur-fast) ease;
  }
  .checklist-card:hover{ background:var(--white); }
  .checklist-q{ display:flex; align-items:center; gap:var(--space-2); font-family:var(--display); font-weight:var(--w-semibold); font-size:var(--text-base); margin-bottom:var(--space-1); color:var(--ink); }
  .checklist-q svg{ color:var(--green-ui); font-size:var(--text-base); width:20px; text-align:center; flex-shrink:0; }
  .checklist-a{ font-size:var(--text-sm); color:var(--gray600); line-height:var(--lh-body); max-width:none; }
  @media (max-width:640px){
    .checklist-grid::before{ left:19px; }
    .checklist-num{ width:40px; height:40px; font-size:var(--text-base); }
    .checklist-q{ font-size:var(--text-base); }
  }

  /* ---------- pricing ---------- */

  /* ---------- the pricing ladder ----------
     A table with three columns and a caption, because it is data. The figures
     are tabular so the column of totals reads down as a column. */
  .sr-only{
    position:absolute; width:1px; height:1px; padding:0; margin:-var(--space-0);
    overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0;
  }
  .tiers{ margin:var(--space-8) 0 0; }
  .tiers-head h3{ font-family:var(--display); font-size:var(--text-xl); font-weight:var(--w-semibold); margin-bottom:var(--space-2); }
  /* ย่อหน้านี้กับหมายเหตุใต้ตารางเคยไม่มีเพดานความกว้างเลย วัดได้ 1206px
     พอตารางถูกจำกัดที่ --w-text ทั้งสองอันจะยื่นเลยขอบตารางไป 472px
     บล็อกนี้ต้องอ่านเป็นก้อนเดียว ขอบขวาจึงต้องตรงกันทั้งสามส่วน */
  .tiers-head p{ font-size:var(--text-base); color:var(--gray600); line-height:var(--lh-loose); margin-bottom:var(--space-5); max-width:var(--w-text); }
  /* ── ตารางราคาตามจำนวนโต๊ะ ────────────────────────────────────────────
     เดิมยืดเต็มความกว้างหน้า 1130px ทั้งที่มีค่าสั้นๆ แค่สามค่า วัดแล้ว
     "30" อยู่ที่ x=75 และ "฿1,900" จบที่ x=1205 — ตาต้องกวาด 742px
     ข้ามที่ว่างเพื่อเชื่อมจำนวนโต๊ะกับราคาของมัน สามค่าจึงอ่านเป็นสามก้อน
     ลอยๆ ไม่ใช่แถวเดียวกัน

     จำกัดที่ --w-text ซึ่งเป็นความกว้างเดียวกับย่อหน้าเหนือตาราง
     ขอบซ้ายขวาจึงตรงกับเนื้อหาที่เหลือของ section ด้วย */
  .tiers-scroll{
    overflow-x:auto; border:1px solid var(--line); border-radius:var(--radius-xl);
    background:var(--white); max-width:var(--w-text);
    container-type:inline-size; container-name:tiers;
  }
  .tiers-table{ width:100%; min-width:300px; border-collapse:collapse; text-align:left; }
  /* ค่าตั้งต้นคือระยะแคบ เพราะตารางนี้ถูกจำกัดที่ 660px อยู่แล้ว
     จึงกว้างเท่าเดิมไม่ว่าหน้าต่างจะ 1280 หรือ 760 — กฎที่ผูกกับความกว้าง
     ของหน้าต่างจึงตัดสินจากตัวเลขที่ไม่เกี่ยวกับตารางเลย */
  .tiers-table th, .tiers-table td{ padding:var(--space-3); font-size:var(--text-base); }
  @container tiers (min-width: 520px){
    .tiers-table th, .tiers-table td{ padding:var(--space-3) var(--space-5); }
  }
  .tiers-table thead th{
    font-size:var(--text-xs); font-weight:var(--w-medium); color:var(--gray600);
    letter-spacing:var(--track-wide); background:var(--grayBg); vertical-align:bottom;
  }
  .tiers-table thead th:nth-child(2), .tiers-table thead th:nth-child(3),
  .tiers-table td{ text-align:right; }
  .tiers-table thead th:first-child, .tiers-table tbody th{ text-align:left; }
  .tiers-table tbody th{ font-family:var(--num); font-variant-numeric:tabular-nums; font-weight:var(--w-regular); color:var(--gray600); }
  /* one cell in that column is a word, not a count — mono cannot draw it */
  .tiers-table .is-words{ font-family:var(--body); }
  .tiers-table tbody td{ font-family:var(--num); font-variant-numeric:tabular-nums; color:var(--gray600); }
  .tiers-table tbody td strong{ color:var(--ink); font-weight:var(--w-semibold); }
  .tiers-table tbody tr + tr th, .tiers-table tbody tr + tr td{ border-top:1px solid var(--line); }

  /* เส้นแบ่งคอลัมน์ — ประกาศเป็น border-left บนช่องที่ไม่ใช่ช่องแรก
     วิธีนี้ได้เส้นระหว่างคอลัมน์ 1|2 และ 2|3 โดยไม่มีเส้นเกินที่ขอบขวาสุด
     ถ้าใช้ border-right จะต้องไปยกเว้นช่องสุดท้ายอีกกฎหนึ่ง

     เส้นจางกว่าเส้นแบ่งแถวหนึ่งขั้น (--line-soft ไม่มี จึงใช้ค่าตรง)
     เพราะแถวคือหน่วยที่คนอ่าน ส่วนคอลัมน์เป็นแค่ตัวช่วยจัดตำแหน่ง
     ถ้าเส้นตั้งเข้มเท่าเส้นนอน ตารางจะกลายเป็นตะแกรงและอ่านยากขึ้น */
  .tiers-table th:not(:first-child),
  .tiers-table td:not(:first-child){ border-left:1px solid rgba(0,0,0,0.05); }

  /* หัวตารางเดิมไม่มีเส้นคั่นจากเนื้อเลย จึงลอยติดกับแถวแรก */
  .tiers-table thead th{ border-bottom:1px solid var(--line); }
  /* ── ในราคานี้ได้อะไรบ้าง ─────────────────────────────────────────────
     วางไว้ใต้ตารางราคา เพราะคำถาม "แล้วฉันได้อะไร" เกิดตอนเห็นตัวเลข
     ไม่ใช่ตอนอ่านฟีเจอร์ */
  .included{ margin-top:var(--space-8); }
  .included-head{
    font-size:var(--text-base); font-weight:var(--w-semibold); color:var(--ink);
    margin-bottom:var(--space-5);
  }
  .included-list{
    list-style:none; margin:0; padding:0;
    display:grid; grid-template-columns:repeat(auto-fit, minmax(280px, 1fr));
    gap:var(--space-4);
  }
  .included-list li{
    display:flex; gap:var(--space-3); align-items:flex-start;
    background:var(--white); border:1px solid var(--line);
    border-radius:var(--radius-lg); padding:var(--space-4);
  }
  .included-list .icon{
    flex-shrink:0; width:20px; height:20px; margin-top:2px; color:var(--green-text);
  }
  .included-list strong{ display:block; font-weight:var(--w-semibold); margin-bottom:var(--space-1); }
  .included-list div{ color:var(--gray600); }

  /* ── Add-on ──────────────────────────────────────────────────────────
     ย้ายขึ้นมาต่อจากการ์ดแพ็กเกจ และเปลี่ยนทรงใหม่ 31 ส.ค. 2569

     ของเดิมเป็นแถวเรียบ ไอคอน | ข้อความ | ราคา ซึ่งอ่านเหมือนเชิงอรรถ
     ทั้งที่มันคือของที่ต้องตัดสินใจซื้อเพิ่ม ทรงใหม่จึงใช้ภาษาเดียวกับ
     .price-card ที่อยู่เหนือมัน — กล่องขาว มุมโค้ง เงาลอย — เพื่อบอกว่า
     นี่คือของที่ "เลือกได้" ไม่ใช่ข้อความอธิบาย

     ราคาถูกยกขึ้นเป็นบรรทัดของตัวเองแทนที่จะเบียดอยู่ขวาสุด เพราะ
     ตัวเลขคือสิ่งที่คนมาอ่านจริง และตอนนี้มันมีที่ให้ใช้ฟอนต์ตัวเลข
     ของแบรนด์ได้เต็มขนาด */
  .addons{ margin-top:var(--space-10); }
  .addons-head{ margin-bottom:var(--space-5); }
  .addons-head h3{
    font-family:var(--display); font-size:var(--text-xl); font-weight:var(--w-semibold);
    color:var(--ink); margin-bottom:var(--space-1);
  }
  .addons-head p{ font-size:var(--text-base); color:var(--gray600); }

  .addon-list{
    list-style:none; margin:0; padding:0;
    display:grid; grid-template-columns:repeat(auto-fit, minmax(280px, 1fr));
    gap:var(--space-4);
  }
  /* คอลัมน์เดียว เรียงลงมา ไอคอน -> ชื่อ -> คำอธิบาย -> ราคา
     ราคาถูกดันลงล่างสุดด้วย margin-top:auto ทุกใบจึงมีราคาอยู่ระดับเดียวกัน
     แม้คำอธิบายจะยาวไม่เท่ากัน */
  .addon-list li{
    display:flex; flex-direction:column; align-items:flex-start;
    background:var(--white); border:1px solid var(--line);
    border-radius:var(--radius-xl); padding:var(--space-6);
  }
  .addon-ico{
    width:44px; height:44px; border-radius:var(--radius-md);
    background:var(--green-tint); color:var(--green-text);
    display:flex; align-items:center; justify-content:center;
    margin-bottom:var(--space-4);
  }
  .addon-ico .icon{ width:22px; height:22px; }
  .addon-name{
    font-family:var(--display); font-size:var(--text-base); font-weight:var(--w-semibold);
    color:var(--ink); margin-bottom:var(--space-1);
  }
  .addon-desc{ font-size:var(--text-base); color:var(--gray600); line-height:var(--lh-body); }
  .addon-price{
    margin-top:var(--space-5); padding-top:var(--space-4);
    border-top:1px solid var(--line); width:100%;
    display:flex; align-items:baseline; gap:var(--space-2);
  }
  .addon-price b{
    font-family:var(--num); font-variant-numeric:tabular-nums;
    font-size:var(--text-head); font-weight:var(--w-semibold); color:var(--ink);
    letter-spacing:var(--track-tight);
  }
  .addon-price span{ font-size:var(--text-base); color:var(--gray600); }

  .tiers-note{ font-size:var(--text-base); color:var(--gray600); line-height:var(--lh-loose); margin-top:var(--space-3); max-width:var(--w-text); }

  /* กฎ padding ของตารางย้ายไปเป็น container query แล้ว */


  /* ---------- the business day ----------
     Two clock faces and an arrow: the whole claim is that these two times
     belong to the same day, so the layout says it before the copy does. */
  .bizday{
    grid-column:1 / -1; grid-row:3;
    display:flex; gap:var(--space-8); align-items:center; flex-wrap:wrap;
    width:100%; margin-top:0;
    padding:var(--space-6) var(--space-8); border-radius:var(--radius-xl);
    background:var(--white); border:1px solid var(--line);
  }
  /* เรียงบนล่าง เพราะสองเวลานี้คือคืนเดียวกันที่คร่อมเที่ยงคืน
     ไม่ใช่ช่วงเวลาที่วิ่งไปข้างหน้า อ่านไล่ลงมาจึงตรงกับเรื่องที่เล่ามากกว่า
     ลูกศรลงมีอยู่จริงในฟอนต์ตัวเลข ส่วนลูกศรขวาที่ใช้เดิมไม่มี
     (วัดได้ว่ากว้างเท่า fallback เป๊ะ คือหล่นไปใช้ฟอนต์อื่นมาตลอด)

     stretch ไม่ใช่ center — Bai Jamjuree ตัวเลขกว้างไม่เท่ากันและไม่มีฟีเจอร์
     tabular-nums ให้เปิด 23:40 จึงกว้าง 69.9px ส่วน 00:20 กว้าง 72.9px
     ถ้าจัดกึ่งกลางทีละตัว ขอบสองบรรทัดจะเหลื่อมกันข้างละ 1.5px ซึ่งเห็นได้
     เพราะสองบรรทัดนี้วางซ้อนกันตรงๆ มีแค่ลูกศรคั่น
     ให้กล่องกว้างเท่าตัวที่กว้างที่สุด แล้วจัดกึ่งกลางข้างในแทน
     ทั้งคู่จึงกว้างเท่ากันเสมอ โดยไม่ต้องฝังตัวเลขความกว้างไว้ */
  .bizday-clock{
    display:flex; flex-direction:column; align-items:stretch;
    width:max-content; gap:var(--space-1); flex-shrink:0;
  }
  .bizday-t{
    font-family:var(--num); text-align:center;
    font-size:var(--text-2xl); font-weight:var(--w-semibold); line-height:var(--lh-tight); color:var(--ink);
  }
    /* ลูกศรตัวเดียวกับที่อื่น หมุนลง — ตรงนี้คือจุดที่อักขระเคยพังจริง
     เพราะกล่องนี้ตั้ง font-family เป็น --num (IBM Plex Mono) ซึ่งไม่มี →
     พอเป็น SVG ก็ไม่ต้องแคร์ว่าฟอนต์ไหนมีอักขระอะไร */
  svg.icon.bizday-arrow{
    width:18px; height:18px; align-self:center; color:var(--gray600);
    transform:rotate(90deg);
  }
  .bizday-copy{ flex:1; min-width:260px; }
  .bizday-copy h3{ font-family:var(--display); font-size:var(--text-xl); font-weight:var(--w-semibold); margin-bottom:var(--space-2); }
  .bizday-copy p{ font-size:var(--text-base); line-height:var(--lh-loose); color:var(--gray600); }
  .bizday-copy strong{ color:var(--ink); font-weight:var(--w-semibold); }
  .bizday-note{ margin-top:var(--space-2); font-size:var(--text-sm) !important; }
  /* ต้องอยู่หลังกฎ .bizday ข้างบน — ตอนแรกเขียนรวมไว้ใน @media 860 ที่บรรทัด 421
     ซึ่งมาก่อนกฎนี้ในไฟล์ grid-row:3 จึงทับกลับ แล้วบนมือถือกล่องวันทำการ
     ไปแทรกอยู่ก่อนบรรทัดคำอธิบาย ทั้งที่ใน DOM อยู่หลังสุด */
  @media (max-width:860px){ .bizday{ grid-column:1; grid-row:auto; } }
  @media (max-width:620px){ .bizday{ gap:var(--space-4); padding:var(--space-5); } }

  /* ---------- peak hours ---------- */
  .peak-pts{
    display:grid; grid-template-columns:repeat(2, minmax(0,1fr)); gap:var(--space-6) var(--space-10);
    list-style:none;
  }
  .peak-pts h3{ font-family:var(--display); font-size:var(--text-xl); font-weight:var(--w-semibold); margin-bottom:var(--space-1); }
  .peak-pts p{ font-size:var(--text-base); line-height:var(--lh-loose); color:var(--gray600); }
  @media (max-width:760px){ .peak-pts{ grid-template-columns:1fr; gap:var(--space-6); } }

  /* เดิม 820 จัดกึ่งกลาง ทำให้ section นี้มีขอบซ้ายสามค่าและไม่มีอันไหนตรงกับ
     ขอบ 74 ของหน้า — เป็น section เดียวที่ลอยอยู่กลางขณะที่ทั้งหน้าชิดซ้าย */
  .price-grid{ display:grid; grid-template-columns:1fr 1fr; gap:var(--space-6); margin:0; }
  .price-card{ border:1px solid var(--line); border-radius:var(--radius-xl); padding:var(--space-8); background:var(--white); }
  .price-card .tag{ font-size:var(--text-xs); color:var(--gray600); margin-bottom:var(--space-2); }
  .price-card h3{ font-family:var(--display); font-size:var(--text-xl); font-weight:var(--w-semibold); margin-bottom:var(--space-4); }
  .price-num{ font-family:var(--num); font-size:var(--text-4xl); font-weight:var(--w-semibold); letter-spacing:var(--track-tight); margin-bottom:var(--space-1); }
  /* letter-spacing ตกทอดมาเป็น 'พิกเซล' ไม่ใช่ em — ค่า -0.022em ของพ่อที่ 38px
     คือ -0.84px ซึ่งพอมาถึงลูกที่ 16px กลายเป็น -0.052em คือบีบกว่าที่ตั้งใจสองเท่า
     ต้องสั่งกลับเป็นปกติที่ลูกเอง */
  .price-num span{ font-family:var(--body); font-size:var(--text-sm); font-weight:var(--w-regular); color:var(--gray600); letter-spacing:var(--track-normal); }
  .price-desc{ font-size:var(--text-sm); color:var(--gray600); margin-bottom:var(--space-6); }
  .price-card .btn{ width:100%; text-align:center; }

  /* ---------- faq (two-column: orientation + contact / accordion) ---------- */
  /* เดิมสองบล็อกนี้จบที่ 820 กับ 960 ขณะที่ section บนล่างจบที่ 1206
     ขอบขวาเลยหดเข้ามาเป็นหย่อม ๆ ตอนเลื่อนผ่าน — คำตอบใน FAQ มี
     max-width:68ch คุมความยาวบรรทัดอยู่แล้ว การขยายกล่องจึงไม่ทำให้บรรทัดยาว */
  .faq-wrap{ display:grid; grid-template-columns:minmax(240px, 280px) 1fr; gap:clamp(32px, 4vw, 64px); align-items:start; margin:0; }
  .faq-side{ position:sticky; top:100px; }
  .faq-side .eyebrow, .faq-side h2{ text-align:left; }
  .faq-side h2{ margin-bottom:var(--space-3); }
  .faq-contact{
    margin-top:var(--space-8); background:var(--white); border:1px solid var(--line); border-radius:var(--radius-lg);
    padding:var(--space-5); box-shadow:var(--elevation-1);
  }
  .faq-contact-icon{
    width:38px; height:38px; border-radius:var(--radius-sm); background:rgba(var(--green-rgb), 0.10); color:var(--green);
    display:flex; align-items:center; justify-content:center; font-size:var(--text-base); margin-bottom:var(--space-3);
  }
  .faq-contact h3{ font-family:var(--display); font-size:var(--text-base); font-weight:var(--w-semibold); margin-bottom:var(--space-1); }
  .faq-contact p{ font-size:var(--text-sm); color:var(--gray600); line-height:var(--lh-body); margin-bottom:var(--space-3); }
  .faq-contact a{ display:inline-flex; align-items:center; gap:var(--space-2); font-size:var(--text-sm); font-weight:var(--w-medium); color:var(--green-text); }
  /* ขนาดมาจาก .link-arrow แล้ว ไม่ต้องคุมด้วย font-size ให้ 1em คำนวณต่อ */
  .faq-contact a svg{ transition:transform var(--dur-fast) var(--ease-lift); }
  .faq-contact a:hover svg{ transform:translateX(3px); }

  .faq-list{ display:flex; flex-direction:column; gap:var(--space-3); }
  .faq-item{
    background:var(--white); border:1px solid var(--line); border-radius:var(--radius-lg); overflow:hidden;
    box-shadow:var(--lift-1), var(--lift-glow); transition:border-color var(--dur-base) ease;
  }
  /* เดิมเป็น [open] ของ <details> ตอนนี้เป็นคลาสที่ JS ใส่ให้ */
  .faq-item.is-open{ border-color:rgba(var(--green-rgb), 0.45); box-shadow:var(--lift-2), var(--lift-glow); }

  .faq-q{
    cursor:pointer; width:100%; text-align:left; background:none; border:0;
    padding:var(--space-4) var(--space-5); font-family:var(--display);
    font-weight:var(--w-medium); font-size:var(--text-base);
    display:flex; align-items:center; gap:var(--space-4); color:var(--ink);
  }
  .faq-q-icon{
    flex-shrink:0; width:36px; height:36px; border-radius:var(--radius-sm); background:rgba(var(--green-rgb), 0.08); color:var(--green);
    display:flex; align-items:center; justify-content:center; font-size:var(--text-sm);
  }
  .faq-q::after{
    content:"";
    background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 6l4 4 4-4' fill='none' stroke='%23366C0A' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat:no-repeat; background-position:center; background-size:14px 14px;
    /* ต้องเป็น background-color ไม่ใช่ background แบบย่อ — ตัวย่อจะรีเซ็ต
       background-image ที่ตั้งลูกศรไว้บรรทัดบน ลูกศรเลยหายกลายเป็นวงกลมเปล่า */
    flex-shrink:0; width:30px; height:30px; border-radius:50%; background-color:rgba(var(--green-rgb), 0.10);
    display:flex; align-items:center; justify-content:center; margin-left:auto;
    transition:transform var(--dur-base) ease, background-color var(--dur-base) ease;
  }
  /* ตอนเปิด: หมุนลูกศรและเข้มพื้นขึ้น ให้เห็นสถานะจากสองทาง ไม่ใช่ทางเดียว
     ใช้ 0.30 ไม่ใช่เขียวทึบ เพราะลูกศรเป็น --green-text ซึ่งบนเขียวทึบจะกลืน
     ค่าจริงวัดใหม่หลังเปลี่ยนบันไดแล้ว ดูผลในบันทึกของ commit */
  .faq-q[aria-expanded="true"]::after{
    transform:rotate(180deg);
    background-color:rgba(var(--green-rgb), 0.30);
  }

  /* ── แผงคำตอบ ────────────────────────────────────────────────────────────
     ใช้ height ที่ JS วัดให้ ไม่ใช่ grid-template-rows 0fr -> 1fr แบบที่ ui-kit ใช้

     เทคนิค 0fr -> 1fr เป็นวิธีที่สวยที่สุดในทางทฤษฎี แต่ทดสอบแล้วมันไม่ animate
     ในเบราว์เซอร์ที่ใช้อยู่ ลองแยกด้วย element เปล่านอกหน้าเว็บก็ยังกระโดด
     จาก 0 เป็นความสูงเต็มทันที getAnimations() คืนลิสต์ว่างทั้งขาเปิดและขาปิด
     ทั้งที่ transition ประกาศไว้ 0.32s และ Chrome รุ่นนี้ควรรองรับ

     height ที่วัดด้วย JS ทำงานได้ทุกเบราว์เซอร์ ข้อเสียคือค่าจะค้างถ้าข้อความ
     reflow ตอนที่แผงเปิดอยู่ เช่นตอนหมุนจอ แก้ด้วยการตั้งกลับเป็น auto
     เมื่อ transition จบ แผงที่เปิดอยู่จึงยืดหดตามเนื้อหาได้ตามปกติ */
  .faq-panel{
    height:0; overflow:hidden;
    transition:height var(--dur-slow) var(--ease-lift);
  }
  .faq-item p{
    padding:0 var(--space-5) var(--space-5) var(--space-20); margin:0; color:var(--gray600);
    font-size:var(--text-sm); line-height:var(--lh-body); max-width:none;
    opacity:0; transition:opacity var(--dur-slow) var(--ease-lift);
  }
  .faq-q[aria-expanded="true"] + .faq-panel p{ opacity:1; }

  /* ถ้าผู้ใช้ขอลดการเคลื่อนไหว กฎคลุมข้างล่างตัด transition ออกอยู่แล้ว
     แต่ opacity:0 เป็นค่าตั้งต้นไม่ใช่ transition ต้องสั่งให้เห็นตรงๆ */
  @media (prefers-reduced-motion: reduce){
    .faq-q[aria-expanded="true"] + .faq-panel p{ opacity:1; }
  }

  @media (max-width:860px){
    .faq-wrap{ grid-template-columns:1fr; gap:var(--space-8); }
    .faq-side{ position:static; }
    .faq-side .eyebrow, .faq-side h2{ text-align:center; }
    .faq-item p{ padding-left:var(--space-5); }
  }

  /* ---------- cta ---------- */
  /* Carries .band-ink in the markup, so background, white text and the white
     eyebrow all come from there. This block only adds what is specific to it.
     It used to restate all of that by hand, which is why the pass that turned
     the dark bands white walked straight past it. */
  .ctaband{ text-align:center; padding:var(--space-25) var(--space-6); }
  .ctaband h2{ margin-bottom:var(--space-4); }
  .ctaband p{ max-width:var(--w-tight); margin:0 auto var(--space-8); font-size:var(--text-lg); }
  .cta-count{ font-size:var(--text-sm); color:var(--gray600); margin-top:var(--space-5); }

  /* ── ข้อเสนอ 10 ร้านแรกของแต่ละจังหวัด (2 ก.ย. 2569) ──────────────────
     วางไว้เหนือปุ่ม ไม่ใช่ใต้ปุ่ม เพราะเป็นเหตุผลที่ทำให้กด ไม่ใช่หมายเหตุ
     ราคาที่ขีดฆ่าใช้ <em> ไม่ใช่ <s> เพราะมันไม่ได้ "ถูกลบ" — ยังเป็นราคาจริง
     ของร้านที่ไม่เข้าเงื่อนไข การขีดฆ่าจึงทำด้วยสายตา ไม่ใช่ด้วยความหมาย */
  .offer{
    list-style:none; display:flex; flex-wrap:wrap; justify-content:center;
    /* ไม่จำกัดความกว้างเอง ปล่อยให้ .wrap-narrow เป็นตัวคุม — ที่ --w-tight
       (480px) สองชิปรวมกัน 548px จึงตกบรรทัด ดูไม่เป็นคู่กัน */
    gap:var(--space-3); margin:var(--space-8) auto 0;
  }
  .offer li{
    display:flex; align-items:center; gap:var(--space-2);
    background:var(--green-tint); border:1px solid var(--line);
    border-radius:var(--radius-lg); padding:var(--space-3) var(--space-4);
    font-size:var(--text-sm); color:var(--ink);
  }
  .offer li .icon{ width:18px; height:18px; color:var(--green-text); flex-shrink:0; }
  .offer li b{ font-weight:var(--w-semibold); }
  .offer li em{
    font-style:normal; font-size:var(--text-xs); color:var(--gray600);
    text-decoration:line-through; text-decoration-thickness:1px;
  }
  .offer-sum{ font-size:var(--text-sm); color:var(--gray600); margin:var(--space-4) auto var(--space-8); }
  .offer-sum strong{ color:var(--ink); font-weight:var(--w-semibold); }

  .addons-offer{ margin-top:var(--space-2); font-size:var(--text-sm); color:var(--green-text); }
  .addons-offer b{ font-weight:var(--w-semibold); }
  /* ป้ายบนชื่อของเสริม — เล็กแต่ต้องอ่านออก จึงไม่ใช้สีจางกว่านี้ */
  .addon-flag{
    display:inline-block; margin-left:var(--space-2);
    font-size:var(--text-2xs); font-weight:var(--w-semibold);
    color:var(--green-text); background:var(--green-tint);
    border:1px solid var(--line); border-radius:var(--radius-full);
    padding:2px var(--space-2); vertical-align:middle; white-space:nowrap;
  }

  /* ---------- footer ---------- */
  /* ── ฟุตเตอร์พื้นเขียวเข้ม (1 ก.ย. 2569) ────────────────────────────────
     เดิมเป็นพื้นเทา #F5F5F7 ซึ่งกลืนไปกับ section ที่มีคลาส .alt ข้างบน
     พื้นเข้มปิดหน้าได้ชัดกว่า และเป็นที่เดียวในหน้าที่แบรนด์ได้พื้นเต็มผืน

     ทุกสีในบล็อกนี้ผ่าน 4.5 หมด ดูตัวเลขที่ --green-deep
     ระวังตอนแก้ — วงโฟกัสของทั้งหน้าคือ --green-ui ซึ่งบนพื้นนี้ได้แค่ 2.33
     ตกเกณฑ์ 3 ของ WCAG 2.4.11 จึงต้องเขียนทับเป็นสีขาวเฉพาะในฟุตเตอร์ */
  footer{ background:var(--green-deep); color:var(--green-deep-soft);
          padding:var(--space-12) 0 var(--space-6); }
  .foot-grid{ display:flex; justify-content:space-between; gap:var(--space-10); flex-wrap:wrap; margin-bottom:var(--space-8); }
  .foot-col h3{ font-size:var(--text-xs); font-weight:var(--w-semibold); color:var(--white); margin-bottom:var(--space-3); }
  /* เดิมเขียนสีไว้เป็น inline style ซึ่งชนะทุกกฎใน stylesheet
     พอเปลี่ยนพื้นเป็นเขียวเข้ม บรรทัดนี้ยังเป็นเทา --gray600 อยู่ ได้ 1.57 */
  .foot-lede{ font-size:var(--text-sm); color:var(--green-deep-soft); }
  .foot-col a{ display:block; font-size:var(--text-sm); margin-bottom:var(--space-2); color:var(--green-deep-soft); }
  /* ลิงก์ลงทะเบียนคือการกระทำเดียวในฟุตเตอร์ที่พาไปทำอะไรต่อ
     เดิมเป็นข้อความบรรทัดหนึ่งปนกับอีเมลและเบอร์โทร มองไม่ออกว่าเป็นปุ่ม */
  /* ต้องระบุ .foot-col a.btn ไม่ใช่แค่ .btn เพราะกฎ .foot-col a ข้างบน
     มีน้ำหนัก (0,1,1) ซึ่งชนะ .btn-on-deep ที่เป็น (0,1,0)
     ลองแบบไม่ระบุแล้วตัวอักษรบนปุ่มขาวได้ 1.31 คือแทบมองไม่เห็น */
  .foot-col a.btn{ display:inline-block; width:auto; margin-bottom:var(--space-4); }
  .foot-col a.btn-on-deep{ color:var(--green-text); }
  .foot-col a.btn-on-deep:hover, .foot-col a.btn-on-deep:focus-visible{ color:var(--green-text); }
  .foot-col a:hover, .foot-col a:focus-visible{ color:var(--white); }
  .foot-bottom{ font-size:var(--text-xs); color:var(--green-deep-soft); display:flex; justify-content:space-between; flex-wrap:wrap; gap:var(--space-2); border-top:1px solid var(--green-deep-line); padding-top:var(--space-5); }
  .foot-bottom a{ color:var(--green-deep-soft); }
  .foot-bottom a:hover, .foot-bottom a:focus-visible{ color:var(--white); }
  footer :focus-visible{ outline-color:var(--white); }
  /* WCAG 2.5.8 — พื้นที่กดต้องไม่ต่ำกว่า 24x24 ข้อยกเว้นคือลิงก์ที่แทรกอยู่กลาง
     ประโยค ซึ่งสองอันนี้ไม่ใช่ กฎเดิมมีอยู่แล้วแต่อยู่แต่ใน media query ของมือถือ */
  .foot-bottom a{ display:inline-flex; align-items:center; min-height:24px; }

  /* ---------- screenshot slide carousel ---------- */
  .shot-frame{
    position:relative; width:100%; max-height:56vh; aspect-ratio:1280/800; border-radius:var(--radius-xl); overflow:hidden;
    box-shadow:0 4px 25px rgba(0,0,0,0.10); background:var(--white); will-change:transform; margin:0 auto;
  }
  .shot-img{
    position:absolute; inset:0; width:100%; height:100%; object-fit:cover; object-position:top center;
    transform:translateX(100%);
  }
  .shot-img.active{ transform:translateX(0%); }
  .feat-full{ margin-bottom:var(--space-20); }
  /* เดิมหัวข้อนี้จัดกลางด้วย inline style เขียนมือ กว้าง 620px ระยะล่าง 44px
     ทั้งสองค่าไม่มีในสเกลของหน้า และมันเป็นหัวข้อเดียวในหน้าที่จัดกลาง
     อยู่ในบล็อกที่ชิดซ้าย — สัญญาณขัดกันเอง */
  .feat-lead{ max-width:var(--w-text); margin:0 0 var(--space-12); }
  .demo-stage{
    position:relative; display:flex; align-items:center; justify-content:center;
    gap:var(--space-16); max-width:var(--w-mid); margin:0 auto; flex-wrap:wrap;
  }
  .demo-col{ flex:1; min-width:210px; max-width:270px; display:flex; flex-direction:column; align-items:center; }
  .demo-caption{
    position:relative; background:var(--ink); color:var(--white); font-family:var(--display); font-weight:var(--w-medium);
    font-size:var(--text-lg); padding:var(--space-3) var(--space-5); border-radius:var(--radius-lg); text-align:center; margin-bottom:var(--space-12);
  }
  .demo-caption::after{
    content:""; position:absolute; left:50%; bottom:-9px; transform:translateX(-50%);
    border-left:9px solid transparent; border-right:9px solid transparent; border-top:9px solid var(--ink);
  }

  .table-card{
    background:var(--white); border:1px solid var(--line); border-radius:var(--radius-xl); padding:var(--space-5);
    display:flex; flex-direction:column; align-items:center; gap:var(--space-3); width:100%;
    box-shadow:var(--elevation-float);
  }
  .qr-frame{ position:relative; padding:var(--space-4); }
  .qr-frame .corner{
    position:absolute; width:22px; height:22px; border:3px solid var(--green);
  }
  .qr-frame .corner.tl{ top:0; left:0; border-right:none; border-bottom:none; border-radius:var(--radius-sm) 0 0 0; }
  .qr-frame .corner.tr{ top:0; right:0; border-left:none; border-bottom:none; border-radius:0 8px 0 0; }
  .qr-frame .corner.bl{ bottom:0; left:0; border-right:none; border-top:none; border-radius:0 0 0 8px; }
  .qr-frame .corner.br{ bottom:0; right:0; border-left:none; border-top:none; border-radius:0 0 8px 0; }
  .qr-box{
    width:132px; height:132px; border-radius:var(--radius-sm); overflow:hidden; position:relative;
    display:grid; grid-template-columns:repeat(21,1fr); grid-template-rows:repeat(21,1fr);
    background:var(--white); padding:var(--space-1); gap:0.var(--space-1);
  }
  .qr-box .cell{ background:var(--ink); border-radius:var(--radius-sm); }
  .qr-box .cell.off{ background:transparent; }
  .qr-logo{
    position:absolute; top:50%; left:50%; transform:translate(-50%,-50%);
    width:32px; height:32px; background:var(--white); border-radius:var(--radius-sm);
    display:flex; align-items:center; justify-content:center;
    box-shadow:0 0 0 4px var(--white), 0 4px 10px rgba(0,0,0,0.15);
  }
  .qr-logo svg{ width:16px; height:16px; }
  .scan-line{
    position:absolute; left:6px; right:6px; height:2px; border-radius:var(--radius-sm);
    background:linear-gradient(90deg, transparent, var(--green) 20%, var(--green) 80%, transparent);
    box-shadow:0 0 10px 2px rgba(60,140,99,0.6);
    top:6px; animation:scanmove 2.2s ease-in-out infinite;
  }
  @keyframes scanmove{ 0%{ top:6%; } 50%{ top:90%; } 100%{ top:6%; } }
  .table-label{ font-family:var(--display); font-weight:var(--w-semibold); font-size:var(--text-sm); color:var(--gray600); }

  .phone-status{
    display:flex; justify-content:space-between; align-items:baseline;
    font-size:var(--text-2xs); font-weight:var(--w-semibold); margin-bottom:var(--space-2);
  }
  .phone-status .ps-dim{ font-weight:var(--w-regular); color:var(--gray600); font-size:10px; }
  .phone-tabs{
    display:flex; gap:var(--space-1); overflow-x:auto; margin-bottom:var(--space-2); padding-bottom:var(--space-0);
    scrollbar-width:none;
  }
  .phone-tabs::-webkit-scrollbar{ display:none; }
  .ptab{
    flex:0 0 auto; font-size:var(--text-2xs); font-weight:var(--w-medium); padding:var(--space-1) var(--space-3); border-radius:var(--radius-full);
    background:var(--grayBg); color:var(--gray600); white-space:nowrap;
  }
  .ptab.active{ background:var(--ink); color:var(--white); }

  .menu-list{
    flex:1; display:flex; flex-direction:column; gap:var(--space-0); overflow:hidden; position:relative;
    -webkit-mask-image:linear-gradient(to bottom, black 82%, transparent 100%);
    mask-image:linear-gradient(to bottom, black 82%, transparent 100%);
  }
  .menu-cat-label{
    font-size:var(--text-2xs); font-weight:var(--w-semibold); color:var(--gray600); margin:var(--space-2) 0 var(--space-1); text-transform:uppercase;
    letter-spacing:0.03em;
  }
  .menu-cat-label:first-child{ margin-top:0; }
  .menu-grid{ display:grid; grid-template-columns:1fr 1fr; gap:var(--space-2); margin-bottom:var(--space-1); }
  .menu-card{ display:flex; flex-direction:column; gap:var(--space-1); }
  .mi-thumb{
    position:relative; width:100%; aspect-ratio:1/1; border-radius:var(--radius-sm); overflow:hidden;
    background:linear-gradient(135deg, var(--grayBg), #eceef2);
    display:flex; align-items:center; justify-content:center;
  }
  .mi-thumb svg{ width:26%; height:26%; opacity:0.35; }
  .mi-badge{
    position:absolute; top:4px; right:4px; min-width:16px; height:16px; padding:0 var(--space-1);
    border-radius:var(--radius-full); background:var(--green); color:var(--white); font-size:9px; font-weight:var(--w-bold);
    display:none; align-items:center; justify-content:center;
  }
  .mi-badge.show{ display:flex; }
  .menu-card .mi-name{ font-size:var(--text-2xs); font-weight:var(--w-medium); line-height:1.25; }
  .menu-card .mi-price{ color:var(--gray600); font-size:10px; }

  .mi-badge.bump{ animation:bump var(--dur-slow) ease; }
  @keyframes bump{ 0%{ transform:scale(1);} 40%{ transform:scale(1.4);} 100%{ transform:scale(1);} }

  .confirm-combo{
    display:flex; align-items:center; justify-content:space-between; gap:var(--space-2);
    border:none; width:100%; margin-top:var(--space-2); padding:var(--space-3) var(--space-4); border-radius:var(--radius-md);
    background:var(--green); color:var(--white); font-family:var(--body); font-weight:var(--w-semibold); font-size:var(--text-sm);
    cursor:default; pointer-events:none; transition:transform var(--dur-fast) ease; text-align:left;
  }
  .confirm-combo #confirmLabel{ white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .confirm-combo #cartTotal{ flex-shrink:0; font-weight:var(--w-bold); }
  .confirm-combo:disabled{ background:var(--gray300); color:var(--gray600); }
  .confirm-combo.bump{ animation:bump var(--dur-slow) ease; }

  .kitchen-panel{
    background:var(--white); border:1px solid var(--line); border-radius:var(--radius-xl); padding:var(--space-4);
    width:100%; min-height:380px; display:flex; flex-direction:column;
    box-shadow:var(--elevation-float);
  }
  .kitchen-head{
    display:flex; justify-content:space-between; align-items:center; font-family:var(--display);
    font-weight:var(--w-semibold); font-size:var(--text-sm); margin-bottom:var(--space-3); padding-bottom:var(--space-2); border-bottom:1px solid var(--line);
  }
  .kq-badge{
    background:var(--red); color:var(--white); font-size:var(--text-2xs); font-weight:var(--w-semibold); padding:var(--space-0) var(--space-2); border-radius:var(--radius-full);
    transition:transform var(--dur-base);
  }
  .kq-badge.bump{ animation:bump var(--dur-slow) ease; }
  .kitchen-list{ width:100%; position:relative; }
  .paper-stack{ position:relative; height:290px; display:flex; flex-direction:column; justify-content:flex-end; align-items:center; }
  .kitchen-empty{ position:absolute; inset:0; display:flex; align-items:center; justify-content:center; font-size:var(--text-xs); color:var(--gray600); text-align:center; }

  .kt-card{
    background:var(--white); width:100%; padding:var(--space-4) var(--space-4) var(--space-4); border-radius:var(--radius-sm);
    box-shadow:0 -10px 24px -14px rgba(0,0,0,0.28); overflow:hidden;
    font-family:var(--body); font-size:var(--text-xs); color:var(--ink);
    transform-origin:bottom center;
    transition:opacity var(--dur-slower) var(--ease-expand), transform var(--dur-slower) var(--ease-expand),
               width var(--dur-slower) var(--ease-expand), max-height var(--dur-slower) var(--ease-expand),
               box-shadow var(--dur-slower) var(--ease-expand);
  }
  .kt-card + .kt-card{ margin-top:-var(--space-0); }
  .kt-card.kt-back{ width:88%; max-height:44px; opacity:0.4; z-index:1; }
  .kt-card.kt-mid{ width:94%; max-height:44px; opacity:0.8; z-index:2; }
  .kt-card.kt-front{ width:100%; max-height:300px; opacity:1; z-index:3; box-shadow:0 -18px 34px -16px rgba(0,0,0,0.32), 0 10px 22px -10px rgba(0,0,0,0.18); }
  .kt-row{ display:flex; justify-content:space-between; align-items:baseline; padding:var(--space-0) 0; letter-spacing:var(--track-normal); }
  .kt-row .k{ color:var(--gray600); }
  .kt-row .v{ font-weight:var(--w-medium); }
  .kt-row .v.kt-strong{ font-weight:var(--w-bold); }
  .kt-line{ height:1px; background:var(--line); margin:var(--space-2) 0; }
  .kt-items .kt-row .v{ color:var(--gray600); font-weight:var(--w-medium); }
  .kt-items .kt-row .k{ color:var(--ink); font-weight:var(--w-semibold); }
  .kt-card.kt-incoming{
    width:100%; max-height:0; opacity:0; z-index:3;
  }
  .kt-card.kt-exit{
    opacity:0 !important; transform:translateY(-28px) !important; max-height:0 !important;
    padding-top:0 !important; padding-bottom:0 !important; margin-top:-var(--space-0) !important;
    transition:opacity var(--dur-slow) var(--ease-collapse), transform var(--dur-slow) var(--ease-collapse),
               max-height var(--dur-slow) var(--ease-collapse) 40ms, padding var(--dur-slow) var(--ease-collapse) 40ms;
  }

  .flying-ticket{
    position:absolute; z-index:var(--z-raised); background:var(--ink); color:var(--white); border-radius:var(--radius-sm);
    padding:var(--space-2) var(--space-3); font-size:var(--text-2xs); font-weight:var(--w-semibold); pointer-events:none;
    box-shadow:0 10px 24px -8px rgba(0,0,0,0.4); transition:transform var(--dur-reveal) var(--ease-out), opacity var(--dur-reveal) ease;
  }
  .demo-stat{
    text-align:center; font-size:var(--text-sm); color:var(--gray600); margin-top:var(--space-6);
  }
  .demo-stat b{ color:var(--green); }

  @media (max-width:1300px) and (min-width:861px){
    .stack-card-inner{ grid-template-columns:minmax(260px,480px) 1fr; gap:var(--space-10); padding:clamp(24px, 6vh, 64px) 24px; }
    .f-text .tag{ font-size:var(--text-base); margin-bottom:var(--space-3); }
    .f-text h3{ font-size:var(--text-2xl); margin-bottom:var(--space-3); }
    .f-text p{ font-size:var(--text-base); margin-bottom:var(--space-3); }
    .flist li{ font-size:var(--text-sm); padding:var(--space-1) 0 var(--space-1) var(--space-6); }
    .flist li::before{ top:5px; font-size:var(--text-sm); }
  }
  @media (max-width:860px){
    .demo-stage{ flex-direction:column; align-items:center; }
    .demo-col{ max-width:280px; }
    .hero-sub{ font-size:var(--text-lg); }
    h2{ font-size:var(--text-2xl); }
    .feat, .feat.rev{ grid-template-columns:1fr; gap:var(--space-8); }
    .feat.rev .f-visual, .feat.rev .f-text{ order:initial; }
    .stack-card-inner{ grid-template-columns:1fr; gap:var(--space-6); padding:var(--space-8) var(--space-6); }
    .price-grid{ grid-template-columns:1fr; }
    .navlinks{ display:none; }
    .device-screen{ grid-template-columns:1fr; }
    .d-rail{ display:none; }
    .d-side{ border-left:none; border-top:1px solid var(--line); }
    .gallery{ grid-template-columns:1fr 1fr; height:auto; }
    .gallery .g1{ grid-row:auto; grid-column:1/3; height:200px; }
    .photo-slot{ height:150px; }
  }

  /* ============================================================
     ENHANCEMENT LAYER — mobile audit + conversion polish
     Additive only: matches existing tokens (green --green, Prompt/
     IBM Plex faces, 980px pills, glass nav). Does not alter the
     finished desktop layout.
     ============================================================ */

  /* --- keep hand-tuned nowrap on desktop, allow wrap on narrow screens --- */
  .nowrap-lg{ white-space:nowrap; }
  @media (max-width:640px){
    .nowrap-lg{ white-space:normal; }
    h1{ white-space:normal; }
    .cover-sub{ white-space:normal; }
  }

  /* --- mobile nav: hamburger trigger (hidden on desktop) --- */
  .nav-hamburger{
    display:none; width:42px; height:42px; border-radius:var(--radius-md);
    align-items:center; justify-content:center; flex-direction:column; gap:var(--space-1);
    background:transparent; border:1px solid transparent; margin-left:var(--space-0);
    transition:background var(--dur-fast);
  }
  .nav-hamburger:hover{ background:rgba(0,0,0,0.04); }
  .nav-hamburger span{
    display:block; width:20px; height:2px; border-radius:var(--radius-sm); background:var(--ink);
    transition:transform var(--dur-slow) var(--ease-in-out), opacity var(--dur-base) ease;
  }
  body.drawer-open .nav-hamburger span:nth-child(1){ transform:translateY(7px) rotate(45deg); }
  body.drawer-open .nav-hamburger span:nth-child(2){ opacity:0; }
  body.drawer-open .nav-hamburger span:nth-child(3){ transform:translateY(-7px) rotate(-45deg); }

  /* --- mobile drawer --- */
  .drawer-backdrop{
    position:fixed; inset:0; z-index:var(--z-overlay); background:rgba(0,0,0,0.42);
    backdrop-filter:blur(2px); opacity:0; visibility:hidden;
    transition:opacity var(--dur-slow) ease, visibility var(--dur-slow) ease;
  }
  body.drawer-open .drawer-backdrop{ opacity:1; visibility:visible; }
  .mobile-drawer{
    position:fixed; top:0; right:0; bottom:0; z-index:var(--z-drawer);
    width:min(360px, 84vw); background:var(--white);
    box-shadow:var(--elevation-4); padding:22px 24px calc(28px + env(safe-area-inset-bottom));
    display:flex; flex-direction:column;
    transform:translateX(100%); transition:transform var(--dur-slower) var(--ease-in-out);
  }
  body.drawer-open .mobile-drawer{ transform:translateX(0); }
  .drawer-head{ display:flex; align-items:center; justify-content:space-between; margin-bottom:var(--space-5); }
  .drawer-close{
    width:40px; height:40px; border-radius:var(--radius-sm); display:flex; align-items:center;
    justify-content:center; font-size:var(--text-xl); color:var(--ink); background:transparent;
    transition:background var(--dur-fast);
  }
  .drawer-close:hover{ background:rgba(0,0,0,0.06); }
  .drawer-links{ display:flex; flex-direction:column; }
  .drawer-links a{
    font-size:var(--text-lg); font-weight:var(--w-medium); color:var(--ink); padding:var(--space-4) var(--space-1);
    border-bottom:1px solid var(--line); transition:color var(--dur-fast), padding-left var(--dur-base);
  }
  .drawer-links a:hover{ color:var(--ink); padding-left:var(--space-2); }
  .drawer-cta{ display:flex; flex-direction:column; gap:var(--space-3); margin-top:auto; padding-top:var(--space-6); }
  .drawer-cta .btn{ width:100%; text-align:center; border-radius:var(--radius-lg); padding:var(--space-3) var(--space-5); font-size:var(--text-base); }

  /* --- sticky mobile CTA bar (conversion) --- */
  .mobile-cta-bar{
    display:none; position:fixed; left:0; right:0; bottom:0; z-index:var(--z-sticky-bar);
    padding:12px 16px calc(12px + env(safe-area-inset-bottom));
    /* ความทึบ 0.9 ไม่พอ — ตอนแถบลอยทับแถบเขียว พื้นที่ผสมแล้วคือ rgb(235,242,231)
       ข้อความรอง --gray600 บนพื้นนั้นได้ 4.44 คือตกเกณฑ์ 4.5 ที่ 0.97 ได้ 4.87 */
    background:rgba(255,255,255,0.97); backdrop-filter:saturate(180%) blur(14px);
    border-top:1px solid var(--line);
    align-items:center; justify-content:space-between; gap:var(--space-3);
    transform:translateY(115%); transition:transform var(--dur-slower) var(--ease-enter);
  }
  .mobile-cta-bar.visible{ transform:translateY(0); }
  .mcb-text{ line-height:var(--lh-tight); }
  .mcb-text b{ font-family:var(--display); font-weight:var(--w-semibold); font-size:var(--text-base); color:var(--ink); }
  .mcb-text span{ display:block; font-size:var(--text-xs); color:var(--gray600); }
  .mobile-cta-bar .btn{ flex-shrink:0; border-radius:var(--radius-lg); padding:var(--space-3) var(--space-5); font-size:var(--text-base); font-weight:var(--w-semibold); }

  /* --- show mobile chrome, hide desktop nav bits, below 860 --- */
  @media (max-width:860px){
    .nav-hamburger{ display:flex; }
    .nav-lang{ display:none; }
    .navcta .btn{ display:none; }
    .mobile-cta-bar{ display:flex; }
  }

  /* --- hide the comparison-table header row once stacked (icons+colour
         already distinguish old vs new per row) --- */
  @media (max-width:640px){

    .switch-old, .switch-new{ padding-top:var(--space-3); padding-bottom:var(--space-3); }
    .switch-label{ padding-bottom:var(--space-1); }
  }

  /* --- phone breakpoint: density + stacking the desktop layer misses --- */
  @media (max-width:480px){
    section{ padding:var(--space-16) 0; }
    #membership{ padding:var(--space-16) 0; }
    #trust-stats{ padding:var(--space-10) 0; }
    .ctaband{ padding:var(--space-20) var(--space-5); }
    .wrap, .wrap-narrow{ padding:0 var(--space-4); }

    h1{ line-height:var(--lh-tight); margin-bottom:var(--space-4); }
    .hero{ padding:var(--space-12) 0 0; }
    .hero-sub{ font-size:var(--text-base); margin-bottom:var(--space-6); }
    h2{ font-size:var(--text-2xl); }
    .s-head{ margin:0 auto var(--space-10); }
    .s-head p{ font-size:var(--text-base); }

    .hero-actions{ flex-direction:column; gap:var(--space-3); padding:0 var(--space-1); }
    .hero-actions .btn{ width:100%; text-align:center; }
    .hero-cta-text{ justify-content:center; }

    .cover-heading{ font-size:var(--text-3xl); }
    .cover-sub{ font-size:var(--text-lg); margin-top:var(--space-4); }

    .price-card{ padding:var(--space-6) var(--space-6); }
    .testi-card{ padding:var(--space-6) var(--space-6); }
    .foot-grid{ gap:var(--space-6); }
    .foot-col{ flex:1 1 40%; }

    /* leave clearance so the sticky CTA never hides the footer legal line */
    footer{ padding-bottom:var(--space-25); }
  }

  /* --- respect reduced-motion for the new chrome --- */
  @media (prefers-reduced-motion: reduce){
    /* The floor: nothing eases, nothing travels. Kept as a blanket rule so a
       component added later is covered without anyone remembering to. */
    *, *::before, *::after{
      animation-duration:0.01ms !important;
      animation-delay:0s !important;
      transition-duration:0.01ms !important;
      transition-delay:0s !important;
      scroll-behavior:auto !important;
    }

    /* A blanket rule is not the whole job. An infinite animation has to be
       stopped rather than run at 0.01ms, or it spins invisibly forever and
       keeps the compositor awake. */
    .logo-track, .scanline, .kitchen-scan{ animation:none !important; }
    [style*="animation"]{ animation:none !important; }

    /* กฎคลุมข้างบนแค่ตัด transition ออก ซึ่งแปลว่าการ์ดยัง "กระโดด" ขึ้น 8px
       ทันทีที่เมาส์แตะ — ไม่มี transition ไม่ได้แปลว่าไม่มีการเคลื่อนไหว
       ที่ยกทั้งหมดจึงต้องถูกสั่งไม่ให้ขยับตรงๆ เงายังลึกขึ้นได้ตามเดิม
       เพราะเงาไม่ใช่การเคลื่อนไหว และมันคือตัวบอกว่าชี้อยู่ตรงไหน */
    .price-card:hover, .price-card:focus-within, .price-card:active{
      transform:none;
    }
    .navlinks a:not(.nav-active)::after{ transform:scaleX(0); }
    .navlinks a:not(.nav-active):hover::after,
    .navlinks a:not(.nav-active):focus-visible::after{ transform:scaleX(1); }
    .hero-cta-text:hover .cta-arrow, .hero-cta-text:focus-visible .cta-arrow,
    .faq-contact a:hover svg, .faq-contact a:focus-visible svg{ transform:none; }
    /* ยกเว้นตัวนี้ — 90° ไม่ใช่แอนิเมชัน แต่เป็นทิศของลูกศร ถ้าล้างทิ้งจะกลายเป็นชี้ขวา */
    .bizday-arrow{ transform:rotate(90deg); }
    .btn:active{ transform:none; }

    /* Reveal-on-scroll starts at opacity 0 and is switched on by an observer.
       With motion off, do not wait for it — the content must simply be there,
       or a reader who never triggers the observer sees an empty page. */
    .reveal, .caption-pop{
      opacity:1 !important; transform:none !important;
    }

    /* Nothing here forces transform:none on the scroll-jack. Its transforms
       are LAYOUT, not decoration — the five cards are position:absolute on one
       origin and cards 2-5 are held 812px down by a translate. Remove that and
       all four land exactly on card 1, so four sections' content vanishes.
       Reduced motion must never cost a reader the content; the blanket rule
       above already takes the easing off, and the positions stay. */
  }

  /* ============================================================
     MENU FEATURES — two sections (เมนูแนะนำ / เซ็ตคอมโบ)
     text + swappable image slot; brand tokens.
     ============================================================ */
  .mf-split{ display:grid; grid-template-columns:1fr 1fr; gap:clamp(32px, 4vw, 64px); align-items:center; }
  .mf-text h2{ margin-bottom:var(--space-4); }
  .mf-text p{ font-size:var(--text-base); color:var(--gray600); line-height:var(--lh-loose); margin-bottom:var(--space-5); }
  .mf-pts{ list-style:none; padding:0; margin:0; display:flex; flex-direction:column; gap:var(--space-3); }
  .mf-pts li{ font-size:var(--text-base); color:var(--ink); display:flex; align-items:flex-start; gap:var(--space-3); line-height:var(--lh-body); }
  .mf-pts li svg{ color:var(--green-ui); font-size:var(--text-sm); margin-top:var(--space-1); flex-shrink:0; }
  .mf-pts li > span{ min-width:0; }
  .mf-imgslot{ position:relative; aspect-ratio:4/3; background:var(--grayBg); border:1px solid var(--line); border-radius:var(--radius-xl); overflow:hidden; box-shadow:var(--elevation-2); display:flex; align-items:center; justify-content:center; }
  section.alt .mf-imgslot{ background:var(--white); }
  .mf-imgslot img{ width:100%; height:100%; object-fit:cover; display:block; }
  .mf-imgslot-hint{ display:flex; flex-direction:column; align-items:center; gap:var(--space-2); color:var(--gray600); text-align:center; padding:var(--space-4); }
  .mf-imgslot-hint svg{ font-size:var(--text-3xl); opacity:0.45; }
  .mf-imgslot-hint span{ font-size:var(--text-sm); }

  @media (max-width:860px){
    .mf-split{ grid-template-columns:1fr; gap:var(--space-8); }
    .mf-split-rev .mf-text{ order:-1; }
  }

  /* ── Lower-half rhythm ───────────────────────────────────────────────────
     The five sections from ร้านแบบไหน down to แพ็กเกจ used to run 3,600px of
     unbroken white with every heading centred — the same flatness the upper
     half was reworked to escape, just further down the page, and on the half
     where the reader is deciding whether to buy.

     The comparison table carries the dark band because it is the one section
     whose content is literally a confrontation: แบบเดิม against NubTang POS. Putting
     the page's darkest moment there also means แพ็กเกจ arrives on white
     straight after it, and reads as the way out. */

  /* เดิมมีกฎที่นี่ให้ตารางรับสีเทา โดยให้เหตุผลว่า section เป็นขาว ตารางจึงต้อง
     ใช้สีต่างเพื่อแยกตัวเอง — ถอดออกแล้ว เพราะหน้านี้มีตัวอย่างที่ค้าน:
     .tiers-scroll เป็นตารางขาววางบน #pricing ที่ขาวเหมือนกัน และแยกตัวได้
     ด้วยเส้นขนหนูอย่างเดียว ตารางเปรียบเทียบจึงใช้แบบเดียวกันได้
     ผลคือแผงทุกอันในหน้าเป็นขาวเหมือนกันหมด ไม่มีอันไหนเป็นแผ่นเทาโดดออกมา */

  /* The checklist is five questions asked in order, so it is set as a list a
     reader works down, with the heading held beside it rather than stacked
     above — the numbers already earn their place, and now they have a column
     to run down. */
  .checklist-wrap{
    display:grid;
    grid-template-columns:minmax(280px, 380px) 1fr;
    gap:var(--space-16);
    align-items:start;
  }
  .checklist-head{ position:sticky; top:120px; margin-bottom:0; }
  .checklist-wrap .checklist-grid{ margin:0; }

  @media (max-width: 1024px){
    .checklist-wrap{ grid-template-columns:1fr; gap:var(--space-10); }
    .checklist-head{ position:static; }
  }

  /* ── Measure ─────────────────────────────────────────────────────────────
     Two blocks of running text had no width cap and were being set to the
     full container: the activity-log note ran about 168 characters a line and
     the FAQ answers about 97, against a comfortable 65-75. Long lines are hard
     to track back to the start of, which is the failure mode you feel as "this
     is a wall of text" rather than as a typographic problem. */
  .log-note{ max-width:62ch; }
  .faq-item p, .faq-a{ max-width:68ch; }

  /* ── Touch targets ───────────────────────────────────────────────────────
     On a phone the two แพ็กเกจ buttons measured 38px tall — the smallest
     targets on the page were the two that close the sale. Everything a finger
     has to hit now clears 44px, which is the floor both Apple and Material
     set, and the footer links get vertical room so they stop being a stack of
     20px strips a thumb has to aim between. */
  @media (max-width: 768px){
    .btn{ min-height:44px; }
    .seg button{ min-height:44px; }
    .foot-col a{ padding:var(--space-3) 0; margin-bottom:0; }
    .faq-contact a{ display:inline-block; padding:var(--space-3) 0; }
    /* the legal links added with the footer are real targets too. 12px of
       padding around an 11px line left them at 41px — three short — so the
       height is set outright rather than inferred from the padding. */
    .foot-bottom a{
      display:inline-flex; align-items:center; min-height:44px;
      padding:var(--space-3) 0;
    }
    /* icon-only controls carry no text to grow them, so they are sized directly */
    .nav-hamburger, .drawer-close{ min-width:44px; min-height:44px; }
  }

  /* ── Featured-menu mock ──────────────────────────────────────────────────
     Shows the three things the copy beside it promises — a pinned dish on
     top, a struck-through promo price, and an item marked sold out — using
     the page's own tokens. Built rather than photographed because the stock
     shots available all show another company's app. */
  .pin-demo{ width:100%; height:100%; padding:var(--space-6); display:flex; flex-direction:column; justify-content:center; gap:var(--space-3); }
  .pin-demo-head{ display:flex; gap:var(--space-2); margin-bottom:var(--space-1); }
  .pin-demo-tab{
    font-size:var(--text-xs); font-weight:var(--w-medium); color:var(--gray600);
    background:rgba(0,0,0,0.045); border-radius:var(--radius-full); padding:var(--space-1) var(--space-3);
  }
  .pin-demo-tab.is-on{ background:var(--ink); color:var(--white); }
  .pin-card{
    position:relative; display:flex; align-items:center; gap:var(--space-3);
    background:var(--white); border:1px solid var(--line);
    border-radius:var(--radius-lg); padding:var(--space-2) var(--space-3); box-shadow:var(--shadow-xs);
  }
  .pin-card.is-pinned{ border-color:rgba(var(--green-rgb), 0.42); box-shadow:0 4px 16px rgba(var(--green-rgb), 0.13); }
  .pin-card.is-out{ opacity:0.55; }
  .pin-badge{
    position:absolute; top:-9px; left:12px; font-size:var(--text-2xs); font-weight:var(--w-semibold); letter-spacing:0.02em;
    background:var(--green-text); color:var(--white); border-radius:var(--radius-full); padding:var(--space-0) var(--space-2);
  }
  .pin-thumb{
    width:46px; height:46px; border-radius:var(--radius-sm); flex-shrink:0;
    background:linear-gradient(135deg, #e8e8ea 0%, #f4f4f6 100%);
  }
    /* brand-100 -> brand-50 ของแอป แทนสองค่าที่เคยเขียนมือไว้ */
  .pin-card.is-pinned .pin-thumb{ background:linear-gradient(135deg, #E1F2D1 0%, #F2F9EC 100%); }
  .pin-body{ flex:1; min-width:0; display:flex; align-items:center; justify-content:space-between; gap:var(--space-2); }
  .pin-name{ font-size:var(--text-sm); font-weight:var(--w-medium); color:var(--ink); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .pin-price{ display:flex; align-items:baseline; gap:var(--space-2); flex-shrink:0; font-family:var(--num); }
  .pin-price s{ font-size:var(--text-xs); color:var(--gray600); }
  .pin-price b{ font-size:var(--text-sm); font-weight:var(--w-semibold); color:var(--ink); }
  .pin-out{ font-size:var(--text-2xs); color:var(--gray600); }

  @media (max-width:520px){
    .pin-demo{ padding:var(--space-4); gap:var(--space-2); }
    .pin-thumb{ width:38px; height:38px; }
  }

  /* Contact lines that are still placeholders read as unfinished, not as links */
  /* ห้ามใส่ opacity ตรงนี้ — ลองแล้วที่ 0.75 สีจริงกลายเป็น rgb(170,196,150)
     ได้ 4.17 ตกเกณฑ์ และด่านตรวจชั้นที่ 2 จับไม่ได้เพราะมันอ่านแต่ค่า color
     ตัวเอียงกับคำว่า "รอใส่ข้อมูลจริง" บอกอยู่แล้วว่ายังใช้ไม่ได้ */
  .foot-col a.foot-mock{ color:var(--green-deep-soft); cursor:default; font-style:italic; }

  /* ── Icons ───────────────────────────────────────────────────────────────
     27 symbols inlined as a sprite in the document, replacing a
     render-blocking stylesheet from an external CDN that shipped the entire
     Font Awesome set for the 27 glyphs this page uses.

     Named `icon` and not `ic`: `.d-rail .ic` already exists for the decorative
     squares in the demo mockup, and reusing it silently restyled them.

     An <svg> does not inherit font-size the way the <i> it replaced did, so
     the box is pinned to 1em and the paint follows currentColor — that keeps
     every existing font-size and color rule working untouched. */
  svg.icon{
    width:1em; height:1em; fill:currentColor;
    display:inline-block; vertical-align:-0.125em; flex-shrink:0;
  }

  /* ── Running-text floor ──────────────────────────────────────────────────
     The FAQ answers and the activity-log rows are sentences, and they were
     set at 14px, which is the label size. On a phone that is below the 16px
     floor this system sets for anything read rather than scanned, so they
     step up there. They stay at 14 on a desktop, where the same text is read
     from half the distance. */
  @media (max-width: 768px){
    .faq-item p, .faq-a{ font-size:var(--text-base); }
    .log-what{ font-size:var(--text-base); }
    .log-note{ font-size:var(--text-base); }
    .checklist-a{ font-size:var(--text-base); }
  }
