/* ═══════════════════════════════════════════════════════════════════════
   tims-ui.css — คลังคอมโพเนนต์ของระบบ
   🔴 ไฟล์นี้ถูก "สร้าง" ขึ้นจาก design/Prototype_TIMS.html — ห้ามแก้ตรงนี้
      แก้ที่ต้นแบบแล้วรัน: node design/extract_ui.js
   ═══════════════════════════════════════════════════════════════════════ */

*{box-sizing:border-box;}
html,body{margin:0;padding:0;}
body{font-family:var(--sans);color:var(--ink);background:var(--paper);
  -webkit-font-smoothing:antialiased;line-height:1.55;font-size:var(--fs-3);}
h1,h2,h3,h4{font-family:var(--serif);font-weight:600;letter-spacing:-.01em;color:var(--ink);margin:0;line-height:1.18;}
/* 🔴 UI-02 · <small> ที่ไม่ได้กำหนดขนาดเอง จะได้ค่า "smaller" ของเบราว์เซอร์ = 0.83 เท่าของแม่
   ⇒ อยู่ในกล่อง 13px ก็ตกไปเหลือ 10.8px เอง โดยที่ไม่มีใครเขียนตัวเลขนั้นไว้ที่ไหนเลย
   (วัดจริงหลังวางสเกล: เหลือข้อความต่ำกว่า 12px อยู่ 479 จุด เป็น <small> ทั้งหมด)
   ⇒ ตรึงไว้ที่ขั้นเล็กสุดของสเกล ให้เป็นพื้นล่างจริง ๆ ไม่ใช่พื้นที่เลื่อนไปตามแม่ */
small{font-size:var(--fs-1);}
.serif{font-family:var(--serif);}
a{text-decoration:none;color:inherit;}
button{font-family:inherit;cursor:pointer;}
:focus-visible{outline:2.5px solid var(--accent);outline-offset:2px;border-radius:4px;}
.eyebrow{font-size:var(--fs-1);font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--accent);}
.muted{color:var(--ink-3);}
svg.i{width:1em;height:1em;stroke:currentColor;fill:none;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round;
  flex-shrink:0;vertical-align:-.135em;}
.paper-bg{background-color:var(--paper);
  background-image:radial-gradient(rgba(58,74,119,.06) 1px, transparent 1.4px);background-size:22px 22px;}

/* ─────────── ปุ่ม (ยกจาก it-cil-ds.css) ─────────── */
.btn{font-family:var(--sans);font-weight:600;font-size:var(--fs-3);border:1.5px solid transparent;border-radius:var(--r2);
  padding:.6rem 1.1rem;display:inline-flex;align-items:center;justify-content:center;gap:.5rem;cursor:pointer;
  text-decoration:none;transition:all .18s ease;white-space:nowrap;line-height:1.2;}
.btn-pri{background:var(--accent-btn);color:var(--on-accent);box-shadow:0 4px 12px color-mix(in srgb,var(--accent) 28%,transparent);}
.btn-pri:hover{background:var(--accent-btn-h);transform:translateY(-1px);}
/* ค-1: พื้นปุ่มใช้เฉดเข้ม (ขาวบน --terra ได้ 3.49:1 ซึ่งไม่ผ่าน · บน --terra-dark ได้ 6.07:1) */
.btn-terra{background:var(--terra-dark);color:var(--on-accent);box-shadow:0 4px 12px rgba(191,93,56,.28);}
.btn-terra:hover{background:var(--terra-deep);transform:translateY(-1px);}
.btn-ghost{background:var(--surface);color:var(--ink);border-color:var(--line);}
.btn-ghost:hover{border-color:var(--accent);color:var(--accent);background:var(--accent-soft);}
.btn-soft{background:var(--accent-soft);color:var(--accent-dark);}
/* ค-1: ขาวบน --ok ได้ 4.02:1 ไม่ผ่าน · บน --ok-deep ได้ 4.91:1 (--bad ผ่านอยู่แล้วที่ 4.64:1) */
.btn-ok{background:var(--ok-deep);color:var(--on-accent);} .btn-bad{background:var(--bad);color:var(--on-accent);}
.btn-block{width:100%;}
.btn-sm{padding:.42rem .8rem;font-size:var(--fs-2);border-radius:var(--r1);}
.btn-lg{padding:.78rem 1.4rem;font-size:var(--fs-4);}
.icon-btn{width:40px;height:40px;border-radius:var(--r2);border:1.5px solid var(--line);background:var(--surface);
  color:var(--ink-2);display:inline-flex;align-items:center;justify-content:center;font-size:var(--fs-4);transition:.15s;}
.icon-btn:hover{border-color:var(--accent);color:var(--accent);}

/* ─────────── การ์ด / ป้าย / แถบ ─────────── */
.card{background:var(--surface);border:1px solid var(--line);border-radius:var(--r3);box-shadow:var(--sh-1);}
.card-pad{padding:22px 24px;}
.badge{display:inline-flex;align-items:center;gap:5px;font-size:var(--fs-1);font-weight:600;padding:3px 10px;
  border-radius:var(--pill);background:var(--surface-2);color:var(--ink-2);}
.badge.ok{background:var(--ok-soft);color:var(--ok-ink);}
.badge.warn{background:var(--warn-soft);color:var(--warn-ink);}
.badge.bad{background:var(--bad-soft);color:var(--bad-ink);}
.badge.draft{background:var(--paper-2);color:var(--ink-3);}
.badge.accent{background:var(--accent-soft);color:var(--accent-dark);}
.badge.terra{background:var(--terra-soft);color:var(--terra-dark);}

/* ── ชิปสถานะแบบเด่น (CR-3) ─────────────────────────────────────────────
   จุดสีนำหน้าทำให้ "กวาดตาหาของที่ค้าง" ได้โดยไม่ต้องอ่านตัวอักษร
   ใช้เฉพาะจุดที่สถานะคือข้อมูลหลักของบรรทัด · ที่อื่นใช้ .badge เหมือนเดิม */
.schip{display:inline-flex;align-items:center;gap:7px;font-size:var(--fs-1);font-weight:700;
  padding:4px 11px 4px 9px;border-radius:var(--pill);border:1px solid transparent;white-space:nowrap;}
.schip-dot{width:7px;height:7px;border-radius:50%;flex-shrink:0;background:currentColor;}
.schip-big{font-size:var(--fs-3);padding:7px 15px 7px 12px;}
.schip-big .schip-dot{width:9px;height:9px;}
.schip-ok{background:var(--ok-soft);color:var(--ok-ink);border-color:color-mix(in srgb,var(--ok) 30%,transparent);}
.schip-warn{background:var(--warn-soft);color:var(--warn-ink);border-color:color-mix(in srgb,var(--warn) 35%,transparent);}
.schip-bad{background:var(--bad-soft);color:var(--bad-ink);border-color:color-mix(in srgb,var(--bad) 32%,transparent);}
.schip-draft{background:var(--paper-2);color:var(--ink-3);border-color:var(--line);}
.schip-accent{background:var(--accent-soft);color:var(--accent-dark);border-color:color-mix(in srgb,var(--accent) 28%,transparent);}

/* ── แถบสรุปตัวเลขสถานะ (CR-5) ──────────────────────────────────────────
   เดิมเป็นข้อความบรรทัดเดียวคั่นด้วยจุด ตัวเล็ก ป้ายกำกับสีเทาจางเท่ากันหมด
   ⇒ ผู้ใช้ต้องอ่านทีละคำถึงจะรู้ว่าอะไรค้าง */
.sumbar{display:flex;flex-wrap:wrap;gap:10px;align-items:stretch;margin-bottom:16px;}
.sumbar-i{display:flex;flex-direction:column;gap:2px;padding:10px 16px;border-radius:var(--r2);
  border:1px solid var(--line);background:var(--surface);min-width:96px;}
.sumbar-n{font-size:var(--fs-5);font-weight:800;line-height:1.1;}
.sumbar-l{font-size:var(--fs-1);font-weight:600;color:var(--ink-3);}
.sumbar-ok{background:var(--ok-soft);border-color:color-mix(in srgb,var(--ok) 30%,transparent);}
.sumbar-ok .sumbar-n,.sumbar-ok .sumbar-l{color:var(--ok-ink);}
.sumbar-warn{background:var(--warn-soft);border-color:color-mix(in srgb,var(--warn) 35%,transparent);}
.sumbar-warn .sumbar-n,.sumbar-warn .sumbar-l{color:var(--warn-ink);}
.sumbar-bad{background:var(--bad-soft);border-color:color-mix(in srgb,var(--bad) 32%,transparent);}
.sumbar-bad .sumbar-n,.sumbar-bad .sumbar-l{color:var(--bad-ink);}
.sumbar-note{align-self:center;font-size:var(--fs-2);color:var(--ink-3);margin-left:auto;}

/* ── หัวเรื่องบริบท (CR-2) ─────────────────────────────────────────────── */
.hero{display:flex;align-items:flex-start;justify-content:space-between;gap:18px;flex-wrap:wrap;
  padding:20px 24px;margin-bottom:22px;border-radius:var(--r3);background:var(--surface);
  border:1px solid var(--line);border-left:5px solid var(--accent);box-shadow:var(--sh-1);}
.hero-main{flex:1;min-width:0;}
.hero-eyebrow{font-size:var(--fs-1);font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  /* ค-1: ใช้เฉดเข้มของบทบาท — บทบาทอาจารย์นิเทศก์ตั้ง --accent เป็นสีส้ม
     ซึ่งเป็นสีข้อความได้แค่ 3.4:1 · --accent-dark ของทุกบทบาทผ่านเกณฑ์หมด */
  color:var(--accent-dark);margin-bottom:5px;}
.hero-title{font-size:var(--fs-6);line-height:1.3;margin:0;font-weight:700;}
.hero-chips{display:flex;flex-wrap:wrap;gap:7px;margin-top:11px;}
.hero-chip{display:inline-flex;align-items:center;gap:6px;font-size:var(--fs-2);font-weight:600;
  padding:4px 11px;border-radius:var(--pill);background:var(--paper-2);color:var(--ink-2);
  border:1px solid var(--line);}
.hero-chip svg{font-size:var(--fs-3);color:var(--ink-3);}
.hero-right{display:flex;flex-direction:column;align-items:flex-end;gap:9px;}
/* 🔴 DP-01 (15 ก.ย. 69): บนจอแคบ .hero-main ยุบได้ถึง 0 (flex:1 = basis 0%) ป้ายสถานะฝั่งขวา
   จึงยึดพื้นที่ไว้ 160px แล้วบีบหัวเรื่องเหลือ 111px — ชื่อวิชาภาษาไทยตกบรรทัดละ 1–2 ตัว
   หัวเรื่องเดียวสูง 175px (วัดจริงที่จอ 375px) ⇒ บังคับให้ทั้งสองฝั่งกินเต็มบรรทัดแล้วตกบรรทัดกัน */
@media(max-width:560px){
  .hero-main{flex:1 1 100%;}
  .hero-right{flex:1 1 100%;align-items:flex-start;}
}
/* จุดไล่ระดับบอกว่าอยู่ครั้งที่เท่าไรของหลักสูตร — เห็นตำแหน่งตัวเองโดยไม่ต้องคิดเลข */
.hero-steps{display:flex;align-items:center;gap:6px;margin-top:12px;}
.hero-step{width:26px;height:5px;border-radius:3px;background:var(--line);flex-shrink:0;}
.hero-step.done{background:var(--ok);}
.hero-step.now{background:var(--accent);box-shadow:0 0 0 3px var(--accent-soft);}
.hero-steps-t{font-size:var(--fs-2);color:var(--ink-3);margin-left:5px;}
.hero-steps-t b{color:var(--ink);}

/* ── รายการงานแบบแถว (CR-4) ─────────────────────────────────────────────
   ปุ่มเข้าไปอยู่ขวาสุดของทุกแถว — ตำแหน่งเดียวกันทุกบรรทัด กดไม่พลาด */
.tk-list{display:flex;flex-direction:column;border:1px solid var(--line);border-radius:var(--r2);overflow:hidden;}
.tkrow{display:flex;align-items:center;gap:14px;padding:13px 16px;background:var(--surface);
  border:none;border-bottom:1px solid var(--line-2);font:inherit;text-align:left;cursor:pointer;
  transition:.15s;width:100%;border-left:4px solid transparent;}
.tkrow:last-child{border-bottom:none;}
.tkrow:hover{background:var(--accent-soft);}
.tkrow.on{background:var(--accent-soft);border-left-color:var(--accent);}
.tkrow.approved{border-left-color:var(--ok);}
.tkrow.submitted{border-left-color:var(--warn);}
.tkrow.rejected{border-left-color:var(--bad);}
.tkrow-n{width:30px;height:30px;flex-shrink:0;border-radius:9px;display:grid;place-items:center;
  background:var(--paper-2);color:var(--ink-3);font-size:var(--fs-2);font-weight:700;}
.tkrow.approved .tkrow-n{background:var(--ok-soft);color:var(--ok-ink);}
.tkrow.submitted .tkrow-n{background:var(--warn-soft);color:var(--warn-ink);}
.tkrow.rejected .tkrow-n{background:var(--bad-soft);color:var(--bad-ink);}
.tkrow-body{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px;}
.tkrow-t{font-size:var(--fs-3);font-weight:600;color:var(--ink);line-height:1.45;}
.tkrow-meta{font-size:var(--fs-1);color:var(--ink-3);display:flex;align-items:center;gap:5px;}
.tkrow-meta svg{font-size:var(--fs-3);}
.tkrow-st{flex-shrink:0;}
.tkrow-go{width:32px;height:32px;flex-shrink:0;border-radius:50%;display:grid;place-items:center;
  background:var(--paper-2);color:var(--ink-3);transition:.15s;}
.tkrow:hover .tkrow-go{background:var(--accent);color:var(--on-accent);}
/* 🔴 DP-01 (15 ก.ย. 69): บนจอแคบแถวงานถูกบีบจนชื่องานเหลือกว้าง 46px
   ตัวหนังสือไทยตกบรรทัดละ 1–2 ตัว แถวเดียวสูง 344px (วัดจริงที่จอ 375px)
   ⇒ ยอมให้ตกบรรทัด: บรรทัดบน = เลขงาน + ชื่องานเต็มความกว้าง · บรรทัดล่าง = สถานะ + ลูกศร
   (คั่นบรรทัดด้วย ::after ที่กิน 100% — วิธีมาตรฐานของ flex-wrap ไม่ต้องเพิ่มโหนดในมาร์กอัป) */
@media(max-width:560px){
  .tkrow{flex-wrap:wrap;gap:8px 10px;}
  .tkrow-n{order:1;}
  .tkrow-st{order:2;}
  /* ลูกศรท้ายแถวเป็นของซ้ำบนจอสัมผัส — ทั้งแถวเป็นปุ่มอยู่แล้ว และมันกินอีกหนึ่งบรรทัดต่อแถว */
  .tkrow-go{display:none;}
  .tkrow-body{order:3;flex:1 1 100%;}
}

/* ── คะแนนแยกรายแบบประเมิน (CR-8) ───────────────────────────────────────
   ยอดรวมก้อนเดียวบอกไม่ได้ว่าชุดไหนได้เท่าไร และชุดที่ยังไม่กรอกทำให้ร้อยละเพี้ยน */
.scorelist{display:flex;flex-direction:column;gap:16px;}
.scoreitem-h{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;}
.scoreitem-t{font-size:var(--fs-3);font-weight:600;color:var(--ink);flex:1;min-width:0;}
.scoreitem-n{font-size:var(--fs-4);font-weight:800;color:var(--ink);white-space:nowrap;}
.scoreitem-n .muted{font-size:var(--fs-2);font-weight:600;}
.scoreitem-sub{font-size:var(--fs-2);color:var(--ink-3);margin-top:3px;display:flex;align-items:center;gap:5px;}
.scorebar{height:8px;border-radius:4px;background:var(--paper-2);overflow:hidden;margin-top:8px;}
.scorebar i{display:block;height:100%;border-radius:4px;transition:width .3s;}
.scorebar i.hi{background:var(--ok);}
.scorebar i.mid{background:var(--warn);}
.scorebar i.lo{background:var(--bad);}
.scorebar i.none{background:transparent;}

/* แถบไปงานก่อนหน้า/ถัดไป — แยกหน้าแล้วต้องไม่ทำให้คลิกเยอะขึ้น (ความเสี่ยงที่จดไว้ในแผน) */
.taskflip{display:flex;justify-content:space-between;gap:10px;margin-top:18px;padding-top:16px;
  border-top:1px solid var(--line-2);}

/* ── ปฏิทินการฝึก (CR-6 · CR-7) ─────────────────────────────────────────
   วันที่เป็นบล็อกซ้ายมือ อ่านง่ายกว่าข้อความในบรรทัด · แถวที่ใกล้ถึงมีขอบเน้น */
.callist{display:flex;flex-direction:column;}
.calrow{display:flex;align-items:center;gap:14px;padding:13px 0;border-bottom:1px solid var(--line-2);}
.calrow:last-child{border-bottom:none;}
.calrow.near{background:var(--warn-soft);margin:0 -14px;padding-left:14px;padding-right:14px;
  border-radius:var(--r2);border-bottom-color:transparent;}
.calrow-body{flex:1;min-width:0;}
.calrow-body>b{font-size:var(--fs-3);}
.calrow-meta{font-size:var(--fs-2);color:var(--ink-3);margin-top:3px;display:flex;align-items:center;gap:5px;}
.calrow-tags{display:flex;flex-wrap:wrap;gap:6px;margin-top:7px;}
.callist-past{opacity:.72;}

/* ── ตารางปฏิทินรายเดือน (เจ้าของงานส่งภาพตัวอย่างมา 22 ส.ค. 2569) ────── */
.calhead{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-bottom:12px;}
.calhead-t{font-size:var(--fs-4);}
.calhead-nav{display:flex;align-items:center;gap:6px;}
.calhead-nav .act:first-child svg{transform:rotate(180deg);}
.calgrid{display:grid;grid-template-columns:repeat(7,1fr);gap:1px;background:var(--line);
  border:1px solid var(--line);border-radius:var(--r2);overflow:hidden;}
.cdow{background:var(--paper-2);padding:7px 6px;text-align:center;font-size:var(--fs-1);
  font-weight:700;color:var(--ink-3);}
/* 🔴 ช่องวัน "สูงเท่ากันทุกช่อง" (เจ้าของงานเคาะ 28 ส.ค. 69) — ล็อกความสูง overflow ซ่อน
   เนื้อหาเกินโควตา 3 แถว ยุบเป็น "+N" · ข้อความยาวตัดด้วย … · ไม่ปล่อยให้เนื้อหาดันช่องสูง */
/* EC-01 (15 ก.ย. 69): ทั้งช่องยังกดได้เหมือนเดิม แต่ตัวที่รับคลิกเป็น "ปุ่มจริง" ที่ซ้อนเต็มช่อง
   (.cday-fill) ⇒ เดินถึงด้วย Tab และกด Enter/Space ได้ · ของในช่อง (เลขวัน · ชิป · แถบช่วง)
   ต้อง position:relative เพื่อให้ลอยอยู่เหนือปุ่มนั้น ไม่งั้นกดชิปตรง ๆ ไม่ได้อีกต่อไป */
.cday{background:var(--surface);height:118px;padding:5px 5px 4px;display:flex;flex-direction:column;
  gap:2px;overflow:hidden;position:relative;}
.cday-fill{position:absolute;inset:0;width:100%;height:100%;padding:0;margin:0;border:0;
  background:none;cursor:pointer;border-radius:inherit;}
.cday-n,.cchip,.cbar,.cmore{position:relative;}
.cday.out{background:var(--paper);opacity:.5;}
.cday.today{background:var(--accent-soft);box-shadow:inset 0 0 0 2px var(--accent);}
.cday-n{font-size:var(--fs-2);font-weight:700;color:var(--ink-2);text-align:right;line-height:1;margin-bottom:1px;}
.cday.today .cday-n{color:var(--accent-dark);}
/* ชิปกิจกรรม — ปุ่มคลิกได้ · ตัดข้อความบรรทัดเดียวด้วย … · สูงคงที่ ไม่ดันช่อง */
.cchip{display:flex;align-items:center;width:100%;height:19px;border:none;border-radius:4px;
  padding:0 5px;font-family:inherit;font-size:var(--fs-1);font-weight:600;text-align:left;cursor:pointer;
  line-height:1;flex-shrink:0;margin:0;appearance:none;}
.cchip>span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0;}
.cchip:hover{filter:brightness(.96);}
.cchip-span{box-shadow:inset 3px 0 0 color-mix(in srgb,currentColor 55%,transparent);}
/* แถบบางของช่วงที่ทะลุผ่านวันกลาง — ไม่มีข้อความ ไม่นับโควตา 3 แถว */
.cbar{height:5px;border-radius:2px;flex-shrink:0;}
.cmore{font-size:var(--fs-1);font-weight:600;color:var(--accent-dark);padding:0 5px;cursor:pointer;
  line-height:1.4;flex-shrink:0;border:0;background:none;font-family:inherit;text-align:left;width:100%;}
.cmore:hover{text-decoration:underline;}
.cday.has{cursor:pointer;}
.cday.has:hover{background:var(--paper);}
.cday.today.has:hover{background:var(--accent-soft);}

/* ── ไล่ระดับสีตามความใกล้ (ใช้ทั้งแถบวาระซ้าย · แถบในตาราง · ป๊อบอัป) ──
   red→orange→amber→neutral · past = จาง · สื่อ "อีกกี่วันจะถึง" เท่านั้น */
.tier-now{background:var(--bad-soft);color:var(--bad-ink);}
.tier-week{background:var(--terra-soft);color:var(--terra-dark);}
.tier-two{background:var(--warn-soft);color:var(--warn-ink);}
.tier-far{background:var(--paper-2);color:var(--ink-3);}
.tier-past{background:var(--paper-2);color:var(--ink-3);}
/* จุดสีนำหน้า (การ์ดแถบวาระ + ป๊อบอัป) */
.tier-dot{width:9px;height:9px;border-radius:50%;flex-shrink:0;}
.tier-now .tier-dot,.dot-now{background:var(--bad);}
.tier-week .tier-dot,.dot-week{background:var(--terra);}
.tier-two .tier-dot,.dot-two{background:var(--warn);}
.tier-far .tier-dot,.dot-far{background:var(--ink-4);}
.tier-past .tier-dot,.dot-past{background:var(--ink-4);}

/* ── สีของกำหนดการในตารางเดือน (ผู้สร้างเลือกเอง) — ชิป=พื้นอ่อน+ตัวเข้ม · แถบช่วง=สีทึบ ── */
.cchip.ccol-blue{background:var(--cal-blue-soft);color:var(--cal-blue-ink);} .cbar.ccol-blue{background:var(--cal-blue);}
.cchip.ccol-green{background:var(--ok-soft);color:var(--ok-ink);} .cbar.ccol-green{background:var(--ok);}
.cchip.ccol-orange{background:var(--terra-soft);color:var(--terra-dark);} .cbar.ccol-orange{background:var(--terra);}
.cchip.ccol-amber{background:var(--warn-soft);color:var(--warn-ink);} .cbar.ccol-amber{background:var(--warn);}
.cchip.ccol-red{background:var(--bad-soft);color:var(--bad-ink);} .cbar.ccol-red{background:var(--bad);}
.cchip.ccol-purple{background:var(--cal-purple-soft);color:var(--cal-purple-ink);} .cbar.ccol-purple{background:var(--cal-purple);}
/* จุดสีในป๊อบอัปรายวัน + ตัวเลือกสีในฟอร์ม */
.cdot-blue{background:var(--cal-blue);} .cdot-green{background:var(--ok);} .cdot-orange{background:var(--terra);}
.cdot-amber{background:var(--warn);} .cdot-red{background:var(--bad);} .cdot-purple{background:var(--cal-purple);}
.colpick{display:flex;gap:8px;flex-wrap:wrap;}
.colpick label{cursor:pointer;}
.colpick input{position:absolute;opacity:0;width:0;height:0;}
.colsw{width:30px;height:30px;border-radius:50%;display:inline-block;border:2px solid transparent;
  box-shadow:0 0 0 1px var(--line);transition:.12s;}
.colpick input:checked + .colsw{border-color:var(--surface);box-shadow:0 0 0 2px var(--ink);transform:scale(1.08);}

/* ── ป๊อบอัปรายละเอียดกำหนดการ ── */
.evtpop{display:flex;flex-direction:column;gap:9px;}
.evtpop-when{display:inline-flex;align-items:center;gap:7px;align-self:flex-start;
  font-size:var(--fs-2);font-weight:700;padding:5px 12px;border-radius:var(--pill);}
.evtpop-row{display:flex;align-items:flex-start;gap:8px;font-size:var(--fs-3);color:var(--ink-2);}
.evtpop-row svg{flex-shrink:0;margin-top:2px;color:var(--ink-3);}
/* รายการทั้งวันในป๊อบอัป — คลิกแต่ละแถวเปิดรายละเอียด */
.cdaylist{display:flex;flex-direction:column;gap:8px;}
.cdayrow{display:flex;align-items:center;gap:10px;width:100%;border:1px solid var(--line-2);
  border-radius:10px;padding:10px 12px;background:var(--surface);font-family:inherit;
  text-align:left;cursor:pointer;}
