/**
 * Parent and student app.
 *
 * Built for a phone held in one hand on a patchy connection: one column, large
 * touch targets, and no web font - a parent should not wait on fonts.gstatic.com
 * to find out whether their child was in school.
 *
 * The school's own colour drives the header and the accents; --brand and
 * --brand-2 are written into the page per school, so this file stays one cached
 * stylesheet shared by every school on the platform. Everything else is a fixed
 * palette, because a school that picks an unreadable brand colour should not be
 * able to make its own fee figures illegible.
 *
 * Attendance leads and fees follow. A parent opens this most days to see that
 * their child was in school; the fee balance is something they check once a
 * month, and it does not need to be the first thing shouted at them.
 */

*, *::before, *::after { box-sizing: border-box; }

:root {
    --ink: #131A2E;
    --ink-2: #3D4761;
    --muted: #78829B;
    --line: #E7EBF3;
    --bg: #F5F7FB;
    --card: #FFFFFF;

    --good: #12A150;
    --good-bg: #E8F8EF;
    --warn: #C2740B;
    --warn-bg: #FEF6E7;
    --bad: #D93B3B;
    --bad-bg: #FDECEC;
    --info: #2563EB;
    --info-bg: #E9F0FE;
    --violet: #6D3BEB;
    --violet-bg: #F0EBFE;

    --radius: 16px;
    --radius-sm: 11px;
    --pad: 16px;
    --tap: 44px;
    --shadow: 0 1px 2px rgba(19,26,46,.05), 0 8px 24px -14px rgba(19,26,46,.28);
}

html { -webkit-text-size-adjust: 100%; }

body {
    margin: 0;
    background: var(--bg);
    color: var(--ink);
    font: 15px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    -webkit-font-smoothing: antialiased;
    overscroll-behavior-y: contain;
}
button, input { font: inherit; color: inherit; }
button { cursor: pointer; }
svg { display: block; }

/* Boot ------------------------------------------------------------------ */
.boot {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    min-height: 100dvh; gap: 18px; color: var(--muted);
}
.boot-mark {
    width: 44px; height: 44px; border-radius: 50%;
    border: 3px solid var(--line); border-top-color: var(--brand);
    animation: spin .9s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .boot-mark { animation-duration: 3s; } }

/* Frame ----------------------------------------------------------------- */
.app { min-height: 100dvh; display: flex; flex-direction: column; }

/* The header carries the school's colour, deepened at one corner so a flat
   brand hex still reads as a designed surface rather than a block of paint. */
