/* Berbar Math — shared dark-purple theme (teacher app + student portal) */

/* Fonts are linked from the page head (preconnected, non-blocking).
   Montserrat carries Latin, Cairo carries Arabic, figures use the system mono. */

:root{
  --ground:#0E0918;
  --panel:#150E24;
  --panel-2:#1B1230;
  --raise:#221639;
  --line:#2C2044;
  --line-soft:#241938;

  --violet:#A66BFF;
  --violet-dim:#7C4DD6;
  --violet-deep:#4A2A86;
  --violet-wash:rgba(166,107,255,.12);

  --mint:#35D0A5;
  --mint-wash:rgba(53,208,165,.12);
  --amber:#F5A524;
  --amber-wash:rgba(245,165,36,.13);
  --rose:#FF5D7A;
  --rose-wash:rgba(255,93,122,.13);

  --ink:#F3EDFF;
  --ink-2:#B9A9D8;
  --ink-3:#7F6EA0;

  --r-sm:8px; --r:12px; --r-lg:18px; --r-xl:24px;
  --sans:"Montserrat","Cairo","Segoe UI",system-ui,sans-serif;
  --display:"Montserrat","Cairo",system-ui,sans-serif;
  --mono:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,monospace;
  --gold:#E9C46A; --gold-wash:rgba(233,196,106,.13);
  --silver:#C3CAD9; --silver-wash:rgba(195,202,217,.11);
  --rail:252px;
  --shadow:0 18px 40px -18px rgba(0,0,0,.85);

  --rail-a:#130C21; --rail-b:#0F0A1B;
  --topbar:rgba(14,9,24,.82);
  --hover:#1A1130;
  --btn:#211636; --btn-hover:#2A1C45; --btn-line:#2C2044;
  --input:#120C1F; --placeholder:#5C4C78;
  --chip:#1D1433; --track:#241938; --out:#110B1D;
  --pop:#241839; --pop-line:#3A2A5C;
  --scrim:rgba(6,3,12,.72);

  --logo-a:#B681FF; --logo-b:#6231BE; --logo-ink:#fff; --logo-dot:#E9C46A;
  --logo-glow:0 6px 14px rgba(166,107,255,.35);
}

/* the same page in daylight — every token flips, nothing else changes */
:root[data-theme="light"]{
  --ground:#F5F2FB;
  --panel:#FFFFFF;
  --panel-2:#FFFFFF;
  --raise:#EFE9F9;
  --line:#DED5EF;
  --line-soft:#EBE4F6;

  --violet:#7A3FE4;
  --violet-dim:#8B5CF6;
  --violet-deep:#D8CBF6;
  --violet-wash:rgba(122,63,228,.10);

  --mint:#0E9A74;
  --mint-wash:rgba(14,154,116,.12);
  --amber:#A96C05;
  --amber-wash:rgba(169,108,5,.13);
  --rose:#D22F52;
  --rose-wash:rgba(210,47,82,.11);

  --ink:#1D1630;
  --ink-2:#544A6B;
  --ink-3:#877CA0;

  /* gold and silver have to darken on a light ground to stay readable */
  --gold:#8A6209; --gold-wash:rgba(138,98,9,.11);
  --silver:#59616F; --silver-wash:rgba(89,97,111,.10);

  --shadow:0 18px 40px -22px rgba(45,30,80,.35);
  --rail-a:#FFFFFF; --rail-b:#FBF9FE;
  --topbar:rgba(245,242,251,.85);
  --hover:#F4F0FC;
  --btn:#FFFFFF; --btn-hover:#F3EEFC; --btn-line:#DED5EF;
  --input:#FFFFFF; --placeholder:#A79CC0;
  --chip:#F3EFFB; --track:#E8E1F5; --out:#F1ECF9;
  --pop:#FFFFFF; --pop-line:#DED5EF;
  --scrim:rgba(35,24,60,.34);

  /* On white the pale-violet tile washes out, so the mark goes deeper and the
     gold point warms up to hold its own against the page. */
  --logo-a:#7A42DF; --logo-b:#3F1C86; --logo-ink:#fff; --logo-dot:#F2B01E;
  --logo-glow:0 4px 10px rgba(63,28,134,.28);
}

*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{
  background:
    radial-gradient(1100px 560px at 82% -12%,rgba(124,77,214,.20),transparent 62%),
    radial-gradient(760px 420px at 0% 100%,rgba(53,208,165,.06),transparent 58%),
    var(--ground);
  background-attachment:fixed;
  color:var(--ink);font-family:var(--sans);
  font-size:14.5px;line-height:1.6;-webkit-font-smoothing:antialiased;min-height:100vh;
}
:root[data-theme="light"] body{
  background:
    radial-gradient(1100px 560px at 82% -12%,rgba(122,63,228,.10),transparent 62%),
    radial-gradient(760px 420px at 0% 100%,rgba(14,154,116,.05),transparent 58%),
    var(--ground);
}
/* Cairo sits lower on the line than Montserrat and wants more air */
[lang="ar"] body,[lang="ar"] .portal-page{line-height:1.75}
[lang="ar"] h1,[lang="ar"] h2,[lang="ar"] h3,[lang="ar"] h4{letter-spacing:0}
h1,h2,h3,h4{font-family:var(--display);margin:0;text-wrap:balance;letter-spacing:-.021em;
  font-weight:600;line-height:1.25}