.cdayrow:hover{border-color:var(--accent);background:var(--accent-soft);}
.cdayrow-b{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px;}
.cdayrow-b b{font-size:var(--fs-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.cdayrow-b small{font-size:var(--fs-1);color:var(--ink-3);}
.cdayrow>svg:last-child{color:var(--ink-4);flex-shrink:0;}

/* ── แถบวาระด้านซ้าย (ไล่ระดับสีตามความใกล้) ── */
.calwrap{display:grid;grid-template-columns:270px 1fr;gap:18px;align-items:start;}
.agenda{display:flex;flex-direction:column;gap:10px;}
.agenda-sec{font-size:var(--fs-1);font-weight:700;letter-spacing:.08em;text-transform:uppercase;
  color:var(--ink-3);padding:2px 2px 0;}
/* การ์ดใบใหญ่ "ใกล้ที่สุด" */
.agnext{border:2px solid;border-radius:var(--r2);padding:13px 15px;background:var(--surface);cursor:pointer;}
.agnext-when{font-size:var(--fs-6);font-weight:800;line-height:1.05;}
.agnext-t{font-size:var(--fs-4);font-weight:700;line-height:1.4;margin:5px 0 4px;}
.agnext-m{font-size:var(--fs-2);color:var(--ink-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
/* การ์ดย่อในรายการถัดไป — ตัดขอบซ้ายสีตามความใกล้ */
.agrow{display:flex;align-items:center;gap:10px;width:100%;border:1px solid var(--line-2);
  border-left:3px solid;border-radius:0 10px 10px 0;padding:8px 11px;background:var(--surface);
  font-family:inherit;text-align:left;cursor:pointer;}
.agrow:hover{background:var(--paper);}
.agrow-b{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px;}
.agrow-b b{font-size:var(--fs-2);font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.agrow-b small{font-size:var(--fs-1);color:var(--ink-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.ag-now{border-color:var(--bad);} .ag-now .agnext-when{color:var(--bad-ink);}
.ag-week{border-color:var(--terra);} .ag-week .agnext-when{color:var(--terra-dark);}
.ag-two{border-color:var(--warn);} .ag-two .agnext-when{color:var(--warn-ink);}
.ag-far{border-color:var(--line);} .ag-far .agnext-when{color:var(--ink-3);}
.ag-more{border:none;background:none;font-family:inherit;font-size:var(--fs-2);font-weight:600;
  color:var(--accent-dark);cursor:pointer;padding:4px 2px;text-align:left;min-height:40px;}
.ag-more:hover{text-decoration:underline;}
@media(max-width:900px){ .calwrap{grid-template-columns:1fr;} }
/* สลับมุมมองปฏิทิน/รายการ + การ์ดรายการจัดการ (Phase 3 · 7 ก.ย. 69) */
.seg-toggle{display:inline-flex;background:var(--surface-2);border:1px solid var(--line);
  border-radius:var(--pill);padding:3px;gap:2px;margin-bottom:16px;}
.seg{border:none;background:transparent;font-family:inherit;font-size:var(--fs-2);font-weight:600;
  color:var(--ink-3);padding:6px 15px;border-radius:var(--pill);cursor:pointer;
  display:inline-flex;align-items:center;gap:6px;transition:.15s;}
.seg:hover{color:var(--ink-2);}
.seg.on{background:var(--surface);color:var(--ink);box-shadow:var(--sh-1);}
/* 🔴 ADD-19 (18 ก.ย. 69): เดิมครอบแค่ ≤700 (โทรศัพท์) — แต่แท็บเล็ตก็เป็นจอสัมผัส
   เกณฑ์เป้ากด 40px จึงต้องครอบถึง 900 ด้วย · เจอจากการเพิ่มขนาดแท็บเล็ตเข้าชุดตรวจจอ
   (ก่อนหน้านี้ไม่มีใครเคยเปิดดูที่ 820px เลยสักครั้ง จึงไม่มีใครเห็นว่าสวิตช์นี้เหลือ 28px) */
@media(max-width:900px){.seg{min-height:40px;}}
.cal-list{display:flex;flex-direction:column;gap:10px;}
.cal-lc{display:flex;align-items:center;gap:14px;padding:13px 16px;background:var(--surface);
  border:1px solid var(--line);border-left:3px solid var(--accent);border-radius:var(--r2);box-shadow:var(--sh-1);}
.cal-lc.past{opacity:.62;border-left-color:var(--line-2);}
.cal-lc-main{flex:1;min-width:0;}
.cal-lc-main b{display:block;font-size:var(--fs-3);}
.cal-lc-main small{display:block;color:var(--ink-3);font-size:var(--fs-2);margin-top:2px;}
.cal-lc-aud{flex-shrink:0;}
.cal-lc-act{flex-shrink:0;display:flex;gap:6px;align-items:center;}
@media(max-width:700px){.cal-lc{flex-wrap:wrap;}.cal-lc-main{flex:1 1 100%;}}
/* แถบตัวกรองปฏิทินหน้าแรก */
.hcal-bar{display:flex;flex-wrap:wrap;gap:10px;margin-bottom:14px;align-items:center;}
.hcal-fld{display:flex;align-items:center;gap:7px;background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r2);padding:0 10px;color:var(--ink-3);}
.hcal-fld svg{flex-shrink:0;font-size:var(--fs-4);}
.hcal-fld .inp{border:none;background:none;padding:9px 4px;min-width:120px;font-weight:600;color:var(--ink);}
.hcal-fld .inp:focus{outline:none;box-shadow:none;}

/* การ์ด "ใกล้ถึงที่สุด" — ตัวเลขวันเป็นสิ่งที่ตาเห็นก่อน ไม่ใช่ชื่อกิจกรรม
   เพราะคำถามแรกคือ "เหลือเวลาเท่าไร" แล้วค่อยอ่านว่าเรื่องอะไร */
.nextcard.urgent{border-color:color-mix(in srgb,var(--terra) 45%,var(--line));
  box-shadow:0 0 0 1px color-mix(in srgb,var(--terra) 22%,transparent);}
.nextcard-when{font-size:var(--fs-6);font-weight:800;line-height:1.15;color:var(--ink-3);margin-top:4px;}
.nextcard.urgent .nextcard-when{color:var(--terra-dark);}
.nextcard-t{font-size:var(--fs-4);font-weight:700;line-height:1.45;margin:6px 0 10px;}
.nextcard-meta{font-size:var(--fs-2);color:var(--ink-3);display:flex;align-items:center;gap:6px;margin-top:4px;}

/* ── แถบ "ตอนนี้อยู่จุดไหน" ตามปฏิทินของรายวิชา ──────────────────────────
   เส้นเดียวอ่านจากซ้ายไปขวา — หมุดที่ผ่านแล้วทึบ · หมุดถัดไปเน้น · ที่เหลือจาง */
.cbone{display:flex;gap:0;overflow-x:auto;padding-bottom:6px;}
.cbone-i{flex:1;min-width:118px;position:relative;padding:0 8px;text-align:center;
  display:flex;flex-direction:column;align-items:center;gap:5px;}
.cbone-i::before{content:'';position:absolute;top:7px;left:0;right:50%;height:2px;background:var(--line);}
.cbone-i::after{content:'';position:absolute;top:7px;left:50%;right:0;height:2px;background:var(--line);}
.cbone-i:first-child::before,.cbone-i:last-child::after{display:none;}
.cbone-i.done::before,.cbone-i.done::after{background:var(--ok);}
.cbone-dot{width:16px;height:16px;border-radius:50%;background:var(--surface);
  border:2px solid var(--line);position:relative;z-index:1;flex-shrink:0;}
.cbone-i.done .cbone-dot{background:var(--ok);border-color:var(--ok);}
.cbone-i.now .cbone-dot{background:var(--accent);border-color:var(--accent);
  box-shadow:0 0 0 4px var(--accent-soft);}
.cbone-t{font-size:var(--fs-1);font-weight:600;line-height:1.4;color:var(--ink-3);}
.cbone-i.done .cbone-t{color:var(--ink-2);}
.cbone-i.now .cbone-t{color:var(--accent-dark);font-weight:700;}
.cbone-d{font-size:var(--fs-1);color:var(--ink-3);}
@media(max-width:900px){
  /* จอแคบ: ช่องเตี้ยลง ชิปเหลือแค่แถบสีบอกว่ามีของ (ตัวอักษรอ่านไม่ไหวอยู่แล้ว)
     — ยังคลิกเปิดป๊อบอัปได้ · แถบวาระด้านบนคือทางอ่านรายละเอียดบนมือถือ */
  .cday{height:52px;padding:3px;gap:1px;}
  .cday-n{font-size:var(--fs-1);}
  /* EC-01 (15 ก.ย. 69): บนจอแคบชิปเหลือแค่แถบสี 5px — เล็กเกินกว่าจะเป็นเป้ากดของนิ้ว
     ⇒ ให้แตะทะลุไปโดนปุ่มเต็มช่อง (.cday-fill สูง 52px) ที่เปิดรายการทั้งวันแทน
     (ตัดออกจากลำดับ Tab ด้วย ที่ applyCalChips — CSS สั่งเรื่องโฟกัสไม่ได้) */
  .cchip,.cmore{pointer-events:none;}
  .cchip{height:5px;font-size:0;padding:0;border-radius:3px;}
  .cchip-span{box-shadow:none;}
  .cbar{height:3px;}
  .cmore{font-size:0;height:5px;padding:0;background:var(--ink-4);border-radius:3px;opacity:.5;}
}
.rolepill{display:inline-flex;align-items:center;gap:6px;font-size:var(--fs-1);font-weight:600;padding:4px 11px;border-radius:var(--pill);}
.rolepill .dot{width:8px;height:8px;border-radius:50%;}
.role-student{background:var(--pine-soft);color:var(--pine-dark);} .role-student .dot{background:var(--pine);}
.role-supervisor{background:var(--terra-soft);color:var(--terra-dark);} .role-supervisor .dot{background:var(--terra);}
.role-committee{background:var(--amber-soft);color:var(--amber-dark);} .role-committee .dot{background:var(--amber);}
.role-admin{background:var(--plum-soft);color:var(--plum);} .role-admin .dot{background:var(--plum);}
.bar{height:9px;border-radius:var(--pill);background:var(--paper-2);overflow:hidden;}
.bar > i{display:block;height:100%;border-radius:var(--pill);
  background:linear-gradient(90deg,var(--accent),var(--accent-dark));transition:width .5s ease;}
.chip{display:inline-flex;align-items:center;gap:6px;font-size:var(--fs-2);font-weight:500;padding:6px 13px;border-radius:var(--pill);
  background:var(--surface);border:1.5px solid var(--line);color:var(--ink-2);transition:.15s;}
.chip:hover{border-color:var(--accent);color:var(--accent);}
.chip.on{background:var(--accent);border-color:var(--accent);color:var(--on-accent);}

/* ─────────── เปลือกแอป (dash.css) ─────────── */
.shell{position:relative;display:grid;grid-template-columns:var(--rail) 1fr;background:var(--paper);
  min-height:calc(100vh - 47px);}
/* 🐛 เดิมไม่มี sticky — เมนูเลื่อนหายไปพร้อมหน้าเมื่อเนื้อหายาว
   (แถบบนมี sticky อยู่แล้ว เหลือแต่เมนูที่หลุด ผู้ใช้จึงต้องเลื่อนกลับขึ้นไปหาเมนูทุกครั้ง)
   47px = ความสูงแถบเครื่องมือโปรโตไทป์ด้านบนสุด */
.rail{background:var(--surface);border-right:1px solid var(--line);display:flex;flex-direction:column;
  position:sticky;top:47px;height:calc(100vh - 47px);min-height:0;}
.rail-brand{display:flex;align-items:center;gap:11px;padding:18px 18px 16px;border-bottom:1px solid var(--line-2);}
/* A-9 (12 ก.ย. 69): .brand-mark เดิมทำหน้าที่ 2 อย่างปนกัน (โลโก้จริง + ไอคอนสถานะ) — แยกเป็น
   .brand-logo-synth (ตราสังเคราะห์ตอนยังไม่มีโลโก้จริง — หน้าตาต้องเหมือน .brand-mark เดิมทุกพิกเซล)
   กับ .status-mark (ไอคอนสถานะ 403/ปิดปรับปรุง/ตั้งรหัสครั้งแรก — ไม่เกี่ยวกับโลโก้ องค์กรเลย) ใช้ CSS ร่วมกัน */
.brand-logo-synth,.status-mark{width:42px;height:42px;border-radius:13px;flex-shrink:0;display:flex;align-items:center;justify-content:center;
  background:linear-gradient(140deg,var(--pine),var(--pine-deep));color:var(--terra);font-size:var(--fs-5);box-shadow:var(--sh-1);position:relative;}
.brand-logo-synth::after,.status-mark::after{content:'';position:absolute;inset:0;border-radius:13px;box-shadow:inset 0 0 0 1px rgba(255,255,255,.12);}
/* โลโก้จริง — ไหลตามสัดส่วนไฟล์เสมอ ห้าม aspect-ratio ตายตัว ห้าม cover (ครอบ/ตัดภาพ) */
.brand-logo{display:inline-flex;align-items:center;flex-shrink:0;}
.brand-logo img{height:var(--logo-h,42px);width:auto;max-width:var(--logo-maxw,150px);object-fit:contain;display:block;}
/* ── ตราหน่วยงาน (มหาวิทยาลัย + คณะ · 14 ก.ย. 69) ──
   สีของตราทั้งสอง (ทอง/เขียว) ไม่ใช่สีของระบบ (น้ำเงิน Pine + ส้ม Terra) และแก้สีตราไม่ได้ตามระเบียบ
   ⇒ วางในโซนที่เป็นทางการซึ่งแยกจาก UI สีแบรนด์เสมอ ไม่แทรกปนกับปุ่ม/แถบสีของระบบ */
.seal-row{display:inline-flex;align-items:center;justify-content:center;gap:14px;}
/* ชุดวางตรา: ตรา | เส้นแบ่งแนวตั้ง | ชื่อคณะ/มหาวิทยาลัย 2 บรรทัด — ไวยากรณ์เดียวกับแบบ
   "หัวกระดาษเอกสาร" ใน design/tims-logo-maker.html (ตราไม่ลอยเดี่ยว ๆ ต้องมีข้อความล็อกคู่เสมอ) */
/* แถบรายละเอียดของประกาศรายชื่อ — บอกให้ครบว่าเป็นประกาศของรหัสไหน รายวิชาอะไร ครั้งที่เท่าไร
   (เจ้าของงานสั่ง 14 ก.ย. 69: ประกาศต้องอ่านแล้วรู้ทันทีว่าเป็นของกลุ่มไหน ไม่ต้องเดา) */
.dur-row{display:flex;align-items:center;gap:10px;margin-bottom:8px;}
.dur-row-l{width:78px;flex:none;color:var(--ink-2);font-size:var(--fs-3);}
.dur-row .d-flex{flex:1;}
.rr-miss{margin-top:5px;font-size:var(--fs-1);color:var(--ink-3);line-height:1.4;}
/* หนังสือส่งตัว (ขั้นที่ 6) — เอกสารราชการ ฉบับละโรงเรียน */
.ref-doc{background:var(--surface-plain);border:1px solid var(--line);border-radius:var(--r3);padding:34px 38px;margin-bottom:22px;}
.ref-p{font-size:var(--fs-3);line-height:1.95;text-indent:2.2em;margin:0 0 10px;}
.ref-p b{font-weight:600;}
.ref-sign{margin-top:26px;text-align:center;margin-left:auto;width:270px;font-size:var(--fs-3);line-height:2;}
.ref-line{border-bottom:1px dotted var(--ink-3);margin:26px 10px 6px;}
.ref-foot{margin-top:18px;padding-top:10px;border-top:1px dashed var(--line);font-size:var(--fs-1);color:var(--ink-3);text-align:right;}
@media print{ .ref-doc{border:0;padding:0;break-after:page;} }
/* ── ผังขั้นตอนของรายวิชา (14 ก.ย. 69) — 1 ไป 2 ไป 3 ตามลำดับเวลา ── */
.stepper{list-style:none;margin:0;padding:0;position:relative;}
.step{position:relative;display:flex;gap:14px;padding:0 0 14px 0;}
.step:not(:last-child)::before{content:'';position:absolute;left:15px;top:32px;bottom:0;width:2px;background:var(--line);}
.step-n{position:relative;z-index:1;flex:none;width:32px;height:32px;border-radius:50%;display:grid;place-items:center;
  font-family:var(--serif);font-weight:700;font-size:var(--fs-3);background:var(--surface-2);color:var(--ink-3);
  border:2px solid var(--line);}
.step-done .step-n{background:var(--ok-soft);color:var(--ok-ink);border-color:var(--ok);}
.step-prog .step-n{background:var(--warn-soft);color:var(--warn-ink);border-color:var(--warn);}
.step-b{flex:1;min-width:0;background:var(--surface);border:1px solid var(--line);border-radius:var(--r3);
  padding:12px 15px;box-shadow:var(--sh-1);}
.step-mine .step-b{border-color:var(--pine-soft);box-shadow:var(--sh-2);}
/* CR-33.2 · ล็อกอ่อน — ขั้นที่ "ขั้นก่อนหน้ายังไม่ถึง 90%" จางลงให้เห็นว่ายังไม่ถึงคิว
   แต่ยังกดเข้าไปทำได้ (ไม่ใช้ pointer-events:none โดยตั้งใจ) */
/* CR-33.13 · กิจกรรม (วันจริง) ที่ผูกอยู่ใต้แผนของรายวิชา */
.calrow-acts{display:flex;flex-wrap:wrap;gap:6px;margin-top:6px;}
.calrow-acts .badge{display:inline-flex;align-items:center;gap:4px;}
.act-xs{width:22px;height:22px;min-height:22px;padding:0;margin-left:2px;}
.act-xs .i{width:12px;height:12px;}
/* CR-33.14 (17 ก.ย. 69) · มุมมองของนักศึกษา — ขั้นที่ไม่ใช่งานของเขา ยุบเป็นแถวบาง
   บอกแค่ว่า "กำลังรอใคร" ไม่ให้ขั้นของคนอื่นมาแย่งพื้นที่ขั้นที่เขาต้องลงมือเอง */
.step-thin .step-b{padding:9px 13px;background:var(--surface-2);box-shadow:none;}
.step-thin .step-h b{font-size:var(--fs-2);font-weight:600;color:var(--ink-2);}
.step-thin .step-n{width:26px;height:26px;font-size:var(--fs-2);}
.step-thin .step-wait{margin:4px 0 0;font-size:var(--fs-1);color:var(--ink-3);display:flex;align-items:flex-start;gap:5px;}
.step-thin .step-wait .i{flex:0 0 auto;margin-top:2px;}
/* จอแคบ: คำอธิบายกระบวนการของแต่ละขั้นซ้ำกับสถานะที่เห็นอยู่แล้ว — ย่อทิ้งเฉพาะผังของนักศึกษา
   (บทบาทอื่นทำงานบนจอคอมเป็นหลัก จึงไม่แตะ) */
@media (max-width:700px){ .stepper-mine .step-d{display:none;} }
/* CR-33.14 รอบสอง (17 ก.ย. 69 · เจ้าของงานสั่ง "ย้ายการทำงาน ส่งงาน เข้าดูอะไรต่าง ๆ ไปอยู่ในขั้นตอนการฝึกของฉัน")
   แผงงาน (ขั้น 7) และแผงผล (ขั้น 9) ย้ายจากใต้ผังเข้ามาอยู่ในตัวขั้นแล้ว
   🔴 การ์ดซ้อนในการ์ดจะได้กรอบสองชั้น + ระยะขอบสองชั้น ⇒ ถอดเปลือกของการ์ดชั้นในทิ้ง
      เหลือแค่เส้นคั่นบอกว่าเป็นคนละบล็อก (ไม่แตะ .card ทั่วไป ซึ่งใช้อีก 400+ จุดทั้งระบบ) */
.step-panel{margin-top:12px;}
.step-panel>.card{background:transparent;border:0;box-shadow:none;border-radius:0;padding:0;margin-bottom:0;}
.step-panel>.card+.card{margin-top:14px;padding-top:12px;border-top:1px solid var(--line);}
.step-soft .step-b{opacity:.62;}
.step-soft:hover .step-b,.step-soft:focus-within .step-b{opacity:1;}
.step-soft-note{margin:6px 0 0;color:var(--ink-3);font-size:var(--fs-2);display:flex;gap:6px;align-items:flex-start;}
.step-soft-note .i{flex:0 0 auto;margin-top:2px;}
.step-h{display:flex;align-items:center;gap:9px;flex-wrap:wrap;}
.step-h b{font-size:var(--fs-4);}
.step-who{font-size:var(--fs-1);font-weight:600;padding:2px 9px;border-radius:var(--pill);background:var(--surface-2);color:var(--ink-2);}
.who-fac{background:var(--plum-soft);color:var(--plum);}
.who-com{background:var(--amber-soft);color:var(--amber-dark);}
.who-sup{background:var(--terra-soft);color:var(--terra-dark);}
.who-stu{background:var(--pine-soft);color:var(--pine);}
.step-st{margin-left:auto;font-size:var(--fs-2);font-weight:600;padding:2px 10px;border-radius:var(--pill);flex:none;}
/* ADD-23: 5 สถานะต้องแยกออกจากกันด้วยตาโดยไม่ต้องอ่าน — เรียงความ "ร้อน" จากซ้ายไปขวา
   ติดขัด (แดง) → ยังไม่ครบ (เหลือง) → กำลังดำเนินการ (ฟ้า) → เสร็จแล้ว (เขียว) → ยังไม่ถึงช่วง (เทา) */
.st-done{background:var(--ok-soft);color:var(--ok-ink);}
.st-short{background:var(--warn-soft);color:var(--warn-ink);}
.st-prog{background:var(--accent-soft);color:var(--accent-dark);}
.st-block{background:var(--bad-soft);color:var(--bad-ink);}
.st-wait{background:var(--surface-2);color:var(--ink-3);}
/* ข้อความรายละเอียดต่อท้ายสถานะ — เป็นคำอธิบาย ไม่ใช่ตัวสถานะ จึงต้องเบากว่า */
.step-stx{font-size:var(--fs-1);color:var(--ink-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%;}
/* ADD-24: ป้ายผู้เกี่ยวข้องรายฝ่าย */
/* ADD-21: บรรทัดข้อมูลย่อยบนการ์ด — ฉลากซ้าย ค่าขวา อ่านกวาดตาได้เร็ว */
/* ADD-22: แถบ "ดูอย่างเดียว" — ต้องเห็นตั้งแต่ก่อนอ่านตาราง ไม่ใช่ไปเจอตอนหาปุ่มแก้ไม่เจอ */
.tip.view-only{align-items:center;}
.tip.view-only .btn{flex:none;margin-left:auto;}
.job-lines{display:flex;flex-direction:column;gap:4px;margin-top:9px;width:100%;}
.job-line{display:flex;align-items:baseline;justify-content:space-between;gap:10px;
  font-size:var(--fs-1);color:var(--ink-3);border-bottom:1px dashed var(--line-2);padding-bottom:3px;}
.job-line:last-child{border-bottom:none;}
.job-line b{color:var(--ink);font-weight:700;white-space:nowrap;}
/* การ์ดที่เป็นแผงข้อมูล ไม่ใช่ปุ่ม — ต้องไม่มีอาการ hover ที่ทำให้นึกว่ากดได้ */
.job-card.job-info{cursor:default;}
.job-card.job-info:hover{border-color:var(--line);box-shadow:var(--sh-1);transform:none;}
.step-parties{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px;}
.step-party{display:inline-flex;align-items:center;gap:5px;font-size:var(--fs-1);font-weight:600;
  padding:3px 10px;border-radius:var(--pill);background:var(--surface-2);color:var(--ink-3);
  border:1px solid var(--line-2);}
.step-party .i{width:13px;height:13px;flex:none;}
.step-party small{font-weight:500;opacity:.85;}
.step-party.pt-done{background:var(--ok-soft);color:var(--ok-ink);border-color:transparent;}
.step-party.pt-own{border-color:var(--accent);}
.step-d{margin:5px 0 0;font-size:var(--fs-2);color:var(--ink-2);line-height:1.5;}
.step-gap{margin:6px 0 0;font-size:var(--fs-2);color:var(--warn-ink);display:flex;align-items:center;gap:6px;}
.step-gap .i{width:14px;height:14px;flex:none;}
.step-note{margin:7px 0 0;font-size:var(--fs-2);color:var(--ink-3);display:flex;align-items:center;gap:6px;}
.step-note .i{width:14px;height:14px;flex:none;}
.step-acts{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px;}
@media (max-width:700px){
  .step{gap:10px;}
  .step-st{margin-left:0;}
}
/* แถบบันทึกลอย (มาตรฐาน "ทุกหน้าต้องกดบันทึก") — ลอยอยู่ล่างจอ เห็นตลอดจนกว่าจะกดบันทึก */
.pend-bar{position:sticky;bottom:14px;z-index:30;display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  margin:16px 0 4px;padding:12px 16px;border-radius:var(--r3);background:var(--surface);
  border:1.5px solid var(--warn);box-shadow:var(--sh-3);}
.pend-bar .i{width:18px;height:18px;color:var(--warn-ink);flex:none;}
.pend-tx{flex:1;min-width:180px;font-size:var(--fs-3);}
.pend-tx b{color:var(--warn-ink);}
.pend-dot{display:inline-block;width:8px;height:8px;border-radius:50%;background:var(--warn);
  margin-left:7px;vertical-align:middle;flex:none;}
tr.pend-row > td{background:var(--warn-soft);}
.rmeta{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 14px;}
.rmeta .rm{display:inline-flex;align-items:center;gap:7px;background:var(--surface-2);border:1px solid var(--line);
  border-radius:var(--pill);padding:7px 13px;font-size:var(--fs-2);line-height:1.3;}
.rmeta .rm .i{width:15px;height:15px;color:var(--pine);flex:none;}
.rmeta .rm span{color:var(--ink-3);}
.rmeta .rm b{font-weight:600;color:var(--ink);}
.seal-lock{display:inline-flex;align-items:center;gap:18px;text-align:left;}
.seal-bar{width:1px;align-self:stretch;background:var(--ink-4);opacity:.55;flex:none;margin:3px 0;}
/* เส้นคั่นส้มสั้น ๆ ระหว่างชุดตราหน่วยงานกับตราระบบ (หน้าเข้าสู่ระบบ) — ยกไวยากรณ์เดียวกับเส้นคั่น
   ใต้ตัวอักษรในแบบ "ตราแนวตั้ง" ของ design/tims-logo-maker.html มาใช้ ให้ดูตั้งใจ ไม่ใช่เส้นจางที่มองไม่เห็น
   🐛 รอบแรกลืมนิยามคลาสนี้ตอนรื้อ CSS ชุดตรา ⇒ <span class="seal-div"> กลายเป็นกล่องสูง 0 มองไม่เห็นเลย */
.seal-div{display:block;width:54px;height:4px;border-radius:999px;background:var(--terra);margin:16px auto;}
.seal-tx{display:flex;flex-direction:column;gap:1px;font-family:var(--serif);line-height:1.34;}
.seal-tx .s1{font-size:var(--fs-4);font-weight:700;color:var(--pine);}
.seal-tx .s2,.seal-tx .s3{font-size:var(--fs-2);font-weight:600;color:var(--ink-2);}
.seal-tx .s2{margin-top:2px;}
.foot-seals{padding:18px 0 2px;}
.lp-foot .seal-bar{background:rgba(255,255,255,.5);opacity:1;}
.lp-foot .seal-tx .s1{color:var(--on-accent);}
.lp-foot .seal-tx .s2,.lp-foot .seal-tx .s3{color:rgba(255,255,255,.66);}
.slip-brand{display:flex;align-items:center;gap:7px;font-size:var(--fs-1);color:var(--ink-3);margin-bottom:8px;}
.pv-og-marks{display:flex;align-items:center;gap:12px;}
.brand-name{font-family:var(--serif);font-weight:700;font-size:var(--fs-4);line-height:1.1;}
.brand-sub{font-size:var(--fs-1);color:var(--ink-3);margin-top:1px;}
.rail-search{margin:13px 12px 2px;position:relative;}
.rail-search svg{position:absolute;left:11px;top:50%;transform:translateY(-50%);color:var(--ink-4);font-size:var(--fs-4);}
.rail-search input{width:100%;border:1.5px solid var(--line);border-radius:var(--r2);background:var(--surface-2);
  padding:.5rem .8rem .5rem 34px;font-family:var(--sans);font-size:var(--fs-2);color:var(--ink);outline:none;}
.rail-search input:focus{border-color:var(--accent);background:var(--surface);}
.rail-nav{flex:1;overflow-y:auto;padding:14px 12px;display:flex;flex-direction:column;gap:3px;}
.rail-sec{font-size:var(--fs-1);font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3);padding:14px 12px 5px;}
.nav-i{display:flex;align-items:center;gap:11px;padding:.6rem .8rem;border-radius:var(--r2);border:none;background:transparent;
  color:var(--ink-2);font-family:var(--sans);font-size:var(--fs-3);font-weight:500;text-align:left;transition:.15s;position:relative;}
.nav-i svg{font-size:var(--fs-5);width:24px;color:var(--ink-3);}
.nav-i:hover{background:var(--surface-2);color:var(--ink);}
.nav-i.on{background:var(--accent-soft);color:var(--accent-dark);font-weight:600;}
.nav-i.on svg{color:var(--accent);}
.nav-i.on::before{content:'';position:absolute;left:-12px;top:50%;transform:translateY(-50%);width:4px;height:22px;
  border-radius:0 4px 4px 0;background:var(--terra);}
.nav-i .tag{margin-left:auto;font-size:var(--fs-1);font-weight:700;padding:1px 8px;border-radius:var(--pill);
  background:var(--terra-soft);color:var(--terra-dark);}
/* 17 ก.ย. 69 · ป้ายบนเมนูแยกสีตามความหมาย — ของเดิมสีเดียวหมด ผู้ใช้จึงบอกไม่ได้ว่าอันไหนเร่ง
   bad = ต้องแก้/ถูกตีกลับ · warn = ค้างรอทำ · ok = ข่าวดี/ของใหม่ที่ยังไม่ได้ดู */
.nav-i .tag.t-bad{background:var(--bad-soft);color:var(--bad-ink);}
.nav-i .tag.t-warn{background:var(--warn-soft);color:var(--warn-ink);}
.nav-i .tag.t-ok{background:var(--ok-soft);color:var(--ok-ink);}
/* ป้าย "ใหม่" ที่ไม่ใช่ตัวเลข — ใช้กับการ์ดข่าวและแถวงานที่เพิ่งเพิ่ม */
.badge-new{display:inline-flex;align-items:center;gap:4px;font-size:var(--fs-1);font-weight:700;
  padding:1px 8px;border-radius:var(--pill);background:var(--ok-soft);color:var(--ok-ink);
  letter-spacing:.02em;vertical-align:middle;}
/* แถบ "ตอนนี้ท่านอยู่ขั้นไหน" — Noti เด้งบนหน้าหลักนักศึกษา */
.nowstep{display:flex;gap:13px;align-items:flex-start;margin:0 0 16px;padding:14px 17px;
  border-radius:var(--r3);background:var(--accent-soft);border:1px solid var(--accent);}
.nowstep-n{flex:none;display:grid;place-items:center;width:38px;height:38px;border-radius:50%;
  background:var(--accent);color:var(--on-accent);font-weight:700;font-size:var(--fs-3);}
.nowstep b{display:block;font-size:var(--fs-3);color:var(--ink);}
.nowstep p{margin:3px 0 0;font-size:var(--fs-2);color:var(--ink-2);line-height:1.55;}
.nowstep .btn{margin-top:9px;}
/* ป้าย "คุณอยู่ที่นี่" บนขั้นปัจจุบันของผัง */
.step-here{display:inline-flex;align-items:center;gap:4px;font-size:var(--fs-1);font-weight:700;
  padding:1px 9px;border-radius:var(--pill);background:var(--accent);color:var(--on-accent);}
.nav-i.danger{color:var(--bad);} .nav-i.danger svg{color:var(--bad);}
.rail-foot{margin:12px;padding:13px 14px;border-radius:var(--r2);background:var(--accent-soft);display:flex;gap:9px;
  font-size:var(--fs-1);color:var(--accent-dark);line-height:1.5;}
.work{display:flex;flex-direction:column;min-height:0;min-width:0;}
.topbar{height:64px;flex-shrink:0;background:color-mix(in srgb,var(--paper) 80%,transparent);
  backdrop-filter:blur(8px);border-bottom:1px solid var(--line);display:flex;align-items:center;
  justify-content:space-between;gap:16px;padding:0 26px;position:sticky;top:47px;z-index:20;}
/* ── เส้นทางนำทางบนแถบบน (แบบ Google ไดร์ฟ) ──
   เดิมแถบบนโชว์แค่ชื่อหน้าเดี่ยว ๆ ผู้ใช้ไม่รู้ว่าหน้านี้อยู่ตรงไหนของระบบ
   ตอนนี้เป็น พื้นที่ › หมวด › หน้าปัจจุบัน ▾ โดยขั้นสุดท้ายกดแล้วสลับหน้าในหมวดเดียวกันได้ */
.topbar-title{font-family:var(--serif);display:flex;align-items:center;gap:1px;min-width:0;}
.crumb{display:inline-flex;align-items:center;gap:6px;padding:5px 9px;border-radius:9px;
  color:var(--ink-3);font-size:var(--fs-3);font-weight:500;white-space:nowrap;
  max-width:230px;overflow:hidden;text-overflow:ellipsis;}
a.crumb{cursor:pointer;}
a.crumb:hover{background:var(--paper-2);color:var(--ink);}
.crumb.cur{color:var(--ink);font-weight:700;}
.crumb-btn{border:none;background:none;font:inherit;cursor:pointer;color:var(--ink);font-weight:700;}
.crumb-btn:hover{background:var(--paper-2);}
.crumb-btn svg{font-size:var(--fs-3);opacity:.6;}
.crumb-sep{display:inline-flex;align-items:center;color:var(--ink-4);}
.crumb-sep svg{font-size:var(--fs-3);}
.crumb-w{position:relative;display:inline-flex;}
.crumb-pop{position:absolute;top:calc(100% + 7px);left:0;z-index:60;display:none;min-width:252px;
  background:var(--surface);border:1px solid var(--line);border-radius:12px;
  box-shadow:0 16px 38px rgba(31,39,71,.17);padding:6px;}
.crumb-w.open .crumb-pop{display:block;}
.crumb-pop-h{font-size:var(--fs-1);font-weight:700;letter-spacing:.07em;color:var(--ink-3);padding:8px 10px 6px;}
.crumb-pop-i{display:flex;align-items:center;gap:9px;padding:9px 10px;border-radius:8px;
  font-size:var(--fs-3);font-weight:500;color:var(--ink-2);cursor:pointer;white-space:nowrap;}
.crumb-pop-i:hover{background:var(--paper);color:var(--ink);}
.crumb-pop-i.on{color:var(--accent-dark);font-weight:700;background:var(--accent-soft);}
.crumb-pop-i svg{color:var(--accent);font-size:var(--fs-4);flex-shrink:0;}
.crumb-pop-sp{width:16px;flex-shrink:0;}
/* จอแคบ: ตัดชื่อพื้นที่ทิ้ง เหลือ หมวด › หน้า พอให้รู้ตำแหน่ง */
/* จอแคบ: เส้นทางเต็มยาวเกินแถบบน ดันให้ทั้งหน้าเลื่อนแนวนอน (วัดจริง เอกสาร 596px บนจอ 485px)
   ⇒ ตัดทีละขั้นตามความแคบ · ขั้นสุดท้าย (หน้าปัจจุบัน) เก็บไว้เสมอ เพราะเป็นตัวบอกว่าอยู่ไหน
   ⚠️ ใช้คลาสกำกับทุกตัวคั่น ไม่ใช้ + หรือ :first-child — เคยพลาดเพราะตัวคัดเลือกอิงตำแหน่งมาแล้ว */
@media (max-width:900px){ .crumb-space, .crumb-sep-1{display:none;} .crumb{max-width:150px;} }
@media (max-width:700px){
  .crumb.sec, .crumb-sep-2{display:none;}
  .crumb{max-width:none;}
  .topbar .rolepill{display:none;}   /* บทบาทดูได้จากแถบเมนูอยู่แล้ว */
}
.topbar-r{display:flex;align-items:center;gap:12px;}
.topbar-web{white-space:nowrap;}
/* จอแคบ: แถบบนแออัด — ซ่อนปุ่ม "ดูเว็บ" (ยังนำทาง/ออกจากระบบผ่านแถบเมนูได้) */
@media(max-width:900px){.topbar-web .tw-label{display:none;}}
@media(max-width:700px){.topbar-web{display:none;}}
/* ── แถบบริบท (ปีการศึกษา · ภาคเรียน · รหัส · สาขา) ──
   อยู่ใต้แถบบนและติดหนึบเหมือนกัน เพราะเป็น "ที่ยืนของทั้งหน้า" ไม่ใช่ตัวกรองของหน้าใดหน้าหนึ่ง
   ⚠️ ขอบในต้องกว้างเท่า .page (1240px + padding 28px) ไม่งั้นชิปกับหัวเรื่องข้างล่างไม่ตรงแนวกัน
      — เป็นบั๊กสายตาที่เคยเจอมาแล้วตอนพื้นที่หน้างานมี 3 มาตรฐาน */
.ctxbar{flex-shrink:0;background:var(--surface);border-bottom:1px solid var(--line);
  position:sticky;top:111px;z-index:19;}
/* ⚠️ ความสูงต้องคงที่ทุกสถานะ — ถ้าแถบยืด/หดเวลาเปลี่ยนบริบท เนื้อหาทั้งหน้าจะกระโดด
   ทำให้ผู้ใช้เสียตำแหน่งสายตาทุกครั้งที่สลับภาคเรียน (เจอจริงจากการเทียบภาพ 19 ส.ค. 69) */
.ctxbar-in{margin:0 auto;padding:0 28px;display:flex;align-items:center;
  gap:12px;flex-wrap:nowrap;width:100%;min-height:52px;}
.ctx-chips{display:flex;align-items:center;gap:8px;flex-wrap:wrap;min-width:0;}
.ctx-chip{display:inline-flex;align-items:center;gap:7px;padding:5px 10px;border-radius:var(--pill);
  border:1px solid var(--line);background:var(--paper);font-size:var(--fs-2);color:var(--ink-2);}
.ctx-chip svg{font-size:var(--fs-4);color:var(--ink-3);flex-shrink:0;}
.ctx-l{color:var(--ink-3);font-size:var(--fs-1);font-weight:600;letter-spacing:.02em;}
.ctx-chip b{font-weight:700;color:var(--ink);}
/* ชิปที่ถูกบังคับตามบทบาท — ต้อง "เห็นว่าล็อก" ไม่ใช่หายไป
   ถ้าซ่อน ผู้ใช้จะไม่รู้ว่าตัวเองเห็นข้อมูลแค่ส่วนเดียวของระบบ */
.ctx-chip.locked{background:var(--surface-2);border-style:dashed;cursor:default;}
.ctx-chip.locked svg:last-child{font-size:var(--fs-2);color:var(--ink-4);}
.ctx-sel{border:none;background:none;font:inherit;font-weight:700;color:var(--ink);cursor:pointer;
  padding:0 2px;max-width:190px;}
.ctx-sel:focus{outline:2px solid var(--accent);outline-offset:3px;border-radius:5px;}
.ctx-r{margin-left:auto;display:flex;align-items:center;gap:12px;flex-shrink:0;}
.ctx-sum{display:inline-flex;align-items:center;gap:6px;font-size:var(--fs-2);color:var(--ink-3);white-space:nowrap;}
.ctx-sum svg{font-size:var(--fs-3);color:var(--ink-4);}
.ctx-sum b{color:var(--ink);font-weight:700;}
.ctx-dot{margin:0 4px;color:var(--ink-3);}
/* ป้ายสถานะ/ปุ่มกลับ — สลับกันในที่เดียว ขนาดใกล้กัน แถบจึงไม่ขยับ */
.ctx-state{display:inline-flex;align-items:center;gap:6px;padding:5px 12px;border-radius:var(--pill);
  font-size:var(--fs-1);font-weight:700;white-space:nowrap;border:1px solid transparent;font-family:var(--sans);}
.ctx-state svg{font-size:var(--fs-3);}
.ctx-state.now{background:var(--ok-soft);color:var(--ok-ink);}
.ctx-state.back{background:var(--surface);border-color:var(--terra);color:var(--terra-dark);cursor:pointer;}
.ctx-state.back:hover{background:var(--terra-soft);}
/* ไม่ได้อยู่ภาคเรียนปัจจุบัน — เตือนเบา ๆ ด้วยเส้นบน ไม่ใช่ด้วยการเพิ่มของจนแถบยืด */
.ctxbar.off{box-shadow:inset 0 3px 0 -1px var(--terra);}
/* ปีย้อนหลัง — ต้องรู้สึกต่างจากปีปัจจุบันทันทีที่มอง ไม่ใช่รู้ตอนกดแล้วกดไม่ได้ */
.ctxbar.past{background:var(--terra-soft);border-bottom-color:var(--terra);}
.ctxbar.past .ctx-chip{background:color-mix(in srgb,var(--surface) 70%,transparent);border-color:var(--terra);}
/* อยู่ช่องเดียวกับตัวเลขสรุป (สลับกัน) — ปีย้อนหลังจึงไม่ทำให้แถบสูงขึ้น */
.ctx-past{display:inline-flex;align-items:center;gap:7px;font-size:var(--fs-2);font-weight:700;
  color:var(--terra-dark);white-space:nowrap;}
.ctx-past svg{font-size:var(--fs-4);}
.is-past{opacity:.5;cursor:not-allowed;}
.ctx-jumps{display:flex;gap:8px;flex-wrap:wrap;}
/* ── เครื่องมือของหน้าที่มีรายการหลักพัน (ค้นหา · เลือกเป็นชุด · แบ่งหน้า) ──
   ออกแบบครั้งเดียวใช้ซ้ำได้กับทุกหน้าที่ต้องรับ 1,950 แถว */
.tbar{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:14px;}
.tbar-search{position:relative;display:flex;align-items:center;flex:1 1 320px;max-width:460px;}
.tbar-search>svg{position:absolute;left:12px;font-size:var(--fs-4);color:var(--ink-4);pointer-events:none;}
.tbar-search .inp{padding-left:38px;padding-right:34px;width:100%;}
.tbar-x{position:absolute;right:8px;border:none;background:none;cursor:pointer;color:var(--ink-3);
  display:flex;padding:4px;border-radius:6px;}
.tbar-x:hover{background:var(--paper-2);color:var(--ink);}
.tbar-n{font-size:var(--fs-2);color:var(--ink-3);white-space:nowrap;}
.tbar-n b{color:var(--ink);}
/* แถบทำงานเป็นชุด — โผล่เมื่อเลือกอย่างน้อย 1 รายการ */
.bulkbar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:14px;padding:11px 14px;
  border-radius:var(--r2);background:var(--accent-soft);border:1px solid color-mix(in srgb,var(--accent) 30%,transparent);}
.bulk-n{display:inline-flex;align-items:center;gap:7px;font-size:var(--fs-3);font-weight:600;color:var(--accent-dark);}
.bulk-n b{font-size:var(--fs-4);}
.bulk-sel{min-width:260px;flex:0 1 320px;}
/* ช่องติ๊กเลือก — พื้นที่กดต้องใหญ่พอ เพราะต้องติ๊กหลายสิบครั้งต่อรอบ */
.ck{display:inline-flex;align-items:center;cursor:pointer;padding:4px;}
.ck input{width:18px;height:18px;accent-color:var(--accent);cursor:pointer;margin:0;}
.srch-res{max-height:52vh;overflow-y:auto;}
.srch-g{font-size:var(--fs-1);font-weight:700;color:var(--ink-3);letter-spacing:.02em;
  margin:12px 0 6px;display:flex;align-items:center;gap:6px;}
.srch-g:first-child{margin-top:0;}
.srch-i{display:flex;align-items:center;gap:11px;width:100%;text-align:left;padding:9px 11px;
  border:1px solid var(--line);border-radius:11px;background:var(--paper);cursor:pointer;
  margin-bottom:5px;transition:border-color .12s,background .12s;}
.srch-i:hover{border-color:var(--accent);background:var(--accent-soft);}
.srch-i .i{width:16px;height:16px;flex-shrink:0;color:var(--ink-3);}
.srch-ic{display:flex;align-items:center;justify-content:center;width:30px;height:30px;
  border-radius:9px;background:var(--sand);flex-shrink:0;}
.srch-tx{display:flex;flex-direction:column;gap:1px;min-width:0;flex:1;}
.srch-tx b{font-size:var(--fs-3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.srch-tx small{font-size:var(--fs-1);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.pager{display:flex;align-items:center;justify-content:space-between;gap:14px;flex-wrap:wrap;
  margin-top:14px;padding:10px 4px;}
.pager-n{font-size:var(--fs-2);color:var(--ink-3);}
.pager-n b{color:var(--ink);}
.pager-b{display:flex;align-items:center;gap:10px;}
.pager-c{font-size:var(--fs-2);color:var(--ink-3);white-space:nowrap;}
.pager-c b{color:var(--ink);}
/* ── การ์ดรายวิชา = ทางเข้างานทั้งหมด (course-centric) ── */
/* CR-21 (13 ก.ย. 69): auto-fit (ไม่ใช่ auto-fill) ทุกกริดการ์ดที่จำนวนชิ้นแปรผัน — auto-fill จองคอลัมน์ตามพื้นที่ที่ "พอจะมี" ไว้ก่อนเสมอ ถ้าการ์ดจริงมีน้อยกว่าที่จองไว้ (เช่น ค้นหาแล้วเหลือ 1-2 ผล) คอลัมน์ที่เหลือจะว่างเปล่าเป็นพื้นที่ว่างเห็นชัด (ยืนยันแล้วจริงบนการ์ดข่าว หน้าแรกที่มีแค่ 2 ข่าว) auto-fit ให้การ์ดที่มีอยู่ขยายเติมแถวเสมอ ไม่ทิ้งพื้นที่ว่าง — ทั้งสองแบบเหมือนกันทุกอย่างเมื่อการ์ดเต็มแถวพอดี ต่างกันเฉพาะตอนมีน้อยกว่าที่จะพอดี */
.crs-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(310px,1fr));gap:14px;}
.crs-card{text-align:left;font:inherit;cursor:pointer;display:flex;flex-direction:column;gap:9px;
  padding:18px;border-radius:var(--r2);border:1px solid var(--line);background:var(--surface);
  transition:.15s;position:relative;}
.crs-card:hover{border-color:var(--accent);transform:translateY(-2px);
  box-shadow:0 10px 24px rgba(31,39,71,.10);}
.crs-top{display:flex;align-items:center;gap:9px;flex-wrap:wrap;}
.crs-code{font-family:var(--serif);font-weight:700;font-size:var(--fs-4);color:var(--ink);}
.crs-round{font-size:var(--fs-1);font-weight:700;padding:2px 9px;border-radius:var(--pill);
  background:var(--accent-soft);color:var(--accent-dark);}
.crs-name{font-size:var(--fs-3);color:var(--ink-2);line-height:1.5;}
.crs-meta{display:flex;align-items:center;gap:5px;font-size:var(--fs-2);color:var(--ink-3);flex-wrap:wrap;}
.crs-meta svg{font-size:var(--fs-3);color:var(--ink-4);}
.crs-nums{display:flex;gap:14px;flex-wrap:wrap;padding-top:10px;margin-top:2px;
  border-top:1px solid var(--line-2);font-size:var(--fs-2);color:var(--ink-3);}
.crs-nums span{display:inline-flex;align-items:center;gap:5px;}
.crs-nums b{color:var(--ink);}
.crs-nums svg{font-size:var(--fs-3);color:var(--ink-4);}
.warn-t{color:var(--warn-ink);} .warn-t b{color:var(--warn-ink);}
/* 🐛 เดิมเป็น position:absolute มุมขวาล่าง → ทับข้อความ "3 โรงเรียน" ในแถวตัวเลข
   และซ่อนไว้จนกว่าจะ hover ซึ่งบนจอสัมผัสไม่มีทางเห็นเลย
   ⇒ ทำเป็นแถวของตัวเองในสายการวางปกติ และแสดงตลอดเวลา */
.crs-go{display:flex;align-items:center;justify-content:flex-end;gap:5px;margin-top:2px;
  font-size:var(--fs-2);font-weight:700;color:var(--accent-dark);}
.crs-go svg{transition:transform .15s;}
.crs-card:hover .crs-go svg{transform:translateX(3px);}
/* งานของรายวิชา — แต่ละอย่างเป็นหน้าของตัวเอง */
.job-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:12px;}
.job-card{text-align:left;font:inherit;cursor:pointer;display:flex;flex-direction:column;gap:6px;
  padding:16px;border-radius:var(--r2);border:1px solid var(--line);background:var(--surface);transition:.15s;}
.job-card:hover:not(:disabled){border-color:var(--accent);background:var(--accent-soft);}
.job-card:disabled{opacity:.55;cursor:not-allowed;}
.job-ic{display:flex;width:38px;height:38px;border-radius:11px;align-items:center;justify-content:center;
  background:var(--accent-soft);color:var(--accent-dark);margin-bottom:4px;}
.job-ic svg{font-size:var(--fs-5);}
.job-t{font-weight:700;font-size:var(--fs-3);color:var(--ink);}
.job-d{font-size:var(--fs-2);color:var(--ink-3);}
/* ── รายงานคุณสมบัติ: แยก "เงื่อนไขจบ" ออกจาก "ข้อมูลประกอบ" ให้เห็นด้วยตา ──
   ถ้าปนกัน เจ้าหน้าที่จะเข้าใจผิดว่าคนไม่มีวุฒิลูกเสือจบไม่ได้ (COURSE_ITEMS 10.4) */
.qual-legend{display:flex;align-items:center;gap:7px;flex-wrap:wrap;margin:0 0 12px;
  font-size:var(--fs-2);color:var(--ink-3);}
.ql-key{width:13px;height:13px;border-radius:4px;display:inline-block;flex-shrink:0;}
.ql-req{background:var(--accent);}
.ql-info{background:var(--line);border:1px solid var(--ink-4);}
.ql-sep{color:var(--ink-3);margin:0 4px;}
.th-req{display:inline-flex;align-items:center;gap:5px;}
.th-req::before{content:'';width:9px;height:9px;border-radius:3px;background:var(--accent);flex-shrink:0;}
.th-info{display:inline-flex;align-items:center;gap:5px;color:var(--ink-3);font-weight:500;}
.th-info::before{content:'';width:9px;height:9px;border-radius:3px;background:var(--line);
  border:1px solid var(--ink-4);flex-shrink:0;}
@media (max-width:900px){
  .ctxbar{position:static;}         /* จอแคบ: แถบติดหนึบ 3 ชั้นกินพื้นที่อ่านจนหมด */
  .ctx-sum{display:none;}
  .ctxbar-in{padding:9px 18px;}
}
.usr{display:flex;align-items:center;gap:10px;}
.usr .av{width:38px;height:38px;border-radius:12px;color:var(--on-accent);font-weight:700;font-size:var(--fs-2);overflow:hidden;
  display:flex;align-items:center;justify-content:center;font-family:var(--serif);background:var(--accent);}
.usr-meta{line-height:1.2;}
.usr-meta b{font-size:var(--fs-2);font-weight:600;display:block;}
.usr-meta small{font-size:var(--fs-1);color:var(--ink-3);}
/* ── พื้นที่หน้างาน: ค่าเดียวทุกหน้า ทุกบทบาท ──
   ⚠️ เดิมมี 3 มาตรฐานปนกัน (วัดจริง 17 ส.ค. 69 ที่จอ 1920px)
        1024px  หน้าของนักศึกษา       (.page max-width:1080)
        1184px  อีก 3 บทบาท           (.page-wide max-width:1240)
         880px  หน้าดูโปรไฟล์ทั้ง 4    (.one-col max-width:880)
      และในหน้าเดียวกันยังไม่ตรงกันเอง — หัวเรื่องกว้างเต็มหน้า แต่การ์ดข้างล่างแคบกว่า
      ทำให้ขอบซ้ายของหัวเรื่องกับการ์ดไม่ตรงแนวกัน เห็นชัดในหน้าแก้ไขโปรไฟล์
   ⇒ เหลือค่าเดียว 1240px ทุกหน้า · ทุกบทบาท · ทุกส่วนในหน้า
      เลือก 1240 เพราะเป็นค่าที่ 25 จาก 36 หน้าใช้อยู่แล้ว (เปลี่ยนน้อยที่สุด)
      และตารางรายงานที่มี 7 คอลัมน์ต้องการความกว้างระดับนี้ */
.page{padding:26px 28px 70px;margin:0 auto;min-width:0;width:100%;}
/* ลิงก์ย้อนกลับเหนือหัวเรื่อง — เบากว่าปุ่ม เพราะเป็นการนำทาง ไม่ใช่การกระทำ */
.back-link{display:inline-flex;align-items:center;gap:7px;margin-bottom:10px;padding:5px 11px 5px 8px;
  border-radius:9px;color:var(--ink-3);font-size:var(--fs-3);font-weight:600;cursor:pointer;}
.back-link:hover{background:var(--paper-2);color:var(--ink);}
.back-link svg{font-size:var(--fs-4);}
.ph-head{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;flex-wrap:wrap;margin-bottom:24px;}
.ph-head h1{font-size:var(--fs-6);font-weight:600;}
.ph-head p{margin:5px 0 0;color:var(--ink-3);font-size:var(--fs-3);}
/* กลุ่มปุ่มมุมขวาของหัวหน้า — ต้องยอมตกบรรทัด ไม่งั้นปุ่ม 3 ตัวดันหน้าให้เลื่อนบนมือถือ
   ⚠️ เดิมเขียนเป็น inline style `display:flex;gap:8px` ⇒ CSS จอแคบทับไม่ได้ (inline ชนะ)
      จึงต้องเป็นคลาส ไม่ใช่ inline style */
.hd-acts{display:flex;gap:8px;flex-wrap:wrap;}
/* รายการติ๊กเลือกในกล่องโต้ตอบ (นัดนิเทศเป็นชุด) — ต้องเลื่อนได้เอง
   โรงเรียนหนึ่งอาจมีนักศึกษาหลายคน ถ้าไม่จำกัดความสูง กล่องจะยาวเกินจอ */
.pick-list{max-height:230px;overflow-y:auto;border:1px solid var(--line);border-radius:var(--r2);
  background:var(--paper);padding:4px;}
.pick-row{display:flex;align-items:center;gap:10px;padding:9px 10px;border-radius:var(--r1);
  cursor:pointer;font-size:var(--fs-3);min-height:40px;}
.pick-row:hover{background:var(--surface-2);}
.pick-row input{width:17px;height:17px;flex-shrink:0;accent-color:var(--accent);cursor:pointer;}
/* ปุ่มชิปเลือกแบบประเมินที่จะกรอก — ต้องเห็นความคืบหน้าของแต่ละชุดพร้อมกัน */
.chipbtn{display:inline-flex;align-items:center;gap:8px;padding:8px 13px;border-radius:var(--pill);
  border:1.5px solid var(--line);background:var(--surface);color:var(--ink-2);font:inherit;
  font-size:var(--fs-2);font-weight:600;cursor:pointer;transition:.15s;min-height:40px;}
.chipbtn:hover{border-color:var(--accent);color:var(--accent);}
.chipbtn.on{border-color:var(--accent);background:var(--accent-soft);color:var(--accent-dark);}
/* รหัส/ตัวเลขอ้างอิง — ฟอนต์ระยะเท่ากัน อ่านรหัสโรงเรียน/นักศึกษาได้ไม่สับสน */
.mono{font-family:ui-monospace,'SF Mono',Menlo,Consolas,monospace;letter-spacing:.2px;}

/* ═══ ตารางกรอกรวมแบบ Excel — เห็นทุกแถวทุกคอลัมน์ กรอกในช่อง (เจ้าของงาน 30 ส.ค. 69)
   หัวตาราง (thead) + คอลัมน์แรก (ชื่อ) ตรึงไว้ เลื่อนแล้วยังเห็นว่าใครข้อไหน
   ใช้ซ้ำได้: คะแนนประเมิน · โควตาโรงเรียนรายสาขา · ข้อมูลชุดใหญ่อื่น ๆ */
.xgrid-wrap{overflow:auto;max-height:68vh;border:1px solid var(--line);border-radius:var(--r2);
  background:var(--surface);box-shadow:var(--sh-1) inset;}
.xgrid{border-collapse:separate;border-spacing:0;width:max-content;min-width:100%;
  font-size:var(--fs-2);color:var(--ink);}
.xgrid th,.xgrid td{border-bottom:1px solid var(--line-2);border-right:1px solid var(--line-2);
  padding:0;white-space:nowrap;background:var(--surface);}
.xgrid thead th{position:sticky;top:0;z-index:3;background:var(--surface-2);
  font-weight:700;color:var(--ink-2);padding:9px 12px;text-align:center;vertical-align:bottom;
  border-bottom:1.5px solid var(--line);}
/* แถวหัวกลุ่ม (เช่นจัดกลุ่มข้อประเมินตามด้าน) — เว้นไม่ปักหมุดแนวตั้ง (position:static ทับกฎด้านบน)
   เพราะ .xgrid thead th ทุกตัวปักที่ top:0 เหมือนกัน ถ้าปักทั้งสองแถวจะซ้อนทับกันตอนเลื่อนแนวตั้ง
   แถวเลขข้อ (แถวล่าง) ปักไว้แทนเพราะมีประโยชน์ตอนกรอกมากกว่า — ป้ายชื่อด้านเห็นตอนแรกพอ
   🔴 เว้น .xg-lead ไว้ — ต้องปักซ้าย (position:sticky;left:0) ต่อไป ไม่งั้นหลุดแนวตอนเลื่อนแนวนอน */
.xgrid thead tr.xg-grouprow th:not(.xg-lead){position:static;}
.xgrid thead th .xg-sub{display:block;font-weight:400;font-size:var(--fs-1);color:var(--ink-3);margin-top:2px;}
.xgrid .xg-lead{position:sticky;left:0;z-index:2;background:var(--surface);
  text-align:left;padding:8px 14px;min-width:190px;max-width:240px;border-right:1.5px solid var(--line);}
.xgrid thead .xg-lead{z-index:4;background:var(--surface-2);}
.xgrid .xg-lead b{display:block;font-size:var(--fs-3);white-space:normal;line-height:1.35;}
.xgrid .xg-lead small{color:var(--ink-3);}
.xgrid tbody tr:hover td{background:var(--surface-2);}
.xgrid tbody tr:hover .xg-lead{background:var(--surface-2);}
.xg-in{border:0;width:100%;min-width:58px;height:40px;text-align:center;background:transparent;
  font:inherit;color:var(--ink);-moz-appearance:textfield;}
.xg-in::-webkit-outer-spin-button,.xg-in::-webkit-inner-spin-button{-webkit-appearance:none;margin:0;}
.xg-in:focus{outline:0;box-shadow:inset 0 0 0 2px var(--accent);background:var(--accent-soft);border-radius:4px;}
.xg-in.txt{text-align:left;padding:0 12px;min-width:150px;}
.xg-in.dirty{background:var(--warn-soft);}
.xg-in:disabled{color:var(--ink-2);cursor:default;-webkit-text-fill-color:var(--ink-2);opacity:1;}
.xgrid-wrap.ro{background:var(--surface-2);}
.xg-tot{text-align:center;font-weight:800;padding:0 14px;color:var(--ink-2);background:var(--surface-2);}
.xg-tot small{font-weight:400;color:var(--ink-3);}
/* แถบสถานะซ้ายสุดของแต่ละแถว — ครบ=เขียว · ขาด=เหลือง (ดูออกทั้งชั้นในตาเดียว) */
.xgrid tbody tr.ok .xg-lead{box-shadow:inset 4px 0 0 var(--ok);}
.xgrid tbody tr.warn .xg-lead{box-shadow:inset 4px 0 0 var(--warn);}
.xgrid tbody tr.bad .xg-lead{box-shadow:inset 4px 0 0 var(--bad);}
.xgrid tbody tr.ok .xg-tot{color:var(--ok-ink);background:var(--ok-soft);}
.xg-legend{display:flex;gap:16px;flex-wrap:wrap;margin:10px 2px 0;font-size:var(--fs-2);color:var(--ink-3);}
.xg-legend span{display:inline-flex;align-items:center;gap:6px;}
.xg-dot{width:10px;height:10px;border-radius:3px;display:inline-block;}
/* แถวกรอกคะแนนรายข้อ — ช่องตัวเลขต้องแคบและอยู่ขวาสุดเสมอ ตากวาดหาได้เร็ว */
.scorerow{display:flex;align-items:center;gap:12px;padding:9px 0;border-bottom:1px solid var(--line-2);}
.scorerow:last-of-type{border-bottom:none;}
.scorerow-q{flex:1;min-width:0;font-size:var(--fs-3);line-height:1.5;}
/* 🔴 ต้องเจาะจงกว่า .inp{width:100%} (นิยามทีหลังในไฟล์ · สเปกเท่ากันตัวหลังชนะ)
   ไม่งั้นช่องคะแนนกิน 100% แล้วดันข้อความคำถามให้เหลือ 1 ตัวอักษรต่อบรรทัด
   (เจ้าของงานพบ 29 ส.ค. 69 — หน้ากรอกคะแนนรายคน) */
input.scorerow-in{width:74px;flex:0 0 74px;text-align:center;}
/* สรุปก่อนบันทึก — แต่ละบรรทัดคือหนึ่งกลุ่มผล ไม่ใช่ข้อความยาวให้อ่านเอาเอง */
.sumlist{border:1px solid var(--line);border-radius:var(--r2);overflow:hidden;}
.sumrow{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:11px 14px;
  border-bottom:1px solid var(--line-2);font-size:var(--fs-3);}
.sumrow:last-child{border-bottom:none;}
.sumrow.ok{background:var(--ok-soft);color:var(--ok-ink);}
.sumrow.warn{background:var(--warn-soft);color:var(--warn-ink);}
.sumrow.bad{background:var(--bad-soft);color:var(--bad-ink);}
/* แถวเงื่อนไขผ่านการฝึก — ต้องอ่านออกในแวบเดียวว่าขาดข้อไหน */
.passrow{display:flex;align-items:center;gap:11px;padding:11px 0;border-bottom:1px solid var(--line-2);}
.passrow:last-of-type{border-bottom:none;}
.passrow-ic{width:28px;height:28px;flex-shrink:0;border-radius:50%;display:grid;place-items:center;
  background:var(--warn-soft);color:var(--warn-ink);font-size:var(--fs-3);}
.passrow.ok .passrow-ic{background:var(--ok-soft);color:var(--ok-ink);}
.passrow-t{flex:1;min-width:0;font-size:var(--fs-3);line-height:1.5;}
.card.pass-done{border-color:color-mix(in srgb,var(--ok) 45%,var(--line));
  box-shadow:0 0 0 1px color-mix(in srgb,var(--ok) 22%,transparent);}
/* เที่ยวเดินทางนิเทศ — วันเดียว สถานที่เดียว = หนึ่งเที่ยว แม้จะนิเทศหลายคน */
.trip{display:flex;gap:16px;align-items:center;padding:14px 0;border-bottom:1px solid var(--line-2);}
.trip:last-child{border-bottom:none;}
.trip-body{flex:1;min-width:0;}
.trip-names{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px;}
.sec-h{display:flex;align-items:center;gap:8px;font-weight:600;font-size:var(--fs-3);color:var(--ink);
  padding-bottom:12px;margin-bottom:18px;border-bottom:1.5px solid var(--line-2);}
.sec-h svg{color:var(--accent);font-size:var(--fs-4);}
.sec-title{font-size:var(--fs-6);margin-top:4px;}
.rail-toggle{display:none;width:40px;height:40px;flex-shrink:0;border:1px solid var(--line);border-radius:var(--r2);
  background:var(--surface);color:var(--ink-2);align-items:center;justify-content:center;font-size:var(--fs-5);}

/* stat cards */
/* CR-21 (13 ก.ย. 69): auto-fit แทน repeat(4,1fr) — บางหน้ามีแค่ 3 การ์ดสถิติ (เช่น comCourse/admForms) การ์ดที่ 4 ที่หายไปเคยทิ้งคอลัมน์ว่างเปล่าไว้เต็มความกว้าง เปลี่ยนเป็น auto-fit ให้การ์ดที่มีอยู่ขยายเติมเต็มแถวเสมอ + ไล่ลดคอลัมน์ลงเองตามพื้นที่จริง (ย่อ/ขยายเบราว์เซอร์) แทนการกระโดดที่จุดตัดเดียว */
.stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:18px;margin-bottom:22px;}
.stat{background:var(--surface);border:1px solid var(--line);border-radius:var(--r3);padding:16px 18px;box-shadow:var(--sh-1);
  transition:.18s;display:block;}
a.stat[data-page]{cursor:pointer;}
a.stat[data-page]:hover{transform:translateY(-3px);box-shadow:var(--sh-2);border-color:color-mix(in srgb,var(--accent) 26%,var(--line));}
.stat .ic{width:42px;height:42px;border-radius:var(--r2);display:flex;align-items:center;justify-content:center;
  font-size:var(--fs-5);color:var(--on-accent);margin-bottom:12px;}
.stat .n{font-family:var(--serif);font-size:var(--fs-6);font-weight:700;line-height:1;}
.stat .l{font-size:var(--fs-2);color:var(--ink-3);margin-top:5px;}
.stat .delta{font-size:var(--fs-1);font-weight:600;color:var(--ok-ink);margin-top:7px;display:inline-flex;align-items:center;gap:3px;}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:18px;}
/* CR-27 (13 ก.ย. 69): การ์ดโลโก้/แบรนด์ — auto-fit แทน .grid2 ตายตัว (จำนวนการ์ดคงที่ 3 ใบ
   แต่ .grid2 เป็น 2 คอลัมน์เสมอ ทำให้ใบที่ 3 ตกแถวเดี่ยวเหลือช่องว่างครึ่งจอ) */
.brand-cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:18px;}
.g-83{display:grid;grid-template-columns:2fr 1fr;gap:20px;}
.g-3{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:18px;}
.g-2{display:grid;grid-template-columns:1fr 1fr;gap:20px;}
@media(max-width:900px){.g-2{grid-template-columns:1fr;}}

/* สรุปผลคะแนน — แถบสัดส่วน · การกระจาย · ค่าเฉลี่ยรายข้อ */
.mbar{display:inline-block;width:100%;min-width:70px;height:9px;border-radius:999px;background:var(--surface-2);
  overflow:hidden;vertical-align:middle;}
.mbar-f{display:block;height:100%;border-radius:999px;}
.distrib{display:flex;flex-direction:column;gap:10px;}
.distrib-row{display:grid;grid-template-columns:64px 1fr 34px;align-items:center;gap:12px;font-size:var(--fs-2);}
.distrib-lb{color:var(--ink-3);text-align:right;}
.distrib-n{text-align:right;font-weight:700;}
.tl-list{display:flex;flex-direction:column;}
.tl-row{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:9px 0;border-bottom:1px solid var(--line-2);font-size:var(--fs-2);}
.tl-row:last-child{border-bottom:none;}
.itemavg{display:flex;flex-direction:column;gap:9px;}
.itemavg-row{display:grid;grid-template-columns:1fr 120px 52px;align-items:center;gap:12px;font-size:var(--fs-2);}
.itemavg-lb{min-width:0;line-height:1.4;}
.itemavg-n{text-align:right;font-weight:700;}
@media(max-width:700px){.itemavg-row{grid-template-columns:1fr 80px 44px;}.distrib-row{grid-template-columns:56px 1fr 30px;}}

/* ตาราง (CR-16 · 5 ก.ย. 69: ฟิกขนาดคอลัมน์ + เส้นตารางชัด + ตรึงหัวตาราง)
   🔴 table-layout:fixed = คอลัมน์ไม่ยืดตามข้อมูล (ความกว้างมาจาก <colgroup> ถ้ามี ไม่งั้นเท่ากันทุกคอลัมน์)
   🔴 .tbl-wrap เป็นกล่องเลื่อนที่มี max-height → thead sticky จึงตรึงหัวได้จริงตอนเลื่อนแถว
   🔴 เส้นแนวตั้ง+แนวนอน = border ทุกด้านของ th/td · word-break กันข้อความล้นคอลัมน์ที่ถูกฟิก */
.tbl-wrap{border:1px solid var(--line);border-radius:var(--r3);overflow:auto;max-height:70vh;background:var(--surface);}
.tbl{width:100%;border-collapse:collapse;table-layout:fixed;}
/* UI-08 (15 ก.ย. 69): เดิม .7rem (10.5px) + letter-spacing + text-transform:uppercase
   — ทั้งสามอย่างยกมาจากแบบอย่างภาษาอังกฤษโดยไม่ได้ปรับให้เข้ากับอักษรไทย
   uppercase ไม่มีผลกับอักษรไทยเลย (กฎที่ไม่ทำงาน) ส่วน letter-spacing ดันสระและวรรณยุกต์
   ให้ลอยห่างจากพยัญชนะ ยิ่งที่ 10.5px ยิ่งอ่านยาก ⇒ ใช้ตัวหนา + สีหมึกเข้มสื่อความเป็นหัวคอลัมน์แทน */
.tbl th{text-align:left;font-size:var(--fs-1);font-weight:700;color:var(--ink-2);
  background:var(--surface-2);padding:11px 18px;border:1px solid var(--line);white-space:nowrap;
  position:sticky;top:0;z-index:2;}
/* WF-06: แถบเครื่องมือของตาราง · หัวคอลัมน์ที่กดเรียงได้ */
/* MS-02: ข้อความผิดพลาดใต้ช่อง + สรุปบนสุดของฟอร์ม */
.inp.is-bad{border-color:var(--bad);box-shadow:0 0 0 3px var(--bad-soft);}
.field-err{display:flex;align-items:flex-start;gap:6px;margin-top:6px;font-size:var(--fs-2);
  color:var(--bad-ink);line-height:1.5;}
.field-err::before{content:'\26A0';flex:none;}
.form-errs{background:var(--bad-soft);border-left:4px solid var(--bad);border-radius:0 var(--r2) var(--r2) 0;
  padding:14px 18px;margin-bottom:18px;color:var(--bad-ink);font-size:var(--fs-3);}
.form-errs b{display:block;margin-bottom:6px;font-size:var(--fs-3);}
.form-errs ul{margin:0;padding-left:1.1rem;}
.form-errs li{margin-bottom:4px;}
.form-errs-go{background:none;border:none;font:inherit;color:var(--bad-ink);font-weight:700;
  text-decoration:underline;cursor:pointer;padding:6px 2px;margin:-6px 2px -6px -2px;border-radius:4px;}
.toast-x{background:none;border:none;color:inherit;cursor:pointer;display:flex;align-items:center;
  padding:9px;margin:-9px -6px -9px 4px;border-radius:7px;opacity:.75;flex:none;}
.toast-x:hover{opacity:1;background:rgba(0,0,0,.07);}
/* ADD-02 · ปุ่มเลิกทำในแถบแจ้งผล — ต้องเด่นกว่าปุ่มปิด เพราะเป็นทางออกของการกดพลาด
   ไม่ใช้สีแดง: การย้อนคือการ "แก้ให้ถูก" ไม่ใช่การทำลาย */
.toast-undo{flex-shrink:0;align-self:center;background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r1);padding:7px 12px;min-height:40px;font:inherit;font-size:var(--fs-1);
  font-weight:700;color:var(--ink);cursor:pointer;display:inline-flex;align-items:center;gap:6px;}
.toast-undo:hover{background:var(--paper-2);border-color:var(--accent);color:var(--accent-dark);}
.tbl-tools{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:10px;}
.tbl-tools .tbl-q{flex:1 1 240px;max-width:340px;}
.tbl-tools .tbl-f{flex:0 1 auto;max-width:230px;font-size:var(--fs-2);}
.tbl-count{font-size:var(--fs-2);color:var(--ink-3);white-space:nowrap;}
.tbl-count b{color:var(--ink);}
/* เป้ากดต้องสูงพอสำหรับนิ้ว (≥40px) โดยไม่ดันหัวตารางให้สูงขึ้น —
   เทคนิคเดียวกับ .linkname: เพิ่มพื้นที่กดด้วย padding แล้วดึงกลับด้วย margin ลบ
   (ถ้าไม่ทำ ปุ่มเรียงลำดับจะสูงแค่ 19px ซึ่งต่ำกว่าเกณฑ์ — ตัวตรวจจอมือถือจับได้จริง) */
.th-sort{display:inline-flex;align-items:center;gap:6px;width:100%;background:none;border:none;
  font:inherit;color:inherit;text-align:left;cursor:pointer;border-radius:4px;
  padding:11px 2px;margin:-11px -2px;}
.th-sort:hover{color:var(--accent-dark);}
.th-sort::after{content:'\2195';font-size:var(--fs-1);opacity:.4;margin-left:auto;padding-left:6px;}
.tbl th.th-s.on .th-sort::after{opacity:1;color:var(--accent-dark);}
.tbl th.th-s.on.asc .th-sort::after{content:'\25B2';}
.tbl th.th-s.on.desc .th-sort::after{content:'\25BC';}
.tbl th.th-s.on{background:var(--accent-soft);}
.tbl-none{text-align:center;color:var(--ink-3);padding:26px 18px;}
@media(max-width:700px){ .tbl-tools .tbl-q,.tbl-tools .tbl-f{max-width:none;flex:1 1 100%;} }
.tbl td{padding:13px 18px;font-size:var(--fs-2);border:1px solid var(--line-2);
  word-break:break-word;overflow-wrap:anywhere;vertical-align:top;}
.tbl tbody tr:hover{background:var(--surface-2);}
/* UI-09 (ลำดับ 22 · 18 ก.ย. 69): เดิม 34×34 ต่ำกว่าเกณฑ์เป้ากด 40px และปุ่มลบอยู่ติดปุ่มแก้ไข
   ⇒ ขยายเป็น 40×40 และเพิ่มระยะห่างระหว่างปุ่มเป็น 6px
   🔴 กรอบที่มองเห็นยังเท่าเดิม (34px) ด้วย background-clip:content-box + padding 3px
      ⇒ ตารางไม่บวมขึ้นทั้งระบบ แต่พื้นที่กดจริงได้ 40px ตามเกณฑ์ */
.act{width:40px;height:40px;padding:3px;border-radius:12px;border:1.5px solid var(--line);
  background:var(--surface);background-clip:content-box;color:var(--ink-3);
  display:inline-flex;align-items:center;justify-content:center;transition:.15s;margin-right:6px;}
.act:hover{border-color:var(--accent);color:var(--accent);background:var(--accent-soft);}
/* MS-08 (ลำดับ 22): ช่องติ๊กเลือกงานเพื่อให้ผ่านยกชุด — เป้ากด 40px ตามเกณฑ์เดียวกับ .act */
.rev-pick{width:40px;height:40px;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;}
.rev-pick input{width:18px;height:18px;cursor:pointer;accent-color:var(--ok);}
.rev-pick input:disabled{cursor:not-allowed;opacity:.45;}
/* CR-15: ชื่อคนที่กดดูโปรไฟล์ได้ — ปุ่มที่หน้าตาเหมือนลิงก์ (ไม่ใช้ inline JS · CSP-safe) */
.linkname{background:none;border:none;font:inherit;color:var(--accent-dark);cursor:pointer;
  text-align:left;text-decoration:underline;text-decoration-color:color-mix(in srgb,var(--accent) 40%,transparent);
  text-underline-offset:2px;
  /* เป้ากดสูงพอสำหรับมือถือ (≥40px) โดยไม่ดันเลย์เอาต์ — padding เพิ่มพื้นที่กด · margin ลบดึงกลับ */
  padding:10px 2px;margin:-10px -2px;}
.linkname:hover{color:var(--accent);text-decoration-color:var(--accent);}

/* ฟอร์ม */
.field{display:flex;flex-direction:column;gap:7px;margin-bottom:18px;}
.field > label{font-size:var(--fs-2);font-weight:600;color:var(--ink-2);}
.field .req{color:var(--bad);}
/* 🐛 min-width:0 ไม่ใช่ของประดับ — textarea มีความกว้างตั้งต้นของตัวเองตาม cols (default 20)
   ราว 350px ในฟอนต์นี้ · ช่องกรอกที่อยู่ใน grid/flex จะ "หดไม่ลงต่ำกว่านั้น"
   เพราะ grid item มี min-width:auto ⇒ ดันทั้งหน้าให้เลื่อนแนวนอนบนจอ 360px
   (เจอจริงตอนตรวจมือถือครั้งแรก 20 ส.ค. 69 ที่หน้าส่งงาน — ไล่หาอยู่นาน
    เพราะตัวที่ "ล้น" คือการ์ดชั้นนอก ไม่ใช่ textarea ที่เป็นต้นเหตุ) */
.inp{min-width:0;}
.g-83 > *, .grid2 > *, .g-3 > *{min-width:0;}
.inp{width:100%;border:1.5px solid var(--line);border-radius:var(--r2);padding:.6rem .85rem;font-family:var(--sans);
  font-size:var(--fs-3);background:var(--surface);color:var(--ink);outline:none;transition:.15s;}
.inp:focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft);}
/* 🐛 select มี appearance ของเบราว์เซอร์เอง ความสูงและระยะขอบจึงไม่เท่า input
   ที่ใช้คลาส .inp เดียวกัน ⇒ ปิด appearance แล้วกำหนดความสูงให้ตรงกัน + วาดลูกศรเอง */
