/* Student bottom bar (dist/student-tabs.js, 2026-10-29): 스피킹 게임 · 복습 · 오답노트 · 내 학습 · 메뉴 (since 2026-11-05:
   랭킹 도전 is part of 내 학습 again and 메뉴 opens dist/student-menu.js's drawer; 내 학습 still opens first), fixed at the
   bottom of the screen. It slides down and away while an
   activity is open (body[data-student-activity="open"]) and back up when it closes. The page keeps the bar's room at all
   times, so nothing moves and an activity window keeps its size. */
:root{--tabbar-h:64px;--tabbar-space:calc(var(--tabbar-h) + max(6px,env(safe-area-inset-bottom)))}
.student-tab-panel[hidden]{display:none!important}
body[data-student-tabs="on"] main{padding-bottom:calc(var(--tabbar-space) + 16px)}
body[data-student-tabs="on"] main>footer{display:none}
.student-tabbar{position:fixed;left:0;right:0;bottom:0;z-index:30;padding-bottom:max(6px,env(safe-area-inset-bottom));padding-left:env(safe-area-inset-left,0px);padding-right:env(safe-area-inset-right,0px);background:var(--n-fffdf8,#fffdf8);border-top:1px solid var(--n-eee3d5,#eee3d5);box-shadow:0 -4px 18px #6d513712;transform:translateY(0);visibility:visible;transition:transform 300ms cubic-bezier(.2,.8,.2,1) 60ms,visibility 0s}
body[data-student-activity="open"] .student-tabbar{transform:translateY(calc(100% + 16px));visibility:hidden;transition:transform 260ms cubic-bezier(.4,0,.2,1),visibility 0s linear 260ms}
.student-tabbar-inner{display:grid;grid-template-columns:minmax(0,4fr) minmax(0,1fr);max-width:850px;height:var(--tabbar-h);margin:auto}
/* The four tabs share one tablist (four fifths of the bar) and 메뉴 takes the last fifth: five equal places as before. */
.student-tabbar-tabs{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));min-width:0;height:100%}
.student-tab.is-menu[aria-expanded="true"]{color:var(--n-a94c31,#a94c31)}
.student-tab.is-menu[aria-expanded="true"] .student-tab-icon{background:var(--n-fbeee3,#fbeee3)}
/* Five labels fit from 320 px: 13 px from 375 px, 12 px from 360 px, 11 px (tighter) below 360 px; is-tight (set by
   student-tabs.js where a label still overflows) takes every label one step smaller together. */
.student-tabbar{--tab-label:13px;--tab-track:-.2px}
@media(max-width:374px){.student-tabbar{--tab-label:12px}}
@media(max-width:359px){.student-tabbar{--tab-label:11px;--tab-track:-.4px}}
.student-tabbar.is-tight{--tab-label-tight:calc(var(--tab-label) - 1px)}
.student-tab{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;min-width:0;height:100%;margin:0;padding:6px 2px 4px;border:0;border-radius:0;background:transparent;color:var(--n-6f685f,#6f685f);font-family:inherit;-webkit-tap-highlight-color:transparent;cursor:pointer}
.student-tab:hover{background:transparent;filter:none}
.student-tab-icon{position:relative;display:grid;place-items:center;width:56px;height:30px;border-radius:15px;transition:background 150ms ease,color 150ms ease}
.student-tab-icon>svg{width:24px;height:24px}
.student-tab-label{font-size:var(--tab-label-tight,var(--tab-label,13px));line-height:16px;font-weight:600;white-space:nowrap;letter-spacing:var(--tab-track,-.2px);transition:color 150ms ease}
.student-tabbar.is-tight .student-tab-label{letter-spacing:-.4px}
.student-tab.is-selected,.student-tab[aria-selected="true"]{color:var(--n-a94c31,#a94c31)}
.student-tab[aria-selected="true"] .student-tab-icon{background:var(--n-fbeee3,#fbeee3)}
.student-tab:focus-visible{outline:3px solid var(--n-d4916b,#d4916b);outline-offset:-3px;border-radius:12px}
.student-tab-badge{position:absolute;top:-4px;left:calc(50% + 6px);min-width:18px;height:18px;padding:0 4px;border:2px solid var(--n-fffdf8,#fffdf8);border-radius:9px;background:var(--n-b4532a,#b4532a);color:var(--n-ffffff,#fff);font:700 11px/14px var(--font-en),Arial,sans-serif;text-align:center;box-sizing:border-box}
.student-tab-badge[hidden],.student-tab-dot[hidden]{display:none}
.student-tab-dot{position:absolute;top:2px;left:calc(50% + 8px);width:8px;height:8px;border-radius:50%;box-shadow:0 0 0 1.5px var(--n-fffdf8,#fffdf8)}
.student-tab-icon.is-pulsing{animation:student-tab-pop 600ms cubic-bezier(.3,1.4,.5,1)}
@keyframes student-tab-pop{0%{transform:scale(1)}45%{transform:scale(1.18)}100%{transform:scale(1)}}
/* A short message just above the bar (an unlock toast, a failure on another tab). */
.student-tab-toast{position:fixed;left:50%;bottom:calc(var(--tabbar-space) + 12px);z-index:31;width:max-content;max-width:min(92vw,520px);margin:0;padding:11px 18px;border-radius:14px;background:var(--n-4d3920,#4d3920);color:var(--n-ffffff,#fff);font-size:14px;font-weight:600;line-height:1.5;text-align:center;box-shadow:0 6px 20px #4d392033;transform:translateX(-50%);animation:student-tab-toast-in 220ms ease-out;cursor:pointer;word-break:keep-all}
.student-tab-toast[hidden]{display:none}
@keyframes student-tab-toast-in{from{opacity:0;transform:translate(-50%,8px)}to{opacity:1;transform:translate(-50%,0)}}
body[data-student-tabs="on"] #notice{bottom:calc(var(--tabbar-space) + 12px)}
/* 친구 대결 (stage 2): an invite marks 스피킹 게임 with a red dot (never a number) and shows a
   card where the toast sits, just above the bar; it hides with the bar while an activity is open. */
.student-tab-dot.is-invite{background:var(--i-c2413a,#c2413a)}
.student-tab-invite{position:fixed;left:50%;bottom:calc(var(--tabbar-space) + 12px);z-index:31;box-sizing:border-box;display:grid;grid-template-columns:minmax(0,1fr) auto;gap:2px 12px;width:min(92vw,420px);margin:0;padding:12px 14px 8px;border:1px solid var(--n-e9c7b9,#e9c7b9);border-radius:18px;background:var(--n-fffdf8,#fffdf8);color:var(--n-403b35,#403b35);box-shadow:0 10px 28px #4d392038;transform:translateX(-50%);animation:student-tab-toast-in 220ms ease-out;word-break:keep-all}
.student-tab-invite[hidden]{display:none}
.student-tab-invite-ring{grid-column:2;grid-row:1/span 3;align-self:center;width:30px;height:30px;border-radius:50%;background:conic-gradient(var(--i-c2413a,#c2413a) var(--invite-ring-left,100%),var(--i-f3e2da,#f3e2da) 0);animation:student-tab-ring var(--invite-ring,30000ms) linear forwards;animation-delay:var(--invite-ring-gone,0ms);-webkit-mask:radial-gradient(circle,transparent 9px,#000 10px);mask:radial-gradient(circle,transparent 9px,#000 10px)}
@property --invite-ring-left{syntax:'<percentage>';inherits:false;initial-value:100%}
@keyframes student-tab-ring{from{--invite-ring-left:100%}to{--invite-ring-left:0%}}
.student-tab-invite-title{grid-column:1;margin:0;color:var(--n-a94c31,#a94c31);font-size:16px;font-weight:800;line-height:1.35}
.student-tab-invite-name{grid-column:1;margin:0;font-size:15px;font-weight:800;line-height:1.4}
.student-tab-invite-detail{grid-column:1;margin:0;color:var(--n-716d63,#716d63);font-size:13px;font-weight:600;line-height:1.45}
.student-tab-invite-actions{grid-column:1/-1;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;margin-top:8px}
.student-tab-invite-actions button{min-height:44px;font-size:15px}
.student-tab-invite-stop{grid-column:1/-1;justify-self:center;min-height:32px;margin-top:2px;padding:4px 8px;border:0;background:transparent;color:var(--n-716d63,#716d63);font-size:12px;font-weight:700;text-decoration:underline;cursor:pointer}
@media(prefers-reduced-motion:reduce){.student-tabbar,body[data-student-activity="open"] .student-tabbar{transition:none}.student-tab-icon,.student-tab-label{transition:none}.student-tab-icon.is-pulsing,.student-tab-toast,.student-tab-invite,.student-tab-invite-ring{animation:none}}

/* 새로고침 · 로그아웃 sit at the brand header's right end on every tab (2026-10-30); since the teacher and parent pages
   have them too, their style and the flag that shows them (body[data-header-tools-shown="on"]) are brand.css's (.header-tools). */

/* The other tabs (스피킹 게임, 복습, 오답노트) share one layout: a top block, the main list and a side block. Portrait reads
   top → main → side in one column; landscape gives the left column (top + side) and the right one (main) their own
   scroll, under the brand header, as 내 학습 does. */
.student-tab-columns{display:flex;flex-direction:column;gap:14px}
.student-tab-left,.student-tab-right{display:contents}
.student-tab-slot[data-slot="top"]{order:1}.student-tab-slot[data-slot="main"]{order:2}.student-tab-slot[data-slot="side"]{order:3}
.student-tab-slot{min-width:0}
/* The title row every tab starts with (2026-10-30, owner: "아래 바 탭 누르면 상단에 중앙 정렬이 안 맞아 이것좀 맞춰줘";
   student-tabs.js tabHeadHTML, and 내 학습's greeting row in student-home.js). One fixed height (--tab-head-h) right
   under the brand header on every tab, at the cards' left edge: the height holds the space above and below the title
   (the same on both sides), so the first block starts right at the row's bottom and switching tabs moves nothing.
   The icon, title and lead are centred on one line; the lead is cut short with … and never wraps. The right slot holds
   a tab's own control (복습's 배운 회차 / 모든 회차 switch, review-tab.css) and never changes the row's height; empty, it takes
   no room (내 학습's is empty: 새로고침 · 로그아웃 are in the brand header, brand.css .header-tools). */
:root{--tab-head-h:48px}
.student-tab-head{display:flex;align-items:center;gap:8px;box-sizing:border-box;height:var(--tab-head-h);min-width:0;margin:0;padding:0}
.student-tab-head-main{display:flex;align-items:center;gap:10px;flex:1 1 auto;min-width:0}
.student-tab-head-title{display:flex;align-items:center;gap:6px;flex:0 0 auto;margin:0;color:var(--home-ink,var(--n-403b35,#403b35));font-size:16px;line-height:24px;font-weight:800;letter-spacing:-.4px;white-space:nowrap}
.student-tab-head-icon{display:grid;place-items:center;flex:0 0 auto;width:20px;height:20px;color:var(--n-a94c31,#a94c31)}
.student-tab-head .student-tab-head-icon svg{display:block;width:20px;height:20px}
.student-tab-head-sub{flex:0 1 auto;min-width:0;margin:0;overflow:hidden;color:var(--home-muted,var(--n-716d63,#716d63));font-size:12px;line-height:18px;text-overflow:ellipsis;white-space:nowrap}
.student-tab-head-slot{display:flex;align-items:center;justify-content:flex-end;gap:8px;flex:0 0 auto;min-width:0;margin-left:auto}
.student-tab-head-slot:empty{display:none}
/* A top block that holds only the row (스피킹 게임 without a notice) lets the next block start at the row's bottom too. */
.student-tab-slot[data-slot="top"]:not(:has(>:not(.student-tab-head):not([hidden]))){margin-bottom:-14px}
.student-tab-soon{margin:8px 0 0;padding:28px 16px;border:1px dashed var(--n-e2d6c4,#e2d6c4);border-radius:16px;background:var(--n-fffdf8,#fffdf8);color:var(--home-muted,var(--n-716d63,#716d63));font-size:13px;line-height:1.7;text-align:center}

/* Landscape: two scrolling columns under the fixed brand header, each keeping the bar's room at its end. */
@media(orientation:landscape){
 body[data-student-tabs="on"]{height:100dvh;overflow:hidden}
 body[data-student-tabs="on"] main,body[data-student-tabs="on"] #schoolPanel,body[data-student-tabs="on"] #schoolContent,body[data-student-tabs="on"] #studentTabs,body[data-student-tabs="on"] .student-tab-panel{width:100%;max-width:none;height:100dvh;min-height:0;margin:0;padding:0}
 body[data-student-tabs="on"] .header{position:fixed;top:0;left:0;z-index:15;width:50%;height:38px;min-height:38px;padding:0 16px 0 max(16px,env(safe-area-inset-left,0px))}
 .student-tab-panel>.student-home-view:not(:has(.student-activities)){max-width:none;height:100dvh;margin:0}
 .student-tab-columns{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0;height:100dvh}
 /* The left column starts right under the 38 px brand header, where the title row starts in portrait too. */
 .student-tab-left,.student-tab-right{display:flex;flex-direction:column;gap:14px;min-height:0;height:100dvh;overflow-y:auto;overflow-x:hidden;overscroll-behavior-y:contain;scrollbar-gutter:stable;padding:38px 16px var(--tabbar-space)}
 .student-tab-right{padding-top:12px;border-left:1px solid var(--home-line,var(--n-eee3d5,#eee3d5));overflow-anchor:none}
 /* An open row's screen (랭킹 도전) or start panel (스피킹 게임) keeps a viewport of room under it, so the column can glide
    it to the middle, as 내 학습 does (row-slide.js restingMax). */
 .student-tab-right:has(.student-inline-activity:not([hidden]),.games-start:not([hidden]),.student-inline-fold){padding-bottom:calc(100dvh + 20px)}
 /* 내 학습's own grid keeps the bar's room below its activity scroller and its left column. */
 :where(body[data-student-tabs="on"]) .student-home-view:has(.student-activities)>.student-activities{padding-bottom:calc(var(--tabbar-space) + 20px)}
 :where(body[data-student-tabs="on"]) .student-home-view:has(.student-activities)>.student-home-status{margin-bottom:calc(var(--tabbar-space) + 6px)}
 body[data-student-tabs="on"] #schoolNotice:not(:empty),body[data-student-tabs="on"] #speechFeedback:not([hidden]){bottom:calc(var(--tabbar-space) + 6px)}
}
/* A short landscape screen keeps a slimmer title row (every tab, 내 학습 too). */
@media(orientation:landscape) and (max-height:480px){:root{--tab-head-h:40px}}
@media(orientation:landscape) and (max-height:500px){
 :root{--tabbar-h:52px}
 .student-tab{flex-direction:row;gap:6px}
 .student-tab-icon{width:40px;height:28px}
 .student-tabbar{--tab-label:11px}
}
/* 화면 색 (2026-10-31): in the four other colour sets the bar's focus ring is the set's --t-focus (3:1 or more on the
   bar); 지금 keeps it. */
:where(:root[data-theme]:not([data-theme="classic"])) .student-tab:focus-visible{outline-color:var(--t-focus)}