button,input,select,textarea{font:inherit;color:inherit}
a{color:var(--violet);text-decoration:none}
a:hover{text-decoration:underline}
::selection{background:var(--violet-deep);color:#fff}
:focus-visible{outline:2px solid var(--violet);outline-offset:2px;border-radius:6px}
::-webkit-scrollbar{width:10px;height:10px}
::-webkit-scrollbar-thumb{background:var(--track);border-radius:10px;border:3px solid var(--ground)}
::-webkit-scrollbar-track{background:transparent}
.num{font-family:var(--mono);font-variant-numeric:tabular-nums}
/* "10 000 DA" must not be reordered when the page runs right-to-left */
.num,.stat .val,.code,.gradepill,.hero-num,.ev b{unicode-bidi:plaintext}
svg{width:16px;height:16px;flex:0 0 auto}
.crumbs svg{width:13px;height:13px;opacity:.6}
.av svg{width:16px;height:16px}
.av.lg svg{width:24px;height:24px}
.hide{display:none !important}

/* ---------------- shell ---------------- */
.app{display:grid;grid-template-columns:var(--rail) 1fr;min-height:100vh}
.rail{
  position:sticky;top:0;height:100vh;background:linear-gradient(180deg,var(--rail-a),var(--rail-b));
  border-inline-end:1px solid var(--line-soft);display:flex;flex-direction:column;gap:2px;
  padding:18px 12px 14px;overflow-y:auto;
}
.brand{display:flex;align-items:center;gap:11px;padding:4px 8px 20px}
.brand .mark{
  width:38px;height:38px;border-radius:11px;flex:0 0 auto;
  background:linear-gradient(145deg,var(--violet),#5B2FB0);display:grid;place-items:center;
  font-family:var(--display);font-weight:700;font-size:15px;color:#fff;
  box-shadow:0 6px 18px -6px rgba(166,107,255,.8);
}
.brand b{font-family:var(--display);font-size:15.5px;font-weight:600;display:block;line-height:1.2}
.brand span{font-size:11.5px;color:var(--ink-3);display:block}
.navgroup{font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);
  padding:16px 10px 7px;font-weight:600}
.navitem{
  display:flex;align-items:center;gap:11px;width:100%;text-align:left;padding:9px 10px;
  border-radius:var(--r);border:0;background:none;color:var(--ink-2);cursor:pointer;
  font-size:14px;position:relative;text-align:start;transition:background .15s,color .15s;
}
.navitem svg{width:17px;height:17px;opacity:.8}
.navitem:hover{background:var(--hover);color:var(--ink)}
.navitem.on{background:var(--violet-wash);color:var(--ink)}
.navitem.on svg{opacity:1;color:var(--violet)}
.navitem.on::before{content:"";position:absolute;inset-inline-start:-12px;top:9px;bottom:9px;width:3px;
  background:var(--violet);border-radius:2px}
.navitem .badge{margin-inline-start:auto;font-size:10.5px;background:var(--rose);color:#fff;
  padding:1px 6px;border-radius:20px;font-weight:600}
.navitem .badge.calm{background:var(--violet-deep)}
.rail .spacer{flex:1}
.railfoot{border-top:1px solid var(--line-soft);padding-top:10px;margin-top:10px}

.main{min-width:0;display:flex;flex-direction:column}
.topbar{
  position:sticky;top:0;z-index:30;background:var(--topbar);backdrop-filter:blur(14px);
  border-bottom:1px solid var(--line-soft);padding:16px 30px;display:flex;align-items:center;
  gap:16px;flex-wrap:wrap;
}
.topbar h1{font-size:20px;font-weight:600}
.topbar .sub{font-size:12.5px;color:var(--ink-3);margin-top:1px}
.topbar .grow{flex:1}
.page{padding:26px 30px 90px;max-width:1240px;width:100%}

/* ---------------- primitives ---------------- */
.btn{
  display:inline-flex;align-items:center;gap:7px;padding:8px 14px;border-radius:10px;
  background:var(--btn);border:1px solid var(--btn-line);color:var(--ink);cursor:pointer;
  font-size:13.5px;font-weight:500;transition:background .15s,border-color .15s,transform .1s;
}
.btn svg{width:15px;height:15px}
.btn:hover{background:var(--btn-hover);border-color:var(--line);text-decoration:none}
.btn:active{transform:translateY(1px)}
.btn.primary{background:linear-gradient(160deg,var(--violet),#6E39C9);border-color:transparent;
  color:#fff;box-shadow:0 8px 20px -10px rgba(166,107,255,.9),
  inset 0 1px 0 rgba(255,255,255,.22)}
.btn.primary:hover{filter:brightness(1.08)}
.btn.ghost{background:transparent;border-color:transparent;color:var(--ink-2)}
.btn.ghost:hover{background:var(--hover);color:var(--ink)}
.btn.danger{color:var(--rose);border-color:rgba(255,93,122,.3);background:var(--rose-wash)}
.btn.ok{color:var(--mint);border-color:rgba(53,208,165,.3);background:var(--mint-wash)}
.btn.sm{padding:5px 10px;font-size:12.5px;border-radius:8px}
.btn.block{width:100%;justify-content:center}
.btn:disabled{opacity:.45;cursor:not-allowed}

.card{background:var(--panel);border:1px solid var(--line-soft);border-radius:var(--r-lg);
  padding:20px;box-shadow:inset 0 1px 0 rgba(255,255,255,.028)}
:root[data-theme="light"] .card{box-shadow:0 1px 2px rgba(45,30,80,.05)}
.card.pad0{padding:0;overflow:hidden}
.card h3{font-size:15px;font-weight:600}
.cardhead{display:flex;align-items:center;gap:12px;padding:16px 20px;border-bottom:1px solid var(--line-soft)}
.cardhead .grow{flex:1}
.grid{display:grid;gap:16px}
.cols{display:grid;gap:16px;grid-template-columns:repeat(auto-fit,minmax(320px,1fr))}
/* one card on its own should not stretch the width of a two-column grid */
.cols.one{grid-template-columns:minmax(0,520px)}
.row{display:flex;align-items:center;gap:10px}
.wrap{flex-wrap:wrap}
.grow{flex:1;min-width:0}
.muted{color:var(--ink-3)}
.mt{margin-top:16px}

.pill{display:inline-flex;align-items:center;gap:5px;padding:3px 9px;border-radius:20px;
  font-size:11.5px;font-weight:600;border:1px solid transparent;white-space:nowrap}
.pill .dot{width:6px;height:6px;border-radius:50%;background:currentColor}
.pill.ok{background:var(--mint-wash);color:var(--mint);border-color:rgba(53,208,165,.25)}
.pill.warn{background:var(--amber-wash);color:var(--amber);border-color:rgba(245,165,36,.28)}
.pill.bad{background:var(--rose-wash);color:var(--rose);border-color:rgba(255,93,122,.28)}
.pill.info{background:var(--violet-wash);color:var(--violet);border-color:rgba(166,107,255,.28)}
.pill.mute{background:var(--chip);color:var(--ink-3);border-color:var(--line)}
.pill.live{background:var(--rose-wash);color:var(--rose);border-color:rgba(255,93,122,.35)}
.pill.live .dot{animation:blip 1.4s infinite}
@keyframes blip{0%,100%{opacity:1}50%{opacity:.25}}

.tag{font-size:11.5px;color:var(--ink-2);background:var(--chip);border:1px solid var(--line);
  padding:2px 8px;border-radius:7px;white-space:nowrap}
.tag.gold{color:var(--gold);border-color:rgba(233,196,106,.32);background:var(--gold-wash)}
.tag.silver{color:var(--silver);border-color:rgba(195,202,217,.26);background:var(--silver-wash)}
.tag.one{color:var(--violet);border-color:rgba(166,107,255,.3);background:var(--violet-wash)}

.av{width:38px;height:38px;border-radius:11px;display:grid;place-items:center;flex:0 0 auto;
  font-family:var(--display);font-weight:600;font-size:13.5px;color:#fff}
.av.lg{width:60px;height:60px;border-radius:16px;font-size:20px}
.av.sm{width:30px;height:30px;border-radius:9px;font-size:11.5px}
.av .online{position:absolute}
.avwrap{position:relative;flex:0 0 auto}
.avwrap .dot-on{position:absolute;inset-inline-end:-2px;bottom:-2px;width:11px;height:11px;border-radius:50%;
  background:var(--mint);border:2px solid var(--panel)}

.seg{display:inline-flex;background:var(--chip);border:1px solid var(--line-soft);border-radius:10px;
  padding:3px;gap:2px;flex-wrap:wrap}
.seg button{border:0;background:none;color:var(--ink-3);padding:5px 12px;border-radius:7px;
  cursor:pointer;font-size:12.5px;font-weight:500;white-space:nowrap}
.seg button:hover{color:var(--ink)}
.seg button.on{background:var(--raise);color:var(--ink)}

.field{display:flex;flex-direction:column;gap:6px}
.field label{font-size:12px;color:var(--ink-2);font-weight:500}
.field .hint{font-size:11.5px;color:var(--ink-3)}
input[type=text],input[type=email],input[type=date],input[type=time],input[type=number],
input[type=url],input[type=password],input[type=datetime-local],select,textarea{
  background:var(--input);border:1px solid var(--line);border-radius:10px;padding:9px 11px;
  color:var(--ink);width:100%;transition:border-color .15s,box-shadow .15s;font-size:13.5px;
}
input:focus,select:focus,textarea:focus{outline:none;border-color:var(--violet-dim);
  box-shadow:0 0 0 3px rgba(166,107,255,.14)}
textarea{resize:vertical;min-height:78px;line-height:1.55}
input::placeholder,textarea::placeholder{color:var(--placeholder)}
select{appearance:none;background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' stroke='%237F6EA0' stroke-width='2'><path d='M4 6l4 4 4-4'/></svg>");
  background-repeat:no-repeat;background-position:right 10px center;padding-right:30px}
input[type=date],input[type=time],input[type=datetime-local]{color-scheme:dark}
.two{display:grid;grid-template-columns:1fr 1fr;gap:12px}

.tbl{width:100%;border-collapse:collapse}
.tbl th{text-align:start;font-size:11px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--ink-3);font-weight:600;padding:11px 20px;border-bottom:1px solid var(--line-soft);
  white-space:nowrap}
.tbl td{padding:13px 20px;border-bottom:1px solid var(--line-soft);vertical-align:middle}
.tbl tr:last-child td{border-bottom:0}
.tbl tbody tr{transition:background .12s}
.tbl tbody tr:hover{background:var(--hover)}
.tbl .num,.tbl .rightnum{white-space:nowrap}
.tblwrap{overflow-x:auto}
.rightnum{text-align:end}

.empty{text-align:center;padding:44px 20px;color:var(--ink-3)}
.empty .ico{width:46px;height:46px;border-radius:14px;background:var(--chip);display:grid;
  place-items:center;margin:0 auto 12px;color:var(--violet)}
.empty .ico svg{width:21px;height:21px}
.empty b{display:block;color:var(--ink-2);font-weight:500;margin-bottom:3px;font-family:var(--display)}
.empty p{margin:0 auto;max-width:46ch;font-size:13px}

.bar{height:6px;background:var(--track);border-radius:20px;overflow:hidden}
.bar span{display:block;height:100%;border-radius:20px;
  background:linear-gradient(90deg,var(--violet-dim),var(--violet))}
.bar.mint span{background:linear-gradient(90deg,#1E9E7C,var(--mint))}

.stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(198px,1fr));gap:14px}
.stat{background:var(--panel);border:1px solid var(--line-soft);border-radius:var(--r-lg);
  padding:16px 18px;box-shadow:inset 0 1px 0 rgba(255,255,255,.028)}
:root[data-theme="light"] .stat{box-shadow:0 1px 2px rgba(45,30,80,.05)}
.stat .lbl{font-size:12px;color:var(--ink-3);display:flex;align-items:center;gap:9px;
  font-weight:500}
.stat .lbl svg{width:14px;height:14px;color:var(--violet)}
.stat .lbl .chip{width:26px;height:26px;border-radius:9px;display:grid;place-items:center;
  background:var(--violet-wash);flex:0 0 auto}
.stat .val{font-family:var(--display);font-size:28px;font-weight:700;line-height:1.15;
  margin-top:10px;font-variant-numeric:tabular-nums;letter-spacing:-.02em}
.stat .val small{font-size:14px;color:var(--ink-3);font-weight:500}
.stat .foot{font-size:11.5px;color:var(--ink-3);margin-top:5px}

/* ---------------- chart ---------------- */
.chart{position:relative}
.chart svg{display:block;width:100%;height:auto;overflow:visible}
.chart .gl{stroke:var(--line-soft);stroke-width:1}
.chart .axl{fill:var(--ink-3);font-size:11px;font-family:var(--sans)}
.chart .bar-r{transition:opacity .12s}
.chart:hover .bar-r{opacity:.55}
.chart .bar-r:hover{opacity:1}
.tip{position:absolute;pointer-events:none;background:var(--pop);border:1px solid var(--pop-line);
  border-radius:10px;padding:7px 10px;font-size:12px;white-space:nowrap;
  transform:translate(-50%,-124%);opacity:0;transition:opacity .1s;box-shadow:var(--shadow);z-index:5}
.tip b{font-family:var(--mono);font-weight:600;display:block}
.tip.on{opacity:1}

/* ---------------- lists ---------------- */
.lrow{display:flex;align-items:center;gap:13px;padding:12px 20px;
  border-bottom:1px solid var(--line-soft);cursor:pointer;transition:background .12s;
  text-align:start;width:100%;background:none;border-left:0;border-right:0;border-top:0;color:inherit}
.lrow:last-child{border-bottom:0}
.lrow:hover{background:var(--hover)}
.lrow.flat{cursor:default}
.lrow.flat:hover{background:none}
.lrow .nm{font-weight:500;font-size:14px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.lrow .mt2{font-size:12px;color:var(--ink-3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* ---------------- calendar ---------------- */
.cal{border:1px solid var(--line-soft);border-radius:var(--r-lg);overflow:hidden;background:var(--panel)}
.calhead{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));background:var(--chip)}
.calhead div{padding:9px 10px;font-size:11px;letter-spacing:.09em;text-transform:uppercase;
  color:var(--ink-3);font-weight:600;border-inline-end:1px solid var(--line-soft)}
.calhead div:last-child{border-inline-end:0}
.calgrid{display:grid;grid-template-columns:repeat(7,minmax(0,1fr))}
.day{min-height:112px;min-width:0;border-inline-end:1px solid var(--line-soft);border-bottom:1px solid var(--line-soft);
  padding:7px 8px;display:flex;flex-direction:column;gap:4px;transition:background .12s}
.day:nth-child(7n){border-inline-end:0}
.day:hover{background:var(--hover)}
.day.out{background:var(--out);color:var(--ink-3)}
.day .dn{font-size:12px;color:var(--ink-3);font-family:var(--mono)}
.day.today .dn{background:var(--violet);color:#fff;border-radius:7px;padding:0 6px;
  font-weight:600;align-self:flex-start}
.ev{font-size:11.5px;padding:4px 7px;border-radius:7px;min-width:0;background:var(--violet-wash);
  border-inline-start:2px solid var(--violet);cursor:pointer;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.ev:hover{background:rgba(166,107,255,.22)}
.ev.static{cursor:default}
.ev.done{background:var(--mint-wash);border-inline-start-color:var(--mint);color:var(--ink-2)}
.ev.cancelled{background:#1E1534;border-left-color:#4A3A6C;color:var(--ink-3);
  text-decoration:line-through}
.ev.live{background:var(--rose-wash);border-inline-start-color:var(--rose)}
.ev b{font-family:var(--mono);font-weight:500;opacity:.85}
.wkgrid{display:grid;grid-template-columns:repeat(7,minmax(0,1fr))}
.wkcol{border-inline-end:1px solid var(--line-soft);min-height:320px;min-width:0;padding:8px;display:flex;
  flex-direction:column;gap:5px}
.wkcol:last-child{border-inline-end:0}
.wkcol h4{font-size:12px;color:var(--ink-2);font-weight:500;display:flex;justify-content:space-between}
.wkcol h4 span{font-family:var(--mono);color:var(--ink-3)}
.wkcol.today{background:var(--hover)}
.hours{display:grid;grid-template-columns:64px 1fr;max-height:620px;overflow-y:auto}
.hr-lbl{font-size:11px;color:var(--ink-3);font-family:var(--mono);padding:6px 10px;text-align:end;
  border-inline-end:1px solid var(--line-soft);border-bottom:1px solid var(--line-soft)}
.hr-cell{border-bottom:1px solid var(--line-soft);padding:5px 8px;min-height:44px;display:flex;
  flex-direction:column;gap:4px}
.hr-cell:hover{background:var(--hover)}
.ctxmenu{position:fixed;z-index:200;background:var(--pop);border:1px solid var(--pop-line);border-radius:11px;
  padding:5px;box-shadow:var(--shadow);min-width:190px}
.ctxmenu button{display:flex;align-items:center;gap:9px;width:100%;background:none;border:0;
  color:var(--ink);padding:8px 10px;border-radius:8px;cursor:pointer;font-size:13px;text-align:start}
.ctxmenu button:hover{background:var(--violet-wash)}
.ctxmenu button svg{color:var(--violet)}
.ctxmenu .hd{font-size:11px;color:var(--ink-3);padding:6px 10px 4px}

/* ---------------- messages ---------------- */
.msg-shell{display:grid;grid-template-columns:270px 1fr;height:calc(100vh - 170px);
  min-height:440px;border:1px solid var(--line-soft);border-radius:var(--r-lg);
  overflow:hidden;background:var(--panel)}
.msg-list{border-inline-end:1px solid var(--line-soft);overflow-y:auto;display:flex;flex-direction:column}
.msg-list .lrow.on{background:var(--violet-wash)}
.thread{display:flex;flex-direction:column;min-width:0}
.thread-head{padding:13px 18px;border-bottom:1px solid var(--line-soft);display:flex;
  align-items:center;gap:11px}
.bubbles{flex:1;overflow-y:auto;padding:20px;display:flex;flex-direction:column;gap:10px}
.bub{max-width:64%;padding:9px 13px;border-radius:14px;font-size:13.5px;line-height:1.5;
  white-space:pre-wrap;word-break:break-word}
.bub .t{font-size:10.5px;opacity:.6;margin-top:3px;font-family:var(--mono)}
.bub.me{align-self:flex-end;background:linear-gradient(160deg,var(--violet-dim),#5C2FAF);
  color:#fff;border-end-end-radius:5px}
.bub.them{align-self:flex-start;background:var(--btn);border:1px solid var(--btn-line);
  border-end-start-radius:5px}
.bub.note{align-self:center;background:transparent;color:var(--ink-3);font-size:11.5px;
  max-width:80%;text-align:center}
.composer{border-top:1px solid var(--line-soft);padding:12px 16px;display:flex;gap:10px;
  align-items:flex-end}
.composer textarea{min-height:42px;max-height:120px}

/* ---------------- modal ---------------- */
.scrim{position:fixed;inset:0;background:var(--scrim);backdrop-filter:blur(4px);z-index:100;
  display:flex;align-items:flex-start;justify-content:center;padding:40px 20px;overflow-y:auto;
  animation:fade .16s ease}
@keyframes fade{from{opacity:0}to{opacity:1}}
.modal{background:var(--panel-2);border:1px solid var(--line);border-radius:var(--r-xl);
  width:100%;max-width:520px;box-shadow:var(--shadow);animation:pop .2s cubic-bezier(.2,.9,.3,1.2)}
.modal.wide{max-width:680px}
@keyframes pop{from{opacity:0;transform:translateY(14px) scale(.98)}to{opacity:1;transform:none}}
.modal header{padding:20px 22px 0;display:flex;align-items:flex-start;gap:12px}
.modal header h3{font-size:17px;font-weight:600;flex:1}
.modal header p{margin:3px 0 0;font-size:12.5px;color:var(--ink-3)}
.modal .body{padding:18px 22px;display:flex;flex-direction:column;gap:14px}
.modal footer{padding:14px 22px 20px;display:flex;gap:9px;justify-content:flex-end;flex-wrap:wrap}
.xbtn{background:none;border:0;color:var(--ink-3);cursor:pointer;padding:4px;border-radius:8px;
  line-height:0}
.xbtn:hover{background:var(--btn-hover);color:var(--ink)}
.xbtn svg{width:17px;height:17px}

/* ---------------- toast ---------------- */
.toasts{position:fixed;bottom:22px;left:50%;transform:translateX(-50%);z-index:300;
  display:flex;flex-direction:column;gap:8px;align-items:center;pointer-events:none}
.toast{background:var(--pop);border:1px solid var(--pop-line);border-radius:11px;padding:10px 15px;
  font-size:13px;box-shadow:var(--shadow);display:flex;align-items:center;gap:9px;
  animation:up .22s ease;max-width:min(92vw,520px)}
.toast svg{color:var(--mint)}
.toast.bad{border-color:rgba(255,93,122,.5)}
.toast.bad svg{color:var(--rose)}
@keyframes up{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}

/* ---------------- floating support ---------------- */
.fab{position:fixed;inset-inline-end:22px;bottom:22px;z-index:90;display:flex;align-items:center;gap:8px;
  padding:11px 16px;border-radius:30px;border:1px solid rgba(166,107,255,.4);cursor:pointer;
  background:linear-gradient(160deg,var(--raise),var(--panel));color:var(--ink);font-size:13.5px;
  font-weight:500;box-shadow:0 14px 34px -14px rgba(0,0,0,.9)}
.fab:hover{border-color:var(--violet);background:var(--btn-hover)}
.fab svg{color:#3AA9EE}

/* ---------------- detail ---------------- */
.crumbs{display:flex;align-items:center;gap:6px;font-size:12.5px;color:var(--ink-3);margin-bottom:14px}
.crumbs button{background:none;border:0;color:var(--ink-3);cursor:pointer;padding:0;font-size:12.5px}
.crumbs button:hover{color:var(--violet)}
.tabs{display:flex;gap:2px;border-bottom:1px solid var(--line-soft);margin-bottom:20px;
  overflow-x:auto;scrollbar-width:none}
.tabs::-webkit-scrollbar{height:0;width:0}
.tblwrap{scrollbar-width:thin}
.tabs button{background:none;border:0;padding:10px 14px;color:var(--ink-3);cursor:pointer;
  font-size:13.5px;border-bottom:2px solid transparent;margin-bottom:-1px;white-space:nowrap;
  font-weight:500}
.tabs button:hover{color:var(--ink)}
.tabs button.on{color:var(--ink);border-bottom-color:var(--violet)}
.kv{display:flex;justify-content:space-between;gap:16px;padding:9px 0;
  border-bottom:1px solid var(--line-soft);font-size:13.5px;flex-wrap:wrap}
.kv > span{min-width:0}
.kv:last-child{border-bottom:0}
.kv span{color:var(--ink-3)}
.kv b{text-align:end;word-break:break-word}
.notebox{background:var(--input);border:1px solid var(--line-soft);border-radius:var(--r);
  padding:13px 15px;font-size:13.5px;color:var(--ink-2);line-height:1.6;white-space:pre-wrap}
.hero-num{font-family:var(--display);font-size:34px;font-weight:600;line-height:1;
  font-variant-numeric:tabular-nums}
.sub-lbl{font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-3);font-weight:600}
/* a select you can type into — same box, but the long lists filter as you go */
.combo{position:relative}
.combo .comboin{
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' stroke='%237F6EA0' stroke-width='2'><path d='M4 6l4 4 4-4'/></svg>");
  background-repeat:no-repeat;background-position:right 11px center;padding-inline-end:32px;
}
[dir="rtl"] .combo .comboin{background-position:left 11px center}
.combolist{
  position:absolute;inset-inline:0;top:calc(100% + 5px);z-index:40;max-height:238px;
  overflow-y:auto;padding:5px;background:var(--pop);border:1px solid var(--pop-line);
  border-radius:12px;box-shadow:var(--shadow);
}
.comboopt{
  display:block;width:100%;text-align:start;border:0;background:none;color:var(--ink);
  font-size:13.5px;padding:8px 10px;border-radius:8px;cursor:pointer;
}
/* display:block above would otherwise beat the hidden attribute */
.comboopt[hidden],.comboempty[hidden],.combolist[hidden]{display:none}
.comboopt:hover,.comboopt.on{background:var(--hover);color:var(--ink)}
.comboopt.on{box-shadow:inset 2px 0 0 var(--violet)}
[dir="rtl"] .comboopt.on{box-shadow:inset -2px 0 0 var(--violet)}
.comboempty{padding:10px;font-size:12.5px;color:var(--ink-3)}

.remember{display:flex;align-items:center;gap:9px;font-size:12.5px;color:var(--ink-2);
  cursor:pointer;margin:-2px 0 14px;user-select:none}
.remember input{width:15px;height:15px;accent-color:var(--violet);flex:0 0 auto}
.checkline{display:flex;align-items:center;gap:11px;padding:10px 12px;
  border:1px solid var(--line-soft);border-radius:var(--r);cursor:pointer;background:var(--chip)}
.checkline:hover{border-color:var(--pop-line)}
.checkline input{width:16px;height:16px;accent-color:var(--violet);flex:0 0 auto}
/* the register: a ticked name is the thing you are checking at a glance */
.attlist{display:flex;flex-direction:column;gap:7px;padding:2px;
  max-height:min(38vh,300px);overflow-y:auto}
.attlist .checkline:has(input:checked){border-color:var(--violet-deep);
  background:var(--violet-wash)}
.attmore{margin-top:3px}
.attmore summary{font-size:12.5px;color:var(--ink-3);cursor:pointer;padding:7px 2px;
  list-style:none}
.attmore summary::-webkit-details-marker{display:none}
.attmore summary::before{content:"+ ";font-weight:600}
.attmore[open] summary::before{content:"– "}
.attmore summary:hover{color:var(--ink-2)}
.attmore[open]{display:flex;flex-direction:column;gap:7px}
.switch{position:relative;width:40px;height:22px;border-radius:20px;background:var(--track);border:0;
  cursor:pointer;flex:0 0 auto;transition:background .18s}
.switch::after{content:"";position:absolute;top:3px;left:3px;width:16px;height:16px;
  border-radius:50%;background:#7F6EA0;transition:transform .18s,background .18s}
.switch.on{background:var(--violet-deep)}
.switch.on::after{transform:translateX(18px);background:var(--violet)}
.code{font-family:var(--mono);background:var(--input);border:1px solid var(--line);border-radius:8px;
  padding:2px 7px;font-size:12.5px;color:var(--ink-2);user-select:all}

/* ---------------- login / portal ---------------- */
.gate{min-height:100vh;display:grid;place-items:center;padding:24px;
  background:radial-gradient(1100px 620px at 50% -10%,#241243 0%,var(--ground) 62%)}
.gate-card{width:100%;max-width:420px;background:var(--panel);border:1px solid var(--line);
  border-radius:var(--r-xl);padding:30px;box-shadow:var(--shadow)}
.gate-card .brand{justify-content:center;padding-bottom:16px}
.gate-card h2{font-size:19px;text-align:center;margin-bottom:6px}
.gate-card .lead{text-align:center;color:var(--ink-3);font-size:13px;margin:0 0 22px}
.gate-form{display:flex;flex-direction:column;gap:14px}
.gate-alt{margin-top:18px;padding-top:16px;border-top:1px solid var(--line-soft);
  text-align:center;font-size:12.5px;color:var(--ink-3)}
.err{background:var(--rose-wash);border:1px solid rgba(255,93,122,.3);color:#FFA9B9;
  border-radius:10px;padding:9px 12px;font-size:12.5px}
.ok-box{background:var(--mint-wash);border:1px solid rgba(53,208,165,.3);color:#8AE6CB;
  border-radius:10px;padding:9px 12px;font-size:12.5px}

.portal{max-width:940px;margin:0 auto;padding:24px 20px 90px}
.portal-top{display:flex;align-items:center;gap:14px;padding:18px 0 24px;flex-wrap:wrap}
.next-card{background:linear-gradient(150deg,var(--raise),var(--panel-2));border:1px solid rgba(166,107,255,.35);
  border-radius:var(--r-xl);padding:22px;display:flex;gap:18px;align-items:center;flex-wrap:wrap}
.next-card .when{font-family:var(--display);font-size:22px;font-weight:600}

@media(max-width:1000px){
  .app{grid-template-columns:1fr}
  .rail{position:fixed;inset-inline-start:0;top:0;width:var(--rail);z-index:80;
    transform:translateX(-100%)}
  /* only animate once the first paint is done, or the drawer slides in from
     nowhere on load */
  html.ready .rail{transition:transform .22s}
  /* the drawer hides off the side it opens from, which flips with the language */
  [dir="rtl"] .rail{transform:translateX(100%)}
  .rail.open,[dir="rtl"] .rail.open{transform:none;box-shadow:0 0 60px rgba(0,0,0,.55)}
  .menubtn{display:inline-flex !important}
  .page,.topbar{padding-left:18px;padding-right:18px}
  .msg-shell{grid-template-columns:1fr}
  .msg-shell.thread-open .msg-list{display:none}
  .msg-shell:not(.thread-open) .thread{display:none}
  .two{grid-template-columns:1fr}
}
.menubtn{display:none}
@media(max-width:620px){
  .stats{grid-template-columns:1fr 1fr}
  .portal{padding:16px 16px 90px}
  .portal-top{padding:10px 0 18px;gap:10px}
  .portal-top .brand span{display:none}
  .portal-top{flex-wrap:nowrap}
  .portal-top .brand{min-width:0;overflow:hidden}
  .portal-top .brand b{font-size:14px;white-space:nowrap}
  .portal-top .tag{display:none}
  .portal-top .btn{padding:6px 10px}
  .stat{padding:13px 14px}
  .stat .val{font-size:23px}
  .day{min-height:76px;padding:5px 4px}
  .calhead div{font-size:9.5px;padding:7px 4px}
  /* a 41px column cannot hold a title, so month view becomes a dot calendar
     and the day and week views carry the detail */
  .day .ev{padding:0;height:5px;border-radius:3px;font-size:0;overflow:hidden;
    border-inline-start:0;background:var(--violet)}
  .day .ev b{display:none}
  .day .ev.done{background:var(--mint)}
  .day .ev.live{background:var(--rose)}
  .day .ev.cancelled{background:var(--ink-3);text-decoration:none}
  .wkgrid{grid-template-columns:1fr}
  .wkcol{border-right:0;border-bottom:1px solid var(--line-soft);min-height:0}
  .bub{max-width:86%}
}
[dir="rtl"] .chevflip{transform:scaleX(-1)}

@media(prefers-reduced-motion:reduce){*{animation-duration:.01ms !important;transition-duration:.01ms !important}}

/* ================= student portal shell ================= */
.stopbar{
  position:sticky;top:0;z-index:40;display:flex;align-items:center;gap:10px;
  padding:10px 22px;background:var(--topbar);backdrop-filter:blur(14px);
  border-bottom:1px solid var(--line-soft);
}
.stopbar .grow{flex:1}
.iconbtn{
  width:36px;height:36px;border-radius:10px;border:1px solid var(--btn-line);
  background:var(--btn);color:var(--ink-2);cursor:pointer;display:grid;place-items:center;
  position:relative;transition:background .15s,color .15s;
}
.iconbtn:hover{background:var(--btn-hover);color:var(--ink)}
.iconbtn svg{width:17px;height:17px}
.iconbtn .count{
  position:absolute;top:-5px;inset-inline-end:-5px;min-width:17px;height:17px;padding:0 4px;
  border-radius:20px;background:var(--rose);color:#fff;font-size:10.5px;font-weight:700;
  display:grid;place-items:center;border:2px solid var(--ground);
}
.brandbadge{display:flex;align-items:center;gap:12px}
.brandbadge .who{text-align:end}
.brandbadge .who b{font-family:var(--display);font-size:14px;display:block;line-height:1.2}
.brandbadge .who span{font-size:11px;color:var(--ink-3);display:block}
/* One honest badge: the role you are actually signed in as. */
.rolepill{
  display:inline-flex;align-items:center;gap:7px;padding:5px 12px;border-radius:20px;
  background:var(--violet-wash);border:1px solid var(--violet-deep);color:var(--violet);
  font-size:var(--t-sm);font-weight:600;white-space:nowrap;
}
.rolepill svg{width:14px;height:14px}

.popover{
  /* Fixed, not absolute: the bar it hangs from is sticky, so the panel has to
     stay with it when the page scrolls. */
  position:fixed;top:60px;inset-inline-start:14px;width:min(360px,calc(100vw - 28px));
  background:var(--pop);border:1px solid var(--pop-line);border-radius:var(--r-lg);
  box-shadow:var(--shadow);z-index:60;overflow:hidden;animation:pop .16s ease;
}
.popover .head{padding:12px 16px;border-bottom:1px solid var(--line-soft);
  display:flex;align-items:center;gap:10px}
.popover .head h4{font-size:14px;flex:1}
.popover .list{max-height:340px;overflow-y:auto}
.popover .opt{display:flex;align-items:center;gap:10px;width:100%;padding:10px 16px;
  background:none;border:0;color:var(--ink);cursor:pointer;font-size:13.5px;text-align:start}
.popover .opt:hover{background:var(--hover)}
.popover .opt.on{color:var(--violet);background:var(--violet-wash)}
/* A language names itself. Its own script is the identity; the English name
   is there for anyone who does not read that script yet. */
.popover .langopt{align-items:center;padding:11px 16px}
.langopt .grow{display:flex;flex-direction:column;gap:1px;min-width:0}
.langopt b{font-size:14.5px;font-weight:600;line-height:1.25}
.langopt .sub{font-size:11.5px;color:var(--ink-3)}
.langopt.on b{color:var(--violet)}
.langgrid{display:grid;gap:10px;grid-template-columns:repeat(auto-fit,minmax(130px,1fr))}
.langtile{
  position:relative;display:flex;flex-direction:column;gap:2px;padding:14px 16px;
  border-radius:14px;border:1px solid var(--line);background:var(--panel-2);
  color:var(--ink);cursor:pointer;text-align:start;
  transition:border-color .18s var(--ease),background .18s var(--ease),
    transform .14s var(--press);
}
.langtile:hover{border-color:var(--violet-deep);background:var(--hover)}
.langtile:active{transform:scale(.98)}
.langtile.on{border-color:var(--violet);background:var(--violet-wash)}
.langtile b{font-size:17px;font-weight:600;line-height:1.3}
/* the stream picker reuses the tiles, but "Sciences expérimentales" needs
   more room than "Français" ever did */
.fieldgrid{grid-template-columns:repeat(auto-fit,minmax(185px,1fr))}
.fieldgrid .langtile b{font-size:15px;line-height:1.3;overflow-wrap:anywhere}
.langtile span{font-size:11.5px;color:var(--ink-3)}
.langtile.on b{color:var(--violet)}
.langtile .tick{position:absolute;top:12px;inset-inline-end:12px;color:var(--violet);
  display:inline-flex}
.langtile .tick svg{width:15px;height:15px}
.notif{display:flex;gap:11px;padding:11px 16px;border-bottom:1px solid var(--line-soft);align-items:flex-start}
.notif:last-child{border-bottom:0}
.notif .ic{width:28px;height:28px;border-radius:9px;display:grid;place-items:center;
  background:var(--chip);color:var(--violet);flex:0 0 auto}
.notif .ic svg{width:14px;height:14px}
.notif.unread{background:var(--violet-wash)}
.notif .t{font-size:11px;color:var(--ink-3);font-family:var(--mono);margin-top:2px}
/* The teacher's bell sits at the end of the top bar, so its panel does too. */
.popover.end{inset-inline-start:auto;inset-inline-end:14px}
button.notif{width:100%;background:none;border:0;border-bottom:1px solid var(--line-soft);
  color:var(--ink);cursor:pointer;text-align:start;font:inherit}
button.notif:hover{background:var(--hover)}
.iconbtn.rec{color:var(--rose);border-color:var(--rose)}
@keyframes recpulse{0%,100%{opacity:1}50%{opacity:.45}}
.iconbtn.rec svg{animation:recpulse 1.1s ease-in-out infinite}

.portal-shell{display:grid;grid-template-columns:var(--rail) 1fr;min-height:100vh}
.portal-main{min-width:0;display:flex;flex-direction:column}
.portal-page{padding:24px 26px 90px;max-width:1180px;width:100%}
.portal-h{margin-bottom:20px}
.portal-h h1{font-size:23px}
.portal-h p{margin:4px 0 0;color:var(--ink-3);font-size:13.5px}

/* ================= steps ================= */
.steps{display:flex;flex-direction:column;gap:14px}
.step{display:flex;gap:14px}
.step .n{
  width:30px;height:30px;border-radius:50%;flex:0 0 auto;display:grid;place-items:center;
  background:var(--chip);border:1px solid var(--line);color:var(--ink-3);
  font-family:var(--display);font-weight:600;font-size:13px;
}
.step.on .n{background:var(--violet);border-color:transparent;color:#fff}
.step.done .n{background:var(--mint-wash);border-color:rgba(53,208,165,.4);color:var(--mint)}
.step .bd{flex:1;min-width:0;padding-bottom:4px}
.step .bd h4{font-size:14px;margin-bottom:3px}
.step .bd p{margin:0 0 10px;font-size:12.5px;color:var(--ink-3)}

.dropzone{border:1.5px dashed var(--pop-line);border-radius:var(--r);padding:22px;
  text-align:center;color:var(--ink-3);cursor:pointer;transition:border-color .15s,background .15s}
.dropzone:hover,.dropzone.over{border-color:var(--violet);background:var(--violet-wash);color:var(--ink-2)}
.dropzone svg{width:20px;height:20px}
.filechip{display:inline-flex;align-items:center;gap:8px;padding:7px 11px;border-radius:10px;
  background:var(--chip);border:1px solid var(--line);font-size:12.5px}
.filechip img{width:34px;height:34px;object-fit:cover;border-radius:7px}

/* ================= chat extras ================= */
.att{display:flex;flex-direction:column;gap:6px;margin-top:6px}
.att img{max-width:230px;border-radius:10px;display:block;cursor:zoom-in}
.att a{display:inline-flex;align-items:center;gap:7px;font-size:12.5px;
  background:rgba(255,255,255,.08);padding:6px 10px;border-radius:9px;color:inherit}
.att audio{width:230px;max-width:100%;height:38px}
.bub.me .att a{background:rgba(255,255,255,.16)}
.bub .who{font-size:11px;font-weight:600;opacity:.75;margin-bottom:3px}
.rec-live{display:flex;align-items:center;gap:8px;color:var(--rose);font-size:12.5px;
  font-family:var(--mono)}
.rec-live .blob{width:9px;height:9px;border-radius:50%;background:var(--rose);
  animation:blip 1s infinite}
.chan-tabs{display:flex;gap:6px;padding:10px 14px;border-bottom:1px solid var(--line-soft);
  overflow-x:auto;scrollbar-width:none}
.chan-tabs::-webkit-scrollbar{height:0}
.chan{display:flex;align-items:center;gap:8px;padding:7px 12px;border-radius:10px;
  border:1px solid var(--line-soft);background:var(--chip);color:var(--ink-2);
  cursor:pointer;font-size:13px;white-space:nowrap}
.chan:hover{color:var(--ink)}
.chan.on{background:var(--violet-wash);border-color:var(--violet-deep);color:var(--ink)}
.chan .n{font-size:11px;color:var(--ink-3)}

/* ================= recordings ================= */
.recgrid{display:grid;gap:14px;grid-template-columns:repeat(auto-fill,minmax(250px,1fr))}
.reccard{background:var(--panel);border:1px solid var(--line-soft);border-radius:var(--r-lg);
  overflow:hidden;display:flex;flex-direction:column}
.recthumb{height:104px;background:linear-gradient(150deg,var(--violet-deep),var(--raise));
  display:grid;place-items:center;color:var(--violet);position:relative}
.recthumb svg{width:26px;height:26px}
.recthumb .len{position:absolute;inset-inline-end:8px;bottom:8px;background:rgba(0,0,0,.55);
  color:#fff;border-radius:6px;padding:1px 6px;font-size:11px;font-family:var(--mono)}
.reccard .bd{padding:13px 15px;display:flex;flex-direction:column;gap:6px;flex:1}
.reccard .bd h4{font-size:14px}
.locked{text-align:center;padding:40px 24px;border:1px dashed var(--pop-line);
  border-radius:var(--r-lg);background:var(--panel)}
.locked .ic{width:52px;height:52px;border-radius:16px;display:grid;place-items:center;
  margin:0 auto 14px;background:linear-gradient(150deg,#F0C85A33,#F0C85A11);color:#F0C85A}
.locked .ic svg{width:24px;height:24px}

/* ================= misc ================= */
.legend{display:flex;gap:14px;flex-wrap:wrap;font-size:12px;color:var(--ink-3)}
.legend span{display:inline-flex;align-items:center;gap:6px}
.legend i{width:9px;height:9px;border-radius:3px;display:inline-block}
.settabs{display:flex;gap:6px;margin-bottom:18px;flex-wrap:wrap}
.settabs button{padding:8px 14px;border-radius:10px;border:1px solid var(--line-soft);
  background:var(--chip);color:var(--ink-2);cursor:pointer;font-size:13.5px}
.settabs button.on{background:var(--violet-wash);border-color:var(--violet-deep);color:var(--ink)}
.pref-row{display:flex;align-items:center;gap:14px;padding:13px 0;
  border-bottom:1px solid var(--line-soft)}
.pref-row:last-child{border-bottom:0}
.pref-row .bd{flex:1;min-width:0}
.pref-row .bd b{display:block;font-weight:500;font-size:13.5px}
.pref-row .bd span{font-size:12px;color:var(--ink-3)}
.soon{font-size:10.5px;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-3);
  border:1px solid var(--line);border-radius:6px;padding:2px 6px}
.choice{display:flex;gap:8px;flex-wrap:wrap}
.choice button{padding:8px 14px;border-radius:10px;border:1px solid var(--line-soft);
  background:var(--chip);color:var(--ink-2);cursor:pointer;font-size:13px;
  display:inline-flex;align-items:center;gap:7px}
.choice button.on{background:var(--violet-wash);border-color:var(--violet);color:var(--ink)}
.gradepill{font-family:var(--mono);font-weight:600;font-size:13px}
.lightbox{position:fixed;inset:0;background:rgba(0,0,0,.85);z-index:400;display:grid;
  place-items:center;padding:24px;cursor:zoom-out}
.lightbox img{max-width:100%;max-height:100%;border-radius:12px}

@media(max-width:1000px){
  .portal-shell{grid-template-columns:1fr}
  .portal-page{padding-left:16px;padding-right:16px}
  .stopbar{padding:10px 14px}
  .brandbadge .who{display:none}
}

/* ================= brand mark ================= */
.logo{display:block;flex:0 0 auto;filter:drop-shadow(var(--logo-glow))}

/* group marks wear their tier */
.av.gmark{color:#fff}
.av.gmark.gold{background:linear-gradient(150deg,#D9A93C,#8C6A18);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.3)}
.av.gmark.silver{background:linear-gradient(150deg,#AFB7C7,#6C7486);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.3)}
.av.gmark.violet{background:linear-gradient(150deg,var(--violet-dim),var(--violet-deep))}
.grouprow{display:flex;align-items:center;gap:10px}

/* chart legend */
.chartkey{display:flex;gap:16px;flex-wrap:wrap;margin-bottom:12px;font-size:12.5px;
  color:var(--ink-2)}
.chartkey span{display:inline-flex;align-items:center;gap:7px}
.chartkey i{width:10px;height:10px;border-radius:3px;display:inline-block}

/* payment instructions image */
.payshot{margin:0;display:flex;flex-direction:column;gap:8px;align-items:flex-start}
.payshot img{max-width:min(100%,340px);border-radius:var(--r);border:1px solid var(--line);
  cursor:zoom-in;display:block;background:var(--input)}
.payshot figcaption{font-size:11.5px;color:var(--ink-3)}

/* ================= past sessions ================= */
.pastgrid{display:grid;gap:14px;grid-template-columns:repeat(auto-fill,minmax(330px,1fr))}
.pastcard{
  background:var(--panel);border:1px solid var(--line-soft);border-radius:var(--r-lg);
  padding:16px 18px;display:flex;flex-direction:column;gap:12px;position:relative;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.028);overflow:hidden;
}
:root[data-theme="light"] .pastcard{box-shadow:0 1px 2px rgba(45,30,80,.05)}
.pastcard::before{content:"";position:absolute;inset-inline-start:0;top:0;bottom:0;width:3px;
  background:var(--line)}
.pastcard.has::before{background:linear-gradient(180deg,var(--mint),transparent)}
.pastcard-top{display:flex;align-items:flex-start;gap:12px}
.pastcard h4{font-size:14.5px;font-weight:600}
.pastdate{
  width:46px;flex:0 0 auto;text-align:center;border-radius:12px;padding:6px 0;
  background:var(--chip);border:1px solid var(--line-soft);line-height:1.1;
}
.pastdate b{display:block;font-family:var(--display);font-size:17px;font-weight:700;
  font-variant-numeric:tabular-nums}
.pastdate span{display:block;font-size:10.5px;color:var(--ink-3);text-transform:lowercase}
.pastnote{margin:0;font-size:12.5px;color:var(--ink-2);line-height:1.6;white-space:pre-wrap;
  max-height:5.2em;overflow:hidden;position:relative}
.pastfile{display:flex;align-items:center;gap:8px;padding-top:11px;
  border-top:1px solid var(--line-soft);flex-wrap:wrap}
.filechip a,.filechip{text-decoration:none;color:inherit}
a.filechip:hover{border-color:var(--violet);color:var(--ink)}

/* the handout as students see it */
.handout{display:inline-flex;align-items:center;gap:10px;padding:9px 13px;border-radius:12px;
  background:var(--violet-wash);border:1px solid var(--violet-deep);color:var(--ink);
  font-size:13px;text-decoration:none;margin-top:8px}
.handout:hover{background:var(--btn-hover);text-decoration:none}
.handout svg{color:var(--violet)}
.handout b{font-weight:600}

/* =====================================================================
   Hierarchy pass — structure comes from rhythm and one loud surface,
   not from wrapping everything in another box.
   ===================================================================== */

:root{
  --t-xs:11.5px; --t-sm:12.5px; --t-base:14px; --t-md:15px;
  --t-lg:17px; --t-xl:22px; --t-2xl:28px;
}

/* section heading that lives outside a card */
.sechead{display:flex;align-items:baseline;gap:12px;margin:28px 0 14px;flex-wrap:wrap}
.sechead:first-child{margin-top:0}
.sechead h2{font-size:var(--t-lg);font-weight:600;letter-spacing:-.02em}
.sechead .count{font-size:var(--t-sm);color:var(--ink-3);font-variant-numeric:tabular-nums}
.sechead .grow{flex:1}
.sechead .note{font-size:var(--t-sm);color:var(--ink-3)}

/* the one loud surface per page */
.hero{
  position:relative;border-radius:var(--r-xl);padding:22px 24px;overflow:hidden;
  background:
    radial-gradient(620px 260px at 88% -40%,rgba(166,107,255,.22),transparent 70%),
    linear-gradient(135deg,rgba(166,107,255,.10),transparent 58%),
    var(--panel);
  border:1px solid var(--violet-deep);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.05);
}
:root[data-theme="light"] .hero{
  background:
    radial-gradient(620px 260px at 88% -40%,rgba(122,63,228,.12),transparent 70%),
    linear-gradient(135deg,rgba(122,63,228,.07),transparent 58%),
    #fff;
  border-color:var(--violet-deep);
  box-shadow:0 2px 10px rgba(63,28,134,.07);
}
.hero-top{display:flex;align-items:flex-start;gap:14px;flex-wrap:wrap;margin-bottom:16px}
.hero-top h2{font-size:var(--t-xl);font-weight:700;letter-spacing:-.025em}
.hero-top .when{font-size:var(--t-sm);color:var(--ink-3);margin-top:3px}
.hero-empty{display:flex;align-items:center;gap:14px;padding:6px 0 2px;flex-wrap:wrap;width:100%}
.hero-empty > .grow{min-width:160px}
.hero-empty .ic{width:42px;height:42px;border-radius:13px;display:grid;place-items:center;
  background:var(--violet-wash);color:var(--violet);flex:0 0 auto}

/* today's teaching, as blocks you can scan in one pass */
.tstrip{display:flex;gap:10px;overflow-x:auto;padding-bottom:4px;scrollbar-width:thin}
.tblock{
  flex:0 0 auto;min-width:196px;max-width:260px;border-radius:var(--r);padding:12px 14px;
  background:var(--panel-2);border:1px solid var(--line);display:flex;flex-direction:column;gap:7px;
}
:root[data-theme="light"] .tblock{background:#fff}
.tblock .hh{font-family:var(--mono);font-size:var(--t-base);font-weight:600;
  font-variant-numeric:tabular-nums;unicode-bidi:plaintext}
.tblock .ti{font-size:var(--t-sm);font-weight:500;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.tblock .who{font-size:var(--t-xs);color:var(--ink-3);overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.tblock.live{border-color:var(--rose);background:var(--rose-wash)}
.tblock.done{opacity:.62}
.tblock .row{margin-top:auto}

/* "needs you" — only rendered when it is actually true */
.needs{display:flex;gap:9px;flex-wrap:wrap;margin-bottom:18px}
.need{
  display:inline-flex;align-items:center;gap:9px;padding:9px 14px;border-radius:30px;
  background:var(--panel);border:1px solid var(--line-soft);cursor:pointer;color:var(--ink);
  font-size:var(--t-sm);transition:border-color .15s,background .15s;
}
.need:hover{border-color:var(--violet);background:var(--hover)}
.need b{font-family:var(--display);font-weight:700;font-variant-numeric:tabular-nums}
.need .dot{width:7px;height:7px;border-radius:50%;flex:0 0 auto}
.need.warn .dot{background:var(--amber)}
.need.bad .dot{background:var(--rose)}
.need.info .dot{background:var(--violet)}
.need.ok .dot{background:var(--mint)}

/* a sparkline is information, so it earns its place in a stat tile */
.stat .spark{margin-top:10px;display:block;width:100%;height:26px;overflow:visible}
.stat .spark .ln{fill:none;stroke:var(--violet);stroke-width:1.8;stroke-linecap:round;
  stroke-linejoin:round}
.stat .spark .ar{fill:var(--violet);opacity:.13}
.stat .spark .pt{fill:var(--violet)}
.stat.lead{grid-column:span 2}
@media(max-width:620px){.stat.lead{grid-column:span 2}}

/* clickable rows say so */
.lrow.link .go{color:var(--ink-3);display:inline-flex;transition:transform .15s,color .15s}
.lrow.link:hover .go{color:var(--violet);transform:translateX(3px)}
[dir="rtl"] .lrow.link:hover .go{transform:translateX(-3px)}
[dir="rtl"] .lrow.link .go svg{transform:scaleX(-1)}

/* breakdown bars */
.bd-row{display:flex;align-items:center;gap:12px;padding:9px 0}
.bd-row + .bd-row{border-top:1px solid var(--line-soft)}
.bd-row .nm{width:92px;flex:0 0 auto;font-size:var(--t-sm)}
.bd-row .bars{flex:1;display:flex;flex-direction:column;gap:5px;min-width:60px}
.bd-row .bars span{height:7px;border-radius:20px;background:var(--track);overflow:hidden;
  display:block}
.bd-row .bars i{display:block;height:100%;border-radius:20px}
.bd-row .bars i.a{background:var(--mint)}
.bd-row .bars i.b{background:var(--violet)}
.bd-row .val{width:112px;text-align:end;font-family:var(--mono);font-size:var(--t-sm);
  font-variant-numeric:tabular-nums;unicode-bidi:plaintext;line-height:1.45}
.bd-row .val .t2{color:var(--ink-3);font-size:var(--t-xs)}

/* empty states should point somewhere */
.empty b{font-size:var(--t-base)}

/* ---- phone ---- */
@media(max-width:620px){
  /* a 69px bar compares nothing: give the bars the full width and put the
     label and figures on their own line */
  .bd-row{flex-wrap:wrap;gap:6px 12px}
  .bd-row .nm{width:auto;flex:1 1 auto;font-weight:500}
  .bd-row .val{width:auto;flex:0 0 auto;text-align:end}
  .bd-row .bars{flex:1 1 100%;order:3;min-width:100%}

  .hero{padding:18px 16px}
  .hero-top{gap:12px;margin-bottom:14px}
  /* the heading must claim its own row, or a pill beside it squeezes the
     date down to one word per line */
  /* Direct child only: an inner .grow (the empty-state row) still has to
     share its line with the button beside it. */
  .hero-top > .grow{flex:1 1 100%;min-width:100%}
  .hero-top h2{font-size:20px}
  .hero .hero-num{font-size:22px}
  .tblock{min-width:180px}
  .needs{gap:7px}
  .need{padding:8px 12px}
  .sechead{margin:22px 0 12px}
  .sechead h2{font-size:var(--t-md)}
  .pastgrid,.recgrid{grid-template-columns:1fr}
  .portal-h h1{font-size:20px}
  .card{padding:16px}
  .cardhead{padding:14px 16px}
  .tbl th,.tbl td{padding:11px 14px}
  .lrow{padding:11px 16px}
}

@media(max-width:620px){
  /* let a session title use two lines rather than vanish into an ellipsis */
  .lrow .nm{white-space:normal;display:-webkit-box;-webkit-line-clamp:2;
    -webkit-box-orient:vertical;overflow:hidden}
  .lrow .mt2{white-space:normal}
  .lrow{gap:10px}
}
@media(max-width:480px){
  /* the label is worth less than the content it covers */
  .fab{padding:13px;border-radius:50%}
  .fab .lbl{display:none}
  .fab svg{width:18px;height:18px}
}

@media(max-width:620px){
  /* typing room matters more than the word "Send" */
  .composer .btn .lbl{display:none}
  .composer .btn{padding:9px 12px}
  .composer{padding:10px 12px;gap:8px}
}

/* right-click is desktop-only advice */
.calnav-title{min-width:190px;text-align:center;flex:0 1 auto}
@media(max-width:620px){
  /* On a phone the month name takes the first line to itself; the arrows,
     Today and the hint share the second. */
  .calnav-title{min-width:0;flex:1 1 100%;order:-1;text-align:start;font-size:17px}
}
.taphint{display:none}
@media(max-width:620px){
  .calhint{display:none}
  .taphint{display:inline}
  .day{cursor:pointer}
}

/* ================= session overlay ================= */
.filepane{
  border:1px solid var(--line);border-radius:var(--r);overflow:hidden;background:var(--input);
  height:min(56vh,430px);display:flex;
}
.filepane iframe{border:0;width:100%;height:100%;background:#fff}
.filepane img{width:100%;height:100%;object-fit:contain;background:var(--out)}
.filemeta{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:10px}
.filemeta .name{font-size:12.5px;color:var(--ink-2);flex:1;min-width:0;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.sessionrow-link{cursor:pointer}
.sessionrow-link:hover{background:var(--hover)}
@media(max-width:620px){ .filepane{height:min(46vh,320px)} }

/* ================= announcements ================= */
/* One notice, whole and readable — not a card in a wall of cards. A pinned
   one wears a stripe on its leading edge rather than a different colour. */
.anngrid{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(340px,1fr));
  margin-bottom:26px}
.announce{position:relative;overflow:hidden}
.announce h3{font-size:15.5px;font-weight:600;letter-spacing:-.015em;min-width:0}
.announce .notebox{margin-top:2px}
.announce.pinned::before{
  content:"";position:absolute;inset-block:0;inset-inline-start:0;width:3px;
  background:var(--violet);
}
.announce.pinned{padding-inline-start:23px}
.videopane{
  margin-top:12px;border-radius:14px;overflow:hidden;background:#000;
  aspect-ratio:16/9;border:1px solid var(--line);
}
.videopane iframe{width:100%;height:100%;border:0;display:block}
.filechip.mt{margin-top:12px}
[lang="ar"] .announce h3{letter-spacing:0}

/* =====================================================================
   Motion
   Four moments, not forty: a page settling after you navigate, bars
   growing from their axis the first time they are drawn, a badge noticing
   it went up, and the drawer. Everything here moves only `transform` and
   `opacity`, so it runs on the compositor and never triggers layout.
   Nothing loops, nothing waits on JavaScript, and every rule is dropped
   for anyone who asked their system for less motion.
   ===================================================================== */
@keyframes settle{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
.page.enter,.portal-page.enter{animation:settle .26s var(--ease) both}

@keyframes rise{from{transform:scaleY(0)}to{transform:scaleY(1)}}
.chart.rise .bar-r{
  transform-box:fill-box;transform-origin:bottom;
  animation:rise .5s var(--ease) both;
}
/* a hair of stagger so the series reads left to right, capped at 8 */
.chart.rise .bar-r:nth-child(2){animation-delay:.03s}
.chart.rise .bar-r:nth-child(3){animation-delay:.06s}
.chart.rise .bar-r:nth-child(4){animation-delay:.09s}
.chart.rise .bar-r:nth-child(5){animation-delay:.12s}
.chart.rise .bar-r:nth-child(6){animation-delay:.15s}
.chart.rise .bar-r:nth-child(7){animation-delay:.18s}
.chart.rise .bar-r:nth-child(n+8){animation-delay:.21s}

@keyframes fill{from{transform:scaleX(0)}to{transform:scaleX(1)}}
.bar span{transform-origin:left;animation:fill .55s var(--ease) both}
[dir="rtl"] .bar span{transform-origin:right}

@keyframes notice{0%{transform:scale(.4);opacity:0}60%{transform:scale(1.15)}100%{transform:none;opacity:1}}
.iconbtn .count{animation:notice .3s var(--press) both}

@media(prefers-reduced-motion:reduce){
  .page.enter,.portal-page.enter,.chart.rise .bar-r,.bar span,.iconbtn .count{
    animation:none !important;
  }
}

/* Three dots that keep time while a student waits to be let in. */
.waiting{display:inline-flex;gap:4px;margin-inline-start:8px;vertical-align:middle}
.waiting i{width:5px;height:5px;border-radius:50%;background:currentColor;opacity:.35;
  animation:waitdot 1.2s ease-in-out infinite}
.waiting i:nth-child(2){animation-delay:.18s}
.waiting i:nth-child(3){animation-delay:.36s}
@keyframes waitdot{0%,100%{opacity:.25;transform:translateY(0)}
  50%{opacity:1;transform:translateY(-3px)}}

/* A link meant to be copied: readable, selectable, one button away. */
.linkbox{
  display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:12px;
  padding:10px 12px;border-radius:12px;background:var(--input);
  border:1px solid var(--line);
}
.linkbox code{
  flex:1;min-width:0;font-family:var(--mono);font-size:12px;color:var(--ink-2);
  overflow-x:auto;white-space:nowrap;scrollbar-width:none;
}
.linkbox code::-webkit-scrollbar{display:none}

/* ================= the tariff, as three cards ================= */
/* A student picks a format, not a number. The card carries the figure they
   have to send, so the amount lives here and nowhere else in the portal. */
.packgrid{
  display:grid;gap:10px;grid-template-columns:repeat(auto-fit,minmax(158px,1fr));
  margin-top:4px;
}
.packcard{
  display:flex;flex-direction:column;gap:4px;text-align:start;cursor:pointer;
  padding:14px 15px;border-radius:16px;border:1px solid var(--line);
  background:var(--panel-2);color:var(--ink);position:relative;
  transition:border-color .18s var(--ease),background .18s var(--ease),
    transform .14s var(--press);
}
.packcard:hover{border-color:var(--violet-deep);background:var(--hover)}
.packcard:active{transform:scale(.98)}
.packcard.on{
  border-color:var(--violet);background:var(--violet-wash);
  box-shadow:0 0 0 1px var(--violet);
}
.packtop{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.packtop b{font-family:var(--display);font-size:14px;font-weight:600;flex:1}
.packprice{font-size:20px;font-weight:700;letter-spacing:-.028em;line-height:1.2}
.packcard.on .packprice{color:var(--violet)}
.packmeta{font-size:12.5px;color:var(--ink-2)}
.packmeta .freebit{color:var(--mint);font-weight:600}
.packnote{font-size:11.5px;color:var(--ink-3);line-height:1.45}
.packcount{max-width:200px;margin-top:12px}
.paytotal{
  display:flex;align-items:baseline;justify-content:space-between;gap:12px;
  margin-top:14px;padding-top:12px;border-top:1px solid var(--line-soft);
  font-size:13px;color:var(--ink-2);
}
.paytotal b{font-size:19px;color:var(--ink);font-weight:700;letter-spacing:-.02em}
[lang="ar"] .packprice,[lang="ar"] .paytotal b{letter-spacing:0}

/* =====================================================================
   Apple pass
   Four ideas borrowed from macOS and iOS, applied on top of the theme:
   translucent material over a tinted ground, one continuous corner scale,
   type that tightens as it grows, and controls that answer a press.
   Nothing here changes a colour — only surface, shape, weight and motion.
   ===================================================================== */

:root{
  /* Shadows Apple's way: a wide, very soft pool plus a hairline contact edge */
  --e1:0 1px 2px rgba(0,0,0,.28), 0 0 0 .5px rgba(255,255,255,.045);
  --e2:0 6px 18px -8px rgba(0,0,0,.55), 0 0 0 .5px rgba(255,255,255,.05);
  --e3:0 28px 64px -28px rgba(0,0,0,.85), 0 2px 10px -4px rgba(0,0,0,.5);
  --shadow:var(--e3);
  --material:saturate(180%) blur(30px);
  --ease:cubic-bezier(.32,.72,0,1);      /* the sheet curve */
  --press:cubic-bezier(.22,1,.36,1);
}
:root[data-theme="light"]{
  --e1:0 1px 2px rgba(45,30,80,.07), 0 0 0 .5px rgba(45,30,80,.05);
  --e2:0 8px 20px -10px rgba(45,30,80,.20), 0 0 0 .5px rgba(45,30,80,.06);
  --e3:0 28px 64px -30px rgba(45,30,80,.32), 0 2px 10px -6px rgba(45,30,80,.16);
}

/* ---- material: bars float above the page instead of sitting on it ---- */
.topbar,.stopbar{
  backdrop-filter:var(--material);-webkit-backdrop-filter:var(--material);
  border-bottom-color:transparent;
  box-shadow:0 .5px 0 var(--line-soft);
}
.rail,.portal-rail{backdrop-filter:var(--material);-webkit-backdrop-filter:var(--material)}

/* ---- shape: one corner scale, larger as the surface grows ---- */
.btn{border-radius:11px}
.btn.sm{border-radius:9px}
.iconbtn{border-radius:11px}
input[type=text],input[type=email],input[type=date],input[type=time],input[type=number],
input[type=url],input[type=password],input[type=datetime-local],select,textarea{border-radius:11px}
.card,.stat,.cal{border-radius:20px}
.modal{border-radius:26px}
.popover{border-radius:18px}
.toast{border-radius:14px}
.card,.stat{box-shadow:var(--e1)}
:root[data-theme="light"] .card,:root[data-theme="light"] .stat{box-shadow:var(--e1)}
.modal{box-shadow:var(--e3)}

/* ---- type: the bigger it is, the tighter it sets ---- */
.topbar h1{font-size:22px;letter-spacing:-.026em}
.sechead h2{letter-spacing:-.024em}
.hero h2,.hero-num{letter-spacing:-.032em}
.stat .val{letter-spacing:-.02em}
[lang="ar"] .topbar h1,[lang="ar"] .sechead h2,[lang="ar"] .hero h2,
[lang="ar"] .hero-num,[lang="ar"] .stat .val{letter-spacing:0}

/* Sentence case reads as a label; tracked-out capitals read as a shout.
   Apple stopped shouting in its sidebars and tables a decade ago. */
.navgroup,.tbl th,.calhead div,.sub-lbl,.soon{
  text-transform:none;letter-spacing:0;
}
.navgroup{font-size:12px;font-weight:600;color:var(--ink-3);padding:18px 10px 6px}
.tbl th{font-size:12px;font-weight:500}
.calhead div{font-size:12px;font-weight:500}
.sub-lbl{font-size:12px;font-weight:600;color:var(--ink-2)}
.soon{font-size:11.5px}

/* ---- controls: a segmented control is a recessed track with a raised pill ---- */
.seg{background:var(--track);border:0;padding:2px;border-radius:11px;gap:0}
.seg button{
  border-radius:9px;padding:6px 13px;font-weight:500;color:var(--ink-2);
  transition:background .2s var(--ease),color .2s var(--ease),box-shadow .2s var(--ease);
}
.seg button.on{background:var(--panel);color:var(--ink);box-shadow:var(--e1);font-weight:600}
.seg button:active{transform:scale(.97)}

/* ---- press: everything tappable answers with a small, quick squeeze ---- */
.btn,.iconbtn,.navitem,.seg button,.lrow,.xbtn{
  transition:background .18s var(--ease),border-color .18s var(--ease),
    color .18s var(--ease),transform .14s var(--press),box-shadow .18s var(--ease);
}
.btn:active,.iconbtn:active,.xbtn:active{transform:scale(.96)}
.btn:active{transform:scale(.96)}          /* replaces the old 1px drop */
.lrow:active,.navitem:active{transform:scale(.995)}
.btn.primary{box-shadow:var(--e2),inset 0 1px 0 rgba(255,255,255,.2)}

/* ---- focus: a soft ring, not a hard box ---- */
:focus-visible{outline:none;box-shadow:0 0 0 4px var(--violet-wash),0 0 0 1.5px var(--violet)}
input:focus,select:focus,textarea:focus{
  border-color:var(--violet-dim);box-shadow:0 0 0 4px var(--violet-wash)}

/* ---- grouped lists: the separator starts where the text starts ---- */
.card.pad0 .lrow{border-bottom:0;position:relative}
.card.pad0 .lrow + .lrow::before{
  content:"";position:absolute;top:0;inset-inline-start:56px;inset-inline-end:0;
  height:1px;background:var(--line-soft);
}
.card.pad0 .lrow:first-child + .lrow::before{inset-inline-start:56px}

/* ---- sheets: scale up from behind the scrim, the way a sheet does ---- */
.scrim{backdrop-filter:saturate(160%) blur(14px);-webkit-backdrop-filter:saturate(160%) blur(14px)}
@keyframes pop{
  from{opacity:0;transform:translateY(10px) scale(.965)}
  to{opacity:1;transform:none}
}
.modal{animation:pop .34s var(--ease)}
.popover{animation:pop .22s var(--ease);box-shadow:var(--e3)}

/* ---- a press should never become a wobble for someone who asked for calm ---- */
@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms !important;transition-duration:.01ms !important}
  .btn:active,.iconbtn:active,.seg button:active,.lrow:active,.navitem:active{transform:none}
}