.inp{height:42px;}
textarea.inp{height:auto;min-height:76px;}
select.inp{appearance:none;-webkit-appearance:none;padding-right:36px;cursor:pointer;
  background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%237e869f' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 12px center;background-size:14px;}
select.inp:disabled,input.inp:disabled{background-color:var(--surface-2);color:var(--ink-3);cursor:not-allowed;}
textarea.inp{resize:vertical;min-height:76px;}
.hint{font-size:var(--fs-1);color:var(--ink-3);}
.upl{display:flex;align-items:center;gap:12px;padding:14px 16px;border:2px dashed var(--line);border-radius:var(--r2);
  background:var(--surface-2);color:var(--ink-2);transition:.15s;}
.upl:hover{border-color:var(--accent);background:var(--accent-soft);color:var(--accent-dark);}
.upl svg{font-size:var(--fs-6);color:var(--accent);}
.upl strong{display:block;font-size:var(--fs-2);} .upl small{display:block;font-size:var(--fs-1);color:var(--ink-3);}
.upl-big{flex-direction:column;text-align:center;padding:34px 20px;}
.upl-big svg{font-size:var(--fs-8);}
.seg{display:inline-flex;background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r2);padding:4px;gap:3px;}
.seg button{border:none;background:transparent;color:var(--ink-2);font-weight:600;font-size:var(--fs-2);padding:.45rem .9rem;
  border-radius:var(--r1);display:inline-flex;align-items:center;gap:6px;transition:.15s;}