.top {
    position: relative;
    background: var(--brand);
    background-image:
        radial-gradient(120% 130% at 88% -20%, rgba(255,255,255,.22), transparent 60%),
        linear-gradient(160deg, rgba(255,255,255,.10), rgba(0,0,0,.16));
    color: #fff;
    padding: calc(env(safe-area-inset-top) + 18px) var(--pad) 22px;
    display: flex; align-items: center; gap: 12px;
}
.top-id { display: flex; align-items: center; gap: 12px; min-width: 0; flex: 1; }
.top-avatar {
    width: 42px; height: 42px; border-radius: 13px; flex: none;
    background: rgba(255,255,255,.22);
    display: inline-flex; align-items: center; justify-content: center;
    font-weight: 700; font-size: 17px; letter-spacing: -.01em;
    box-shadow: inset 0 0 0 1px rgba(255,255,255,.28);
}
.top-name { font-size: 16.5px; font-weight: 650; letter-spacing: -.015em;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.top-sub { font-size: 12.5px; opacity: .82; margin-top: 1px; }
.top-btn {
    background: rgba(255,255,255,.16); border: 0; color: #fff;
    width: 36px; height: 36px; border-radius: 11px; flex: none;
    display: inline-flex; align-items: center; justify-content: center;
}
.top-btn:active { background: rgba(255,255,255,.28); }

/* Content clears the header rather than overlapping it: pulling it up looked
   neat until a child had a class line under their name, which the first card
   then sat on top of. */
.screen { flex: 1; padding: 18px var(--pad) 96px; }
.has-install .screen { padding-bottom: 170px; }

.sec { margin: 22px 2px 10px; font-size: 12.5px; font-weight: 700;
    letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.sec:first-child { margin-top: 14px; }

/* Cards ----------------------------------------------------------------- */
.card {
    background: var(--card); border: 1px solid var(--line);
    border-radius: var(--radius); padding: var(--pad);
    margin-bottom: 12px; box-shadow: var(--shadow);
}
.card-flush { padding: 4px var(--pad); }
button.card, a.card { display: block; width: 100%; text-align: left; font: inherit; color: inherit; }
button.card:active { transform: scale(.995); }

/* Attendance hero ------------------------------------------------------- */
.hero { display: flex; align-items: center; gap: 18px; }
.hero-main { flex: 1; min-width: 0; }
.hero-label { font-size: 12.5px; color: var(--muted); font-weight: 600; }
.hero-value { font-size: 30px; font-weight: 750; letter-spacing: -.035em; margin-top: 2px; }
.hero-note { font-size: 13px; color: var(--ink-2); margin-top: 4px; }

.ring { position: relative; width: 78px; height: 78px; flex: none; }
.ring svg { transform: rotate(-90deg); }
.ring-track { stroke: var(--line); }
.ring-fill { stroke: var(--good); stroke-linecap: round; transition: stroke-dashoffset .6s ease; }
.ring.is-warn .ring-fill { stroke: var(--warn); }
.ring.is-bad  .ring-fill { stroke: var(--bad); }
.ring-text {
    position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
    font-size: 16px; font-weight: 750; letter-spacing: -.03em;
}

/* Tiles ----------------------------------------------------------------- */
.tiles { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin-bottom: 12px; }
.tile {
    background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
    padding: 13px 11px; text-align: left; box-shadow: var(--shadow);
    display: flex; flex-direction: column; gap: 8px;
}
.tile:active { transform: scale(.985); }
.tile-ico {
    width: 32px; height: 32px; border-radius: 10px;
    display: inline-flex; align-items: center; justify-content: center;
}
.tile-n { font-size: 20px; font-weight: 750; letter-spacing: -.03em; line-height: 1; }
.tile-l { font-size: 11.5px; color: var(--muted); font-weight: 600; line-height: 1.25; }

.ico-warn { background: var(--warn-bg); color: var(--warn); }
.ico-info { background: var(--info-bg); color: var(--info); }
.ico-violet { background: var(--violet-bg); color: var(--violet); }
.ico-good { background: var(--good-bg); color: var(--good); }
.ico-bad { background: var(--bad-bg); color: var(--bad); }

/* Rows ------------------------------------------------------------------ */
.row { display: flex; align-items: center; gap: 12px; padding: 13px 0;
    border-bottom: 1px solid var(--line); width: 100%; text-align: left;
    background: 0; border-left: 0; border-right: 0; border-top: 0; }
.row:last-child { border-bottom: 0; }
.row-main { flex: 1; min-width: 0; }
.row-title { font-weight: 600; font-size: 14.5px; }
.row-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; }
/* These are written as <span> in some rows and <div> in others; without this
   the span version runs the title and the sub-line together on one line and
   pushes the chevron onto its own. */
.row-title, .row-sub { display: block; }
.row-main { display: block; }
.row-value { font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }
.row-value.is-due { color: var(--bad); }
.row-value.is-ok { color: var(--good); }
.row-chevron { color: var(--muted); flex: none; }

.badge {
    display: inline-flex; align-items: center; gap: 5px;
    padding: 4px 9px; border-radius: 999px; font-size: 11.5px; font-weight: 700;
}
.badge-good { background: var(--good-bg); color: var(--good); }
.badge-warn { background: var(--warn-bg); color: var(--warn); }
.badge-bad  { background: var(--bad-bg);  color: var(--bad); }
.badge-info { background: var(--info-bg); color: var(--info); }

/* Fees, deliberately quieter than the rest ------------------------------ */
.fee-strip { display: flex; align-items: center; gap: 14px; }
.fee-amount { font-size: 21px; font-weight: 750; letter-spacing: -.03em; }
.fee-bar { height: 6px; border-radius: 999px; background: var(--line); overflow: hidden; margin-top: 10px; }
.fee-bar span { display: block; height: 100%; background: var(--good); border-radius: 999px; }

/* Timetable ------------------------------------------------------------- */
.period { display: flex; gap: 12px; padding: 11px 0; border-bottom: 1px solid var(--line); }
.period:last-child { border-bottom: 0; }
.period-time { width: 54px; flex: none; font-size: 12px; font-weight: 700;
    color: var(--muted); font-variant-numeric: tabular-nums; padding-top: 2px; }
.period-body { flex: 1; min-width: 0; }
.period-rule { width: 3px; border-radius: 999px; background: var(--brand); opacity: .5; flex: none; }

/* Marks ----------------------------------------------------------------- */
.mark-bar { height: 6px; border-radius: 999px; background: var(--line); overflow: hidden; margin-top: 7px; }
.mark-bar span { display: block; height: 100%; border-radius: 999px; background: var(--good); }
.mark-bar.is-low span { background: var(--warn); }

/* Children -------------------------------------------------------------- */
.kid { display: flex; align-items: center; gap: 12px; width: 100%;
    background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
    padding: 14px; margin-bottom: 10px; text-align: left; box-shadow: var(--shadow); }
.kid.is-on { border-color: var(--brand); box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 14%, transparent); }
.avatar { width: 42px; height: 42px; border-radius: 13px; flex: none; background: var(--brand);
    color: #fff; display: inline-flex; align-items: center; justify-content: center;
    font-weight: 700; font-size: 16px; }

