/* ==========================================================================
   MISS J BIMBEL CENTER · Portal Shared Design System (Fable Mission 1)
   ---------------------------------------------------------------------------
   Sections 1-4 (tokens, base, buttons, nav) and the footer are copied
   verbatim from enrollment.css / payment.css / student-update.css so every
   portal page shares the exact same brand — colors, fonts, radii, shadows,
   nav, footer — as the rest of the site. Component naming (.field,
   .field-error, .btn, .kicker, .dot, .reveal, etc.) deliberately matches
   those same files' existing vocabulary instead of inventing a parallel one,
   so this genuinely IS the same design system, not a lookalike of it.

   This file is meant to be reused, unchanged, by the Parent, Student, and
   Teacher portal entry screens (login, and later similar auth-shaped
   screens) — see portal-hero / portal-card / portal-* below for the parts
   specific to that shape. Nothing here is wired to any backend; see the
   single TODO(engineering) block in parent-login.js for the one real
   integration point.
   ========================================================================== */

/* ---------- 1 · Tokens (identical across every portal-family page) ---------- */
:root{
  --sky:#8ECDF3; --sky-soft:#EAF6FE;
  --sun:#FFC94D; --sun-soft:#FFF3D6;
  --coral:#FF8A5F; --coral-soft:#FFE4D8;
  --mint:#7FD8B4; --mint-soft:#E2F7EE;
  --cream:#FFF6E8; --white:#FFFDF9;
  --ink:#2B4066; --ink-soft:#5E7194;
  --dusk:#35548F; --night:#1E3061; --deep-night:#152347;

  --font-display:'Fredoka',system-ui,sans-serif;
  --font-body:'Nunito',system-ui,sans-serif;
  --r-lg:34px; --r-md:22px; --r-sm:16px;
  --shadow:0 12px 30px rgba(43,64,102,.10);
  --shadow-big:0 22px 50px rgba(43,64,102,.16);
  --wrap:1120px;
  --form-wrap:520px;
}

/* ---------- 2 · Base ---------- */
*{margin:0;padding:0;box-sizing:border-box}
html{scroll-behavior:smooth}
body{
  font-family:var(--font-body);color:var(--ink);background:var(--cream);
  line-height:1.6;font-size:17px;overflow-x:hidden;
}
img,svg{display:block;max-width:100%}
a{color:inherit;text-decoration:none}
ul,ol{list-style:none}
:focus-visible{outline:3px solid var(--sun);outline-offset:3px;border-radius:8px}
::selection{background:var(--sun);color:var(--ink)}
h1,h2,h3{font-family:var(--font-display);font-weight:600;line-height:1.15}
.wrap{max-width:var(--wrap);margin:0 auto;padding:0 clamp(20px,4vw,40px)}