.seg button:hover{color:var(--ink);}
.seg button.on{background:var(--surface);color:var(--accent-dark);box-shadow:var(--sh-1);}
.f-actions{display:flex;gap:10px;justify-content:flex-end;padding-top:18px;margin-top:4px;border-top:1px solid var(--line-2);}
.tip{display:flex;gap:9px;align-items:flex-start;padding:11px 13px;border-radius:var(--r2);background:var(--accent-soft);
  color:var(--accent-dark);font-size:var(--fs-2);line-height:1.5;}
.empty{text-align:center;padding:46px 20px;color:var(--ink-3);}
/* B-3 (12 ก.ย. 69): เจาะจงแค่ลูกตรง (>) ไม่ใช่ลูกหลานทั่วไป (space) — denied()/errorState() ใหม่วาง
   ไอคอนไว้ใน .status-mark ที่ซ้อนอีกชั้น (.empty > .status-mark > svg) ถ้าใช้ "svg" เฉย ๆ (ลูกหลาน)
   กฎนี้จะไปทับสี/ขนาดของ .status-mark ที่ตั้งไว้เอง (specificity ของ descendant selector สูงกว่าคลาส
   ยูทิลิตี้เดี่ยวอย่าง .fs-180/.t-white) — ทุกจุดเดิมที่ใช้ .empty (19 จุด) วางไอคอนเป็นลูกตรงอยู่แล้ว
   จึงเปลี่ยนเป็น > ได้โดยพฤติกรรมเดิมไม่เปลี่ยนเลยสักจุด */
.empty > svg{font-size:var(--fs-8);color:var(--ink-4);display:block;margin:0 auto 8px;}
/* ลำดับ 16 · WF-07 + ADD-10 (17 ก.ย. 69): สถานะว่างต้องบอกทางไปต่อเสมอ
   .empty-go = ปุ่มพาไปทำต่อ · .empty-why = เหตุผลว่าทำไมจุดนี้ถึงไม่มีปุ่ม (ปลายทางจริง)
   ทั้งสองคลาสมีไว้ให้ตัวตรวจจับได้ด้วย ไม่ใช่แค่ตกแต่ง */
.empty .empty-go{margin-top:14px;}
.empty .empty-why{margin:10px 0 0;font-size:var(--fs-1);}
/* B-3 (12 ก.ย. 69): skeleton(kind) — โครงเทาแทนเนื้อหาระหว่างรอ · สัดส่วนคุมด้วย flex/grid ของ
   คอนเทนเนอร์ ไม่ใช้คลาสความกว้างเฉพาะจุด (สอดคล้องแนวทาง B-1 ไม่สร้างคลาสใหม่เกินจำเป็น) */
.skel-wrap{display:flex;flex-direction:column;gap:14px;}
.skel-row{display:flex;gap:16px;align-items:center;}
.skel-row .skel-bar:first-child{flex:0 0 44px;height:16px;}
.skel-row .skel-bar{flex:1;height:12px;}
.skel-field{display:flex;flex-direction:column;gap:7px;}
.skel-field .skel-bar:first-child{width:110px;height:11px;}
.skel-field .skel-bar:last-child{height:38px;}
.skel-cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:14px;}
.skel-card{display:flex;flex-direction:column;gap:9px;}
.skel-card .skel-bar:first-child{width:55%;height:11px;}
.skel-card .skel-bar:nth-child(2){width:75%;height:22px;}
.skel-card .skel-bar:last-child{width:90%;height:12px;}
.skel-bar{display:block;border-radius:5px;background:linear-gradient(90deg,var(--line-2) 25%,var(--line) 37%,var(--line-2) 63%);
  background-size:400% 100%;animation:skel-shimmer 1.5s ease-in-out infinite;}
@keyframes skel-shimmer{0%{background-position:120% 0;}100%{background-position:-120% 0;}}
@media (prefers-reduced-motion:reduce){.skel-bar{animation:none;}}
/* busy(btn)/idle(btn) — ไอคอนรีลบ (retry) หมุนวนระหว่างรอ ให้เห็นว่ากำลังทำงานอยู่จริง ไม่ใช่ปุ่มค้าง
   สโคปเฉพาะ .is-busy ไม่แตะปุ่ม disabled อื่นที่มีอยู่ก่อนแล้ว (ปีย้อนหลัง/ไม่มีสิทธิ์ ฯลฯ) */
.btn.is-busy{opacity:.72;cursor:progress;}
.btn.is-busy svg.i{animation:btn-spin .8s linear infinite;}
@keyframes btn-spin{to{transform:rotate(360deg);}}
@media (prefers-reduced-motion:reduce){.btn.is-busy svg.i{animation:none;}}

/* ─────────── หน้าสาธารณะ (landing.css) ─────────── */
.lp-nav{position:sticky;top:47px;z-index:40;background:color-mix(in srgb,var(--paper) 86%,transparent);
  backdrop-filter:blur(10px);border-bottom:1px solid var(--line);}
/* CR-21 (13 ก.ย. 69): ลบเพดาน 1160px ออกเหมือน .page/.ctxbar-in — หน้าแรกสาธารณะ (nav/hero/ข่าวสาร/
   ปฏิทิน/ส่วนท้าย/หน้าย่อยทั้งหมด) ใช้ .lp-wrap คุมความกว้างเดียวกันทั้งหน้า เข้าหลักการเดียวกัน:
   จอกว้างแค่ไหนก็ใช้เต็มพื้นที่ ไม่เหลือขอบว่างสองข้าง (ต่างจากหน้าเข้าสู่ระบบ/403/ปิดปรับปรุง ซึ่งใช้
   .solo จัดกึ่งกลางการ์ดขนาดคงที่ — คนละโครงกัน ไม่ใช่เพดานความกว้างแบบนี้ จึงไม่ต้องแก้) */
.lp-wrap{margin:0 auto;padding:14px 28px;}
.lp-links{display:flex;gap:6px;}
.lp-links a{font-size:var(--fs-3);font-weight:500;color:var(--ink-2);padding:7px 13px;border-radius:var(--r2);transition:.15s;cursor:pointer;}
.lp-links a:hover{background:var(--surface-2);color:var(--ink);}
.lp-links a.on{color:var(--pine-dark);background:var(--pine-soft);font-weight:600;}
/* UI-06 · ADD-14 (18 ก.ย. 69): แพตเทิร์นเมนูจอแคบของหน้าสาธารณะ
   🔴 ปุ่มเปิดเมนูซ่อนไว้บนจอกว้างด้วย display:none — ไม่ใช่ซ่อนด้วย visibility
      เพราะแป้นพิมพ์จะแท็บไปโดนปุ่มที่มองไม่เห็น (บทเรียนเดียวกับชุดรหัสผ่านยุบได้ของหน้าเข้าสู่ระบบ) */
.lp-burger{display:none;flex:0 0 auto;}
/* ADD-15 — ช่องในแถบสรุปที่กรองได้ ต้องดูกดได้และมีเป้ากดพอ (เกณฑ์ 40px เหมือนปุ่มอื่น) */
button.sumbar-i{font-family:inherit;border:1px solid transparent;cursor:pointer;min-height:40px;
  transition:.15s;text-align:left;}
button.sumbar-i:hover{border-color:var(--line);background:var(--surface-2);}
.sumbar-i.on{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent) inset;}
@media(max-width:700px){
  .lp-nav .lp-wrap{position:relative;}
  .lp-burger{display:inline-flex;}
  /* เมนูกางลงมาทับเนื้อหา ไม่ดันหน้าลง — ปิดแล้วตำแหน่งที่อ่านค้างไว้ไม่เลื่อน */
  .lp-links{display:none;position:absolute;left:0;right:0;top:100%;z-index:41;
    flex-direction:column;gap:2px;background:var(--surface);
    border-bottom:1px solid var(--line);box-shadow:var(--sh-2);padding:8px 28px 14px;}
  .lp-nav.open .lp-links{display:flex;}
  .lp-links a{padding:11px 13px;}
}
.lp-hero{position:relative;overflow:hidden;}
.lp-hero::before{content:'';position:absolute;top:-180px;right:-160px;width:520px;height:520px;border-radius:50%;
  background:radial-gradient(circle,var(--pine-soft) 0%,transparent 68%);opacity:.85;z-index:0;}
.lp-hero::after{content:'';position:absolute;bottom:-120px;left:-100px;width:360px;height:360px;border-radius:50%;
  background:radial-gradient(circle,var(--terra-soft) 0%,transparent 70%);opacity:.6;z-index:0;}
.lp-hero-split{position:relative;z-index:1;display:grid;grid-template-columns:1.15fr .85fr;gap:46px;align-items:center;
  padding-top:52px;padding-bottom:44px;}
.lp-eyebrow{display:inline-flex;align-items:center;gap:7px;font-size:var(--fs-1);font-weight:600;letter-spacing:.06em;
  color:var(--pine-dark);background:var(--pine-soft);padding:6px 13px;border-radius:var(--pill);}
.lp-eyebrow svg{color:var(--amber-dark);}
.lp-title{font-size:var(--fs-8);line-height:1.14;margin:18px 0 0;font-weight:600;letter-spacing:-.02em;max-width:800px;text-wrap:balance;}
.u-terra{color:var(--terra);position:relative;}
.u-terra::after{content:'';position:absolute;left:0;right:0;bottom:4px;height:9px;background:var(--amber-soft);z-index:-1;border-radius:3px;}
.lp-hero-research{font-size:var(--fs-5);color:var(--pine-dark);font-weight:500;line-height:1.45;margin:14px 0 0;max-width:680px;}
.lp-lede{font-size:var(--fs-4);color:var(--ink-2);line-height:1.7;margin:20px 0 26px;max-width:520px;}
.lp-ctas{display:flex;gap:12px;flex-wrap:wrap;}
.lp-hero-tag{display:flex;align-items:center;gap:8px;margin-top:14px;font-size:var(--fs-2);color:var(--ink-3);}
.lp-hero-tag svg{color:var(--amber-dark);}
/* การ์ดวิดีโอแนะนำ */
.lp-feat{display:block;width:100%;text-align:left;background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r4);overflow:hidden;box-shadow:var(--sh-3);transition:.22s;padding:0;}
.lp-feat:hover{transform:translateY(-4px);box-shadow:0 18px 50px rgba(31,36,51,.16);}
.lp-feat-poster{position:relative;aspect-ratio:16/9;display:flex;align-items:center;justify-content:center;
  background:radial-gradient(ellipse at 32% 28%, hsl(214,52%,55%) 0%, transparent 58%),
             linear-gradient(140deg, hsl(224,46%,32%), hsl(250,50%,46%));}
.lp-feat-cat{position:absolute;top:13px;left:13px;background:rgba(31,36,51,.5);color:var(--on-accent);font-size:var(--fs-1);font-weight:600;
  padding:5px 11px;border-radius:var(--pill);display:inline-flex;align-items:center;gap:6px;backdrop-filter:blur(4px);}
.lp-play{width:66px;height:66px;border-radius:50%;background:rgba(255,253,248,.95);color:var(--pine-deep);
  display:flex;align-items:center;justify-content:center;font-size:var(--fs-6);box-shadow:0 8px 26px rgba(0,0,0,.3);transition:.2s;border:none;}