/* Sign-in --------------------------------------------------------------- */
.auth { padding: 7vh var(--pad) var(--pad); max-width: 26rem; margin: 0 auto; }
.auth-mark {
    width: 66px; height: 66px; border-radius: 20px; background: var(--brand);
    background-image: linear-gradient(160deg, rgba(255,255,255,.18), rgba(0,0,0,.14));
    color: #fff; display: flex; align-items: center; justify-content: center;
    font-size: 27px; font-weight: 750; margin: 0 auto 20px;
    box-shadow: 0 10px 26px -10px color-mix(in srgb, var(--brand) 60%, transparent);
}
.auth h1 { font-size: 22px; text-align: center; margin: 0 0 7px; letter-spacing: -.025em; }
.auth p.lede { text-align: center; color: var(--muted); margin: 0 0 24px; font-size: 14px; }

.field { margin-bottom: 14px; }
.field label { display: block; font-size: 12.5px; color: var(--muted); font-weight: 600; margin-bottom: 6px; }
.field input {
    width: 100%; height: 50px; padding: 0 15px;
    border: 1.5px solid var(--line); border-radius: var(--radius-sm); background: #fff;
}
.field input:focus { outline: 0; border-color: var(--brand);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 16%, transparent); }

.btn { width: 100%; min-height: 50px; border: 0; border-radius: var(--radius-sm);
    background: var(--brand); color: #fff; font-weight: 650; letter-spacing: -.01em; }
.btn:disabled { opacity: .55; }
.btn-quiet { background: transparent; color: var(--brand); font-weight: 600; min-height: var(--tap); }

.note { font-size: 13px; color: var(--muted); margin: 10px 0 0; }
.err { background: var(--bad-bg); border: 1px solid #F6CBCB; color: #8F1D1D;
    border-radius: var(--radius-sm); padding: 12px 14px; font-size: 13.5px; margin-bottom: 14px; }
.ok-note { background: var(--good-bg); border: 1px solid #BCE9CE; color: #0B5F30;
    border-radius: var(--radius-sm); padding: 12px 14px; font-size: 13.5px; margin-bottom: 14px; }

/* Tabs ------------------------------------------------------------------ */
.tabs {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;
    display: grid; grid-template-columns: repeat(4, 1fr);
    background: rgba(255,255,255,.96); border-top: 1px solid var(--line);
    padding-bottom: env(safe-area-inset-bottom);
    backdrop-filter: saturate(180%) blur(10px);
}
.tab { background: 0; border: 0; padding: 9px 4px 8px; min-height: var(--tap);
    display: flex; flex-direction: column; align-items: center; gap: 4px;
    font-size: 10.5px; font-weight: 600; color: var(--muted); }
.tab.is-on { color: var(--brand); }
.tab.is-on .tab-ico { background: color-mix(in srgb, var(--brand) 12%, transparent); }
.tab-ico { width: 30px; height: 22px; border-radius: 8px;
    display: inline-flex; align-items: center; justify-content: center; }

/* Empty, stale, skeleton ------------------------------------------------ */
.empty { text-align: center; color: var(--muted); padding: 46px 14px; }
.empty svg { margin: 0 auto 12px; opacity: .35; }
.stale { background: var(--warn-bg); color: var(--warn); text-align: center;
    font-size: 12.5px; font-weight: 600; padding: 8px 12px; }
.skeleton { background: linear-gradient(90deg,#EDF0F6,#F7F9FC,#EDF0F6);
    background-size: 200% 100%; animation: sheen 1.2s linear infinite;
    border-radius: 8px; height: 14px; margin: 10px 0; }
@keyframes sheen { to { background-position: -200% 0; } }
@media (prefers-reduced-motion: reduce) { .skeleton { animation: none; } }

/* Install prompt -------------------------------------------------------- */
.install {
    position: fixed; left: 12px; right: 12px; bottom: 76px; z-index: 40;
    background: var(--ink); color: #fff; border-radius: var(--radius);
    padding: 13px 15px; display: flex; align-items: center; gap: 12px;
    box-shadow: 0 14px 34px -12px rgba(0,0,0,.5);
}
.install p { margin: 0; font-size: 13.5px; flex: 1; }
.install button { background: #fff; color: var(--ink); border: 0;
    border-radius: 9px; padding: 9px 14px; font-weight: 700; }
.install .install-x { background: transparent; color: rgba(255,255,255,.65); padding: 8px; }

@media (min-width: 640px) {
    .app { max-width: 30rem; margin: 0 auto; background: var(--bg);
           box-shadow: 0 0 0 1px var(--line); }
    .tabs, .install { max-width: 30rem; margin: 0 auto; }
}

/* Module launcher --------------------------------------------------------
   Four across is what fits a phone without the labels wrapping, and it is
   also what a parent can take in without reading each one. */
.grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 4px; }
.mod { background: 0; border: 0; padding: 10px 2px; display: flex;
    flex-direction: column; align-items: center; gap: 7px; border-radius: 12px; }
.mod:active { background: var(--bg); }
.mod .tile-ico { width: 40px; height: 40px; border-radius: 13px; }
.mod-l { font-size: 11px; font-weight: 600; color: var(--ink-2);
    text-align: center; line-height: 1.25; }

/* Attendance calendar ---------------------------------------------------- */
.cal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.cal-title { font-weight: 700; letter-spacing: -.02em; }
.cal-nav { background: var(--bg); border: 0; width: 32px; height: 32px; border-radius: 10px;
    color: var(--ink-2); display: inline-flex; align-items: center; justify-content: center; }
.cal-nav:first-child svg { transform: rotate(180deg); }
.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.cal-dow { font-size: 10.5px; font-weight: 700; color: var(--muted);
    text-align: center; margin-bottom: 4px; text-transform: uppercase; }
.cal-cell { aspect-ratio: 1; display: flex; flex-direction: column;
    align-items: center; justify-content: center; gap: 3px; }
.cal-n { font-size: 12.5px; font-weight: 600; color: var(--ink-2); }
.cal-dot { width: 6px; height: 6px; border-radius: 50%; background: transparent; }
.dot-good { background: var(--good); } .dot-bad { background: var(--bad); }
.dot-warn { background: var(--warn); } .dot-info { background: #94A3B8; }
.cal-legend { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 14px;
    padding-top: 12px; border-top: 1px solid var(--line); }
.cal-key { display: inline-flex; align-items: center; gap: 5px;
    font-size: 11.5px; color: var(--muted); font-weight: 600; }

/* Homework ---------------------------------------------------------------
   Filter chips carry their counts, so a parent can see there is nothing
   pending without tapping into the tab to find out. */
.chips { display: flex; gap: 8px; overflow-x: auto; padding: 2px 0 14px;
    -webkit-overflow-scrolling: touch; scrollbar-width: none; }
.chips::-webkit-scrollbar { display: none; }
.chip { flex: none; display: inline-flex; align-items: center; gap: 6px;
    padding: 8px 13px; border-radius: 999px; border: 1px solid var(--line);
    background: var(--card); color: var(--ink-2); font-size: 13px; font-weight: 600; }
.chip.is-on { background: var(--brand); border-color: var(--brand); color: #fff; }
.chip-n { font-size: 11px; font-weight: 700; opacity: .7; }
.chip.is-on .chip-n { opacity: .85; }

.hw-head { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.hw-code { font-weight: 600; color: var(--muted); font-size: 12.5px; }
.hw-body { border-top: 1px solid var(--line); padding-top: 4px; }
.hw-row { display: flex; justify-content: space-between; gap: 12px; padding: 7px 0;
    font-size: 13px; color: var(--muted); }
.hw-row b { color: var(--ink); font-weight: 650; text-align: right; }
.hw-desc { margin: 10px 0 0; padding-top: 11px; border-top: 1px solid var(--line);
    font-size: 13.5px; line-height: 1.55; color: var(--ink-2); }
.hw-note { margin-top: 10px; padding: 10px 12px; border-radius: var(--radius-sm);
    background: var(--good-bg); color: #0B5F30; font-size: 13px; }

/* Home ------------------------------------------------------------------
   One card carries the colour and everything under it stays quiet, so the
   eye lands on the number the parent opened the app to see. The gradient is
   mixed from the school's own colour rather than replacing it, which keeps a
   grey-branded school looking deliberate instead of unfinished. */
.top-hello { font-size: 12px; opacity: .75; margin-bottom: 1px; }

.spot {
    position: relative; overflow: hidden;
    border-radius: 20px; padding: 20px; margin-bottom: 14px; color: #fff;
    background:
        radial-gradient(115% 120% at 92% -10%, rgba(255,255,255,.26), transparent 55%),
        linear-gradient(135deg,
            color-mix(in srgb, var(--brand) 88%, #2B6BE4),
            color-mix(in srgb, var(--brand) 62%, #6D3BEB));
    box-shadow: 0 12px 28px -14px color-mix(in srgb, var(--brand) 70%, #000);
}
.spot::after {
    content: ''; position: absolute; right: -30px; bottom: -46px;
    width: 140px; height: 140px; border-radius: 50%;
    background: rgba(255,255,255,.07);
}
.spot-top { display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.spot-kicker { font-size: 12.5px; font-weight: 600; opacity: .82; }
.spot-big { font-size: 42px; font-weight: 780; letter-spacing: -.045em; line-height: 1.05; margin-top: 2px; }
.spot-big span { font-size: 22px; font-weight: 650; opacity: .8; margin-left: 2px; }
.spot-sub { font-size: 13px; opacity: .85; margin-top: 3px; }
.spot-bar { height: 6px; border-radius: 999px; background: rgba(255,255,255,.24);
    overflow: hidden; margin-top: 18px; position: relative; z-index: 1; }
.spot-bar span { display: block; height: 100%; border-radius: 999px; background: #fff; }

.ring.on-dark .ring-track { stroke: rgba(255,255,255,.26); }
.ring.on-dark .ring-fill  { stroke: #fff; }
.ring.on-dark .ring-text  { color: #fff; }

/* Three figures worth glancing at, each its own colour so they separate. */
.stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin-bottom: 4px; }
.stat { border: 0; border-radius: 16px; padding: 14px 12px; text-align: left;
    display: flex; flex-direction: column; gap: 4px; }
.stat:active { transform: scale(.985); }
.stat-n { font-size: 19px; font-weight: 780; letter-spacing: -.03em; line-height: 1.1; }
.stat-l { font-size: 11.5px; font-weight: 600; opacity: .8; }
.s-warn { background: var(--warn-bg); color: #8A5208; }
.s-info { background: var(--info-bg); color: #1B4ACB; }
.s-good { background: var(--good-bg); color: #0B6B36; }
.s-bad  { background: var(--bad-bg);  color: #A32020; }

/* button.card sets display:block and outranks a single class, so this has
   to match with the same reach or the row stacks. */
.card.next { display: flex; align-items: center; gap: 14px; }
.next-time { flex: none; font-size: 13px; font-weight: 750; color: var(--brand);
    background: color-mix(in srgb, var(--brand) 10%, transparent);
    padding: 8px 10px; border-radius: 10px; font-variant-numeric: tabular-nums; }

/* Launcher tiles carry a tint, so the grid reads as buttons not a table. */
.mod .tile-ico { width: 46px; height: 46px; border-radius: 15px; }
.grid { gap: 6px; }
.mod { padding: 12px 2px; }