/* ---------- 3 · Buttons ---------- */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:10px;
  font-family:var(--font-display);font-weight:600;font-size:1.02rem;
  padding:15px 28px;min-height:52px;border-radius:999px;border:none;cursor:pointer;
  transition:transform .3s cubic-bezier(.34,1.56,.64,1),box-shadow .3s;
}
.btn.big{padding:18px 36px;font-size:1.15rem;min-height:60px}
.btn-sun{background:var(--sun);color:var(--ink);box-shadow:0 10px 26px rgba(255,201,77,.5)}
.btn-sun:hover{transform:translateY(-4px) scale(1.02);box-shadow:0 16px 34px rgba(255,201,77,.55)}
.btn-sun:active{transform:translateY(-1px) scale(.99)}
.btn-sun:disabled{opacity:.65;cursor:not-allowed;transform:none;box-shadow:none}
.btn-cloud{background:#fff;color:var(--ink);box-shadow:var(--shadow);border:1px solid rgba(43,64,102,.08)}
.btn-cloud:hover{transform:translateY(-3px);box-shadow:var(--shadow-big)}
.btn-full{width:100%}

/* ---------- 4 · Nav (identical to enrollment.css / payment.css / student-update.css) ---------- */
.nav{
  position:sticky;top:0;z-index:100;background:rgba(255,253,249,.9);
  backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
  border-bottom:1px solid rgba(43,64,102,.08);
}
.nav-inner{
  max-width:var(--wrap);margin:0 auto;padding:14px clamp(20px,4vw,40px);
  display:flex;align-items:center;justify-content:space-between;gap:16px;
}
.logo{display:flex;align-items:center;gap:10px}
.logo img{height:44px;width:auto;display:block;border-radius:12px;transition:transform .3s cubic-bezier(.34,1.56,.64,1)}
.logo:hover img{transform:scale(1.06) rotate(-2deg)}
.logo span{font-family:var(--font-display);font-weight:700;font-size:1.02rem;color:var(--ink)}
.nav-help{font-size:.92rem;font-weight:700;color:var(--ink-soft)}
.nav-help a{color:var(--dusk);border-bottom:2px solid var(--sky-soft);transition:border-color .2s ease}
.nav-help a:hover{border-color:var(--sky)}

/* ---------- 5 · Shared scaffolding ---------- */
.kicker{
  display:inline-block;font-family:var(--font-display);font-weight:800;font-size:.76rem;
  letter-spacing:.16em;text-transform:uppercase;background:#fff;border-radius:999px;
  padding:8px 18px;margin-bottom:18px;color:var(--ink);box-shadow:var(--shadow);
}
.reveal{opacity:0;transform:translateY(28px);transition:opacity .7s ease,transform .7s ease}
.reveal.is-visible{opacity:1;transform:translateY(0)}
@media (prefers-reduced-motion:reduce){.reveal{opacity:1;transform:none;transition:none}}
.dot{width:8px;height:8px;border-radius:50%;background:var(--mint);flex:none;display:inline-block}

/* ---------- 6 · Portal hero (shared shape for every portal entry screen) ---------- */
.portal-hero{
  position:relative;overflow:hidden;text-align:center;
  padding:clamp(48px,9vw,88px) 0 clamp(32px,5vw,44px);
  background:linear-gradient(180deg,var(--sky-soft) 0%,var(--cream) 65%);
}
.portal-hero-inner{display:flex;flex-direction:column;align-items:center;max-width:var(--form-wrap);margin:0 auto}
.portal-hero-icon{
  background:#fff;border-radius:var(--r-lg);box-shadow:var(--shadow-big);
  padding:clamp(14px,2.6vw,20px);margin-bottom:clamp(16px,2.6vw,20px);
}
.portal-hero-icon svg{width:clamp(48px,7vw,60px);height:auto}
.portal-hero-inner h1{font-size:clamp(1.8rem,4.2vw,2.5rem);color:var(--ink)}
.portal-hero-sub{font-size:1.02rem;color:var(--ink-soft);margin-top:14px;max-width:32rem}

/* ---------- 7 · Portal card (the auth form shell) ---------- */
.portal-section{padding:clamp(8px,2vw,16px) 0 clamp(64px,9vw,100px)}
.portal-wrap{max-width:var(--form-wrap)}
.portal-card{
  background:#fff;border-radius:var(--r-lg);box-shadow:var(--shadow-big);
  padding:clamp(28px,5vw,44px);
}

/* ---------- 8 · Form fields (identical vocabulary to student-update.css) ---------- */
.field-grid{display:grid;grid-template-columns:1fr;gap:18px}
.field{display:flex;flex-direction:column;gap:6px}
.field label{font-family:var(--font-display);font-weight:600;font-size:.92rem;color:var(--ink)}

.field input[type="text"],
.field input[type="email"],
.field input[type="password"]{
  width:100%;padding:13px 16px;border-radius:var(--r-sm);border:1.5px solid rgba(43,64,102,.14);
  background:var(--cream);color:var(--ink);font-family:var(--font-body);font-size:1rem;
  transition:border-color .2s ease,background .2s ease;
}
.field input:focus{outline:none;border-color:var(--sky);background:#fff}
.field-error{font-size:.82rem;color:var(--coral);font-weight:700;min-height:1em;display:none}
.field.is-invalid input{border-color:var(--coral)}
.field.is-invalid .field-error{display:block}

/* Password field with an inline show/hide toggle — the input keeps normal
   .field styling; this wrapper only positions the toggle button over it. */
.field-password-wrap{position:relative}
.field-password-wrap input{padding-right:52px}
.field-password-toggle{
  position:absolute;top:50%;right:6px;translate:0 -50%;
  width:38px;height:38px;border-radius:50%;border:none;background:none;cursor:pointer;
  display:flex;align-items:center;justify-content:center;color:var(--ink-soft);
  transition:background .2s ease,color .2s ease;
}
.field-password-toggle:hover{background:var(--sky-soft);color:var(--ink)}
.field-password-toggle svg{width:20px;height:20px}

/* ---------- 9 · Form-level status (loading note + error banner) ---------- */
.portal-form-note{
  display:flex;align-items:flex-start;gap:8px;margin-top:16px;
  font-size:.86rem;color:var(--ink-soft);padding:8px 12px;border-radius:12px;
  transition:background .3s ease,color .3s ease;
}
.portal-form-note .dot{margin-top:6px}
.portal-form-note.is-emphasized{background:var(--sky-soft);color:var(--ink)}
.portal-form-note.is-emphasized.success{background:var(--mint-soft);color:#1f7a56}
.portal-form-note.is-emphasized.error{background:var(--coral-soft);color:#a83e1f}

.portal-error-banner{
  display:flex;align-items:flex-start;gap:10px;
  background:var(--coral-soft);border:1.5px solid rgba(255,138,95,.4);border-radius:var(--r-sm);
  padding:14px 16px;margin-bottom:20px;font-size:.92rem;color:#a83e1f;font-weight:600;
}
/* The [hidden] global attribute and this class both carry (0,1,0)
   specificity, so without this override the class's own display:flex
   above would win the cascade tie and defeat "hidden" entirely. */
.portal-error-banner[hidden]{display:none}
.portal-error-banner svg{width:20px;height:20px;flex:none;margin-top:1px}

/* Spinner used inside a submit button while a form is "loading" — purely
   visual, no request is actually made anywhere in this page. */
.portal-spinner{
  width:18px;height:18px;border-radius:50%;
  border:2.5px solid rgba(43,64,102,.25);border-top-color:var(--ink);
  animation:portalSpin .7s linear infinite;flex:none;
}
@keyframes portalSpin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){.portal-spinner{animation:none}}

/* ---------- 9b · Auth onboarding (Fable Task — Portal Account Onboarding UI) ---------- */
/* UI-only additions for the "first-time user" activation flow and the
   "Lupa Kata Sandi?" reset flow, layered onto the existing login card via
   the same show/hide-a-block pattern .portal-error-banner already uses.
   No new page, no new request — parent-onboarding.js is the only script
   that drives these, and it never calls fetch(). See its own header
   comment and the .portal-note block below for the explicit, visible
   disclosure that a real backend endpoint doesn't exist for either flow
   yet. */
.portal-auth-links{display:flex;justify-content:space-between;align-items:center;margin-top:-6px}

.portal-inline-link{
  background:none;border:none;padding:0;font-family:inherit;
  font-size:.88rem;font-weight:700;color:var(--dusk);cursor:pointer;
}
.portal-inline-link:hover{text-decoration:underline}

.portal-switch-row{
  text-align:center;margin-top:22px;padding-top:18px;
  border-top:1px solid rgba(43,64,102,.1);font-size:.92rem;color:var(--ink-soft);
}

.portal-back-link{
  display:inline-flex;align-items:center;gap:6px;background:none;border:none;padding:0;
  font-family:inherit;font-size:.9rem;font-weight:700;color:var(--ink-soft);
  cursor:pointer;margin-bottom:20px;
}
.portal-back-link:hover{color:var(--ink)}

.portal-step-label{
  font-size:.76rem;font-weight:800;color:var(--dusk);
  text-transform:uppercase;letter-spacing:.06em;margin-bottom:10px;
}

/* Card-internal header — the activation/forgot-password views live inside
   the same .portal-card shell as the login form, but need their own
   icon/title/subtitle (the page-level .portal-hero above stays on "Masuk
   ke Portal Orang Tua" throughout, so this is what actually tells a
   parent which screen they're on). */
.portal-card-header{text-align:center;margin-bottom:26px}
.portal-card-icon{
  width:56px;height:56px;margin:0 auto 14px;border-radius:50%;
  background:var(--sky-soft);display:flex;align-items:center;justify-content:center;
  font-size:1.6rem;
}
.portal-card-title{font-size:1.3rem;color:var(--ink)}
.portal-card-subtitle{font-size:.92rem;color:var(--ink-soft);margin-top:8px}

.portal-confirm-icon{
  width:64px;height:64px;margin:4px auto 18px;border-radius:50%;
  background:var(--mint-soft);display:flex;align-items:center;justify-content:center;
  font-size:1.8rem;
}
.portal-confirm-title{font-size:1.15rem;text-align:center;color:var(--ink);margin-bottom:8px}
.portal-confirm-text{text-align:center;color:var(--ink-soft);font-size:.94rem;line-height:1.6;margin-bottom:18px}

/* The one honest, always-visible disclosure that a given screen isn't
   backed by a real endpoint yet — informational (sky), not error/success. */
.portal-note{
  display:flex;align-items:flex-start;gap:8px;background:var(--sky-soft);
  border-radius:var(--r-sm);padding:13px 16px;font-size:.86rem;color:var(--ink);
  line-height:1.55;margin-top:18px;
}
.portal-note-icon{flex:none;line-height:1}

/* ---------- 10 · Footer (identical to the rest of the site) ---------- */
.foot{background:var(--night);color:rgba(255,255,255,.75);padding:40px 0}
.foot-inner{display:flex;flex-direction:column;align-items:center;gap:8px;text-align:center;font-size:.92rem}
.foot-inner a{color:#fff;border-bottom:1px solid rgba(255,255,255,.35)}
.foot-inner a:hover{border-color:#fff}

/* ---------- 12 · Portal subnav (Fable Mission 2) ---------- */
/* Not sticky — deliberately avoids stacking on top of the already-sticky
   .nav header, which would need a hardcoded pixel offset that breaks the
   moment either bar's height changes. A simple static bar underneath is
   the same tradeoff Mission 1 made when it chose a plain nav-links entry
   over a new sticky/floating button. Reusable as-is for the Student and
   Teacher portal dashboards later — only the link set changes. */
.portal-subnav{background:#fff;border-bottom:1px solid rgba(43,64,102,.08)}
.portal-subnav-inner{
  max-width:var(--wrap);margin:0 auto;padding:0 clamp(20px,4vw,40px);
  display:flex;align-items:center;gap:2px;overflow-x:auto;scrollbar-width:none;
}
.portal-subnav-inner::-webkit-scrollbar{display:none}
.portal-subnav-link{
  display:flex;align-items:center;gap:8px;white-space:nowrap;flex:none;
  font-family:var(--font-display);font-weight:600;font-size:.9rem;color:var(--ink-soft);
  padding:15px 14px;border:none;background:none;cursor:pointer;
  border-bottom:3px solid transparent;transition:color .2s ease,border-color .2s ease;
}
.portal-subnav-link svg{width:18px;height:18px;flex:none}
.portal-subnav-link:hover{color:var(--ink)}
.portal-subnav-link.is-active{color:var(--ink);border-bottom-color:var(--sun)}
.portal-subnav-link.is-logout{margin-left:auto;color:var(--coral)}
.portal-subnav-link.is-logout:hover{color:#d9633c}

/* ---------- 13 · Portal dashboard header (welcome area) ---------- */
.portal-dashboard-header{
  background:linear-gradient(180deg,var(--sky-soft) 0%,var(--cream) 100%);
  padding:clamp(28px,5vw,40px) 0;
}
.portal-welcome{display:flex;align-items:center;justify-content:space-between;gap:20px;flex-wrap:wrap}
.portal-welcome-text h1{font-size:clamp(1.4rem,3vw,1.9rem);color:var(--ink)}
.portal-welcome-text p{color:var(--ink-soft);margin-top:6px;font-size:.96rem}
.portal-welcome-actions{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.portal-profile-chip{
  display:flex;align-items:center;gap:12px;background:#fff;border-radius:999px;
  padding:8px 18px 8px 8px;box-shadow:var(--shadow);
}
.portal-profile-avatar{
  width:42px;height:42px;border-radius:50%;background:var(--sky-soft);flex:none;
  display:flex;align-items:center;justify-content:center;font-family:var(--font-display);
  font-weight:700;color:var(--dusk);
}
.portal-profile-info{display:flex;flex-direction:column;line-height:1.25}
.portal-profile-name{font-family:var(--font-display);font-weight:600;font-size:.9rem;color:var(--ink)}
.portal-profile-email{font-size:.76rem;color:var(--ink-soft)}
.portal-logout-btn{
  display:flex;align-items:center;gap:6px;font-family:var(--font-display);font-weight:600;
  font-size:.86rem;color:var(--coral);padding:11px 16px;border:1.5px solid rgba(255,138,95,.35);
  border-radius:999px;background:#fff;cursor:pointer;transition:background .2s ease,color .2s ease;
}
.portal-logout-btn:hover{background:var(--coral-soft);color:#d9633c}
.portal-logout-btn svg{width:16px;height:16px}

/* ---------- 14 · Demo/placeholder-data banner ---------- */
/* Every value inside .portal-dashboard-body below is illustrative demo
   data, never a real student/account record — this banner is the
   page-wide, impossible-to-miss disclosure of that fact, on top of the
   "(Contoh)" suffix on each individual value. */
.portal-demo-banner{
  display:flex;align-items:flex-start;gap:10px;background:var(--sun-soft);
  border:1.5px dashed rgba(184,140,26,.45);border-radius:var(--r-sm);
  padding:13px 16px;margin-bottom:28px;font-size:.86rem;font-weight:700;color:#8a6a1a;
}
.portal-demo-banner svg{width:18px;height:18px;flex:none;margin-top:1px}

/* ---------- 15 · Section head (reusable above Children / Tuition / etc.) ---------- */
.portal-section-head{display:flex;align-items:center;gap:12px;margin-bottom:18px}
.portal-section-head-icon{
  width:38px;height:38px;border-radius:12px;background:#fff;box-shadow:var(--shadow);flex:none;
  display:flex;align-items:center;justify-content:center;
}
.portal-section-head-icon svg{width:20px;height:20px}
.portal-section-head h2{font-size:1.2rem;color:var(--ink)}
.portal-dashboard-section{margin-bottom:clamp(32px,5vw,44px)}

/* ---------- 16 · Child cards ---------- */
.portal-child-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:18px}
.portal-child-card{
  background:#fff;border-radius:var(--r-md);box-shadow:var(--shadow);padding:22px;
  display:flex;flex-direction:column;gap:14px;transition:box-shadow .25s ease,transform .25s ease;
}
.portal-child-card:hover{box-shadow:var(--shadow-big);transform:translateY(-3px)}
.portal-child-avatar{
  width:52px;height:52px;border-radius:50%;background:var(--mint-soft);flex:none;
  display:flex;align-items:center;justify-content:center;font-family:var(--font-display);
  font-weight:700;font-size:1.05rem;color:#1f7a56;
}
.portal-child-name{font-family:var(--font-display);font-weight:600;font-size:1.02rem;color:var(--ink)}
.portal-child-meta{font-size:.86rem;color:var(--ink-soft);margin-top:2px}
.portal-status-badge{
  display:inline-flex;align-items:center;gap:6px;font-size:.72rem;font-weight:800;
  padding:5px 12px;border-radius:999px;width:fit-content;text-transform:uppercase;letter-spacing:.04em;
}
.portal-status-badge.is-active{background:var(--mint-soft);color:#1f7a56}
.portal-status-badge.is-inactive{background:rgba(43,64,102,.08);color:var(--ink-soft)}
.portal-child-card .btn{margin-top:auto}

/* ---------- 17 · Tuition summary card ---------- */
.portal-tuition-card{
  background:#fff;border-radius:var(--r-lg);box-shadow:var(--shadow);padding:clamp(22px,4vw,30px);
  display:flex;align-items:center;justify-content:space-between;gap:24px;flex-wrap:wrap;
}
.portal-tuition-info{display:flex;flex-direction:column;gap:6px}
.portal-tuition-label{font-size:.84rem;color:var(--ink-soft);font-weight:700}
.portal-tuition-amount{font-family:var(--font-display);font-size:1.6rem;font-weight:600;color:var(--ink)}
.portal-tuition-status{display:flex;align-items:center;gap:8px;font-size:.88rem;font-weight:700}
.portal-tuition-status .dot{background:currentColor}
.portal-tuition-status.is-outstanding{color:var(--coral)}
.portal-tuition-status.is-clear{color:#1f7a56}

/* ---------- 18 · Reusable state panel (loading / empty / error) ---------- */
/* Same shape as .pmt-state-panel in payment.css — kept here instead of
   duplicated so any future portal dashboard can reuse it unchanged. */
.portal-state-panel{text-align:center;padding:clamp(28px,5vw,40px) 20px}
.portal-state-icon-wrap{
  width:68px;height:68px;border-radius:50%;margin:0 auto 16px;
  display:flex;align-items:center;justify-content:center;
}
.portal-state-panel h3{font-size:1.08rem;color:var(--ink);margin-bottom:6px}
.portal-state-panel p{color:var(--ink-soft);font-size:.9rem;max-width:26rem;margin:0 auto}

/* Loading skeleton — purely decorative, reachable via
   MissJParentDashboard.showPageState('loading') for QA preview; nothing on
   this page auto-triggers a fake loading delay on real page load. */
.portal-skeleton-row{
  height:14px;border-radius:8px;margin:0 auto 10px;
  background:linear-gradient(90deg,rgba(43,64,102,.08) 25%,rgba(43,64,102,.15) 37%,rgba(43,64,102,.08) 63%);
  background-size:400% 100%;animation:portalSkeleton 1.4s ease infinite;
}
@keyframes portalSkeleton{0%{background-position:100% 50%}100%{background-position:0 50%}}
@media (prefers-reduced-motion:reduce){.portal-skeleton-row{animation:none}}

/* ---------- 19 · "Coming soon" toast ---------- */
/* Used by every dashboard action that points at a screen this mission
   explicitly does not build yet (Child Detail, Tuition Detail, Profile).
   Never a fake navigation or a fake result — just an honest, dismissable
   note that the destination isn't built yet. */
.portal-toast{
  position:fixed;left:50%;bottom:28px;translate:-50% 0;z-index:200;
  display:flex;align-items:center;gap:10px;background:var(--night);color:#fff;
  padding:13px 20px;border-radius:999px;box-shadow:var(--shadow-big);
  font-size:.88rem;font-weight:600;max-width:calc(100vw - 40px);
  opacity:0;pointer-events:none;transition:opacity .25s ease,transform .25s ease;
  transform:translate(-50%,10px);
}
.portal-toast.is-visible{opacity:1;transform:translate(-50%,0)}
.portal-toast .dot{background:var(--sun)}

/* ---------- 20b · Learning Hub (Fable Task — Student Portal UI) ---------- */
/* Reuses section 11-19's dashboard shell (.portal-subnav, .portal-child-*,
   .portal-status-badge, .portal-state-panel) as-is — everything below is
   new only where the Learning Hub's own content shape (assignment cards,
   a submission-history table, a file list, an upload dropzone) has no
   existing equivalent. Status-badge color variants are additive: the
   existing is-active/is-inactive keep working for whatever already used
   them; is-missing/is-submitted/is-late/is-graded are new modifiers on
   the same component. */

.portal-assignment-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:18px}
.portal-assignment-card{
  background:#fff;border-radius:var(--r-md);box-shadow:var(--shadow);padding:22px;
  display:flex;flex-direction:column;gap:10px;text-align:left;border:none;cursor:pointer;
  font-family:var(--font-body);color:var(--ink);width:100%;
  transition:box-shadow .25s ease,transform .25s ease;
}
.portal-assignment-card:hover{box-shadow:var(--shadow-big);transform:translateY(-3px)}

/* Same base look as .portal-assignment-card but genuinely non-interactive
   (a plain summary number, not a button) — a separate class instead of
   .portal-assignment-card + an inline cursor override, since that still
   left the hover lift/shadow animation active and made these three
   stat boxes look clickable when nothing happens on click. */
.portal-stat-card{
  background:#fff;border-radius:var(--r-md);box-shadow:var(--shadow);padding:22px;
  display:flex;flex-direction:column;gap:10px;text-align:left;
  font-family:var(--font-body);color:var(--ink);width:100%;
}
.portal-assignment-subject{font-size:.82rem;color:var(--ink-soft);font-weight:700}
.portal-assignment-title{font-family:var(--font-display);font-weight:600;font-size:1.05rem;color:var(--ink)}
.portal-assignment-desc{font-size:.88rem;color:var(--ink-soft);line-height:1.5;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
.portal-assignment-due{font-size:.82rem;color:var(--ink-soft);font-weight:700;margin-top:auto}

.portal-status-badge.is-missing{background:var(--coral-soft);color:#a83e1f}
.portal-status-badge.is-submitted{background:var(--sky-soft);color:#2a5c85}
.portal-status-badge.is-late{background:var(--sun-soft);color:#8a6a1a}
.portal-status-badge.is-graded{background:var(--mint-soft);color:#1f7a56}

/* Assignment detail — read-only title/deadline context, instructions,
   materials, then the inline submit widget. No "pick a different
   assignment" control anywhere on this screen by design. */
.portal-detail-meta{display:flex;flex-wrap:wrap;gap:8px 18px;color:var(--ink-soft);font-size:.9rem;font-weight:700;margin:10px 0 18px}
.portal-detail-instructions{
  background:var(--cream);border-radius:var(--r-sm);padding:16px 18px;
  white-space:pre-wrap;line-height:1.6;margin-bottom:22px;
}

.portal-file-list{list-style:none;margin:0;padding:0;display:grid;gap:10px}
.portal-file-item{
  display:flex;align-items:center;gap:12px;padding:13px 16px;
  border:1.5px solid rgba(43,64,102,.1);border-radius:var(--r-sm);background:#fff;
}
.portal-file-icon{font-size:1.3rem;flex:none}
.portal-file-name{flex:1;font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.portal-file-meta{color:var(--ink-soft);font-size:.8rem;flex:none}

.portal-upload-drop{
  display:flex;flex-direction:column;align-items:center;gap:8px;text-align:center;
  padding:clamp(24px,4vw,32px) 20px;border:2px dashed rgba(43,64,102,.18);border-radius:var(--r-sm);
  background:var(--cream);cursor:pointer;color:var(--ink-soft);font-weight:700;
  transition:border-color .2s ease,background .2s ease;
}
.portal-upload-drop:hover{border-color:var(--sky);background:#fff}
.portal-upload-drop-icon{font-size:1.9rem}
.portal-upload-drop-name{font-weight:800;color:var(--ink)}

.portal-grade-hero{display:flex;align-items:center;gap:20px;flex-wrap:wrap;margin-bottom:14px}
.portal-grade-value{font-family:var(--font-display);font-size:2.6rem;font-weight:600;color:var(--dusk)}

/* Simple table — Pengumpulan Saya (submission history). */
.portal-table-wrap{overflow-x:auto;border-radius:var(--r-sm);border:1px solid rgba(43,64,102,.1)}
.portal-table{width:100%;border-collapse:collapse;min-width:520px}
.portal-table th,.portal-table td{padding:13px 16px;text-align:left;border-bottom:1px solid rgba(43,64,102,.08)}
.portal-table th{background:var(--cream);font-family:var(--font-display);font-size:.76rem;text-transform:uppercase;letter-spacing:.04em;font-weight:700}
.portal-table td{font-size:.92rem}
.portal-table tr:last-child td{border-bottom:0}

/* ---------- 20 · Mobile ---------- */
@media (max-width:640px){
  .portal-card{padding:22px}
  .portal-welcome{flex-direction:column;align-items:flex-start}
  .portal-tuition-card{flex-direction:column;align-items:flex-start}
}