.lp-feat:hover .lp-play{transform:scale(1.08);}
.lp-feat-dur{position:absolute;right:13px;bottom:13px;background:rgba(31,36,51,.7);color:var(--on-accent);font-size:var(--fs-1);
  font-weight:600;padding:3px 9px;border-radius:6px;}
.lp-feat-body{padding:16px 18px;}
.lp-feat-body h4{font-size:var(--fs-4);line-height:1.35;margin-bottom:9px;}
.lp-feat-meta{display:flex;gap:14px;font-size:var(--fs-1);color:var(--ink-3);}
.lp-feat-meta span{display:inline-flex;align-items:center;gap:5px;}
/* flow strip */
.lp-flow{display:flex;align-items:center;gap:8px;background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r4);padding:18px 22px;box-shadow:var(--sh-1);}
.lp-flow-step{display:flex;align-items:center;gap:13px;flex:1;}
.lp-flow-ic{width:46px;height:46px;border-radius:14px;flex-shrink:0;display:flex;align-items:center;justify-content:center;font-size:var(--fs-5);}
.lp-flow-step b{font-size:var(--fs-3);font-family:var(--serif);}
.lp-flow-step p{margin:2px 0 0;font-size:var(--fs-1);color:var(--ink-3);line-height:1.4;}
.lp-flow-arr{color:var(--ink-4);font-size:var(--fs-5);flex-shrink:0;}
/* การ์ด grid */
.lp-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:18px;}
.lc{display:flex;flex-direction:column;text-align:left;background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r3);overflow:hidden;box-shadow:var(--sh-1);transition:.2s;color:inherit;}
.lc:hover{transform:translateY(-3px);box-shadow:var(--sh-3);border-color:color-mix(in srgb,var(--pine) 22%,var(--line));}
.lc-body{padding:15px 17px 17px;display:flex;flex-direction:column;flex:1;}
.lc-cat{font-size:var(--fs-1);font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--terra);}
/* ภาพหัวการ์ดข่าว (Phase 4 · 7 ก.ย. 69) */
.lc-thumb{aspect-ratio:16 / 9;background-size:cover;background-position:center;position:relative;flex-shrink:0;}
.lc-thumb-cat{position:absolute;left:12px;top:12px;font-size:var(--fs-1);font-weight:700;padding:3px 11px;
  border-radius:999px;background:rgba(255,255,255,.94);color:var(--terra-dark);box-shadow:var(--sh-1);}
.lc-thumb-cat.warn{color:var(--bad);}
.news-hero{aspect-ratio:1200 / 340;background-size:cover;background-position:center;}
.lc-title{font-size:var(--fs-4);line-height:1.4;margin:5px 0 0;}
.lc-desc{font-size:var(--fs-2);color:var(--ink-3);line-height:1.55;margin:7px 0 0;}
.lc-meta{display:flex;align-items:center;gap:12px;margin-top:auto;padding-top:12px;font-size:var(--fs-1);color:var(--ink-3);}
.lc-meta span{display:inline-flex;align-items:center;gap:5px;}
/* ── ประกาศรายชื่อ: ค้นหา + การ์ดรายคน (item 2 · 11 ก.ย. 69) ── */
.rs-search{display:flex;align-items:center;gap:9px;background:var(--surface);border:1.5px solid var(--line);
  border-radius:var(--r2);padding:0 14px;transition:.15s;}
.rs-search:focus-within{border-color:var(--pine);box-shadow:0 0 0 3px var(--pine-soft);}
.rs-search .rs-ic{color:var(--ink-3);display:inline-flex;flex-shrink:0;}
.rs-input{flex:1;border:0;background:transparent;padding:12px 0;font:inherit;color:var(--ink);outline:none;min-height:44px;}
.rs-btn{display:inline-flex;align-items:center;gap:6px;flex-shrink:0;border:0;background:var(--pine);color:var(--on-accent);
  font:inherit;font-weight:600;border-radius:var(--r2);padding:9px 16px;min-height:40px;cursor:pointer;transition:.15s;}
.rs-btn:hover{background:var(--pine-deep);}
.rs-idle,.rs-none{margin-top:14px;padding:16px;border-radius:var(--r2);background:var(--surface-2);
  color:var(--ink-3);font-size:var(--fs-2);display:flex;align-items:center;gap:8px;justify-content:center;text-align:center;}
.rs-grid{margin-top:14px;display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:10px;}
.rs-card{display:flex;align-items:center;gap:12px;text-align:left;background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r2);padding:11px 13px;cursor:pointer;transition:.15s;color:inherit;width:100%;}
.rs-card:hover{border-color:var(--pine);box-shadow:var(--sh-2);transform:translateY(-2px);}
.rs-av{width:46px;height:46px;border-radius:50%;overflow:hidden;flex-shrink:0;background:var(--surface-2);}
.rs-av img{width:100%;height:100%;object-fit:cover;}
.rs-tx{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1;}
.rs-tx b{font-size:var(--fs-3);}
.rs-tx small{font-size:var(--fs-1);color:var(--ink-3);display:flex;align-items:center;gap:4px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.rs-arr{color:var(--ink-3);flex-shrink:0;}
/* การ์ดประกาศรายคน — บัตรแนวนอน (แนวบัตรนักศึกษา) · ลอยบนพื้นหลัง */
.acard-back{position:fixed;inset:0;z-index:1200;background:rgba(18,22,40,.62);backdrop-filter:blur(3px);
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:18px;padding:22px;overflow:auto;}
.acard-stage{display:flex;flex-direction:column;align-items:center;gap:18px;max-width:100%;}
.acard{width:580px;max-width:100%;border-radius:var(--r3);overflow:hidden;background:var(--surface);
  box-shadow:0 24px 60px rgba(0,0,0,.4);border:1px solid rgba(255,255,255,.5);}
.acard-head{position:relative;display:flex;align-items:center;gap:13px;padding:15px 20px;
  background-size:cover;background-position:center;color:var(--on-accent);}
.acard-head::after{content:"";position:absolute;inset:0;background:linear-gradient(90deg,rgba(20,26,48,.62),rgba(20,26,48,.32));}
.acard-head>*{position:relative;z-index:1;}
.acard-logo{width:42px;height:42px;border-radius:9px;background:var(--surface-plain);padding:3px;box-shadow:var(--sh-1);flex-shrink:0;}
.acard-htx{display:flex;flex-direction:column;gap:2px;min-width:0;}
.acard-htx b{font-size:var(--fs-3);line-height:1.3;text-shadow:0 1px 4px rgba(0,0,0,.3);}
.acard-htx small{font-size:var(--fs-1);opacity:.95;}
.acard-mid{display:flex;gap:18px;padding:20px;align-items:center;}
.acard-photo{width:112px;height:140px;border-radius:var(--r2);overflow:hidden;flex-shrink:0;
  border:3px solid var(--surface);background:var(--surface-2);box-shadow:var(--sh-2);}
.acard-photo img{width:100%;height:100%;object-fit:cover;}
.acard-body{flex:1;min-width:0;}
.acard-name{font-size:var(--fs-5);font-weight:800;font-family:var(--serif);color:var(--ink);line-height:1.2;}
.acard-sub{font-size:var(--fs-2);color:var(--ink-3);margin:3px 0 13px;}
.acard-info{display:flex;flex-direction:column;gap:8px;}
.acard-row{display:flex;align-items:center;gap:8px;font-size:var(--fs-2);color:var(--ink);}
.acard-row svg{color:var(--pine);flex-shrink:0;}
.acard-row .acard-l{color:var(--ink-3);flex-shrink:0;min-width:82px;}
.acard-row b{text-align:left;}
.acard-greet{display:flex;gap:10px;margin:0 20px;background:var(--pine-soft);border-radius:var(--r2);padding:13px 15px;color:var(--pine-deep);}
.acard-greet svg{flex-shrink:0;color:var(--pine);margin-top:2px;}
.acard-greet p{margin:0;font-size:var(--fs-2);line-height:1.55;}
.acard-foot{padding:12px 20px 16px;font-size:var(--fs-1);color:var(--ink-3);letter-spacing:.03em;text-align:center;}
.acard-acts{display:flex;gap:10px;flex-wrap:wrap;justify-content:center;}
.acard-acts .btn{box-shadow:0 6px 18px rgba(0,0,0,.25);}
@media(max-width:560px){.acard-mid{flex-direction:column;text-align:center;}.acard-row{justify-content:center;}
  .acard-body{text-align:center;}.acard-info{align-items:flex-start;display:inline-flex;}}
.lp-date{display:flex;gap:14px;align-items:center;}
.lp-datebox{background:var(--pine-soft);border-radius:var(--r2);padding:9px 14px;text-align:center;flex-shrink:0;}
.lp-datebox .m{font-size:var(--fs-1);font-weight:700;color:var(--pine);}
.lp-datebox .d{font-size:var(--fs-6);font-weight:700;color:var(--pine-deep);line-height:1;font-family:var(--serif);}
/* แถบเข้ม */
.lp-research{background:linear-gradient(150deg,var(--pine-dark),var(--pine-deep));margin-top:30px;padding:42px 0;
  position:relative;overflow:hidden;}
.lp-research-grid{display:grid;grid-template-columns:1.1fr .9fr;gap:40px;align-items:center;}
.lp-obj{background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.13);border-radius:var(--r3);padding:20px 22px;}
.lp-obj-item{display:flex;gap:11px;margin-bottom:13px;}
.lp-obj-item:last-child{margin-bottom:0;}
.lp-obj-item span{width:24px;height:24px;border-radius:50%;background:rgba(235,90,38,.22);color:var(--terra);
  font-size:var(--fs-1);font-weight:700;display:grid;place-items:center;flex-shrink:0;font-family:var(--serif);}
.lp-obj-item p{margin:0;color:rgba(255,255,255,.82);font-size:var(--fs-3);line-height:1.6;}
.lp-nums{display:grid;grid-template-columns:repeat(2,1fr);gap:12px;}
.lp-num{background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.13);border-radius:var(--r3);padding:16px 18px;}
.lp-num .n{font-family:var(--serif);font-size:var(--fs-6);font-weight:700;line-height:1;color:var(--on-accent);}
.lp-num .l{font-size:var(--fs-1);color:rgba(255,255,255,.7);margin-top:5px;}
/* footer */
.lp-foot{background:var(--pine-deep);color:rgba(255,255,255,.6);padding:34px 0 26px;font-size:var(--fs-2);}
.lp-foot .cols{display:grid;grid-template-columns:1.5fr 1fr 1fr;gap:30px;padding-bottom:22px;
  border-bottom:1px solid rgba(255,255,255,.1);}
.lp-foot b{color:var(--on-accent);display:block;margin-bottom:9px;font-size:var(--fs-3);font-family:var(--serif);}
.lp-foot a{display:block;padding:3px 0;color:rgba(255,255,255,.6);cursor:pointer;}
.lp-foot a:hover{color:var(--on-accent);}
.lp-foot .bot{padding-top:18px;display:flex;justify-content:space-between;gap:12px;flex-wrap:wrap;font-size:var(--fs-1);}
/* หน้าเข้าสู่ระบบ */
.solo{display:grid;place-items:center;padding:56px 24px 70px;min-height:calc(100vh - 47px);position:relative;overflow:hidden;}
.solo::before{content:'';position:absolute;top:-200px;right:-120px;width:520px;height:520px;border-radius:50%;
  background:radial-gradient(circle,var(--pine-soft) 0%,transparent 68%);opacity:.9;}
.solo::after{content:'';position:absolute;bottom:-140px;left:-110px;width:400px;height:400px;border-radius:50%;
  background:radial-gradient(circle,var(--terra-soft) 0%,transparent 70%);opacity:.65;}
.solo > *{position:relative;z-index:1;}
.btn-google{width:100%;display:flex;align-items:center;justify-content:center;gap:11px;background:var(--surface-plain);
  border:1.5px solid var(--g-line);border-radius:var(--r2);padding:.85rem;font-size:var(--fs-3);font-weight:600;color:var(--g-ink);transition:.16s;}
.btn-google:hover{background:var(--g-hover);box-shadow:var(--sh-2);border-color:var(--g-line-h);}
.alt-link{font-size:var(--fs-2);color:var(--ink-3);background:none;border:none;text-decoration:underline;text-underline-offset:3px;padding:2px;}
.alt-link:hover{color:var(--accent);}
[hidden]{display:none!important;}

/* รายการงานรอตรวจ */
.lg{display:flex;gap:16px;padding:17px 20px;border-bottom:1px solid var(--line-2);align-items:flex-start;}
.lg:last-child{border-bottom:none;}
.lg .who{min-width:168px;}
.lg .who b{font-size:var(--fs-3);display:block;}
.lg .who small{font-size:var(--fs-1);color:var(--ink-3);}
.lg .body{flex:1;font-size:var(--fs-2);color:var(--ink-2);line-height:1.6;}
.lg .acts{display:flex;gap:7px;flex-shrink:0;align-items:center;}

/* ── ประกาศระบบ: แถบบน + ป๊อบอัป + สวิตช์ (Phase A · 7 ก.ย. 69) ── */
.ann-bar{display:flex;align-items:center;gap:12px;
  padding:9px 18px;font-size:var(--fs-2);font-weight:500;
  background:linear-gradient(90deg,var(--pine),var(--pine-dark));color:var(--on-accent);}
.ann-bar.warn{background:linear-gradient(90deg,var(--warn),var(--warn-ink));}
/* EC-04 · แถบ "ติดต่อเซิร์ฟเวอร์ไม่ได้" — ไม่บังหน้าจอ ไม่ล็อกการทำงาน
   ผู้ใช้ยังกรอกต่อได้ระหว่างเน็ตหลุด แล้วค่อยกดบันทึกทีเดียวเมื่อกลับมาออนไลน์ */
.net-bar{display:flex;align-items:center;gap:12px;padding:9px 18px;
  font-size:var(--fs-2);font-weight:500;color:var(--on-accent);
  background:linear-gradient(90deg,var(--bad),var(--bad-ink));}
.net-bar .net-tx{flex:1;min-width:0;}
.fail-sim{display:flex;flex-direction:column;gap:8px;}
/* ผัง 10 ขั้นฉบับหน้าสาธารณะ (รอบสี่ ข้อ 5) */
.lp-rolebar{display:flex;flex-wrap:wrap;gap:8px;}
.lp-flow10{display:flex;flex-direction:column;gap:2px;}
.lp-fstep{display:flex;gap:14px;padding:13px 2px;border-bottom:1px solid var(--line-2);}
.lp-fstep:last-child{border-bottom:0;}
.lp-fstep.dim{opacity:.4;}
.lp-fno{flex:0 0 auto;width:30px;height:30px;border-radius:var(--pill);
  display:grid;place-items:center;font-weight:700;font-size:var(--fs-2);
  background:var(--accent-soft);color:var(--accent-dark);}
.lp-fbody{flex:1;min-width:0;}
.lp-fbody>b{display:flex;align-items:center;gap:7px;font-size:var(--fs-3);}
.lp-fby{display:flex;gap:8px;margin-top:7px;font-size:var(--fs-2);color:var(--ink-2);line-height:1.6;}
.lp-fby .tag{flex:0 0 auto;align-self:flex-start;}
@media (max-width:560px){.lp-fby{flex-direction:column;gap:3px;}}
.ronly-bar{display:flex;align-items:center;gap:12px;}
.ronly-bar .btn{flex:0 0 auto;margin-left:auto;}
@media (max-width:560px){.ronly-bar{flex-wrap:wrap;}.ronly-bar .btn{margin-left:0;width:100%;}}
.lp-num-note{grid-column:1/-1;display:flex;align-items:center;gap:7px;
  margin-top:4px;font-size:var(--fs-1);color:var(--ink-4);}
/* แถบเสนอให้กู้ฉบับร่าง — สีต่างจากแถบ "ยังไม่บันทึก" เพื่อไม่ให้สับสนว่าเป็นอันเดียวกัน */
.draft-bar{border-color:var(--warn);background:var(--warn-soft);}
.fail-sim .btn{justify-content:flex-start;}
.ann-bar .ann-ic{flex-shrink:0;font-size:var(--fs-4);opacity:.9;}
.ann-bar .ann-tx{flex:1;min-width:0;line-height:1.4;}
.ann-bar .ann-x{flex-shrink:0;width:26px;height:26px;border-radius:50%;border:none;cursor:pointer;
  background:rgba(255,255,255,.16);color:var(--on-accent);display:grid;place-items:center;font-size:var(--fs-3);}
.ann-bar .ann-x:hover{background:rgba(255,255,255,.3);}
.ann-pop-back{position:fixed;inset:0;z-index:2000;background:rgba(31,36,51,.5);backdrop-filter:blur(3px);
  display:flex;align-items:center;justify-content:center;padding:20px;}
.ann-pop{background:var(--surface);border-radius:var(--r3);box-shadow:var(--sh-3);width:min(440px,100%);overflow:hidden;}
.ann-pop-img{aspect-ratio:16 / 9;background-size:cover;background-position:center;background-color:var(--surface-2);}
.ann-pop-b{padding:22px 24px 24px;}
.ann-pop-b h3{font-size:var(--fs-5);margin:0 0 8px;}
.ann-pop-b p{font-size:var(--fs-3);color:var(--ink-2);line-height:1.65;margin:0;}
.ann-pop-f{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:20px;flex-wrap:wrap;}
.ann-pop-never{font-size:var(--fs-2);color:var(--ink-3);background:none;border:none;cursor:pointer;text-decoration:underline;}
.ann-pop-never:hover{color:var(--ink);}
/* สวิตช์เปิด/ปิด (checkbox) แบบ IT·CIL */
.switch{position:relative;display:inline-block;width:46px;height:26px;flex-shrink:0;}
.switch input{position:absolute;opacity:0;width:100%;height:100%;margin:0;cursor:pointer;}
.switch .sw-track{position:absolute;inset:0;border-radius:999px;background:var(--line);transition:.18s;}
.switch .sw-track::before{content:'';position:absolute;left:3px;top:3px;width:20px;height:20px;border-radius:50%;
  background:var(--surface-plain);box-shadow:var(--sh-1);transition:.18s;}
.switch input:checked + .sw-track{background:var(--accent);}
.switch input:checked + .sw-track::before{transform:translateX(20px);}
.switch-row{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:12px 0;}
.switch-row .sw-l{font-weight:600;font-size:var(--fs-3);color:var(--ink);}
.switch-row .sw-l small{display:block;font-weight:400;font-size:var(--fs-2);color:var(--ink-3);margin-top:2px;}
.mk-tog input{width:34px;height:19px;appearance:none;background:rgba(255,255,255,.2);border-radius:var(--pill);
  position:relative;transition:.2s;margin:0;}
.mk-tog input::after{content:'';position:absolute;top:2px;left:2px;width:15px;height:15px;background:var(--surface-plain);border-radius:50%;transition:.2s;}
.mk-tog input:checked{background:var(--terra);}
.mk-tog input:checked::after{transform:translateX(15px);}
.note{display:none;background:var(--terra-soft);border:1px solid color-mix(in srgb,var(--terra) 32%,transparent);
  border-left:3px solid var(--terra);border-radius:var(--r2);padding:10px 13px;font-size:var(--fs-2);color:var(--terra-dark);
  margin:12px 0;line-height:1.6;}
.note::before{content:'เปลี่ยนจากเดิม · ';font-weight:700;}
body.notes .note{display:block;}
.screen{display:none;} .screen.on{display:block;}

@media(max-width:900px){ .lp-hero-split{grid-template-columns:1fr;gap:30px;padding-top:38px;} }
/* ═══ ADD-19 (18 ก.ย. 69) — แถบเมนูแบบไอคอนช่วงแท็บเล็ต (701–900px) ═══
   🔴 ของเดิม "ซ่อนแถบเมนูทั้งแถบ" ตั้งแต่ 900px ลงมา ⇒ แท็บเล็ตแนวตั้งที่มีที่ว่างเหลือเฟือ
      กลับต้องกดเปิดลิ้นชักทุกครั้งที่จะเปลี่ยนหน้า เหมือนใช้บนโทรศัพท์
      ผลตรวจจัดข้อนี้ไว้ที่ "รอดูว่ามีคนใช้แท็บเล็ตจริงแค่ไหน" — แต่ของจริงคือ
      อาจารย์นิเทศก์พกแท็บเล็ตออกไปนิเทศที่โรงเรียน (ระบุไว้ในสมมติฐานของผลตรวจเอง)
   ⇒ 3 ช่วงตามสเกลจุดเปลี่ยนจอ: ≥901 แถบเต็ม · 701–900 แถบไอคอน · ≤700 ลิ้นชัก
   ⚠️ ข้อความของรายการเมนูเป็น "ข้อความเปล่า" ไม่ได้ห่อแท็กไว้ ⇒ เลือกซ่อนด้วย CSS ตรง ๆ ไม่ได้
      ใช้ font-size:0 ที่ตัวรายการ แล้วให้ไอคอน/ป้ายมีขนาดของตัวเอง (ทั้งคู่กำหนดขนาดไว้แล้ว)
      🔴 ข้อความยังอยู่ใน DOM ครบ ⇒ โปรแกรมอ่านหน้าจอยังอ่านชื่อเมนูได้เหมือนเดิมทุกประการ
         และ applyRailTips() เติม title ให้ทุกปุ่ม ⇒ คนที่เห็นภาพก็ยังรู้ว่าไอคอนไหนคืออะไร */
@media(min-width:701px) and (max-width:900px){
  .shell{grid-template-columns:var(--rail-icon) 1fr;}
  .rail-brand{padding:14px 0;justify-content:center;}
  .rail-brand > div{display:none;}          /* ชื่อระบบ/ชื่อพื้นที่ — เหลือแต่ตรา */
  .rail-search{display:none;}               /* ช่องค้นเมนู พิมพ์ไม่ได้ในความกว้างนี้ */
  .rail-sec{display:none;}                  /* หัวข้อหมวด อ่านไม่ออกถ้าบีบ */
  .rail-foot{display:none;}
  .rail-nav{padding:12px 8px;gap:4px;}
  .nav-i{font-size:0;justify-content:center;padding:11px 0;gap:0;}
  .nav-i.on::before{left:-8px;}
  /* ป้ายตัวเลขย้ายไปเกาะมุมบนขวาของไอคอน — วางในแถวเดิมจะดันไอคอนหลุดกรอบ */
  .nav-i .tag{position:absolute;top:3px;right:8px;margin-left:0;padding:0 5px;min-width:17px;text-align:center;}
}
@media(max-width:700px){
  .shell{grid-template-columns:1fr;}
  .rail{position:fixed;top:0;left:0;bottom:0;width:min(280px,82vw);z-index:1200;transform:translateX(-100%);
    transition:transform .26s cubic-bezier(.4,0,.2,1);box-shadow:var(--sh-3);}
  .shell.nav-open .rail{transform:translateX(0);}
  .rail-toggle{display:inline-flex;}
}
@media(max-width:900px){
  .topbar{padding:0 16px;gap:10px;} .page{padding:20px 16px 60px;}
  .g-83,.grid2,.lp-research-grid,.lp-foot .cols{grid-template-columns:1fr;}
  .lp-flow{flex-direction:column;align-items:stretch;gap:14px;} .lp-flow-arr{transform:rotate(90deg);align-self:center;}
  /* ⚠️ ไม่ต้องมี .card:has(> .tbl){overflow:auto} ที่นี่ — table() ห่อด้วย .tbl-wrap
     (บรรทัด ~818) ที่มี overflow:auto ของตัวเองอยู่แล้วเสมอ กฎซ้ำที่นี่ทำให้เข้าใจผิดว่าแก้ตรงนี้ได้ผล
     (จับได้ตอน --prove: ถอดกฎนี้ออกแล้วไม่มีเทสต์ล้มเลย เพราะมันไม่เคยทำงาน) */
  .tbl{min-width:620px;}

  /* ── ที่เพิ่มหลังตรวจจอมือถือจริงครั้งแรก (20 ส.ค. 69 · node design/check_mobile.js) ──
     ก่อนหน้านี้ไม่เคยเปิดดูบนจอ 390px เลยสักครั้ง จึงไม่มีใครเห็นว่าอะไรล้น */

  /* 1) เมนูหน้าสาธารณะยาว 4 ลิงก์ ดันหน้าให้เลื่อนแนวนอน 665px บนจอ 390px
        ⇒ ให้ตกบรรทัดได้ และเลื่อนในตัวเองถ้ายังไม่พอ */
  .lp-wrap{padding:14px 16px;}
  .lp-links{flex-wrap:wrap;justify-content:flex-end;row-gap:4px;}

  /* 2) แถบบริบทล็อก nowrap ไว้เพื่อกันความสูงกระโดดบนจอทำงาน
        แต่บนมือถือ ชิป 4 ตัว + ปุ่มยัดบรรทัดเดียวไม่ได้ ⇒ ปลดล็อกเฉพาะจอแคบ
        (ความสูงกระโดดไม่ใช่ปัญหาบนมือถือ เพราะแถบไม่ได้ติดหนึบเหมือนจอกว้าง) */
  .ctxbar-in{flex-wrap:wrap;padding:8px 16px;min-height:0;row-gap:8px;}
  .ctxbar{position:static;}

  /* 3) แถวงานรอตรวจ (.lg) วางชื่อ-เนื้อหา-ปุ่ม เรียงนอนกัน ⇒ กว้าง 586px
        ⇒ เรียงลงเป็นชั้นแทน และปุ่มกินเต็มความกว้าง */
  .lg{flex-direction:column;gap:10px;padding:15px 16px;}
  .lg .who{min-width:0;}
  .lg .acts{width:100%;flex-wrap:wrap;}
  .lg .acts .btn{flex:1 1 auto;}

  /* 4) เป้ากดต้องกดถูกด้วยนิ้วโป้ง — WCAG 2.2 ขั้นต่ำ 24px · Apple HIG แนะนำ 44px
        เลือก 40px เป็นเกณฑ์ของระบบนี้ (ปุ่มเดิม 31px · ปุ่มไอคอน 22px กดพลาดแน่นอน) */
  .btn, .btn-sm{min-height:40px;}
  .act, .sens-btn{min-width:40px;min-height:40px;}
  .miss-chip{min-height:40px;padding:7px 13px;}
  .nav-i{min-height:44px;}

  /* 5) หัวข้อในการ์ดที่มีปุ่มท้ายแถว ดันการ์ดกว้างเกินจอ */
  .sec-h{flex-wrap:wrap;row-gap:8px;}
  .ph-head{flex-wrap:wrap;row-gap:10px;}

  /* 6) แถวปุ่มท้ายฟอร์ม — .btn มี white-space:nowrap ⇒ 2 ปุ่มยาวรวมกันเกินจอ 360px
        (เจอที่หน้าส่งงาน: "บันทึกร่าง" + "ส่งให้อาจารย์นิเทศก์") */
  .f-actions{flex-wrap:wrap;}
  .f-actions .btn{flex:1 1 140px;}
}
@media(max-width:560px){
  .lp-title{font-size:var(--fs-7);} .topbar{height:58px;} .usr-meta{display:none;} .ph-head h1{font-size:var(--fs-5);}
}

/* ═══════════════════════════════════════════════════════════════════════════
   ชั้นที่เพิ่มเข้ามาตอนทำโปรโตไทป์ให้ "ทำงานได้จริง"
   ทุกอย่างในบล็อกนี้ยกไปเป็น tims-ds.css ของระบบจริงได้ตรง ๆ
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── ระยะห่างระหว่างกรอบข้อมูล ──
   บทเรียนจาก IT-CIL (ข้อ 3 ของการวินิจฉัยดีไซน์): "ระยะห่างใหญ่" คือหนึ่งในตัวแปรหลัก
   ที่ทำให้หน้าจอดูไม่อึดอัด — ของเดิม 9–17px ทั่วทุกที่ ทำให้ตาไม่มีที่พัก
   ⚠️ .mb / .mt ถูกใช้ในโค้ดตั้งแต่แรกแต่ลืมนิยาม ⇒ การ์ดที่ควรมีช่องไฟจึงติดกันหมด */
.mb{margin-bottom:20px;}
.mt{margin-top:20px;}
/* ⭐ กันบล็อกระดับหน้า "ชนกันเอง" — บล็อกลูกตรงของพื้นที่หน้าทุกอันมีระยะห่างบนอย่างน้อย 16px
   margin ยุบกับ margin-bottom เดิม (.mb 20px, .hero ฯลฯ) จึงไม่ทบซ้อน
   🔴 เดิม .tip/.calwrap/.hero ที่วางเดี่ยวไม่มี margin ⇒ การ์ด "กำลังอยู่ในช่วง" ชนตารางปฏิทิน
      (เจ้าของงานพบ 29 ส.ค. 69) · ห้ามเกิดซ้ำ — คุมที่ชั้นเดียวครอบทุกหน้า ทุกบทบาท */
