/* ------------------------------------------------------------------ fonts
   Plus Jakarta Sans, woff2, LATIN SUBSET ONLY (self-hosted, no runtime CDN).
   Arabic / Devanagari / Malayalam fall through to the system stack in --font.
   ------------------------------------------------------------------------ */
@font-face{font-family:"Plus Jakarta Sans";font-style:normal;font-weight:400;font-display:swap;src:url(/assets/fonts/plus-jakarta-sans-latin-400.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:"Plus Jakarta Sans";font-style:normal;font-weight:500;font-display:swap;src:url(/assets/fonts/plus-jakarta-sans-latin-500.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:"Plus Jakarta Sans";font-style:normal;font-weight:600;font-display:swap;src:url(/assets/fonts/plus-jakarta-sans-latin-600.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:"Plus Jakarta Sans";font-style:normal;font-weight:700;font-display:swap;src:url(/assets/fonts/plus-jakarta-sans-latin-700.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:"Plus Jakarta Sans";font-style:normal;font-weight:800;font-display:swap;src:url(/assets/fonts/plus-jakarta-sans-latin-800.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}

/* ==========================================================================
   FILE      public/assets/css/app.css
   DESIGN    Edumia — Direction A · "Clarity". Calm, airy, content-first:
             persistent light sidebar + generous whitespace. Lowest-risk,
             highest-familiarity for school administrators.
   PURPOSE   Single application stylesheet: semantic colour tokens + shell +
             components for every screen in the tenant app.
   TOKENS    Contract 01-CONTRACT.md S1. Component rules must reference
             var(--c-*) only; a tenant override in <style id="tenant-theme">
             (emitted later in <head>) re-colours the whole app.
   ALIASES   S1.2 legacy names are aliased to the semantic tokens because the
             older screens are written against them. Do not remove in Phase 1.
   NOTES     Hand-written CSS, logical properties only (RTL-safe), zero build
             step, zero JS. Dormant dark theme at the foot of this file.
   LAST UPDATED: 2026-09-13
   ========================================================================== */

:root{
  /* ---- semantic tokens (Edumia defaults) ---- */
  --c-brand:#4C7430; --c-brand-strong:#4C7430; --c-brand-hover:#395724; --c-brand-mark:#689F42;
  --c-brand-50:#F0F5EC; --c-brand-100:#E4EEDD; --c-brand-200:#D2E2C6;
  --c-brand-600:#5F913C; --c-brand-700:#395724; --c-brand-800:#263A18;
  --c-accent:#885704; --c-accent-strong:#885704;
  --c-surface:#F7F9FB; --c-surface-2:#FFFFFF; --c-surface-3:#F1F5F9; --c-surface-hover:#FBFCFD;
  --c-text:#0F172A; --c-text-2:#334155; --c-text-muted:#64748B; --c-text-faint:#94A3B8;
  --c-border:#E4E9EF; --c-border-strong:#D3DAE3; --c-focus:#4C7430;
  --c-success:#15803D; --c-warning:#B45309; --c-danger:#B91C1C; --c-info:#1D4ED8;
  --c-success-50:#F0FDF4; --c-success-100:#BBF7D0;
  --c-warning-50:#FFFBEB; --c-warning-100:#FEF3C7; --c-warning-400:#FBBF24;
  --c-danger-50:#FEF2F2; --c-danger-100:#FECACA;
  --c-info-50:#EFF6FF; --c-info-100:#BFDBFE;
  /* ---- decorative brand gradient stops (login aside) ---- */
  --c-brand-sheen:#75B44B; --c-brand-deep:#2B421B; --c-brand-base:#1F2F14;
  /* ---- geometry / elevation / motion / type ---- */
  --radius-sm:8px; --radius:12px; --radius-lg:18px; --radius-pill:999px;
  --shadow-1:0 1px 2px rgba(15,23,42,.05);
  --shadow-2:0 6px 20px -8px rgba(15,23,42,.14), 0 1px 2px rgba(15,23,42,.05);
  --shadow-3:0 24px 48px -16px rgba(15,23,42,.18);
  --sidebar-w:268px;
  --ease:cubic-bezier(.4,0,.2,1);
  --font:"Plus Jakarta Sans",system-ui,-apple-system,"Segoe UI",Roboto,"Noto Sans Arabic",sans-serif;
  --font-mono:ui-monospace,SFMono-Regular,Menlo,Consolas,"Liberation Mono",monospace;
  /* ---- legacy aliases (S1.2) ---- */
  --brand:var(--c-brand); --brand-mark:var(--c-brand-mark);
  --brand-600:var(--c-brand-600); --brand-700:var(--c-brand-700); --brand-800:var(--c-brand-800);
  --brand-050:var(--c-brand-50); --brand-100:var(--c-brand-100); --brand-200:var(--c-brand-200);
  --ink:var(--c-text); --ink-2:var(--c-text-2); --muted:var(--c-text-muted); --faint:var(--c-text-faint);
  --line:var(--c-border); --line-2:var(--c-surface-3); --bg:var(--c-surface); --card:var(--c-surface-2);
  --amber:var(--c-warning); --amber-050:var(--c-warning-50); --amber-100:var(--c-warning-100);
  --green:var(--c-success); --green-050:var(--c-success-50);
  --red:var(--c-danger); --red-050:var(--c-danger-50);
  --blue:var(--c-info); --blue-050:var(--c-info-50);
  --r-sm:var(--radius-sm); --r:var(--radius); --r-lg:var(--radius-lg); --r-pill:var(--radius-pill);
  --sh-1:var(--shadow-1); --sh-2:var(--shadow-2); --sh-3:var(--shadow-3);
}

*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{font-family:var(--font); color:var(--c-text); background:var(--c-surface); font-size:15px; line-height:1.55; -webkit-font-smoothing:antialiased;}
a{color:inherit;text-decoration:none}
h1,h2,h3,h4{margin:0;font-weight:700;letter-spacing:-.015em;line-height:1.25}
h1{font-size:1.45rem}
h2{font-size:1.05rem}
h3{font-size:.9rem}
hr{border:0;border-top:1px solid var(--c-border);margin:0}

/* ---------------------------------------------------------------- layout */
.shell{display:grid;grid-template-columns:var(--sidebar-w) 1fr;min-height:100vh}

/* ---------------------------------------------------------------- sidebar */
.sidebar{background:var(--c-surface-2); border-inline-end:1px solid var(--c-border); padding:1.15rem .85rem 2rem; position:sticky; top:0; height:100vh; overflow-y:auto; display:flex; flex-direction:column; gap:1.25rem;}
.brand-row{display:flex;align-items:center;gap:.65rem;padding:.15rem .55rem 0}
.brand-mark{width:36px; height:36px; border-radius:10px; flex:none; background:linear-gradient(150deg,var(--c-brand),var(--c-brand-700)); display:grid; place-items:center; color:#fff; font-weight:800; font-size:1.05rem; box-shadow:0 4px 10px -3px rgba(76,116,48,.45);}
.brand-text{display:flex;flex-direction:column;line-height:1.15;min-width:0}
.brand-text b{font-size:1.02rem;letter-spacing:-.02em}
.brand-text span{font-size:.7rem;color:var(--c-text-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

.org-chip{display:flex; align-items:center; gap:.6rem; background:var(--c-brand-50); border:1px solid var(--c-brand-100); border-radius:var(--radius); padding:.55rem .65rem;}
.org-chip .dot{width:8px;height:8px;border-radius:50%;background:var(--c-brand);flex:none}
.org-chip div{min-width:0}
.org-chip b{display:block;font-size:.82rem;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.org-chip small{font-size:.7rem;color:var(--c-text-muted)}

.nav-group{display:flex;flex-direction:column;gap:.15rem}
.nav-label{font-size:.68rem; font-weight:700; text-transform:uppercase; letter-spacing:.09em; color:var(--c-text-faint); padding:.2rem .6rem .45rem;}
.nav-item{display:flex; align-items:center; gap:.65rem; padding:.5rem .6rem; border-radius:10px; color:var(--c-text-2); font-size:.875rem; font-weight:500; transition:background 160ms var(--ease),color 160ms var(--ease); position:relative;}
.nav-item svg{--icon-stroke:1.7;width:18px;height:18px;flex:none;stroke:currentColor;fill:none;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round;color:var(--c-text-faint);transition:color 160ms var(--ease)}
.nav-item:hover{background:var(--c-surface-3);color:var(--c-text)}
.nav-item:hover svg{color:var(--c-text-2)}
.nav-item.active{background:var(--c-brand-50);color:var(--c-brand-700);font-weight:600}
.nav-item.active svg{color:var(--c-brand-700)}
.nav-item .count{margin-inline-start:auto; font-size:.7rem; font-weight:700; background:var(--c-surface-3); color:var(--c-text-muted); border-radius:var(--radius-pill); padding:.05rem .4rem; min-width:1.35rem; text-align:center;}
.nav-item.active .count{background:var(--c-brand-100);color:var(--c-brand-700)}
.nav-item .count.alert{background:var(--c-danger-50);color:var(--c-danger)}

.sidebar-foot{margin-top:auto;padding:.75rem .6rem 0;border-top:1px solid var(--c-surface-3)}
.licence-pill{display:flex; align-items:center; gap:.5rem; font-size:.75rem; color:var(--c-text-muted); padding:.35rem 0;}
.licence-pill .dot{width:7px;height:7px;border-radius:50%;background:var(--c-success);flex:none;box-shadow:0 0 0 3px var(--c-success-50)}

/* ---------------------------------------------------------------- canvas */
.canvas{display:flex;flex-direction:column;min-width:0}

.topbar{display:flex; align-items:center; gap:1rem; padding:.7rem 1.5rem; background:rgba(255,255,255,.85); backdrop-filter:blur(8px); border-block-end:1px solid var(--c-border); position:sticky; top:0; z-index:20;}
.crumb{display:flex;align-items:center;gap:.45rem;font-size:.8rem;color:var(--c-text-muted);min-width:0}
.crumb b{color:var(--c-text);font-weight:600}
.crumb .sep{color:var(--c-text-faint)}

.search{margin-inline-start:auto; display:flex; align-items:center; gap:.5rem; background:var(--c-surface); border:1px solid var(--c-border); border-radius:var(--radius-pill); padding:.4rem .8rem; width:min(300px,32vw); color:var(--c-text-muted); font-size:.82rem; cursor:text;}
.search svg{width:15px;height:15px;stroke:currentColor;fill:none;stroke-width:1.9;stroke-linecap:round}
.search kbd{margin-inline-start:auto; font-family:inherit; font-size:.68rem; background:var(--c-surface-2); border:1px solid var(--c-border); border-radius:5px; padding:.05rem .3rem; color:var(--c-text-faint);}

.icon-btn{width:34px; height:34px; border-radius:9px; border:1px solid var(--c-border); background:var(--c-surface-2); display:grid; place-items:center; cursor:pointer; color:var(--c-text-2); position:relative; transition:background 160ms var(--ease);}
.icon-btn:hover{background:var(--c-surface-3)}
.icon-btn svg{width:17px;height:17px;stroke:currentColor;fill:none;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.icon-btn .badge{position:absolute; top:-4px; inset-inline-end:-4px; background:var(--c-danger); color:#fff; font-size:.6rem; font-weight:700; border-radius:var(--radius-pill); padding:.05rem .28rem; border:2px solid var(--c-surface-2);}

.user-chip{display:flex; align-items:center; gap:.55rem; border:1px solid var(--c-border); border-radius:var(--radius-pill); padding:.22rem .7rem .22rem .22rem; background:var(--c-surface-2); cursor:pointer;}
.avatar{width:29px; height:29px; border-radius:50%; flex:none; background:var(--c-brand-50); color:var(--c-brand-700); display:grid; place-items:center; font-size:.72rem; font-weight:700; border:1px solid var(--c-brand-100);}
.user-chip b{font-size:.8rem;font-weight:600;display:block;line-height:1.15}
.user-chip small{font-size:.68rem;color:var(--c-text-muted);display:block;line-height:1.15}

/* ---------------------------------------------------------------- content */
.content{padding:1.5rem;max-width:1400px;width:100%;min-width:0}

.page-head{display:flex;flex-wrap:wrap;align-items:flex-end;gap:1rem;margin-block-end:1.25rem}
.page-head .title{min-width:0}
.page-head p{margin:.3rem 0 0;color:var(--c-text-muted);font-size:.85rem}
.page-actions{margin-inline-start:auto;display:flex;gap:.5rem;flex-wrap:wrap}

/* ---------------------------------------------------------------- buttons */
.btn{display:inline-flex; align-items:center; gap:.45rem; padding:.55rem .95rem; border-radius:10px; border:1px solid transparent; background:var(--c-brand); color:#fff; font:inherit; font-size:.85rem; font-weight:600; cursor:pointer; box-shadow:0 1px 2px rgba(76,116,48,.28); transition:background 160ms var(--ease),transform 160ms var(--ease),box-shadow 160ms var(--ease); white-space:nowrap;}
.btn:hover{background:var(--c-brand-700);box-shadow:0 4px 12px -4px rgba(76,116,48,.45)}
.btn:active{transform:translateY(1px)}
.btn svg{--icon-stroke:2;width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.btn-secondary{background:var(--c-surface-2);color:var(--c-text-2);border-color:var(--c-border);box-shadow:var(--shadow-1)}
.btn-secondary:hover{background:var(--c-surface);border-color:var(--c-border-strong)}
.btn-ghost{background:transparent;color:var(--c-text-muted);box-shadow:none}
.btn-ghost:hover{background:var(--c-surface-3);color:var(--c-text)}
.btn-sm{padding:.38rem .7rem;font-size:.8rem;border-radius:9px}

/* ---------------------------------------------------------------- cards */
.card{background:var(--c-surface-2); border:1px solid var(--c-border); border-radius:var(--radius-lg); box-shadow:var(--shadow-1);}
.card-head{display:flex; align-items:center; gap:.75rem; padding:1rem 1.15rem .85rem;}
.card-head h2{font-size:.95rem}
.card-head .sub{font-size:.78rem;color:var(--c-text-muted);font-weight:400;margin-inline-start:.4rem}
.card-head .right{margin-inline-start:auto;display:flex;gap:.4rem;align-items:center}
.card-body{padding:0 1.15rem 1.15rem}

/* ---------------------------------------------------------------- KPI row */
.kpi-row{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));margin-block-end:1rem}
.kpi{background:var(--c-surface-2); border:1px solid var(--c-border); border-radius:var(--radius-lg); padding:1rem 1.15rem; box-shadow:var(--shadow-1); position:relative; overflow:hidden;}
.kpi-top{display:flex;align-items:center;gap:.5rem;color:var(--c-text-muted);font-size:.78rem;font-weight:600;text-transform:uppercase;letter-spacing:.05em}
.kpi-top .ico{width:28px; height:28px; border-radius:8px; background:var(--c-brand-50); color:var(--c-brand-700); display:grid; place-items:center; flex:none;}
.kpi-top .ico svg{width:15px;height:15px;stroke:currentColor;fill:none;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round}
.kpi-val{font-size:1.7rem;font-weight:800;letter-spacing:-.03em;margin:.5rem 0 .1rem;line-height:1.1}
.kpi-val small{font-size:.9rem;font-weight:600;color:var(--c-text-muted);letter-spacing:0}
.kpi-foot{font-size:.78rem;color:var(--c-text-muted);display:flex;align-items:center;gap:.35rem}
.trend{display:inline-flex;align-items:center;gap:.2rem;font-weight:700;font-size:.75rem}
.trend.up{color:var(--c-success)}
.trend.down{color:var(--c-danger)}
.trend svg{--icon-stroke:2.4;width:12px;height:12px;stroke:currentColor;fill:none;stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round}

/* ---------------------------------------------------------------- grid */
.grid-2{display:grid;gap:1rem;grid-template-columns:1.55fr 1fr;align-items:start}
.grid-3{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));align-items:start}
@media(max-width:1100px){.grid-2{grid-template-columns:1fr}}

/* ---------------------------------------------------------------- chart */
.chart{width:100%;height:200px;display:block}
.bars{display:flex;align-items:flex-end;gap:.9rem;height:180px;padding:.5rem .25rem 0}
.bar-col{flex:1;display:flex;flex-direction:column;align-items:center;gap:.5rem;height:100%;justify-content:flex-end}
.bar{width:100%; max-width:46px; border-radius:7px 7px 3px 3px; background:linear-gradient(180deg,var(--c-brand),var(--c-brand-700)); transition:height 400ms var(--ease),filter 160ms var(--ease); position:relative;}
.bar-col:hover .bar{filter:brightness(1.1)}
.bar.low{background:linear-gradient(180deg,var(--c-warning-400),var(--c-warning))}
.bar-val{font-size:.72rem;font-weight:700;color:var(--c-text-2)}
.bar-lab{font-size:.7rem;color:var(--c-text-muted);white-space:nowrap}

/* donut */
.donut-wrap{display:flex;align-items:center;gap:1.25rem;padding:.25rem 0 .5rem}
.donut{width:132px;height:132px;flex:none;transform:rotate(-90deg)}
.donut circle{fill:none;stroke-width:13;stroke-linecap:round}
.legend{display:flex;flex-direction:column;gap:.6rem;min-width:0}
.legend-row{display:flex;align-items:center;gap:.5rem;font-size:.8rem}
.legend-row .sw{width:10px;height:10px;border-radius:3px;flex:none}
.legend-row b{margin-inline-start:auto;font-variant-numeric:tabular-nums}

/* ---------------------------------------------------------------- table */
table{width:100%;border-collapse:collapse;font-size:.84rem}
th{text-align:start; font-size:.7rem; font-weight:700; text-transform:uppercase; letter-spacing:.06em; color:var(--c-text-faint); padding:.5rem .75rem; border-block-end:1px solid var(--c-border); white-space:nowrap;}
td{padding:.62rem .75rem;border-block-end:1px solid var(--c-surface-3);color:var(--c-text-2);vertical-align:middle}
tbody tr:last-child td{border-block-end:0}
tbody tr{transition:background 140ms var(--ease)}
tbody tr:hover{background:var(--c-surface-hover)}
td.num{text-align:end;font-variant-numeric:tabular-nums;font-weight:600;color:var(--c-text)}
td strong{color:var(--c-text);font-weight:600}
.who-cell{display:flex;align-items:center;gap:.6rem}
.who-cell .avatar{width:30px;height:30px;font-size:.72rem}

/* ---------------------------------------------------------------- badges */
.badge{display:inline-flex; align-items:center; gap:.3rem; font-size:.72rem; font-weight:700; padding:.16rem .5rem; border-radius:var(--radius-pill); background:var(--c-surface-3); color:var(--c-text-muted); white-space:nowrap;}
.badge-ok{background:var(--c-success-50);color:var(--c-success)}
.badge-warn{background:var(--c-warning-50);color:var(--c-warning)}
.badge-danger{background:var(--c-danger-50);color:var(--c-danger)}
.badge-info{background:var(--c-info-50);color:var(--c-info)}
.badge .dot{width:5px;height:5px;border-radius:50%;background:currentColor}

/* ---------------------------------------------------------------- tasks */
.task-list{display:flex;flex-direction:column}
.task{display:flex; align-items:center; gap:.7rem; padding:.7rem .25rem; border-block-end:1px solid var(--c-surface-3);}
.task:last-child{border-block-end:0}
.task .ico{width:32px; height:32px; border-radius:9px; flex:none; display:grid; place-items:center; background:var(--c-brand-50); color:var(--c-brand-700);}
.task .ico.warn{background:var(--c-warning-50);color:var(--c-warning)}
.task .ico.danger{background:var(--c-danger-50);color:var(--c-danger)}
.task .ico svg{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round}
.task-body{min-width:0;flex:1}
.task-body b{display:block;font-size:.84rem;font-weight:600}
.task-body small{font-size:.75rem;color:var(--c-text-muted)}

/* ---------------------------------------------------------------- notices */
.notice{display:flex; align-items:flex-start; gap:.6rem; padding:.7rem .9rem; border-radius:var(--radius); font-size:.83rem; margin:0; border:1px solid transparent;}
.notice svg{--icon-stroke:2;width:16px;height:16px;flex:none;margin-top:.1rem;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.notice-warn{background:var(--c-warning-50);color:var(--c-warning);border-color:var(--c-warning-100)}
.notice-ok{background:var(--c-success-50);color:var(--c-success);border-color:var(--c-success-100)}
.notice-info{background:var(--c-info-50);color:var(--c-info);border-color:var(--c-info-100)}
.notice-danger{background:var(--c-danger-50);color:var(--c-danger);border-color:var(--c-danger-100)}
.notice b{font-weight:700}
.notice a{text-decoration:underline;font-weight:600}

/* ---------------------------------------------------------------- forms */
.field{display:flex;flex-direction:column;gap:.35rem;margin-block-end:.9rem}
.field label{font-size:.8rem;font-weight:600;color:var(--c-text-2)}
.field .hint{font-size:.75rem;color:var(--c-text-muted)}
.field input,.field select{width:100%; padding:.68rem .8rem; border:1px solid var(--c-border); border-radius:10px; font:inherit; font-size:.9rem; background:var(--c-surface-2); color:var(--c-text); transition:border-color 150ms var(--ease),box-shadow 150ms var(--ease);}
.field input::placeholder{color:var(--c-text-faint)}
.field input:focus,.field select:focus{outline:none; border-color:var(--c-brand); box-shadow:0 0 0 3.5px var(--c-brand-50);}
.field-row{display:flex;align-items:center;justify-content:space-between;gap:.5rem;margin-block-end:1.1rem;font-size:.8rem}
.check{display:flex;align-items:center;gap:.45rem;color:var(--c-text-2);cursor:pointer}
.check input{width:15px;height:15px;accent-color:var(--c-brand);margin:0}
.link{color:var(--c-brand-700);font-weight:600;font-size:.8rem}
.link:hover{text-decoration:underline}
.btn-block{width:100%;justify-content:center;padding:.72rem 1rem;font-size:.9rem}

/* ---------------------------------------------------------------- login */
.login-page{min-height:100vh; display:grid; grid-template-columns:1.05fr .95fr; background:var(--c-surface-2);}
@media(max-width:960px){.login-page{grid-template-columns:1fr}}
.login-aside{position:relative; overflow:hidden; background:
    radial-gradient(1100px 620px at -10% 8%,var(--c-brand-sheen) 0%,transparent 58%),
    radial-gradient(760px 560px at 108% 96%,var(--c-brand-deep) 0%,transparent 62%),
    linear-gradient(158deg,var(--c-brand-base) 0%,var(--c-brand-700) 54%,var(--c-brand) 100%); color:#fff; padding:3rem 3.2rem; display:flex; flex-direction:column;}
.login-aside::after{content:""; position:absolute; inset:0; background-image:
    linear-gradient(rgba(255,255,255,.045) 1px,transparent 1px),
    linear-gradient(90deg,rgba(255,255,255,.045) 1px,transparent 1px); background-size:46px 46px; mask-image:radial-gradient(70% 60% at 30% 30%,#000 20%,transparent 100%); pointer-events:none;}
.login-aside>*{position:relative;z-index:1}
.la-brand{display:flex;align-items:center;gap:.7rem}
.la-brand .brand-mark{background:rgba(255,255,255,.16);backdrop-filter:blur(6px);box-shadow:none;border:1px solid rgba(255,255,255,.25)}
.la-brand b{font-size:1.15rem;letter-spacing:-.02em}
.la-brand small{display:block;font-size:.72rem;opacity:.75;font-weight:500}
.la-mid{margin-block:auto;max-width:30rem}
.la-mid h2{font-size:2.1rem;line-height:1.2;letter-spacing:-.035em;font-weight:800}
.la-mid p{opacity:.82;font-size:.98rem;margin:.9rem 0 0;max-width:26rem}
.la-stats{display:flex;gap:2rem;margin-top:2.4rem}
.la-stats div b{display:block;font-size:1.5rem;font-weight:800;letter-spacing:-.02em}
.la-stats div span{font-size:.75rem;opacity:.72}
.la-foot{display:flex;align-items:center;gap:.75rem;font-size:.78rem;opacity:.88}

.login-main{display:grid;place-items:center;padding:2rem;background:var(--c-surface-2)}
.login-box{width:100%;max-width:394px}
.login-box h1{font-size:1.6rem;letter-spacing:-.03em}
.login-box>.sub{color:var(--c-text-muted);font-size:.9rem;margin:.5rem 0 1.75rem}
.lang-row{display:flex;gap:.35rem;flex-wrap:wrap;margin-block-end:1.75rem}
.lang{font-size:.75rem; padding:.28rem .6rem; border:1px solid var(--c-border); border-radius:var(--radius-pill); color:var(--c-text-muted); cursor:pointer; background:var(--c-surface-2); font-family:inherit; transition:all 160ms var(--ease);}
.lang:hover{border-color:var(--c-border-strong);color:var(--c-text-2)}
.lang.active{background:var(--c-brand-50);color:var(--c-brand-700);border-color:var(--c-brand-100);font-weight:700}
.login-help{margin-top:1.5rem;padding-top:1.25rem;border-top:1px solid var(--c-surface-3);font-size:.78rem;color:var(--c-text-muted);text-align:center}
.login-help a{color:var(--c-brand-700);font-weight:600}

/* ---------------------------------------------------------------- misc */
.muted{color:var(--c-text-muted)}
.tiny{font-size:.75rem}
.mono{font-variant-numeric:tabular-nums}
.stack{display:flex;flex-direction:column;gap:1rem}
.inline{display:inline-flex;align-items:center;gap:.4rem}
/* ---------------------------------------------------------------- responsive */
@media(max-width:1080px){
  .shell{grid-template-columns:1fr}
  .sidebar{position:static; height:auto; display:block; gap:0; border-inline-end:0; border-block-end:1px solid var(--c-border); padding:.8rem 1rem 1rem;}
  .org-chip,.sidebar-foot,.nav-label{display:none}
  .brand-row{padding:0 0 .7rem}
  .nav-group{flex-direction:row;flex-wrap:wrap;gap:.3rem}
  .nav-group+.nav-group{margin-top:.45rem}
  .nav-item{padding:.35rem .65rem;font-size:.82rem;border:1px solid var(--c-border)}
  .nav-item.active{border-color:transparent}
  .content{padding:1.25rem}
}
@media(max-width:700px){
  .search{display:none}
  .topbar{flex-wrap:wrap;padding:.6rem 1rem}
  .content{padding:1rem}
  .kpi-row{grid-template-columns:1fr 1fr}
  .page-actions{margin-inline-start:0}
}
@media(max-width:480px){
  .kpi-row{grid-template-columns:1fr}
  .crumb span:first-child,.crumb .sep{display:none}
}

@media(prefers-reduced-motion:reduce){*{transition:none!important;animation:none!important}}

/* ==================================================================
   D-final additions
   1. real Edumia logo
   2. dense data tables borrowed from Direction B
   3. status-as-word (no pill noise in long tables)
   ================================================================== */

/* ---------------------------------------------------------- logo */
/* align-self:flex-start is required — these sit inside column flex
   containers (sidebar, login panel) whose default align-items:stretch
   would otherwise stretch the image and distort its aspect ratio. */
.logo{display:block;height:26px;width:auto;align-self:flex-start}
.logo-lg{display:block;height:34px;width:auto;align-self:flex-start}
.logo-sm{display:block;height:20px;width:auto;align-self:flex-start}

/* ---------------------------------------------------------- dense tables */
.table-dense{width:100%;border-collapse:collapse;font-size:.82rem}
.table-dense th{text-align:start; background:var(--c-surface); font-size:.66rem; font-weight:700; letter-spacing:.07em; text-transform:uppercase; color:var(--c-text-faint); padding:.45rem .7rem; border-block-end:1px solid var(--c-border); white-space:nowrap;}
.table-dense td{padding:.48rem .7rem; border-block-end:1px solid var(--c-surface-3); color:var(--c-text-2); vertical-align:middle;}
.table-dense tbody tr{transition:background 140ms var(--ease)}
.table-dense tbody tr:hover{background:var(--c-surface-hover)}
.table-dense tbody tr:last-child td{border-block-end:0}
.table-dense td.num{text-align:end;font-variant-numeric:tabular-nums;font-weight:600;color:var(--c-text)}
.table-dense .ref{font-variant-numeric:tabular-nums;color:var(--c-text-muted);font-size:.78rem}
.table-dense .name{font-weight:600;color:var(--c-text)}
.table-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch}
.table-wrap .table-dense{min-width:640px}

.dot-status{display:inline-flex;align-items:center;gap:.35rem;font-size:.76rem;font-weight:600;white-space:nowrap}
.dot-status::before{content:"";width:6px;height:6px;border-radius:50%;background:currentColor;flex:none}
.s-ok{color:var(--c-success)}
.s-warn{color:var(--c-warning)}
.s-bad{color:var(--c-danger)}

/* ================================================================== dark theme
   Authored + testable, DORMANT: nothing in the UI sets data-theme="dark"
   in Phase 1 (View::head() writes Theme::mode(), which returns 'light').
   No toggle, no prefers-color-scheme query, no JS. Every --c-* token is
   re-declared here; contrast rules from the contract are preserved.
   ================================================================== */
[data-theme="dark"]{
  --c-brand:#8CC46A; --c-brand-strong:#436A2B; --c-brand-hover:#33511F; --c-brand-mark:#8CC46A;
  --c-brand-50:#16240F; --c-brand-100:#1E3016; --c-brand-200:#2A4120;
  --c-brand-600:#6FA84F; --c-brand-700:#A8D48C; --c-brand-800:#C3E3AD;
  --c-accent:#D9A75B; --c-accent-strong:#885704;
  --c-surface:#0B1220; --c-surface-2:#111C2E; --c-surface-3:#16233A; --c-surface-hover:#16233A;
  --c-text:#E6EDF6; --c-text-2:#C3CEDD; --c-text-muted:#9FB0C4; --c-text-faint:#7C8DA3;
  --c-border:#22304A; --c-border-strong:#2E3F5C; --c-focus:#8CC46A;
  --c-success:#4ADE80; --c-warning:#FBBF24; --c-danger:#F87171; --c-info:#60A5FA;
  --c-success-50:#072013; --c-success-100:#0E3A22;
  --c-warning-50:#241A05; --c-warning-100:#3D2C08; --c-warning-400:#FBBF24;
  --c-danger-50:#240E0E; --c-danger-100:#3D1717;
  --c-info-50:#0B1A33; --c-info-100:#13294D;
  --c-brand-sheen:#5F913C; --c-brand-deep:#152009; --c-brand-base:#0E1608;
  --shadow-1:0 1px 2px rgba(0,0,0,.5);
  --shadow-2:0 6px 20px -8px rgba(0,0,0,.6), 0 1px 2px rgba(0,0,0,.5);
  --shadow-3:0 24px 48px -16px rgba(0,0,0,.65);
}
/* the two surfaces that are literally white in the light design */
[data-theme="dark"] .topbar{background:rgba(17,28,46,.85)}
[data-theme="dark"] .icon-btn .badge{border-color:var(--c-surface-2)}

/* ==================================================================
   CSS <-> JS CONTRACT — agent A7
   app.js (agent A3) drives this shell entirely through data-* attributes
   and the `hidden` attribute. Neither agent could see the other's output,
   so this section is the other half of that contract. Without it: the
   mobile nav toggle is inert, the notification panel has no styling, tab
   groups do nothing, and a bare .ico-svg has no size at all (an unstyled
   <svg> renders at its 300x150 default and blows out any layout using one).
   Every rule below keys off an attribute or class that only exists when
   A3's markup is present, so nothing here can restyle a screen A3 does
   not touch. Nothing here is bang-important: [hidden][hidden] at the foot of
   this section wins on specificity instead, which keeps the tenant-theme
   cascade alive. Verified by rendering — see /tmp/uiforge/a7_verify.py.
   LAST UPDATED: 2026-09-13
   ================================================================== */

/* 1 — fallback size for a bare sprite icon. Every icon carries .ico-svg.
   The context rules (.nav-item svg, .btn svg, .notice svg, ...) are all
   more specific than this single-class rule, so this is only the floor
   that stops an unsized icon from breaking its container. */
.ico-svg{width:1.15em;height:1.15em;flex:none;stroke-width:var(--icon-stroke,1.75)}

/* 2 — the --icon-stroke handoff. Each <symbol> in icons.svg declares
   stroke-width twice on purpose: the presentation attribute 1.75 and
   style="stroke-width:var(--icon-stroke,1.75)". A presentation attribute
   beats an inherited value, so a host `stroke-width` reaches nothing — but a
   custom property DOES inherit into the <use> shadow tree. So the weight is
   driven by the variable, which is why --icon-stroke:1.7 / 2 / 2.4 / 2 were
   added to the existing context rules `.nav-item svg`, `.btn svg`,
   `.trend svg` and `.notice svg` earlier in this file. The legacy
   stroke-width declarations stay in place as the fallback for the one
   inline icon (View::homeIcon()) that is not a sprite reference. */

/* 3 — mobile nav toggle (<=1080px). At <=1080px the sidebar collapses to a
   wrapping strip. With JS present it is HIDDEN until body[data-nav-open] is
   set — the flag A3 flips and mirrors in aria-expanded on the toggle — and
   then expands as an in-flow block above the topbar. Deliberately NOT a
   position:fixed drawer: a fixed panel at z-index 60 covers the topbar, which
   is where the only close control lives (app.js closes the nav on a nav-link
   click, not on an outside tap), so a drawer would strand the user with no way
   to close it. In flow, the toggle stays visible and clickable beneath the
   expanded block. The "hidden until opened" half is scoped under
   html[data-js], so a visitor with JS disabled still gets A1's always-visible
   strip: progressive enhancement, not a dependency. max-height bounds the
   block on short viewports so it scrolls internally instead of pushing the
   page far down. Nothing here can add a horizontal scroller. */
@media(max-width:1080px){
  html[data-js] .sidebar{display:none}
  html[data-js] body[data-nav-open] .sidebar{
    display:flex; flex-direction:column; gap:.75rem;
    position:static; height:auto; max-height:calc(100vh - 4rem); overflow-y:auto;
    padding:.85rem .85rem 1rem; border-block-end:1px solid var(--c-border);
  }
  /* the parts the collapsed strip hides come back when the menu is expanded, and the
     spacing is tightened so the whole nav + foot fits an 800px viewport. Everything
     else keeps the approved desktop geometry of the sidebar. */
  html[data-js] body[data-nav-open] .sidebar .org-chip{display:flex}
  html[data-js] body[data-nav-open] .sidebar .nav-label,
  html[data-js] body[data-nav-open] .sidebar .sidebar-foot{display:block}
  html[data-js] body[data-nav-open] .sidebar .nav-group{margin-top:0; flex-direction:column; flex-wrap:nowrap}
  html[data-js] body[data-nav-open] .sidebar .nav-item{padding:.5rem .6rem; font-size:.875rem; border-width:0}
  html[data-js] body[data-nav-open] .sidebar .brand-row{padding:.15rem .55rem 0}
}

/* 4 — keyboard focus for every hook A3 activates. The toggle must be
   reachable and visibly focused; the same ring is given to the other
   scripted controls so the shell is operable without a mouse. */
[data-nav-toggle]:focus-visible,[data-menu-toggle]:focus-visible,[data-tab]:focus-visible,
[data-row-href]:focus-visible,[data-menu] a:focus-visible{outline:2px solid var(--c-focus);outline-offset:2px}

/* 5 — dropdown panel. View::notificationsMenu() renders <button
   data-menu-toggle aria-expanded> followed by its sibling .card[data-menu],
   both direct children of .topbar. A3 clears/sets the panel's hidden
   attribute and flips aria-expanded on the trigger. .card already supplies
   surface, border and radius, so this adds only the float and the elevation
   a panel needs. .topbar is position:sticky, so it is the containing block. */
[data-menu]{position:absolute; top:calc(100% + .35rem); inset-inline-end:1.5rem; z-index:50; min-width:17rem; max-width:min(24rem,92vw); margin:0; box-shadow:var(--shadow-2)}
[data-menu-toggle][aria-expanded="true"]{background:var(--c-brand-50); border-color:var(--c-brand-100); color:var(--c-brand-700)}
@media(max-width:700px){[data-menu]{inset-inline-end:1rem}}

/* 6 — clickable table rows. A3 puts tabindex=0 on tr[data-row-href] and
   navigates on click or Enter; the tint matches .table-dense tbody tr:hover
   exactly, so a clickable dense table hovers like every other one. */
[data-row-href]{cursor:pointer}
[data-row-href]:hover{background:var(--c-surface-hover)}

/* 7 — tab groups. A3 toggles .active plus aria-selected inside [data-tabgroup]
   and hides the panel named by aria-controls / [data-tab-panel]. The .active
   look is the existing .lang.active idiom, so a segmented control reads the
   same as the language switcher. */
[data-tabgroup]{display:flex;gap:.35rem;flex-wrap:wrap}
[data-tab]{font-size:.78rem; padding:.3rem .7rem; border:1px solid var(--c-border); border-radius:var(--radius-pill); background:var(--c-surface-2); color:var(--c-text-muted); font-family:inherit; cursor:pointer; transition:border-color 160ms var(--ease),color 160ms var(--ease),background 160ms var(--ease)}
[data-tab]:hover{border-color:var(--c-border-strong);color:var(--c-text-2)}
[data-tab].active{background:var(--c-brand-50);color:var(--c-brand-700);border-color:var(--c-brand-100);font-weight:700}

/* 8 — THE [hidden] TRAP. MUST STAY THE LAST RULES IN THIS FILE.
   `hidden` is enforced only by the UA sheet's [hidden]{display:none}, which is
   specificity (0,1,0): ANY author rule that sets display on the same element
   beats it, so a panel that also carries something like .card-head .right
   (0,2,0) would stay visible with hidden set. Repeating the attribute selector
   raises this to (0,2,0) and, being last in the file, it wins the tie against
   every component display rule. Deliberately not bang-important — that would
   also defeat the tenant-theme cascade. */
[hidden][hidden]{display:none}