[data-view="stu"] > * + *,
[data-view="sup"] > * + *,
[data-view="com"] > * + *,
[data-view="adm"] > * + * { margin-top: 16px; }
/* ⭐ ศูนย์ตั้งค่าแบบการ์ด (พอร์ตจาก IT-CIL dash.css .hub-* · เจ้าของงานสั่ง 29 ส.ค. 69)
   การ์ดหนึ่งใบ = ทางเข้าหนึ่งเรื่อง · กดแล้วเปิดหน้าย่อยของเรื่องนั้น */
.hub-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:14px;}
.hub-card{display:flex;gap:13px;align-items:flex-start;text-align:left;padding:17px 18px;background:var(--surface);
  border:1.5px solid var(--line);border-radius:var(--r3);cursor:pointer;text-decoration:none;color:inherit;
  transition:border-color .16s,box-shadow .16s,transform .16s;box-shadow:var(--sh-1);width:100%;font-family:inherit;}
.hub-card:hover{border-color:var(--accent);transform:translateY(-2px);box-shadow:var(--sh-2);}
.hub-ic{width:42px;height:42px;border-radius:var(--r2);flex-shrink:0;display:flex;align-items:center;justify-content:center;
  font-size:var(--fs-5);color:var(--on-accent);}
.hub-tx{min-width:0;flex:1;}
.hub-tx b{display:block;font-size:var(--fs-3);color:var(--ink);}
.hub-tx small{display:block;font-size:var(--fs-1);color:var(--ink-3);margin-top:3px;line-height:1.45;}
.hub-tag{display:inline-block;margin-top:7px;font-size:var(--fs-1);font-weight:700;padding:2px 8px;border-radius:999px;
  background:var(--warn-soft);color:var(--warn-ink);}
/* หมวดในศูนย์ตั้งค่า (จัดกลุ่มให้หาง่าย · 7 ก.ย. 69) */
.set-group{margin-bottom:24px;}
.set-group-h{display:flex;align-items:center;gap:8px;font-size:var(--fs-2);font-weight:700;
  letter-spacing:.03em;color:var(--ink-2);margin:0 0 12px;padding-bottom:8px;border-bottom:1px solid var(--line-2);}
.set-group-h svg{font-size:var(--fs-4);color:var(--accent);}
/* ⭐ Part B — ศูนย์ตั้งค่าหน้าตาอิงต้นแบบ IT-CIL (เจ้าของงานสั่ง 5 ก.ย. 69)
   ฟอร์มซ้าย + แผงพรีวิว/บริบทขวา · ป้าย "แสดงที่" · ตัวนับตัวอักษร · การ์ดพรีวิวการแชร์
   CR-26 (13 ก.ย. 69): เดิมแบ่ง 1.1fr/.9fr ทำให้ฟอร์มถูกบีบเหลือ ~55% ของความกว้างจอเสมอ
   ทั้งที่ .page ขยายเต็มจอไปแล้ว (CR-21) ⇒ เปลี่ยน .set-2col เป็นเรียงคอลัมน์เดียวเต็มความกว้าง
   (ฟอร์ม+ตัวอย่างสลับกันได้อิสระตามลำดับ HTML ที่แต่ละหน้าเรียก — ไม่ผูกตำแหน่งตายตัว)
   ⚠️ เจ้าของงานรีวิวแล้วให้ตัวอย่างอยู่ "ท้ายฟอร์ม" ไม่ใช่บนสุด (org/landing) และให้ SEO
   กลับไปใช้เลย์เอาต์ 2 คอลัมน์เดิมเพราะย้ายขึ้นบนแล้ว "ไม่สวย" (ดู .set-2col-cls ด้านล่าง) */
.set-2col{display:flex;flex-direction:column;gap:18px;}
.set-side{display:flex;flex-wrap:wrap;gap:14px;align-items:flex-start;}
.set-side .sec-h{flex:1 1 100%;font-size:var(--fs-2);font-weight:700;color:var(--ink-2);margin:0 0 -6px;display:flex;align-items:center;gap:7px;}
.set-side>.pv-card,.set-side>.tip,.set-side>.env-card,.set-side>.src-note{flex:0 1 380px;}
/* CR-26ข (13 ก.ย. 69): SEO หน้าแรก — กลับไปใช้เลย์เอาต์ 2 คอลัมน์เดิม (พรีวิวขวา) เฉพาะหน้านี้
   ตามที่เจ้าของงานสั่งกลับ ("เอากลับตำแหน่งเดิม เหมือนเดิม อันนี้ไม่สวย") ไม่ใช้ .set-2col ร่วมกับหน้าอื่น */
.set-2col-cls{display:grid;grid-template-columns:1.1fr .9fr;gap:18px;align-items:start;}
@media(max-width:900px){.set-2col-cls{grid-template-columns:1fr;}}
.set-2col-cls>.set-side{flex-direction:column;flex-wrap:nowrap;}
.set-2col-cls>.set-side>.pv-card,.set-2col-cls>.set-side>.tip,
.set-2col-cls>.set-side>.env-card,.set-2col-cls>.set-side>.src-note{flex:0 0 auto;width:100%;}
@media(min-width:901px){.set-2col-cls>.set-side{position:sticky;top:14px;}}
/* ป้าย "แสดงที่:" ใต้ช่องกรอก — บอกว่าค่านี้ไปโผล่ที่ไหนบ้าง */
.shown-at{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin-top:-8px;margin-bottom:2px;font-size:var(--fs-1);}
/* 🔴 18 ก.ย. 69 — ป้าย "แสดงที่:" ใช้ได้ 2 ตำแหน่ง และระยะห่างของสองที่นั้นไม่เท่ากัน
   · วางต่อจาก .field (8 จุด) — .field มี margin-bottom 18px ⇒ ดึงขึ้น 8px แล้วเหลือ 10px กำลังดี
   · วางไว้ "ข้างใน" .field (1 จุด) — .field เป็น flex column gap 7px ⇒ ดึงขึ้น 8px แล้วเหลือ **-1px**
     คือทับขอบล่างของช่องกรอกพอดี (เจ้าของงานเห็นจากภาพจริงที่ "โดเมนอีเมลที่อนุญาต")
   ⇒ ล้างค่าดึงขึ้นเมื่ออยู่ในกล่องที่จัดระยะให้เองอยู่แล้ว · แก้ที่นี่ที่เดียวครอบทุกจุดที่จะเขียนใหม่ */
.field > .shown-at{margin-top:0;}
.shown-at .sa-lead{color:var(--ink-3);font-weight:700;}
.sa-chip{display:inline-flex;align-items:center;gap:4px;padding:2px 9px;border-radius:999px;
  background:var(--plum-soft);color:var(--plum);font-weight:600;font-size:var(--fs-1);white-space:nowrap;}
.sa-chip svg{font-size:var(--fs-2);}
/* ตัวนับตัวอักษร (คู่กับ label) */
.lab-count{display:flex;align-items:baseline;justify-content:space-between;gap:10px;}
.charc{font-size:var(--fs-1);color:var(--ink-3);font-weight:700;font-variant-numeric:tabular-nums;white-space:nowrap;}
.charc.over{color:var(--bad);} .charc.good{color:var(--ok-ink);}
/* หมายเหตุ "แหล่งเดียว" (single source of truth) สีเขียว */
.src-note{display:flex;gap:8px;align-items:flex-start;padding:10px 12px;border-radius:var(--r2);
  background:var(--ok-soft);color:var(--ok-ink);font-size:var(--fs-1);line-height:1.55;
  border:1px solid color-mix(in srgb,var(--ok) 30%,transparent);}
.src-note svg{flex-shrink:0;margin-top:2px;font-size:var(--fs-4);}
/* การ์ดพรีวิว (Google · Facebook · LINE) */
.pv-card{border:1px solid var(--line);border-radius:var(--r2);background:var(--surface);overflow:hidden;box-shadow:var(--sh-1);}
.pv-head{display:flex;align-items:center;gap:7px;padding:8px 12px;font-size:var(--fs-1);font-weight:700;color:var(--ink-2);
  border-bottom:1px solid var(--line-2);background:var(--surface-2);}
.pv-head svg{font-size:var(--fs-3);}
.pv-body{padding:12px 14px;}
.pv-g-url{font-size:var(--fs-1);color:var(--ok-ink);word-break:break-all;}
.pv-g-title{font-size:var(--fs-4);color:var(--seo-link);line-height:1.3;margin:2px 0;font-weight:600;word-break:break-word;}
.pv-g-desc{font-size:var(--fs-2);color:var(--ink-2);line-height:1.5;word-break:break-word;}
.pv-og-img{aspect-ratio:1200/630;background:linear-gradient(135deg,var(--pine),var(--pine-deep));
  display:flex;align-items:center;justify-content:center;color:color-mix(in srgb,var(--on-accent) 82%,transparent);
  font-size:var(--fs-1);font-weight:600;text-align:center;padding:10px;}
.pv-og-tx{padding:10px 12px;background:var(--surface-2);}
.pv-og-dom{font-size:var(--fs-1);text-transform:uppercase;letter-spacing:.05em;color:var(--ink-3);}
.pv-og-title{font-size:var(--fs-3);font-weight:700;color:var(--ink);line-height:1.35;margin:3px 0;word-break:break-word;}
.pv-og-desc{font-size:var(--fs-1);color:var(--ink-3);line-height:1.45;word-break:break-word;}
/* การ์ดอธิบายว่าค่าจริงเก็บใน .env / system_settings */
.env-card{border:1px dashed color-mix(in srgb,var(--ink-4) 55%,var(--line));border-radius:var(--r2);
  background:var(--surface-2);padding:12px 14px;font-size:var(--fs-1);color:var(--ink-3);line-height:1.6;}
.env-card b{color:var(--ink-2);}
/* ป้ายตัวแปรในเทมเพลตแจ้งเตือน + แถวสถานะในแผงตั้งค่า */
.var-chip{display:inline-block;background:var(--accent-soft);color:var(--accent-dark);font-weight:700;
  font-size:var(--fs-1);padding:1px 7px;border-radius:6px;white-space:nowrap;}
.set-stat{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:9px 0;
  border-top:1px solid var(--line-2);font-size:var(--fs-2);color:var(--ink-2);}
.set-stat:first-child{border-top:none;}
.set-stat span{display:inline-flex;align-items:center;gap:6px;}
.set-stat b{color:var(--ink);}
/* ตัวแก้นโยบายแบบแบ่งข้อ (numbered sections) */
.pol-list{display:flex;flex-direction:column;}
.pol-sec{display:flex;gap:13px;padding:15px 0;border-top:1px solid var(--line-2);}
.pol-sec:first-child{border-top:none;}
.pol-num{width:28px;height:28px;border-radius:50%;flex-shrink:0;display:flex;align-items:center;justify-content:center;
  background:var(--accent-soft);color:var(--accent-dark);font-weight:800;font-size:var(--fs-2);}
.pol-tx{flex:1;min-width:0;}
.pol-tx b{display:block;font-size:var(--fs-3);color:var(--ink);margin-bottom:4px;}
.pol-tx p{font-size:var(--fs-2);color:var(--ink-2);line-height:1.65;margin:0;}
.pol-act{flex-shrink:0;}
/* รายการเนื้อหาเป็นการ์ด (ประกาศ/ช่วยเหลือ · แทนตารางเส้นกริด · 7 ก.ย. 69) */
.ctl-head{margin-bottom:14px;}
.ctl{display:flex;flex-direction:column;gap:10px;}
.ctl-card{display:flex;gap:14px;align-items:flex-start;padding:14px 16px;background:var(--surface);
  border:1px solid var(--line);border-radius:var(--r3);box-shadow:var(--sh-1);transition:border-color .15s;}
.ctl-card:hover{border-color:color-mix(in srgb,var(--accent) 22%,var(--line));}
.ctl-ic{width:40px;height:40px;border-radius:var(--r2);flex-shrink:0;display:grid;place-items:center;font-size:var(--fs-4);}
.ctl-b{flex:1;min-width:0;}
.ctl-t{display:flex;align-items:center;gap:10px;flex-wrap:wrap;}
.ctl-t b{font-size:var(--fs-3);color:var(--ink);}
.ctl-t code{font-size:var(--fs-1);background:var(--surface-2);padding:2px 8px;border-radius:6px;color:var(--ink-3);}
.ctl-b p{margin:6px 0 0;font-size:var(--fs-2);color:var(--ink-2);line-height:1.55;word-break:break-word;}
.ctl-meta{margin-top:8px;font-size:var(--fs-1);color:var(--ink-3);display:inline-flex;align-items:center;gap:5px;}
.ctl-card .act{flex-shrink:0;}
/* คอมโพเนนต์อัปโหลดรูป (โลโก้/OG/แบนเนอร์) — พรีวิว + hover เปลี่ยน/ลบ */
.imgup{position:relative;border-radius:var(--r2);overflow:hidden;border:1px solid var(--line);
  background:var(--surface-2);width:100%;}
.imgup>img{width:100%;height:100%;object-fit:cover;display:block;}
/* A-9 (12 ก.ย. 69): ratio:'auto' (โลโก้) — ไฟล์สัดส่วนอะไรก็ได้ ห้ามครอบ/บีบเป็นสี่เหลี่ยมจัตุรัส
   ต้องเจาะจงกว่า .imgup>img ธรรมดา (2 คลาสรวมกัน) ถึงจะชนะ object-fit:cover ของกฎฐาน */
.imgup.imgup-auto{height:160px;display:flex;align-items:center;justify-content:center;padding:14px;}
.imgup.imgup-auto>img{width:auto;height:auto;max-width:100%;max-height:100%;object-fit:contain;display:block;}
.imgup-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:7px;
  border:2px dashed var(--line);color:var(--ink-3);cursor:pointer;font-family:inherit;transition:.15s;}
.imgup-empty:hover{border-color:var(--accent);background:var(--accent-soft);color:var(--accent-dark);}
.imgup-empty svg{font-size:var(--fs-7);color:var(--accent);}
.imgup-empty span{font-size:var(--fs-2);font-weight:600;}
.imgup-empty small{font-size:var(--fs-1);color:var(--ink-3);}
.imgup-ov{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;gap:8px;
  background:color-mix(in srgb,var(--ink) 42%,transparent);opacity:0;transition:.15s;}
.imgup:hover .imgup-ov,.imgup:focus-within .imgup-ov{opacity:1;}
.imgup-ov .btn{background:var(--surface-plain);color:var(--ink);border:none;box-shadow:var(--sh-1);}
.imgup-ov .btn-bad{background:var(--bad);color:var(--on-accent);}
/* ── ข่าวสาร: ตัวเขียนบล็อก + หน้าอ่าน (Phase B · 7 ก.ย. 69) ── */
.chips-pick{display:flex;flex-wrap:wrap;gap:8px;}
.pick-chip{display:inline-flex;align-items:center;gap:7px;padding:8px 14px;border:1.5px solid var(--line);
  border-radius:var(--pill);font-size:var(--fs-2);cursor:pointer;transition:.15s;background:var(--surface);}
.pick-chip:has(input:checked){border-color:var(--accent);background:var(--accent-soft);color:var(--accent-dark);font-weight:600;}
.pick-chip input{accent-color:var(--accent);}
.nb-list{display:flex;flex-direction:column;gap:12px;margin-bottom:14px;}
.nb-e{border:1px solid var(--line);border-radius:var(--r2);padding:13px 14px;background:var(--surface-2);}
.nb-e-h{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:9px;}
.nb-e-tag{display:inline-flex;align-items:center;gap:6px;font-size:var(--fs-1);font-weight:700;color:var(--ink-2);}
.nb-e-tag svg{font-size:var(--fs-3);color:var(--accent);}
.nb-e-act{display:flex;gap:4px;}
.nb-e .inp{background:var(--surface);}
.nb-add-row{display:flex;flex-wrap:wrap;gap:8px;padding-top:4px;}
.nb-add{display:inline-flex;align-items:center;gap:6px;font-family:inherit;font-size:var(--fs-2);font-weight:600;
  color:var(--ink-2);background:var(--surface);border:1.5px dashed var(--line);border-radius:var(--r2);
  padding:8px 12px;cursor:pointer;transition:.15s;}
.nb-add:hover{border-color:var(--accent);color:var(--accent-dark);background:var(--accent-soft);}
.nb-add svg{font-size:var(--fs-3);color:var(--accent);}
/* หน้าอ่านบทความ */
.nb-lead{font-size:var(--fs-4);line-height:1.75;color:var(--ink-2);font-weight:500;margin:0 0 16px;}
.nb-h{font-size:var(--fs-5);margin:22px 0 8px;color:var(--ink);}
.nb-p{font-size:var(--fs-4);line-height:1.85;margin:0 0 14px;color:var(--ink-2);}
.nb-q{margin:0 0 16px;padding:12px 18px;border-left:4px solid var(--accent);background:var(--accent-soft);
  color:var(--accent-dark);font-style:italic;border-radius:0 var(--r2) var(--r2) 0;}
.nb-ul{margin:0 0 16px;padding-left:22px;line-height:1.85;color:var(--ink-2);}
.nb-ul li{margin-bottom:4px;}
.nb-hr{border:none;border-top:1px solid var(--line);margin:22px 0;}
.nb-fig{margin:0 0 18px;}
.nb-fig img{width:100%;border-radius:var(--r2);display:block;}
.nb-fig figcaption{font-size:var(--fs-2);color:var(--ink-3);text-align:center;margin-top:7px;}
.nb-yt{position:relative;aspect-ratio:16 / 9;border-radius:var(--r2);overflow:hidden;margin:0 0 18px;background:var(--video-bg);}
.nb-yt iframe{position:absolute;inset:0;width:100%;height:100%;border:none;}
.nb-file{display:inline-flex;align-items:center;gap:8px;font-size:var(--fs-3);padding:10px 14px;border:1px solid var(--line);
  border-radius:var(--r2);background:var(--surface-2);color:var(--ink-2);margin:0 0 14px;}
/* ⭐ หน้าย่อยสาธารณะ (CR-1 หน้าแรก · เจ้าของงานสั่ง 29 ส.ค. 69) — ป๊อบอัปบนหน้าแรก
   กลายเป็น "หน้าของตัวเอง": ซ่อนเนื้อหาการตลาด เหลือแถบนำทาง + หน้าย่อยเต็มความกว้าง */
.lp-sub{padding:34px 0 60px;}
#s-home.lp-subon > *:not(.lp-nav):not(.lp-sub){display:none !important;}
.lp-sub-head{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;flex-wrap:wrap;margin:14px 0 22px;}
.lp-sub-head h1{font-size:var(--fs-6);line-height:1.25;margin:6px 0 0;}
.lp-sub-eyebrow{font-size:var(--fs-1);font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--terra);}
/* ⭐ การ์ดคะแนนจำแนกรายผู้ประเมิน (CR-8ข · เจ้าของงานสั่ง 29 ส.ค. 69)
   แทนแถบยาวรวม — กดการ์ดผู้ประเมิน → เห็นแบบประเมินของคนนั้น → กดต่อ = รายละเอียดข้อ
   คิดเป็นแพตเทิร์นใช้ซ้ำ (.drill-card) กับหน้าที่ต้องเจาะจากสรุป → รายตัว → รายละเอียด */
.drill-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:14px;}
.drill-card{display:block;width:100%;text-align:left;font-family:inherit;cursor:pointer;
  background:var(--surface);border:1.5px solid var(--line);border-radius:var(--r3);padding:16px 18px;
  box-shadow:var(--sh-1);transition:border-color .16s,box-shadow .16s,transform .16s;}
.drill-card:hover{border-color:var(--accent);transform:translateY(-2px);box-shadow:var(--sh-2);}
.drill-h{display:flex;align-items:center;gap:12px;}
.drill-ic{width:40px;height:40px;border-radius:var(--r2);flex-shrink:0;display:flex;align-items:center;justify-content:center;
  background:var(--accent-soft);color:var(--accent-dark);font-size:var(--fs-4);}
.drill-tx{flex:1;min-width:0;}
.drill-tx b{display:block;font-size:var(--fs-3);color:var(--ink);}
.drill-tx small{display:block;font-size:var(--fs-1);color:var(--ink-3);margin-top:2px;}
.drill-sc{font-size:var(--fs-4);font-weight:800;color:var(--ink);white-space:nowrap;}
.drill-sc .muted{font-size:var(--fs-2);font-weight:600;}
.drill-card > .scorebar{margin-top:12px;}
.drill-arr{color:var(--ink-4);flex-shrink:0;}
/* ⭐ หน้าย่อยสาธารณะแบบกราฟิก (เจ้าของงานสั่ง 29 ส.ค. 69) */
.info-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:14px;}
.info-tile{background:var(--surface);border:1.5px solid var(--line);border-radius:var(--r3);padding:18px;box-shadow:var(--sh-1);}
.info-tile .info-ic{width:44px;height:44px;border-radius:var(--r2);display:flex;align-items:center;justify-content:center;
  font-size:var(--fs-5);margin-bottom:12px;background:var(--accent-soft);color:var(--accent-dark);}
.info-tile b{display:block;font-size:var(--fs-3);}
.info-tile p{margin:5px 0 0;color:var(--ink-3);font-size:var(--fs-3);line-height:1.6;}
.tl-i .place{font-size:var(--fs-1);color:var(--ink-3);margin-top:1px;}
.tl-month{font-size:var(--fs-1);font-weight:800;letter-spacing:.06em;color:var(--terra);text-transform:uppercase;
  margin:2px 0 12px;padding-top:4px;}
.tl-i.past::before{opacity:.5;}
/* การ์ดที่วางซ้อนกันในคอลัมน์เดียว ต้องมีช่องไฟเสมอ ไม่ต้องรอให้ใส่คลาสเอง */
.g-83 > div > .card + .card,
.grid2 > div > .card + .card,
.page > .card + .card{margin-top:20px;}

/* ── หน้าสำหรับพิมพ์ (layout print ตาม B-19) ── */
.print-page{max-width:900px;margin:0 auto;padding:22px 24px 60px;}
.print-bar{display:flex;align-items:center;justify-content:space-between;gap:14px;flex-wrap:wrap;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r3);padding:14px 18px;margin-bottom:22px;box-shadow:var(--sh-1);}
.slip{background:var(--surface-plain);border:1px dashed var(--ink-4);border-radius:var(--r2);padding:18px 20px;margin-bottom:14px;
  display:grid;grid-template-columns:1fr auto;gap:16px;align-items:center;}
.slip h4{font-size:var(--fs-4);margin:0 0 4px;}
.slip .meta{font-size:var(--fs-2);color:var(--ink-3);line-height:1.6;}
.slip .pw{font-family:ui-monospace,monospace;font-size:var(--fs-4);font-weight:700;letter-spacing:.06em;
  background:var(--paper-2);border-radius:var(--r1);padding:9px 16px;white-space:nowrap;}
@media print{
  .mk-bar,.print-bar,.note,.no-print{display:none!important;}
  body{background:var(--surface-plain);} .print-page{padding:0;} .slip{break-inside:avoid;}
}


/* ── แจ้งผลการทำงาน (toast) ── */
.toast-wrap{position:fixed;right:20px;bottom:20px;z-index:2000;display:flex;flex-direction:column;gap:10px;
  align-items:flex-end;pointer-events:none;}
.toast{pointer-events:auto;display:flex;align-items:flex-start;gap:10px;background:var(--surface);
  border:1px solid var(--line);border-left:4px solid var(--accent);border-radius:var(--r2);
  box-shadow:var(--sh-3);padding:12px 16px;max-width:380px;font-size:var(--fs-2);color:var(--ink);
  animation:toast-in .22s cubic-bezier(.2,.8,.3,1);}
.toast.ok{border-left-color:var(--ok);} .toast.ok svg{color:var(--ok);}
.toast.bad{border-left-color:var(--bad);} .toast.bad svg{color:var(--bad);}
.toast.warn{border-left-color:var(--warn);} .toast.warn svg{color:var(--warn);}
.toast svg{font-size:var(--fs-4);color:var(--accent);margin-top:1px;}
.toast b{display:block;font-size:var(--fs-3);margin-bottom:2px;}
.toast small{color:var(--ink-3);font-size:var(--fs-1);line-height:1.5;display:block;}
@keyframes toast-in{from{opacity:0;transform:translateY(14px) scale(.97);}to{opacity:1;transform:none;}}

/* ── กล่องโต้ตอบ (modal) ── */
.modal-back{position:fixed;inset:0;z-index:1900;background:rgba(31,36,51,.45);backdrop-filter:blur(3px);
  display:grid;place-items:center;padding:24px;animation:fade .16s ease;}
@keyframes fade{from{opacity:0;}to{opacity:1;}}
.modal{background:var(--surface);border-radius:var(--r3);box-shadow:var(--sh-3);width:min(560px,100%);
  max-height:88vh;overflow:auto;animation:pop .2s cubic-bezier(.2,.8,.3,1);}
.modal-wide{width:min(820px,100%);}
@keyframes pop{from{opacity:0;transform:translateY(12px) scale(.98);}to{opacity:1;transform:none;}}
.modal-h{display:flex;align-items:center;gap:10px;padding:18px 22px;border-bottom:1px solid var(--line-2);}
.modal-h h3{font-size:var(--fs-4);flex:1;}
.modal-b{padding:20px 22px;}
.modal-f{display:flex;gap:10px;justify-content:flex-end;padding:16px 22px;border-top:1px solid var(--line-2);
  background:var(--surface-2);border-radius:0 0 var(--r3) var(--r3);}

/* ── จุดแดงบนกระดิ่ง ── */
.dot-n{position:absolute;top:7px;right:7px;width:8px;height:8px;border-radius:50%;background:var(--terra);
  box-shadow:0 0 0 2px var(--surface);display:none;}
.dot-n.on{display:block;}

/* ── แท็บในหน้า ── */
.tabs{display:flex;gap:4px;border-bottom:1.5px solid var(--line);margin-bottom:22px;flex-wrap:wrap;}
.tabs button{border:none;background:transparent;font-family:var(--sans);font-size:var(--fs-3);font-weight:600;
  color:var(--ink-3);padding:.6rem 1rem;border-bottom:2.5px solid transparent;margin-bottom:-1.5px;transition:.15s;
  display:inline-flex;align-items:center;gap:7px;}
.tabs button:hover{color:var(--ink);}
.tabs button.on{color:var(--accent-dark);border-bottom-color:var(--accent);}
.tabs .cnt{font-size:var(--fs-1);font-weight:700;padding:1px 7px;border-radius:var(--pill);background:var(--surface-2);color:var(--ink-3);}
.tabs button.on .cnt{background:var(--accent-soft);color:var(--accent-dark);}

/* ── ไทม์ไลน์ (การนิเทศ) ── */
.tl{position:relative;padding-left:26px;}
.tl::before{content:'';position:absolute;left:7px;top:6px;bottom:6px;width:2px;background:var(--line);}
.tl-i{position:relative;padding-bottom:18px;}
.tl-i:last-child{padding-bottom:0;}
.tl-i::before{content:'';position:absolute;left:-23px;top:5px;width:12px;height:12px;border-radius:50%;
  background:var(--surface);border:2.5px solid var(--ink-4);}
.tl-i.done::before{border-color:var(--ok);background:var(--ok);}
.tl-i.next::before{border-color:var(--terra);background:var(--terra);box-shadow:0 0 0 4px var(--terra-soft);}
.tl-i b{font-size:var(--fs-3);} .tl-i .meta{font-size:var(--fs-2);color:var(--ink-3);margin-top:2px;}

/* ── รายการไฟล์แนบ ── */
.file-row{display:flex;align-items:center;gap:10px;padding:9px 12px;border:1px solid var(--line);
  border-radius:var(--r2);background:var(--surface-2);font-size:var(--fs-2);margin-top:8px;}
.file-row svg{color:var(--accent);font-size:var(--fs-4);}
.file-row .nm{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.file-row .sz{font-size:var(--fs-1);color:var(--ink-3);}
/* แถวลิงก์งาน — งานเก็บไว้ที่ไดรฟ์ของนักศึกษา ระบบเก็บแค่ที่อยู่ */
.lnk-row{display:flex;align-items:center;gap:10px;padding:9px 12px;border:1px solid var(--line);
  border-radius:var(--r2);background:var(--surface-2);margin-top:10px;flex-wrap:wrap;}
.lnk-row svg{color:var(--accent);font-size:var(--fs-4);flex-shrink:0;}
.lnk-row .nm{flex:1;min-width:120px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  font-size:var(--fs-2);color:var(--ink-2);}
.lnk-row .kind{font-size:var(--fs-1);font-weight:700;padding:2px 9px;border-radius:var(--pill);
  background:var(--accent-soft);color:var(--accent-dark);white-space:nowrap;}
.tip-warn{background:var(--warn-soft);color:var(--warn-ink);}
/* การ์ดโรงเรียนเครือข่ายที่นักศึกษาเปิดดู — ต้องเห็นข้อมูลครบก่อนตัดสินใจเลือก */
.sch-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:14px;}
.sch-card{display:flex;flex-direction:column;gap:8px;padding:16px;border-radius:var(--r2);
  border:1px solid var(--line);background:var(--surface);}
.sch-card.mine{border-color:var(--ok);box-shadow:0 0 0 2px var(--ok-soft);}
.sch-top{display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap;}
.sch-top b{font-size:var(--fs-3);line-height:1.4;}
.sch-meta{display:flex;align-items:center;gap:5px;flex-wrap:wrap;font-size:var(--fs-2);color:var(--ink-3);}
.sch-meta svg{font-size:var(--fs-3);color:var(--ink-4);}
.sch-rows{display:flex;flex-direction:column;gap:5px;font-size:var(--fs-2);color:var(--ink-2);
  padding-top:9px;border-top:1px solid var(--line-2);}
.sch-rows svg{font-size:var(--fs-3);color:var(--ink-4);margin-right:3px;}
.sch-rows .muted{color:var(--ink-3);}
.sch-seat{margin-top:auto;padding-top:9px;}
.tip-warn svg{color:var(--warn-ink);}

/* ── กล่องสรุปด้านข้าง ── */
.side-item{display:flex;gap:11px;align-items:flex-start;padding:11px 0;border-bottom:1px solid var(--line-2);}
.side-item:last-child{border-bottom:none;padding-bottom:0;}
.side-item .ic{width:34px;height:34px;border-radius:10px;display:grid;place-items:center;flex-shrink:0;
  background:var(--accent-soft);color:var(--accent-dark);font-size:var(--fs-4);}
.side-item b{font-size:var(--fs-2);display:block;} .side-item small{font-size:var(--fs-1);color:var(--ink-3);}

/* ── แถวแจ้งเตือน ── */
/* EC-01: แถวแจ้งเตือนเป็นปุ่มจริง (เดิมเป็น div ที่กดได้แต่แป้นพิมพ์เข้าไม่ถึง) */
.noti{display:flex;gap:12px;padding:14px 18px;border:none;border-bottom:1px solid var(--line-2);
  align-items:flex-start;transition:.15s;width:100%;background:none;font:inherit;color:inherit;
  text-align:left;cursor:pointer;}
.noti:last-child{border-bottom:none;}
.noti.unread{background:var(--accent-soft);}
.noti .ic{width:36px;height:36px;border-radius:11px;display:grid;place-items:center;flex-shrink:0;
  background:var(--surface);border:1px solid var(--line);color:var(--accent);}
.noti .txt{flex:1;font-size:var(--fs-2);line-height:1.55;}
.noti .txt small{display:block;color:var(--ink-3);font-size:var(--fs-1);margin-top:3px;}

/* ── การ์ดโปรไฟล์ใบเดียว แบ่งด้วย "แถบหัวข้อ" ──
   หัวข้อเดิมเป็นแค่บรรทัดตัวหนา จมไปกับแถวข้อมูลจนแยกไม่ออกว่าอันไหนหัวข้อ อันไหนข้อมูล
   ⇒ ทำเป็นแถบเต็มความกว้างการ์ด มีพื้นหลังและเส้นขอบบน-ล่าง อ่านแล้วรู้ทันทีว่าขึ้นส่วนใหม่ */
.prof-body{padding:0;}
.vsec + .vsec{margin-top:0;}
/* พื้นหลังแยกหัวข้อออกจากข้อมูลได้แล้ว แต่ .76rem เล็กเกินไปจนอ่านลำบาก (เจ้าของงานทัก 16 ส.ค. 69)
   ⇒ ขยายเป็น .98rem และลด letter-spacing ลง เพราะตัวโตแล้วไม่ต้องพึ่งระยะห่างช่วยแยก
   ความต่างจากข้อมูลยังอยู่ที่ "พื้นหลัง + สี + ไอคอน" ไม่ใช่ที่ขนาดตัวอักษร */
.vsec-h{display:flex;align-items:center;gap:10px;padding:13px 24px;
  background:var(--surface-2);border-top:1px solid var(--line);border-bottom:1px solid var(--line);
  font-size:var(--fs-3);font-weight:700;letter-spacing:.01em;color:var(--accent-dark);}
.vsec:first-child .vsec-h{border-top:none;}
.vsec-h svg{color:var(--accent);font-size:var(--fs-4);}
.vsec-h .badge{margin-left:auto;letter-spacing:0;font-weight:600;}
.vsec-b{padding:6px 24px 16px;}
.vsec.flash .vsec-h{background:var(--accent-soft);transition:background .25s;}

/* ── แถบกระโดดของหน้าแก้ไข — หน้ายาวลงมาเป็นหน้าเดียว จึงต้องมีทางลัดไปยังหัวข้อ ── */
.jump{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:14px;}
.jump-b{display:inline-flex;align-items:center;gap:6px;padding:7px 13px;border-radius:999px;
  border:1px solid var(--line);background:var(--surface);color:var(--ink-2);
  font:inherit;font-size:var(--fs-2);font-weight:600;cursor:pointer;}
.jump-b:hover{border-color:var(--accent);color:var(--accent-dark);background:var(--accent-soft);}
.jump-b svg{font-size:var(--fs-3);}
.jump-b.miss{border-color:var(--warn);color:var(--warn-ink);}
.jump-b .cnt{background:var(--warn);color:var(--on-accent);border-radius:999px;padding:0 6px;font-size:var(--fs-1);}

/* ── แถบระบุตัวตนบนหน้าแก้ไข (แทนการ์ดใหญ่ที่ทวนข้อมูลซ้ำ) ── */

/* ── แถวในการ์ดบัญชีเข้าระบบ: เรื่องหนึ่ง + ปุ่มของเรื่องนั้น อยู่บรรทัดเดียวกัน ── */
.acct-row{display:flex;align-items:center;gap:14px;padding:11px 0;border-bottom:1px solid var(--line-2);}
.acct-row:last-of-type{border-bottom:none;}
.acct-t{min-width:0;flex:1;}
.acct-t span{display:block;color:var(--ink-3);font-size:var(--fs-1);}
.acct-t b{display:block;font-size:var(--fs-3);font-weight:600;word-break:break-all;margin-top:1px;}
.acct-row .btn{flex-shrink:0;}

/* ── ชิป "ยังขาด" ที่กดไปแก้ได้เลย ── */
.miss-chips{display:flex;flex-wrap:wrap;gap:7px;margin-top:11px;}
.miss-chip{display:inline-flex;align-items:center;gap:5px;font-size:var(--fs-1);font-weight:600;
  padding:5px 11px;border-radius:var(--pill);background:var(--warn-soft);color:var(--warn-ink);
  border:1px solid color-mix(in srgb,var(--warn) 35%,transparent);transition:.15s;}
.miss-chip:hover{background:var(--warn);color:var(--on-accent);border-color:var(--warn);}
.miss-chip svg{font-size:var(--fs-3);}

/* ── แถบบันทึกลอย (หน้าแก้ไขเต็ม) ── */
.save-bar{position:sticky;bottom:14px;max-width:100%;z-index:30;display:flex;align-items:center;justify-content:space-between;
  gap:14px;flex-wrap:wrap;background:var(--surface);border:1px solid var(--line);border-radius:var(--r3);
  padding:12px 16px;box-shadow:var(--sh-3);margin-top:6px;font-size:var(--fs-2);}

/* ── หน้าดูโปรไฟล์ — ยกฮีโร่จาก itcil-php/resources/views/teacher/profile.blade.php ──
   ต่างจากต้นแบบตรงที่ใช้ var(--accent) แทนสีส้มตายตัว ฮีโร่จึงเปลี่ยนสีตามบทบาทเอง */
.prof-hero{overflow:hidden;border:none;}
.prof-hero-top{display:flex;align-items:stretch;gap:22px;padding:22px;flex-wrap:wrap;color:var(--on-accent);
  background:linear-gradient(120deg,var(--accent),var(--accent-dark));}
/* รูปโปรไฟล์: ขยายให้สูงเท่ากรอบสีน้ำเงิน คงสัดส่วนจัตุรัส (เจ้าของงานสั่ง 17 ส.ค. 69)
   148px → 248px

   🐛 ทำไมถึงต้องเป็น "ค่าตายตัว" ไม่ใช่ยืดตามกล่อง — พิสูจน์แล้ว 2 ครั้ง
   ครั้งที่ 1 (IT-CIL v1.3.0p6): เขียน height:100% + aspect-ratio:1 ที่ตัวรูป
     → % ของความสูงต้องอ้างกล่องแม่ที่ "สูงตามลูก" อยู่แล้ว = อ้างอิงวนกัน
       เบราว์เซอร์ตกไปใช้ขนาดจริงของไฟล์ (512×512) รูปใหญ่เต็มการ์ด
   ครั้งที่ 2 (ที่นี่ 17 ส.ค. 69): ลอง align-self:stretch + aspect-ratio:1 ที่กล่องครอบ
     → วัดจริงได้ สูง 249px ถูก แต่ กว้างค้าง 148px
       เพราะ flex คำนวณ "ความกว้างของรายการ" จบไปก่อนแล้วค่อยยืดความสูง
       aspect-ratio จึงมองไม่เห็นความสูงที่ยืด — ได้สี่เหลี่ยมผืนผ้า ไม่ใช่จัตุรัส

   ✅ วิธีที่ใช้: กำหนดจัตุรัสตายตัว 248px ให้ "รูปเป็นตัวกำหนดความสูงของกรอบ"
      แทนที่จะไปตามความสูงของคอลัมน์ขวา — ทิศทางเดียว ไม่มีวง ไม่มีเงื่อนไขของเบราว์เซอร์
      (คอลัมน์ขวาสูง ~249px พอดี ⇒ ทั้งสองฝั่งสูงเท่ากันตามที่ต้องการ) */
.pf-avatar-wrap{position:relative;flex-shrink:0;align-self:center;
  width:248px;height:248px;}
.pf-avatar{width:100%;height:100%;border-radius:14px;overflow:hidden;
  background:rgba(255,255,255,.2);border:3px solid rgba(255,255,255,.6);
  display:flex;align-items:center;justify-content:center;
  font-family:var(--serif);font-size:var(--fs-9);font-weight:700;color:var(--on-accent);}
.pf-cam{position:absolute;right:8px;bottom:8px;width:34px;height:34px;border-radius:9px;
  background:var(--surface-plain);color:var(--accent);border:2px solid var(--accent-soft);
  display:flex;align-items:center;justify-content:center;font-size:var(--fs-4);
  box-shadow:0 2px 8px rgba(0,0,0,.22);transition:.15s;}
.pf-cam:hover{background:var(--accent-soft);}
.pf-g{position:absolute;left:8px;bottom:8px;width:28px;height:28px;border-radius:50%;background:var(--surface-plain);
  display:grid;place-items:center;box-shadow:0 2px 8px rgba(0,0,0,.22);font-size:var(--fs-2);}
.prof-hero-id{flex:1 1 340px;min-width:280px;}
/* คอลัมน์ที่ 2 ของการ์ดหัว — ข้อมูลส่วนตัวอื่น ๆ ที่เดิมเป็นการ์ดแยกอยู่ข้างล่าง
   เส้นคั่นบาง ๆ ด้านซ้ายบอกว่าเป็นคนละชุดข้อมูล โดยไม่ต้องใช้กล่องซ้อนกล่อง */
.prof-hero-side{flex:1 1 300px;min-width:260px;align-self:stretch;
  border-left:1px solid rgba(255,255,255,.22);padding-left:22px;}
.pf-side-h{display:flex;align-items:center;gap:8px;font-weight:700;font-size:var(--fs-3);
  color:rgba(255,255,255,.92);margin-bottom:12px;}
.pf-side-h svg{font-size:var(--fs-4);}
.pf-side-row{display:flex;justify-content:space-between;align-items:baseline;gap:14px;
  padding:9px 0;border-bottom:1px solid rgba(255,255,255,.14);font-size:var(--fs-3);}
.pf-side-row:last-of-type{border-bottom:none;}
.pf-side-row dt{color:rgba(255,255,255,.7);flex-shrink:0;}
.pf-side-row dd{margin:0;font-weight:600;color:var(--on-accent);text-align:right;}
.pf-side-row dd i{font-style:italic;font-weight:400;color:rgba(255,255,255,.55);}
.pf-side-note{display:flex;gap:7px;margin-top:12px;font-size:var(--fs-1);line-height:1.5;
  color:rgba(255,255,255,.62);}
.pf-side-note svg{font-size:var(--fs-3);flex-shrink:0;margin-top:2px;}
@media (max-width:900px){
  .prof-hero-side{border-left:none;border-top:1px solid rgba(255,255,255,.22);
    padding-left:0;padding-top:18px;}
}
.pf-actions{display:flex;gap:8px;margin-top:14px;flex-wrap:wrap;}
.pf-actions .btn{background:rgba(255,255,255,.16);color:var(--on-accent);border:1px solid rgba(255,255,255,.28);}
.pf-actions .btn:hover{background:rgba(255,255,255,.26);border-color:rgba(255,255,255,.45);}
.prof-hero .rolepill{background:rgba(255,255,255,.18);color:var(--on-accent);}
.prof-hero .rolepill .dot{background:var(--surface-plain);}
.prof-hero-bar{padding:16px 22px 20px;border-top:1px solid var(--line-2);}

/* ── ลำดับในคอลัมน์ขวา (เจ้าของงานกำหนด 17 ส.ค. 69) ──
   เลขบัตร (เล็ก เงียบ) → ชื่อเต็ม (เด่นสุด) + ชื่อเล่น → สาขา → รหัส/อีเมล/เบอร์ */
.pf-nid{margin-bottom:10px;}
.pf-name{font-size:var(--fs-6);margin:0 0 4px;color:var(--on-accent);line-height:1.35;}
.pf-nick{font-weight:400;font-size:var(--fs-4);color:rgba(255,255,255,.82);}
.pf-major{display:inline-flex;align-items:center;gap:7px;font-size:var(--fs-3);font-weight:600;
  color:var(--on-accent);background:rgba(255,255,255,.16);border-radius:999px;padding:5px 13px;margin-bottom:14px;}
.pf-major svg{font-size:var(--fs-4);}
/* รหัส/อีเมล/เบอร์ — ป้ายซ้ายจาง ค่าขวาชัด อ่านกวาดตาลงมาได้ */
.pf-meta{display:grid;grid-template-columns:auto 1fr;gap:6px 18px;margin:0;font-size:var(--fs-3);}
.pf-meta dt{color:rgba(255,255,255,.7);}
.pf-meta dd{margin:0;font-weight:600;color:var(--on-accent);word-break:break-all;}
.pf-meta dd i{font-style:normal;font-weight:400;color:rgba(255,255,255,.6);}

/* เลขบัตรบนพื้นเข้ม — ชิปเดิมเป็นโทนสว่าง ต้องกลับด้านไม่งั้นจมหายไปกับพื้น */
.prof-hero .sens{background:rgba(255,255,255,.1);border-color:rgba(255,255,255,.2);
  color:rgba(255,255,255,.78);font-size:var(--fs-1);padding:3px 7px;gap:5px;}
.prof-hero .sens:hover{color:var(--on-accent);border-color:rgba(255,255,255,.34);}
.prof-hero .sens-btn{width:22px;height:22px;font-size:var(--fs-3);}
.prof-hero .sens.shown{background:rgba(255,255,255,.92);border-color:var(--on-accent);color:var(--accent-dark);}
.prof-hero .sens-btn{color:rgba(255,255,255,.75);}
.prof-hero .sens-btn:hover{color:var(--on-accent);background:rgba(255,255,255,.2);}
.prof-hero .sens.shown .sens-btn{color:var(--accent-dark);}
.prof-hero .sens.shown .sens-btn:hover{background:var(--accent-soft);}
.prof-hero .sens-lock{color:rgba(255,255,255,.78);}
.prof-hero .sens-timer{color:rgba(255,255,255,.9);}

/* ── แถวผลการทดสอบ: ไอคอนซ้ายเด่น · ผลขวาเด่น ── */
.trow{display:flex;align-items:center;gap:15px;padding:14px 0;border-bottom:1px solid var(--line-2);}
.trow:last-child{border-bottom:none;padding-bottom:0;}
.trow-ic{width:42px;height:42px;flex-shrink:0;border-radius:12px;display:grid;place-items:center;
  background:var(--accent-soft);color:var(--accent-dark);font-size:var(--fs-5);}
.trow-l{flex:1;min-width:0;font-weight:600;font-size:var(--fs-3);}
.trow-v{text-align:right;font-weight:700;font-size:var(--fs-3);display:flex;align-items:center;
  justify-content:flex-end;gap:8px;flex-wrap:wrap;}
.trow-v .vsub{font-weight:500;font-size:var(--fs-2);color:var(--ink-3);}

/* ── กล่องรูปโปรไฟล์บนหน้าแก้ไข (ย้ายมาจากหน้าดู) ── */
.edit-photo{display:flex;align-items:center;gap:20px;padding:20px;flex-wrap:wrap;}
/* กล่องรูปในหน้าแก้ไขไม่ได้อยู่ในโครงที่ยืดตามคอลัมน์ขวา ⇒ ล้าง stretch/aspect-ratio ทิ้ง
   แล้วกลับไปใช้ขนาดตายตัว ไม่งั้นได้กล่องสี่เหลี่ยมยักษ์ตามความสูงการ์ด */
.edit-photo-av{align-self:auto;aspect-ratio:auto;min-height:0;max-height:none;
  width:104px;height:104px;}
.edit-photo-av .pf-avatar{font-size:var(--fs-7);
  background:var(--accent-soft);border-color:var(--accent);color:var(--accent-dark);}
.edit-photo-txt{flex:1;min-width:200px;}
.edit-photo-txt b{display:block;font-size:var(--fs-4);}
.edit-photo-txt small{display:block;color:var(--ink-3);font-size:var(--fs-2);margin-top:3px;line-height:1.5;}
.edit-photo-btns{display:flex;gap:8px;margin:12px 0 8px;flex-wrap:wrap;}

@media(max-width:560px){
  /* จอแคบ .prof-hero-top ตกบรรทัด รูปจึงไม่มีคอลัมน์ขวาให้ยืดตาม
     ถ้าปล่อย aspect-ratio ไว้จะกลายเป็นจัตุรัสเต็มความกว้างจอ ⇒ ล็อกกลับเป็นขนาดตายตัว */
  .pf-avatar-wrap{align-self:flex-start;aspect-ratio:auto;
    width:104px;height:104px;min-height:0;max-height:none;}
  .pf-avatar{font-size:var(--fs-7);}
  .pf-name{font-size:var(--fs-5);}
  .pf-meta{grid-template-columns:1fr;gap:1px 0;}
  .pf-meta dt{margin-top:8px;font-size:var(--fs-2);}
  .trow{flex-wrap:wrap;}
  .trow-v{width:100%;justify-content:flex-start;padding-left:57px;}
}
.vrow{display:flex;justify-content:space-between;gap:18px;padding:12px 0;
  border-bottom:1px solid var(--line-2);font-size:var(--fs-3);align-items:baseline;flex-wrap:wrap;}
.vrow:last-child{border-bottom:none;padding-bottom:0;}
.vlabel{color:var(--ink-3);flex-shrink:0;}
.vvalue{font-weight:600;text-align:right;word-break:break-word;}
.vempty{font-weight:400;color:var(--ink-3);font-style:italic;}
.vsub{font-weight:400;color:var(--ink-3);font-size:var(--fs-2);}

/* ── รูปโปรไฟล์ ── */
.av-photo{position:relative;border-radius:50%;display:grid;place-items:center;flex-shrink:0;
  background:linear-gradient(140deg,var(--accent),var(--accent-dark));color:var(--on-accent);
  font-family:var(--serif);font-weight:700;font-size:var(--fs-6);box-shadow:var(--sh-1);}
.av-photo i{position:absolute;right:-2px;bottom:-2px;width:22px;height:22px;border-radius:50%;
  background:var(--surface-plain);display:grid;place-items:center;font-size:var(--fs-1);box-shadow:var(--sh-1);}
/* ── รูปโปรไฟล์จริง (Phase 1 · 7 ก.ย. 69) — <img> เต็มกรอบ ทับตัวอักษรย่อ ── */
.pf-avatar img,.av-photo img,.usr .av img{width:100%;height:100%;object-fit:cover;display:block;}
.av-photo{overflow:hidden;} .av-photo img{border-radius:50%;}
.prof-hero-top{background-size:cover;background-position:center;}
.pf-eyebrow{display:inline-flex;align-items:center;gap:6px;font-size:var(--fs-1);font-weight:700;
  letter-spacing:.05em;color:rgba(255,255,255,.82);margin-bottom:6px;}
.pf-eyebrow svg{font-size:var(--fs-3);}
.pf-chips{display:flex;flex-wrap:wrap;gap:8px;}
.av-mini{display:inline-block;border-radius:8px;overflow:hidden;flex-shrink:0;vertical-align:middle;
  background:var(--surface-2);border:1px solid var(--line);}
.av-mini img{width:100%;height:100%;object-fit:cover;display:block;}
.cell-person{display:flex;align-items:center;gap:9px;min-width:0;}
.cell-person .linkname{min-width:0;word-break:break-word;}
/* จอแคบมาก (≤430px) ตารางบัญชีมีหลายคอลัมน์ — ซ่อนอวาตาร์จิ๋วในเซลล์ กันดันหน้าให้เลื่อน */
@media(max-width:560px){.cell-person .av-mini{display:none;}}
.prof-head{display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.prof-head b{font-size:var(--fs-4);display:block;}
.prof-head small{display:block;color:var(--ink-3);font-size:var(--fs-2);line-height:1.5;}

/* ── ฟอร์มคอลัมน์เดียว ── */
/* ⚠️ ตัดคอลัมน์ที่ 2 ออกแล้วต้องขยายคอลัมน์ที่เหลือด้วย
   ไม่งั้นเนื้อหากองอยู่ 640px ในพื้นที่ 1080px เหลือที่ว่างข้างขวาเป็นแถบใหญ่ */
/* .one-col เดิมบีบเหลือ 880px ทำให้หน้าโปรไฟล์แคบกว่าหน้าอื่นทั้งระบบ
   ตอนนี้เหลือหน้าที่เดียวคือ "จัดเรียงเป็นคอลัมน์เดียว" ไม่ใช่ "ทำให้แคบ" */
.one-col{max-width:100%;}
.inline2{display:grid;grid-template-columns:1fr 1fr;gap:0 16px;}
.inline3{display:grid;grid-template-columns:1fr 1fr 1fr;gap:0 16px;}
@media(max-width:700px){.inline2,.inline3{grid-template-columns:1fr;}}

/* ── ข้อมูลอ่อนไหว (เลขบัตรประชาชน) ── */
.sens{display:inline-flex;align-items:center;gap:8px;font-family:ui-monospace,"SF Mono",Menlo,monospace;
  font-size:var(--fs-2);letter-spacing:.02em;background:var(--surface-2);border:1px solid var(--line);
  border-radius:var(--r1);padding:5px 9px;white-space:nowrap;}
.sens.shown{background:var(--warn-soft);border-color:color-mix(in srgb,var(--warn) 45%,transparent);color:var(--warn-ink);}
.sens-btn{border:none;background:transparent;color:var(--ink-3);font-size:var(--fs-4);display:grid;place-items:center;
  width:26px;height:26px;border-radius:6px;transition:.15s;}
.sens-btn:hover{color:var(--accent);background:var(--accent-soft);}
.sens-lock{display:inline-flex;align-items:center;gap:7px;font-size:var(--fs-2);color:var(--ink-3);}
.sens-lock svg{font-size:var(--fs-4);}
.sens-timer{font-size:var(--fs-1);font-weight:700;color:var(--warn-ink);font-family:var(--sans);}

/* ── ช่องรหัสผ่าน: ปุ่มดูรหัส + แถบความแข็งแรง + เกณฑ์ ── */
.pw-wrap{position:relative;}
.pw-wrap .inp{padding-right:44px;}
.pw-eye{position:absolute;right:6px;top:50%;transform:translateY(-50%);width:34px;height:34px;
  border:none;background:transparent;color:var(--ink-3);border-radius:var(--r1);
  display:grid;place-items:center;font-size:var(--fs-4);transition:.15s;}
.pw-eye:hover{color:var(--accent);background:var(--accent-soft);}
.pw-meter{margin-top:11px;}
.pw-meter-head{display:flex;justify-content:space-between;align-items:baseline;font-size:var(--fs-2);margin-bottom:6px;}
.pw-meter-head b{font-weight:700;}
.pw-bar{height:6px;border-radius:var(--pill);background:var(--paper-2);overflow:hidden;}
.pw-bar > i{display:block;height:100%;width:0;border-radius:var(--pill);transition:width .3s ease,background .3s ease;}
.pw-lv1 > i{width:33%;background:var(--bad);}   .pw-lv1 .pw-meter-head b{color:var(--bad);}
.pw-lv2 > i{width:66%;background:var(--warn);}  .pw-lv2 .pw-meter-head b{color:var(--warn-ink);}
.pw-lv3 > i{width:100%;background:var(--ok);}   .pw-lv3 .pw-meter-head b{color:var(--ok-ink);}
.pw-rules{display:flex;flex-wrap:wrap;gap:9px 16px;margin-top:12px;}
.pw-rule{display:inline-flex;align-items:center;gap:6px;font-size:var(--fs-2);color:var(--ink-3);transition:.18s;}
.pw-rule .dot{width:13px;height:13px;border-radius:50%;background:var(--paper-2);flex-shrink:0;
  display:grid;place-items:center;font-size:var(--fs-1);color:var(--on-accent);line-height:1;transition:.18s;}
.pw-rule.ok{color:var(--ok-ink);font-weight:600;}
.pw-rule.ok .dot{background:var(--ok);}

/* ── แถบขั้นตอนของวิซาร์ดเปิดใช้งานบัญชี ── */
.wiz-steps{display:flex;gap:8px;margin-bottom:20px;flex-wrap:wrap;}
.wiz-step{display:flex;align-items:center;gap:8px;flex:1;min-width:150px;font-size:var(--fs-2);font-weight:600;
  color:var(--ink-3);background:var(--surface);border:1px solid var(--line);border-radius:var(--r2);padding:10px 13px;}
.wiz-step span{width:24px;height:24px;border-radius:50%;display:grid;place-items:center;flex-shrink:0;
  background:var(--paper-2);color:var(--ink-3);font-size:var(--fs-1);font-weight:700;}
.wiz-step.now{color:var(--accent-dark);border-color:var(--accent);background:var(--accent-soft);}
.wiz-step.now span{background:var(--accent);color:var(--on-accent);}
.wiz-step.done{color:var(--ok-ink);border-color:color-mix(in srgb,var(--ok) 40%,var(--line));}
.wiz-step.done span{background:var(--ok);color:var(--on-accent);}

/* ── หน้าเข้าสู่ระบบ: กล่องล็อกอินแคบ · กล่องบัญชีทดสอบกว้างเต็มกรอบ ── */
/* ⚠️ เคยใช้ :first-child/:last-child ตรงนี้ แล้วชนกันเองจนการ์ดกว้างผิด
   (ตัวคัดเลือกที่มี type + pseudo-class มี specificity สูงกว่าคลาสเดี่ยว)
   ⇒ เปลี่ยนมาใช้ "คลาสที่ตั้งใจ" ทั้งหมด อ่านง่ายและไม่มีทางกำกวม */
.login-narrow{max-width:470px;margin-left:auto;margin-right:auto;}

/* ── กล่อง "เข้าสู่ระบบครั้งแรก" — เส้นทางที่ผู้ใช้ทุกคนต้องผ่านหนึ่งครั้ง
   จึงยกขึ้นมาเป็นกล่องเต็มความกว้าง ไม่ซ่อนไว้หลังลิงก์เล็ก ── */
/* น้ำหนักการเน้น: ปุ่ม Google (ทางหลัก ใช้ตลอดไป) ต้องเด่นกว่ากล่องนี้เสมอ
   กล่องนี้ใช้ครั้งเดียวต่อคน — ต้อง "หาเจอง่าย" พอ ไม่ใช่ "ตะโกน"
   ⚠️ เคยทำเป็นพื้นไล่สี + กรอบหนา + ปุ่มส้มทึบ = เน้น 3 ชั้นซ้อนกัน แล้วแย่งซีนปุ่มหลัก */
.first-box{border:1px solid var(--line);background:var(--surface-2);
  border-radius:var(--r3);padding:14px 16px;margin-top:16px;text-align:left;}
.first-box .fh{display:flex;align-items:center;gap:8px;font-weight:600;font-size:var(--fs-3);color:var(--ink);}
.first-box .fh svg{font-size:var(--fs-4);color:var(--terra);}
.first-box p{margin:6px 0 11px;font-size:var(--fs-2);line-height:1.55;color:var(--ink-3);}
.first-box .btn{border-color:color-mix(in srgb,var(--terra) 40%,var(--line));color:var(--terra-dark);}
.first-box .btn:hover{border-color:var(--terra);background:var(--terra-soft);}
.first-box.on{border-color:color-mix(in srgb,var(--terra) 40%,var(--line));background:var(--terra-soft);}
.login-alt{margin-top:14px;padding-top:14px;border-top:1px dashed var(--line);text-align:center;}
/* เส้นคั่นระหว่างช่องกรอกรหัสผ่าน (ทางหลักที่เห็นทันที) กับปุ่ม Google (ทางเลือกที่สอง) */
/* หัวข้อกำกับชุดกรอกรหัสผ่าน — บอกว่า "ชุดนี้สำหรับใคร" (17 ก.ย. 69)
   เพราะชุดปกติกับชุดเปิดใช้งานครั้งแรกหน้าตาเหมือนกันเป๊ะ (สองช่อง + ปุ่ม) */
/* กล่องยุบ "เข้าด้วยรหัสผ่านของตัวเอง" (17 ก.ย. 69 · เจ้าของงานสั่งให้หน้าสั้นลง)
   🔴 ต่างจากลิงก์ข้อความลอย ๆ ของเดิม ตรงที่หัวกล่องบอกครบว่า "ข้างในคืออะไร สำหรับใคร"
      ⇒ ยุบได้โดยที่ผู้ใช้ยังตัดสินใจถูกว่าต้องกดหรือไม่ */
.pw-fold{border:1px solid var(--line);border-radius:var(--r3);background:var(--surface);overflow:hidden;}
.pw-fold.on{border-color:var(--accent);box-shadow:var(--sh-1);}
.pw-toggle{display:flex;align-items:center;gap:12px;width:100%;padding:13px 15px;text-align:left;
  background:none;border:0;cursor:pointer;font:inherit;color:inherit;min-height:44px;}
.pw-toggle:hover{background:var(--surface-2);}
.pw-toggle-ic{flex:none;display:grid;place-items:center;width:32px;height:32px;border-radius:50%;
  background:var(--accent-soft);color:var(--accent-dark);}
.pw-toggle-ic svg{width:16px;height:16px;}
.pw-toggle-tx{flex:1;min-width:0;}
.pw-toggle-tx b{display:block;font-size:var(--fs-3);color:var(--ink);}
.pw-toggle-tx span{display:block;margin-top:1px;font-size:var(--fs-1);color:var(--ink-3);line-height:1.45;}
.pw-toggle-ar{flex:none;color:var(--ink-3);}
.pw-toggle-ar svg{width:15px;height:15px;transform:rotate(180deg);transition:transform .16s;}
.pw-fold.on .pw-toggle-ar svg{transform:rotate(0deg);}
.pw-body{padding:2px 15px 15px;border-top:1px solid var(--line-2);}
.pw-body .field:first-child{margin-top:13px;}
/* ทางเข้า "ครั้งแรก" — คำถามสั้น ๆ + ปุ่ม · คำอธิบายเต็มอยู่หน้าถัดไป */
.first-line{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;
  margin-top:14px;padding-top:14px;border-top:1px dashed var(--line);}
.first-line > span{font-size:var(--fs-2);color:var(--ink-2);}
/* ขั้นตอน 1-2-3 บนหน้าเข้าสู่ระบบครั้งแรก */
.steps-mini{display:flex;flex-direction:column;gap:9px;}
.steps-mini > div{display:flex;align-items:flex-start;gap:10px;font-size:var(--fs-2);color:var(--ink-2);line-height:1.5;}
.steps-mini b{flex:none;display:grid;place-items:center;width:22px;height:22px;border-radius:50%;
  background:var(--pine-soft);color:var(--pine);font-size:var(--fs-1);}
.login-or{display:flex;align-items:center;gap:12px;margin:18px 0 14px;
  font-size:var(--fs-2);color:var(--ink-3);}
.login-or::before,.login-or::after{content:'';flex:1;height:1px;background:var(--line);}
.login-test{width:100%;overflow-x:auto;}
.login-test .tbl th,.login-test .tbl td{padding:9px 12px;white-space:nowrap;}
/* ═══ หน้าเข้าสู่ระบบสองฝั่ง (17 ก.ย. 69 · เจ้าของงานสั่ง) ═══
   ซ้าย = ป้ายองค์กร · ขวา = จุดล็อกอิน
   🔴 .solo ใช้ place-items:center ⇒ ลูกหดตามเนื้อหา ต้องกำหนดความกว้างเป็นค่าจริง
      (บทเรียนเดิมของกล่องล็อกอิน — width:100% จะวนกลับมาที่เนื้อหา) */
/* 🔴 ห้ามใช้ width:<ค่าคงที่> ตรง ๆ กับลูกของ .solo — .solo เป็น grid + place-items:center
   ⇒ ช่องกริดถูกกำหนดขนาดจาก max-content ของลูกเอง แล้ว max-width:100% ก็วนกลับมาที่ค่านั้น
      (จอ 375px ได้กล่องกว้าง 470px ล้นออกนอกจอเงียบ ๆ เพราะ .solo ตั้ง overflow:hidden)
   ⇒ ให้ลูก stretch เต็มช่องก่อน แล้วค่อยคุมด้วย max-width — วงจรจึงขาด */
.login-2col{display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,420px);
  gap:52px;align-items:center;justify-self:stretch;width:100%;max-width:1060px;margin:0 auto;}
/* 17 ก.ย. 69 (เจ้าของงานสั่ง) · ฝั่งซ้ายจัดกึ่งกลางของฝั่งตัวเอง ไม่ใช่ชิดซ้าย
   ⚠️ ชุดวางตรา (.seal-lock) ยังต้องชิดซ้ายข้างในตัวมันเอง — ตรา | เส้น | ชื่อ 3 บรรทัด
      ถ้าจัดกลางข้างในด้วย ชื่อหน่วยงาน 3 บรรทัดจะเหลื่อมกันอ่านยาก */
.login-left{min-width:0;display:flex;flex-direction:column;align-items:center;text-align:center;}
.login-left .seal-lock{text-align:left;}
.login-left .login-msg{text-align:left;}
.login-right{min-width:0;}
.login-left .seal-lock{margin-bottom:0;}
.login-left .seal-div{margin:18px 0;}
.login-name-th{margin:0;font-family:var(--serif);font-size:var(--fs-6);line-height:1.25;color:var(--pine);}
.login-name-en{margin:6px 0 0;font-size:var(--fs-3);font-weight:500;color:var(--ink-3);letter-spacing:.01em;}
/* 🔵 ที่ยืนของ "มาสคอต" ในอนาคต — ตอนนี้วางตราระบบนิ่ง ๆ ไว้ก่อน
   กันพื้นที่ด้วย min-height เพื่อให้เลย์เอาต์ไม่กระตุกตอนเปลี่ยนเป็นตัวการ์ตูนเคลื่อนไหว */
.login-mascot{display:flex;align-items:center;min-height:104px;margin:22px 0 0;}
.login-msg{position:relative;display:flex;gap:13px;margin:0;padding:16px 18px;border-radius:var(--r3);
  background:var(--surface);border:1px solid var(--line);box-shadow:var(--sh-1);}
/* หางกล่องคำพูด — ชี้ "ลงซ้าย" ไปหาตัวผู้พูดที่อยู่ใต้กล่อง (ตามเฟรมเวิร์คของเจ้าของงาน)
   วาดสองชั้น: ชั้นล่างคือสีขอบ ชั้นบนคือสีพื้น เหลื่อมกันเท่าความหนาขอบ ⇒ หางมีเส้นขอบเหมือนตัวกล่อง */
.login-msg::before{content:'';position:absolute;bottom:-14px;left:48px;width:28px;height:15px;
  background:var(--line);clip-path:polygon(0 0,100% 0,14% 100%);}
.login-msg::after{content:'';position:absolute;bottom:-12px;left:50px;width:24px;height:13px;
  background:var(--surface);clip-path:polygon(0 0,100% 0,14% 100%);}
/* ที่ทางของ "คำพูด + ผู้พูด" — ตัวผู้พูดชิดซ้ายใต้หางกล่อง ไม่ใช่กลางคอลัมน์ */
.login-say{width:100%;max-width:560px;margin-top:4px;}
.seal-div-sm{width:34px;height:3px;margin:15px auto;opacity:.75;}
.login-msg-mark{flex:none;display:grid;place-items:center;width:34px;height:34px;border-radius:50%;
  background:var(--pine-soft);color:var(--pine);}
.login-msg-mark svg{width:17px;height:17px;}
.login-msg b{display:block;font-size:var(--fs-3);color:var(--ink);}
.login-msg p{margin:4px 0 0;font-size:var(--fs-2);line-height:1.6;color:var(--ink-2);}
@media (max-width:900px){
  /* จอแคบ: คอลัมน์เดียว ป้ายองค์กรขึ้นก่อน (บอกว่ามาถูกที่) แล้วจึงเป็นจุดล็อกอิน */
  .login-2col{grid-template-columns:1fr;gap:26px;max-width:470px;text-align:center;}
  .login-left .seal-lock{text-align:left;}
  .login-mascot{justify-content:center;min-height:0;margin-top:16px;}
  .login-msg{text-align:left;}
}
/* ═══ B-1 (12 ก.ย. 69): คลาสยูทิลิตี้แทนแอตทริบิวต์กำหนดสไตล์อินไลน์ทั้งหมด ═══
   CSP ของระบบจริงตั้ง style-src 'self' (ไม่มี unsafe-inline) — กำหนดสไตล์อินไลน์ในแท็กใช้กับ
   Laravel ไม่ได้เลย ต้องย้ายออกมาเป็นคลาสก่อนพอร์ต (ดู docs/TIMS_REBUILD_PLAN.md)
   ทุกคลาสด้านล่างมาจากการไล่ grep ค่ากำหนดสไตล์อินไลน์จริงในไฟล์นี้ทั้งหมด (542 จุดเดิม)
   แล้วถอดเป็นคลาสอะตอมมิกที่ประกอบกันได้ — เทียบแล้วค่าที่ได้เหมือนของเดิมทุกจุด (mutation-proof
   ผ่าน check_prototype ข้อใหม่ที่แบนแอตทริบิวต์นี้ + check_context/check_mobile เขียวเท่าเดิม) */
/* ระยะห่างแนวตั้ง — margin-top / margin-bottom */
.mt-n8{margin-top:-8px;}.mt-n6{margin-top:-6px;}.mt-n4{margin-top:-4px;}.mt-n2{margin-top:-2px;}
.mb-0{margin-bottom:0px;}.mt-0{margin-top:0px;}.mb-2{margin-bottom:2px;}.mt-2{margin-top:2px;}.mt-3{margin-top:3px;}
.mb-4{margin-bottom:4px;}.mt-4{margin-top:4px;}.mb-5{margin-bottom:5px;}.mt-5{margin-top:5px;}
.mb-6{margin-bottom:6px;}.mt-6{margin-top:6px;}.mt-7{margin-top:7px;}.mb-8{margin-bottom:8px;}.mt-8{margin-top:8px;}
.mt-9{margin-top:9px;}.mb-10{margin-bottom:10px;}.mt-10{margin-top:10px;}.mt-11{margin-top:11px;}
.mb-12{margin-bottom:12px;}.mt-12{margin-top:12px;}.mb-13{margin-bottom:13px;}.mt-13{margin-top:13px;}
.mb-14{margin-bottom:14px;}.mt-14{margin-top:14px;}.mb-16{margin-bottom:16px;}.mt-16{margin-top:16px;}
.mb-18{margin-bottom:18px;}.mt-18{margin-top:18px;}.mb-20{margin-bottom:20px;}.mt-20{margin-top:20px;}
.mb-22{margin-bottom:22px;}.mt-22{margin-top:22px;}.mb-24{margin-bottom:24px;}
/* ระยะห่างแนวนอน — margin-left / margin-right / margin-x / margin ทุกด้าน */
.m-0{margin:0;}.ml-auto{margin-left:auto;}.mx-0{margin-left:0px;margin-right:0px;}
.mx-auto{margin-left:auto;margin-right:auto;}.mr-5{margin-right:5px;}.ml-6{margin-left:6px;}.ml-8{margin-left:8px;}
/* padding ทุกทิศทาง */
.p-0{padding:0;}.px-0{padding-left:0px;padding-right:0px;}.pb-6{padding-bottom:6px;}.pt-6{padding-top:6px;}
.pb-9{padding-bottom:9px;}.pt-9{padding-top:9px;}.pb-10{padding-bottom:10px;}.pb-11{padding-bottom:11px;}
.pt-11{padding-top:11px;}.pb-13{padding-bottom:13px;}.pt-13{padding-top:13px;}.pt-14{padding-top:14px;}
.px-18{padding-left:18px;padding-right:18px;}.p-20{padding:20px;}.pl-20{padding-left:20px;}
.pb-22{padding-bottom:22px;}.pt-22{padding-top:22px;}.pt-24{padding-top:24px;}.pb-26{padding-bottom:26px;}
.pt-26{padding-top:26px;}.px-26{padding-left:26px;padding-right:26px;}.pt-32{padding-top:32px;}
/* ขนาดตัวอักษร — ใช้ได้เฉพาะ 9 ขั้นของสเกล (UI-02) */
.fs-1{font-size:var(--fs-1);}.fs-2{font-size:var(--fs-2);}.fs-3{font-size:var(--fs-3);}.fs-4{font-size:var(--fs-4);}.fs-5{font-size:var(--fs-5);}.fs-6{font-size:var(--fs-6);}.fs-7{font-size:var(--fs-7);}.fs-8{font-size:var(--fs-8);}.fs-9{font-size:var(--fs-9);}
/* ความสูงบรรทัด (line-height, ×100) */
.lh-130{line-height:1.3;}.lh-140{line-height:1.4;}.lh-155{line-height:1.55;}.lh-160{line-height:1.6;}
.lh-165{line-height:1.65;}.lh-170{line-height:1.7;}.lh-175{line-height:1.75;}.lh-180{line-height:1.8;}
.lh-190{line-height:1.9;}
/* น้ำหนักตัวอักษร */
.fw-400{font-weight:400;}.fw-600{font-weight:600;}.fw-700{font-weight:700;}
/* สีตัวอักษร (t- = text) */
.t-accent{color:var(--accent);}.t-accent-dark{color:var(--accent-dark);}.t-amber-dark{color:var(--amber-dark);}
.t-bad{color:var(--bad);}.t-bad-ink{color:var(--bad-ink);}.t-ink{color:var(--ink);}.t-ok-ink{color:var(--ok-ink);}
.t-pine{color:var(--pine);}.t-pine-deep{color:var(--pine-deep);}.t-plum{color:var(--plum);}
.t-terra{color:var(--terra);}.t-terra-dark{color:var(--terra-dark);}.t-warn-ink{color:var(--warn-ink);}
.t-white{color:var(--on-accent);}.t-ink-2{color:var(--ink-2);}.t-ink-3{color:var(--ink-3);}
.t-white-42{color:rgba(255,255,255,.42);}.t-white-80{color:rgba(255,255,255,.8);}
.t-white-82{color:rgba(255,255,255,.82);}
/* สีพื้นหลัง */
.bg-accent-soft{background:var(--accent-soft);}.bg-amber-soft{background:var(--amber-soft);}
.bg-bad-soft{background:var(--bad-soft);}.bg-grad-bad{background:linear-gradient(140deg,var(--bad),var(--bad-deep));}
.bg-grad-pine{background:linear-gradient(160deg,var(--pine-deep),var(--pine));}.bg-ok{background:var(--ok);}
.bg-ok-soft{background:var(--ok-soft);}.bg-pine-soft{background:var(--pine-soft);}
.bg-plum-soft{background:var(--plum-soft);}.bg-terra-soft{background:var(--terra-soft);}
.bg-warn{background:var(--warn);}.bg-warn-soft{background:var(--warn-soft);}
.bg-surface-2{background:var(--surface-2);}.bg-white-12{background:rgba(255,255,255,.12);}
/* display / flex / grid */
.d-block{display:block;}.d-flex{display:flex;}.d-grid{display:grid;}.d-iflex{display:inline-flex;}
.d-none{display:none;}.flex-col{flex-direction:column;}.flex-wrap{flex-wrap:wrap;}.shrink-0{flex-shrink:0;}
.flex-1{flex:1;}
/* จัดวางแนวแกน flex */
.items-center{align-items:center;}.items-start{align-items:flex-start;}
.justify-between{justify-content:space-between;}.justify-center{justify-content:center;}
.place-center{place-items:center;}.self-center{align-self:center;}
/* จัดข้อความ */
.text-center{text-align:center;}.text-left{text-align:left;}.text-right{text-align:right;}
.underline{text-decoration:underline;}.ws-prewrap{white-space:pre-wrap;}
/* ระยะห่างระหว่างไอเทม (gap) */
.gap-2{gap:2px;}.gap-6{gap:6px;}.gap-7{gap:7px;}.gap-8{gap:8px;}.gap-9{gap:9px;}.gap-10{gap:10px;}.gap-11{gap:11px;}
.gap-12{gap:12px;}.gap-14{gap:14px;}.gap-20{gap:20px;}
/* ขนาดกล่อง (width/height/max/min) */
.h-19{height:19px;}.w-19{width:19px;}.h-40{height:40px;}.w-40{width:40px;}.h-44{height:44px;}.w-44{width:44px;}
.h-54{height:54px;}.w-54{width:54px;}.h-60{height:60px;}.w-60{width:60px;}.w-90{width:90px;}.h-100p{height:100%;}
.mw-100p{max-width:100%;}.w-100{width:100px;}.w-100p{width:100%;}.w-110{width:110px;}.w-120{width:120px;}
.mh-180{max-height:180px;}.minw-190{min-width:190px;}.mh-200{max-height:200px;}.mh-220{max-height:220px;}
.minw-220{min-width:220px;}.minw-230{min-width:230px;}.minw-250{min-width:250px;}.mw-470{max-width:470px;}
.w-660{width:660px;}
/* ขอบและมุมโค้ง */
.bb-line2{border-bottom:1px solid var(--line-2);}.bd-dashed{border-style:dashed;}
.bd-line{border:1px solid var(--line);}.bdc-bad-mix{border-color:color-mix(in srgb,var(--bad) 40%,var(--line));}
.bl-terra{border-left:4px solid var(--terra);}.bt-line{border-top:1.5px solid var(--line);}
.r-var4{border-radius:var(--r4);}.r-10{border-radius:10px;}.r-12{border-radius:12px;}
.bd-bad-15{border:1.5px solid var(--bad);}.bdc-white-20{border-color:rgba(255,255,255,.2);}
/* เงา / ความโปร่งใส / ทัศนวิสัย */
.pe-none{pointer-events:none;}.sh-none{box-shadow:none;}.vis-hidden{visibility:hidden;}.sh-3{box-shadow:var(--sh-3);}
.op-70{opacity:0.7;}.op-75{opacity:0.75;}.op-90{opacity:0.9;}
/* อื่น ๆ (ตำแหน่ง/แบบอักษร/สัดส่วน/หมุน/ตัด) */
.cursor-default{cursor:default;}.cursor-pointer{cursor:pointer;}.ff-mono{font-family:ui-monospace,monospace;}
.ff-serif{font-family:var(--serif);}.fit-cover{object-fit:cover;}.of-auto{overflow:auto;}.of-hidden{overflow:hidden;}
.pos-rel{position:relative;}.stroke-none{stroke:none;}.ar-169{aspect-ratio:16 / 9;}.rot-180{transform:rotate(180deg);}
/* ═══════════ น้อง TIMS · มาสคอตประจำระบบ ═══════════
   ออกแบบใน design/tims-logo-maker.html (ที่นั่นดาวน์โหลดไฟล์ได้ 7 รูปแบบ)
   🔴 คีย์เฟรมอยู่ที่นี่ ไม่ได้ฝังใน <svg> แบบไฟล์ที่ดาวน์โหลดไป
      เพราะ CSP ของระบบจริงไม่มี unsafe-inline ⇒ <style> ในมาร์กอัปถูกบล็อก (R-1 ข้อ 7)
      โชคดีที่จุดหมุนทุกจุดเป็นค่าคงที่ (กรอบภาพ 280×320 เท่ากันทุกท่า) จึงย้ายมาไว้ที่นี่ได้ครบ
   🔴 ห้ามกำหนดจุดหมุนเป็นแอตทริบิวต์สไตล์อินไลน์ที่ตัว svg เด็ดขาด — check_prototype ข้อ 5ข แบนไว้ */
.nt{display:block;width:100%;height:auto;}
.nt-xs{max-width:46px;}.nt-sm{max-width:74px;}.nt-md{max-width:124px;}.nt-lg{max-width:186px;}
.nt-body{transform-origin:140px 300px;}
.nt-cap{transform-origin:140px 90px;}
.nt-arm-l{transform-origin:64px 168px;}
.nt-arm-r{transform-origin:216px 168px;}
.nt-eye-l{transform-origin:114px 162px;}
.nt-eye-r{transform-origin:166px 162px;}
.nt-z1{transform-origin:220px 94px;}.nt-z2{transform-origin:240px 70px;}.nt-z3{transform-origin:262px 42px;}
.nt-anim .nt-body{animation:nt-float 3s ease-in-out infinite;}
.nt-anim[data-pose="pass"] .nt-body{animation-name:nt-bounce;}
.nt-anim[data-pose="guide"] .nt-body{animation-name:nt-nod;}
.nt-anim[data-pose="think"] .nt-body{animation-name:nt-think;}
.nt-anim[data-pose="sorry"] .nt-body{animation-name:nt-sorry;}
.nt-anim[data-pose="cheer"] .nt-body{animation-name:nt-cheer;}
.nt-anim[data-pose="sleep"] .nt-body{animation-name:nt-sleep;}
.nt-anim .nt-cap{animation:nt-capbob 2.9s ease-in-out infinite;}
.nt-anim[data-pose="cheer"] .nt-cap{animation:nt-toss 3s ease-in-out infinite;}
.nt-anim .nt-arm-l{animation:nt-armb 2.6s ease-in-out infinite;}
.nt-anim .nt-arm-r{animation:nt-armb 2.6s ease-in-out .5s infinite;}
.nt-anim[data-pose="hello"] .nt-arm-r{animation:nt-wave 1.7s ease-in-out infinite;}
.nt-anim .nt-eye-l,.nt-anim .nt-eye-r{animation:nt-blink 5.2s infinite;}
.nt-anim .nt-z1,.nt-anim .nt-z2,.nt-anim .nt-z3{opacity:0;animation:nt-zf 3.2s ease-in-out infinite;}
.nt-anim .nt-z2{animation-delay:.5s;}.nt-anim .nt-z3{animation-delay:1s;}
@keyframes nt-float{0%,100%{transform:translateY(0);}50%{transform:translateY(-7px);}}
@keyframes nt-bounce{0%,100%{transform:translateY(0) scaleY(1);}30%{transform:translateY(-16px) scaleY(1.03);}55%{transform:translateY(0) scaleY(.97);}75%{transform:translateY(-5px) scaleY(1);}}
@keyframes nt-nod{0%,100%{transform:rotate(0);}30%{transform:rotate(-3.5deg);}65%{transform:rotate(2.5deg);}}
@keyframes nt-think{0%,100%{transform:translateY(0) rotate(0);}50%{transform:translateY(-4px) rotate(3deg);}}
@keyframes nt-sorry{0%,100%{transform:translateY(0) rotate(0);}50%{transform:translateY(4px) rotate(-2deg);}}
@keyframes nt-cheer{0%,100%{transform:translateY(0);}40%{transform:translateY(-24px);}70%{transform:translateY(-4px);}}
@keyframes nt-sleep{0%,100%{transform:translateY(0) scale(1);}50%{transform:translateY(3px) scale(.985);}}
@keyframes nt-capbob{0%,100%{transform:translateY(0);}50%{transform:translateY(-4px);}}
@keyframes nt-toss{0%,100%{transform:translateY(0) rotate(0);}40%{transform:translateY(-26px) rotate(-13deg);}70%{transform:translateY(-6px) rotate(5deg);}}
@keyframes nt-armb{0%,100%{transform:translateY(0);}50%{transform:translateY(-4px);}}
@keyframes nt-wave{0%,100%{transform:rotate(0);}25%{transform:rotate(-19deg);}60%{transform:rotate(13deg);}}
@keyframes nt-blink{0%,92%,100%{transform:scaleY(1);}96%{transform:scaleY(.08);}}
@keyframes nt-zf{0%{opacity:0;transform:translateY(6px) scale(.8);}35%{opacity:1;}100%{opacity:0;transform:translateY(-16px) scale(1.1);}}
/* ปิดการเคลื่อนไหวให้ผู้ที่ตั้งค่าระบบปฏิบัติการไว้ว่าไม่ต้องการ — แต่ตัว Z ต้องยังเห็น ไม่งั้นท่านอนอ่านไม่ออก */
@media (prefers-reduced-motion:reduce){
  .nt-anim .nt-body,.nt-anim .nt-cap,.nt-anim .nt-arm-l,.nt-anim .nt-arm-r,
  .nt-anim .nt-eye-l,.nt-anim .nt-eye-r,.nt-anim .nt-z1,.nt-anim .nt-z2,.nt-anim .nt-z3{animation:none;}
  .nt-anim .nt-z1,.nt-anim .nt-z2,.nt-anim .nt-z3{opacity:1;}
}
/* ═══ ป๊อบอัปผลลัพธ์กลางจอของน้อง TIMS ═══
   ต่างจาก toast มุมจอตรงที่อยู่กลางสายตา ⇒ ใช้กับ "ผลของสิ่งที่เพิ่งทำ" ให้รับรู้แน่ ๆ
   เสริม toast ไม่ใช่แทน — toast ยังถือปุ่ม "เลิกทำ" ไว้ ซึ่งเป็นทางถอยที่ห้ามหาย
   🔴 pointer-events:none — ห้ามขวางการคลิกเด็ดขาด เพราะบางงานทำถี่ ๆ ทีละหลายรายการ
      (อนุมัติรายคน) ถ้าขวางแม้เสี้ยววินาที มือที่กำลังรัวจะพลาดทันที
   🔴 ความเร็วเลือกตามบริบท: quick (งานถี่) · normal · hold (งานที่จบเป็นชิ้น ควรหยุดรับรู้ก่อนไปต่อ) */
.ntpop-back{position:fixed;inset:0;z-index:2100;display:grid;place-items:center;pointer-events:none;}
.ntpop{display:flex;flex-direction:column;align-items:center;gap:9px;padding:20px 28px 18px;
  border-radius:var(--r4);background:var(--surface);box-shadow:var(--sh-3);border:1px solid var(--line);
  min-width:230px;max-width:min(92vw,360px);text-align:center;
  animation:ntpop-in .26s cubic-bezier(.2,1.4,.4,1);}
.ntpop.out{animation:ntpop-out .22s ease-in forwards;}
.ntpop .nt{width:92px;max-width:92px;}
.ntpop b{font-size:var(--fs-4);color:var(--ink);}
.ntpop p{margin:0;font-size:var(--fs-2);line-height:1.6;color:var(--ink-2);}
.ntpop-bad{border-color:var(--bad);}
@keyframes ntpop-in{from{opacity:0;transform:scale(.86) translateY(10px);}to{opacity:1;transform:none;}}
@keyframes ntpop-out{to{opacity:0;transform:scale(.96) translateY(-6px);}}
@media (prefers-reduced-motion:reduce){.ntpop,.ntpop.out{animation:none;}}

/* ที่ยืนของน้อง TIMS ในแต่ละหน้า
   🔴 ห้ามตั้ง width:auto ให้ svg ในกล่อง flex — svg ไม่มีขนาดในตัว จะยุบเหลือ 0 ทันที
      (เจอจริงตอนต่อสายหน้าเข้าสู่ระบบ: อยู่ใน DOM ครบ แอนิเมชันวิ่ง แต่วัดได้ 0×0) */
.login-mascot{justify-content:flex-start;padding-left:10px;margin:0;min-height:0;}
.login-mascot .nt{flex:0 0 auto;width:172px;}
.nt-slot{display:flex;justify-content:center;margin:0 0 14px;}
.nt-slot .nt{flex:0 0 auto;}
/* แถบ "ตอนนี้ควรทำอะไรต่อ" บนหน้าหลักของทั้ง 4 บทบาท + คำแนะนำตัวบนหน้าแรกสาธารณะ
   🔴 ใช้เปลือกเดียวกับ .card (surface/line/r3/sh-1) เพื่อไม่ให้กลายเป็นของแปลกปลอมในหน้า */
.nt-home,.lp-greet{display:flex;align-items:center;gap:14px;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r3);box-shadow:var(--sh-1);}
.nt-home{margin:0 0 16px;padding:12px 16px;}
.lp-greet{margin:18px 0 0;padding:14px 16px;}
.nt-home .nt{flex:0 0 auto;width:62px;}
.lp-greet .nt{flex:0 0 auto;width:70px;}
.nt-home .nt-slot,.lp-greet .nt-slot{margin:0;flex:0 0 auto;}
.nt-home-tx{flex:1;min-width:0;}
.nt-home-tx b{display:block;font-size:var(--fs-3);color:var(--ink);}
.nt-home-tx span{display:block;margin-top:2px;font-size:var(--fs-2);color:var(--ink-3);}
.lp-greet p{margin:0;font-size:var(--fs-2);color:var(--ink-2);}
@media (max-width:560px){
  .nt-home .nt{width:52px;}
  .lp-greet .nt{width:56px;}
}
