/* =====================================================================
   The Exam Room — the design system, written for this app's own markup.
   Canvas: claude.ai/artifact/1on2znjrvgXPyEq2SGP3Xg

   Rules this file enforces:
     one screen, one job · a number beats a sentence · a subject reads as
     a tint or a dot, never a coloured edge · work you sit down to do
     takes the whole window.
   ===================================================================== */

:root{
  --ground:#F5F6F8; --surface:#FFFFFF; --sunk:#F5F6F8; --line:#ECEDF1; --line2:#DDDFE6;
  --ink:#33353F; --ink2:#4A4C58; --muted:#6B6E7C; --faint:#9C9FAC;

  /* violet. Fills use the deep one: white on #5B54F0 misses 4.5:1. */
  --accent:#4A43C9; --accent-hi:#3A34A8; --accent-soft:#EDECFE;
  --night:#2A2B33; --night-2:#A8AAB8;

  --good:#17694B; --good-bg:#E6F6EC;
  --warn:#7A5600; --warn-bg:#FFF9EA;
  --bad:#A32F22;  --bad-bg:#FFF1EF;

  --r-card:24px; --r-row:18px; --r-tile:14px; --r-pill:999px;
  --shadow:0 2px 40px rgba(205,208,223,.4);
  --shadow-lift:0 18px 44px -18px rgba(13,27,42,.4);

  --f:"Plus Jakarta Sans",system-ui,-apple-system,"Segoe UI",sans-serif;
  --display:"Bricolage Grotesque",var(--f);
  --rail:248px;
  color-scheme:light;
}

*,*::before,*::after{box-sizing:border-box}
/* hidden means hidden, whatever a component says about display */
[hidden]{display:none!important}
html,body{margin:0;background:var(--ground)}
body{font-family:var(--f);font-size:15px;line-height:1.55;color:var(--ink);
  font-variant-numeric:tabular-nums;-webkit-font-smoothing:antialiased}
h1,h2,h3{margin:0;font-family:var(--display);font-weight:700;letter-spacing:-.025em;line-height:1.1}
h1{font-size:2.1rem} h2{font-size:1.25rem} h3{font-size:1.05rem}
p{margin:0}
a{color:var(--accent);text-decoration:none}
a:hover{color:var(--accent-hi)}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}
input,textarea,select{font:inherit;color:inherit}
:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:6px}
/* Reduced motion means less travel, not no answer.

   Entrances and anything that slides go. What stays: every colour,
   background and opacity transition, at its normal speed, because that
   is how this interface says a thing happened — and the chevron's
   rotation, which is a state and not a movement. */
@media (prefers-reduced-motion:reduce){
  *{scroll-behavior:auto!important}
  .arrive,.opened,.opened .goalcard,.toast,.toast.out,
  .task.ticking,.task.ticking .tick{animation:none!important}
  .btn:active,.pill:active,.chip:active,.step:active,.put:active,
  .dayplus:active,.tick:active,.overrow:hover .dot,.standrow:hover .dot,
  .task:hover .dot{transform:none!important}
  .overrow .chev{transition:color var(--t-state)}
}

/* ---------------------------------------------------------- text roles */
.eyebrow{font-size:.7rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--faint)}
.metric{font-family:var(--display);font-weight:700;letter-spacing:-.02em;line-height:1}
.sm{font-size:.86rem} .xs{font-size:.78rem}
.muted{color:var(--muted)} .faint{color:var(--faint)}
.grow{flex:1;min-width:0}

/* -------------------------------------------------------------- shell */
.shell{display:grid;grid-template-columns:var(--rail) minmax(0,1fr);min-height:100vh}
.rail{position:sticky;top:0;height:100vh;overflow-y:auto;background:var(--surface);
  padding:24px 16px;display:flex;flex-direction:column;gap:4px}
.brand{display:flex;align-items:center;gap:11px;padding:0 10px 18px}
.brandmark{width:36px;height:36px;border-radius:12px;background:#5B54F0;color:#fff;flex:0 0 auto;
  display:flex;align-items:center;justify-content:center;font-family:var(--display);font-size:.95rem;font-weight:700}
.brand b{font-family:var(--display);font-size:1.18rem;letter-spacing:-.02em}
.searchbtn{display:flex;align-items:center;gap:9px;height:40px;padding:0 12px;margin-bottom:10px;
  border-radius:12px;background:var(--sunk);color:var(--faint);font-size:.86rem;width:100%}
.searchbtn kbd{margin-left:auto;font:inherit;font-size:.72rem;font-weight:700;color:#C3C5CE}

.nav{display:flex;align-items:center;gap:11px;width:100%;height:44px;padding:0 12px;
  border-radius:12px;font-size:.92rem;font-weight:600;color:var(--ink);text-align:left}
.nav:hover{background:var(--sunk)}
.nav.on{background:var(--accent-soft);color:var(--accent-hi);font-weight:700}
.nav .n{margin-left:auto;font-size:.78rem;font-weight:700;color:var(--faint)}
.nav.on .n{color:var(--accent-hi)}
.nav .pip{margin-left:auto;min-width:22px;height:22px;padding:0 7px;border-radius:var(--r-pill);
  background:var(--accent);color:#fff;font-size:.72rem;font-weight:700;
  display:inline-flex;align-items:center;justify-content:center}
.nav.on .pip{background:var(--accent-hi)}
.nav.child{height:38px;padding-left:34px;font-size:.85rem;font-weight:600;color:var(--ink2);position:relative}
.nav.child .swatch{position:absolute;left:13px;top:50%;margin-top:-5px;width:10px;height:10px;
  border-radius:3px;background:var(--sub,var(--line2))}
.nav.add{color:var(--faint);font-weight:600}
.railfoot{margin-top:auto;display:flex;align-items:center;gap:11px;padding:14px 10px 0;border-top:1px solid var(--line)}
.avatar{width:34px;height:34px;border-radius:var(--r-pill);flex:0 0 auto;display:flex;
  align-items:center;justify-content:center;font-size:.8rem;font-weight:700;background:var(--accent-soft);color:var(--accent-hi)}

/* width:100% matters: .page is a grid item, and auto margins on a grid
   item shrink it to its content instead of centring it. */
.page{width:100%;padding:40px 36px 96px;max-width:1240px;margin-inline:auto}
.phead{display:flex;align-items:flex-end;justify-content:space-between;gap:22px;margin-bottom:26px}
.phead .sub{margin-top:6px;font-size:.94rem;color:var(--muted)}
.stack{display:flex;flex-direction:column;gap:22px}

/* -------------------------------------------------------------- atoms */
.card{background:var(--surface);border-radius:var(--r-card);box-shadow:var(--shadow);padding:24px 26px}
.card.flat{box-shadow:none;background:transparent;padding:0}
.card h2+.sub{margin-top:4px}
.cardhead{display:flex;align-items:baseline;gap:12px;margin-bottom:14px}
.cardhead .sm{color:var(--muted)}

.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;height:44px;padding:0 22px;
  border-radius:var(--r-pill);border:1px solid var(--line2);background:var(--surface);
  font-size:.92rem;font-weight:700;line-height:1;white-space:nowrap}
.btn:hover{background:var(--sunk)}
.btn.primary{background:var(--accent);border-color:var(--accent);color:#fff}
.btn.primary:hover{background:var(--accent-hi);border-color:var(--accent-hi)}
.btn.quiet{border-color:transparent;color:var(--muted)}
.btn.quiet:hover{background:var(--sunk);color:var(--ink)}
.btn.small{height:36px;padding:0 16px;font-size:.84rem}

.chip{display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 11px;border-radius:var(--r-pill);
  background:var(--sunk);color:var(--muted);font-size:.75rem;font-weight:700;white-space:nowrap}
.chip.accent{background:var(--accent-soft);color:var(--accent-hi)}
.chip.good{background:var(--good-bg);color:var(--good)}
.chip.warn{background:var(--warn-bg);color:var(--warn)}
.chip.bad{background:var(--bad-bg);color:var(--bad)}
.dot{width:10px;height:10px;border-radius:3px;flex:0 0 auto;background:var(--sub,var(--line2))}

.bar{height:8px;border-radius:var(--r-pill);background:#F0F1F5;overflow:hidden}
.bar i{display:block;height:100%;border-radius:var(--r-pill);background:var(--sub,var(--accent))}

.empty{border:1px dashed var(--line2);border-radius:var(--r-row);padding:26px 22px;
  color:var(--muted);font-size:.9rem;text-align:center}

/* ---------------------------------------------------------- a task row */
.task{display:flex;align-items:center;gap:14px;padding:14px 18px;border-radius:var(--r-row);
  border:1px solid var(--line);background:var(--surface)}
.task+.task{margin-top:10px}
.task .tick{width:22px;height:22px;flex:0 0 auto;border-radius:7px;border:1.8px solid var(--line2);
  background:var(--surface);display:flex;align-items:center;justify-content:center;color:transparent}
.task .tick:hover{border-color:var(--accent)}
.task .body{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px;text-align:left}
.task .t{font-size:1rem;font-weight:700;line-height:1.35}
.task .m{display:flex;align-items:center;gap:8px;font-size:.82rem;color:var(--muted)}
.task.first{border-color:transparent}
.task.done{opacity:.55}
.task.done .t{text-decoration:line-through}
.task.done .tick{background:var(--accent);border-color:var(--accent);color:#fff}
@supports (background:color-mix(in srgb,#000 10%,#fff)){
  .task.first{background:color-mix(in srgb,var(--sub) 12%,#fff)}
  .task.first .m{color:color-mix(in srgb,var(--sub) 76%,#33353F);font-weight:600}
}

/* ------------------------------------------------------- the ledger
   Every countdown in the app: dot, name, date, days. Nothing else. */
.ledger{display:flex;flex-direction:column}
.ledger .line{display:flex;align-items:baseline;gap:12px;padding:11px 0;border-top:1px solid var(--line)}
.ledger .line:first-child{border-top:0}
.ledger .nm{flex:1;min-width:0;font-size:.94rem;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ledger .dt{font-size:.8rem;color:var(--faint);white-space:nowrap}
.ledger .dy{width:40px;text-align:right;font-family:var(--display);font-size:1.1rem;font-weight:700}
.ledger .line.next .nm{font-weight:700}
@media (max-width:820px){
  /* flex:1 with min-width:0 shrinks rather than wrapping, because a
     line only wraps when the flex BASES overflow it and a base of zero
     never does. Two fixed columns left the name 91px. A floor makes
     the line overflow honestly, so the row wraps instead. */
  .ledger .line{flex-wrap:wrap;gap:6px 12px}
  .ledger .nm{min-width:55%;white-space:normal}
}

/* -------------------------------------------------------- subject card */
.subjects{display:grid;grid-template-columns:repeat(auto-fit,minmax(236px,1fr));gap:18px}
.subjcard{display:flex;flex-direction:column;gap:13px;padding:20px;border-radius:var(--r-card);
  background:var(--sunk);color:var(--ink);text-align:left}
.subjcard .top{display:flex;align-items:center;justify-content:space-between}
.subjcard .tile{width:44px;height:44px;border-radius:var(--r-tile);background:#fff;
  display:flex;align-items:center;justify-content:center}
.subjcard .tile i{width:16px;height:16px;border-radius:5px;background:var(--sub,var(--line2))}
.subjcard .days{height:26px;padding:0 11px;border-radius:var(--r-pill);background:#fff;
  display:inline-flex;align-items:center;font-size:.74rem;font-weight:700}
.subjcard .nm{font-family:var(--display);font-size:1.15rem;font-weight:700;letter-spacing:-.02em}
.subjcard .m{font-size:.82rem;opacity:.85}
.subjcard:hover{box-shadow:var(--shadow)}
@supports (background:color-mix(in srgb,#000 10%,#fff)){
  .subjcard{background:color-mix(in srgb,var(--sub) 12%,#fff);color:color-mix(in srgb,var(--sub) 84%,#33353F)}
  .subjcard .bar{background:color-mix(in srgb,var(--sub) 24%,#fff)}
  .subjcard .bar i{background:currentColor}
}

/* ------------------------------------------------------- subject page */
.withmargin{display:grid;grid-template-columns:minmax(0,1fr) 320px;gap:26px;align-items:start}
.withmargin>.main{display:flex;flex-direction:column;gap:20px;min-width:0}
.withmargin>.margin{display:flex;flex-direction:column;gap:18px;position:sticky;top:24px}
@media (max-width:1080px){.withmargin{grid-template-columns:minmax(0,1fr)}.withmargin>.margin{position:static}}
.index{display:flex;flex-direction:column;gap:2px}
.index .row{display:flex;align-items:center;gap:12px;height:46px;padding:0 12px;border-radius:var(--r-tile);text-align:left}
.index .row:hover{background:var(--sunk)}
.index .ico{width:32px;height:32px;border-radius:10px;flex:0 0 auto;display:flex;align-items:center;justify-content:center}
.index .t{flex:1;min-width:0;font-size:.92rem;font-weight:700}
.index .s{font-size:.82rem;color:var(--muted);white-space:nowrap}

/* --------------------------------------------------- adding to the list
   The row that puts something on the list sits at the foot of the list
   it adds to, not behind a button on another screen. */
.addrow{display:flex;align-items:center;gap:10px;padding:14px 18px;margin-top:10px;
  border:1px dashed var(--line2);border-radius:var(--r-row)}
.addrow input,.addrow select{height:40px;border:1px solid var(--line2);border-radius:12px;
  padding:0 12px;background:var(--surface);font-size:.88rem;min-width:0}
.addrow input[name=title]{flex:1;border-style:dashed}
.addrow input[name=title]:focus{border-style:solid}
.addrow input[name=mins]{width:74px}
.addrow select{max-width:150px}
.addrow input:focus,.addrow select:focus{border-color:var(--accent);outline:none;
  box-shadow:0 0 0 3px var(--accent-soft)}
.dayadd{display:flex;flex-direction:column;gap:8px;margin-top:auto}
.dayadd input{height:36px;border:1px solid var(--accent);border-radius:12px;padding:0 10px;
  font-size:.78rem;box-shadow:0 0 0 3px var(--accent-soft);width:100%}
@media (max-width:820px){
  .addrow{flex-wrap:wrap}
  .addrow input[name=title],.addrow input[name=name]{flex:1 1 100%}
  .addrow select,.addrow input{min-width:96px}
}

/* the exam dates, when they are not the point of the page */
.datesline{display:flex;align-items:center;gap:12px;width:100%;padding:14px 18px;
  border-radius:var(--r-row);background:var(--surface);font-size:.9rem;color:var(--ink2);text-align:left}
.datesline:hover{box-shadow:var(--shadow)}
.datesline b{color:var(--ink)}
/* The same line, holding a paper you have not handed in. It is a div
   rather than a button because it carries two controls: pick it up,
   and throw it away. A button inside a button is not markup. */
.paperback{cursor:default}
.paperback .dot{flex:none}
.paperback .grow{flex:1;min-width:0;text-align:left;font:inherit;color:inherit;
  white-space:normal;line-height:1.35}
.paperback .grow:hover{color:var(--accent-hi)}
.paperback .toss{width:30px;height:30px;flex:0 0 auto;border-radius:999px;
  color:var(--faint);font-size:.8rem}
.paperback .toss:hover{color:var(--bad);background:var(--bad-bg)}
/* This one throws work away, so it gets the 44px this stylesheet asks
   for a few rules further down and the older discard controls never
   got. It sits beside a 243px target; a mis-tap should be hard.*/
@media (max-width:820px){ .paperback .toss{width:44px;height:44px} }

/* ------------------------------------------------------- the grading
   Rust to green, 1 to 5. The colour carries the meaning, so a page of
   green reads as ready and a page of rust reads as tonight's work. */
:root{--g1:#B4442E;--g2:#C4741B;--g3:#8E8412;--g4:#3E8A57;--g5:#17694B}
.grade{display:flex;gap:3px}
.grade button{width:28px;height:24px;border-radius:6px;background:#EFF0F4;
  font-size:.72rem;font-weight:700;color:var(--faint);line-height:1}
.grade button:hover{outline:2px solid var(--accent);outline-offset:1px}
.grade button.on{color:#fff}
.grade button.g1.on{background:var(--g1)} .grade button.g2.on{background:var(--g2)}
.grade button.g3.on{background:var(--g3)} .grade button.g4.on{background:var(--g4)}
.grade button.g5.on{background:var(--g5)}
.gradekey{display:flex;align-items:center;gap:8px;font-size:.76rem;color:var(--faint)}
.gradekey i{width:14px;height:8px;border-radius:3px;display:inline-block}

/* the syllabus: one line per point, rating on the right */
.topic{display:flex;flex-direction:column;gap:2px}
.topic .th{display:flex;align-items:center;gap:12px;margin-bottom:8px}
.point{display:flex;align-items:center;gap:16px;padding:12px 0;width:100%;min-width:0;border-top:1px solid var(--line)}
/* A button, so a keyboard can reach it — and still a line of text, so
   nothing about the row looks different. */
.point .lbl{flex:1;min-width:0;font-size:.92rem;font-weight:600;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap;text-align:left;padding:0;
  background:none;border:0;color:inherit;font-family:inherit}
.point .lbl:hover{color:var(--accent-hi)}
.point .lbl.full{white-space:normal}
.point .note{font-size:.78rem;color:var(--faint);white-space:nowrap}
.rate{display:flex;gap:3px}
.rate button{width:26px;height:22px;border-radius:5px;background:#ECEDF1;font-size:.7rem;font-weight:700;color:transparent}
.rate button.on{background:var(--sub,var(--accent))}
.rate button:hover{outline:2px solid var(--accent);outline-offset:1px}

/* ------------------------------------------------------------ the week */
.week{display:flex;gap:12px;align-items:stretch}
.day{flex:1;min-width:0;min-height:480px;padding:14px 12px;border-radius:var(--r-card);
  background:var(--surface);box-shadow:var(--shadow);display:flex;flex-direction:column;gap:8px}
.day.today{outline:2px solid var(--accent);outline-offset:-2px}
.day .dhead{display:flex;align-items:flex-start;justify-content:space-between}
.day .dnum{font-family:var(--display);font-size:1.3rem;font-weight:700;line-height:1}
.day.today .dnum,.day.today .eyebrow{color:var(--accent)}
.day .plus{width:26px;height:26px;border-radius:9px;background:var(--sunk);color:var(--muted);
  font-size:1rem;font-weight:700;line-height:1}
.day .plus:hover{background:var(--accent-soft);color:var(--accent)}
/* how full the day is against the time you said you had */
.day .load{height:4px;border-radius:var(--r-pill);background:#F0F1F5;overflow:hidden}
.day .load i{display:block;height:100%;background:var(--accent);border-radius:var(--r-pill)}
.day .load.over i{background:var(--bad)}
.day .loadlab{font-size:.66rem;color:var(--faint);font-weight:600;margin-top:-4px}
/* a busy day scrolls inside its own column instead of stretching the page */
.day .slots{display:flex;flex-direction:column;gap:7px;overflow-y:auto;flex:1;
  margin:0 -4px;padding:0 4px;scrollbar-width:thin}
.slot{position:relative;padding:9px 11px;border-radius:var(--r-tile);background:var(--sunk);
  display:flex;flex-direction:column;gap:2px}
.slot .grab{text-align:left;display:flex;flex-direction:column;gap:2px;color:inherit}
.slot .at{font-size:.64rem;font-weight:700;letter-spacing:.06em;opacity:.75}
.slot b{font-size:.78rem;font-weight:700;line-height:1.3}
.slot span{font-size:.7rem}
.slot.done{opacity:.5}.slot.done b{text-decoration:line-through}
@supports (background:color-mix(in srgb,#000 10%,#fff)){
  .slot{background:color-mix(in srgb,var(--sub) 13%,#fff);color:color-mix(in srgb,var(--sub) 82%,#33353F)}
}
.anytime{font-size:.62rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  color:var(--faint);padding:6px 2px 2px;border-top:1px solid var(--line)}
.dayempty{font-size:.72rem;color:var(--faint);padding:6px 2px}
.day .clear{font-size:.72rem;font-weight:700;color:var(--good);padding:4px 2px}
.dayadd .two{display:flex;gap:6px}
.dayadd .two select,.dayadd .two input{min-width:0;flex:1}
.dayadd input[type=time]{height:32px;border:1px solid var(--line2);border-radius:10px;
  padding:0 6px;font-size:.72rem;background:var(--surface)}
@media (max-width:1100px){.week{flex-wrap:wrap}.day{flex:1 1 30%;min-height:300px}}

/* how long you have each day */
.hours{display:flex;align-items:center;gap:16px;flex-wrap:wrap}
.hours .days{display:flex;gap:6px}
.dayflag{height:32px;padding:0 12px;border-radius:var(--r-pill);background:var(--sunk);
  font-size:.76rem;font-weight:700;color:var(--muted)}
.dayflag.on{background:var(--accent-soft);color:var(--accent-hi)}
.hours .mins{display:flex;align-items:center;gap:8px;margin-left:auto;font-size:.8rem;
  font-weight:700;color:var(--muted)}
.hours .mins input{width:80px;height:36px;border:1px solid var(--line2);border-radius:10px;
  padding:0 10px;font-size:.86rem;background:var(--surface)}
.addrow input[type=time]{width:110px}

/* a card that is reference, not the point of the page */
.card.quiet{box-shadow:none;background:transparent;border:1px solid var(--line);padding:18px 22px}
.card.quiet .ledger .dy{font-size:1rem}

/* one subject's standing: name, how far through, average, days left */
.standrow{display:grid;grid-template-columns:auto 200px minmax(80px,1fr) 60px 76px;
  align-items:center;gap:14px;padding:13px 0;border-top:1px solid var(--line);text-align:left;width:100%}
.standrow .nm{font-size:.94rem;font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.standrow .av{text-align:right;font-size:.92rem;font-weight:700}
.standrow .dy{text-align:right;font-size:.82rem;color:var(--muted)}
.standrow:hover .nm{color:var(--accent)}
@media (max-width:820px){
  .standrow{grid-template-columns:auto 1fr auto;row-gap:8px}
  .standrow .bar{grid-column:1/-1}
  /* The name column is 1fr, which is 150px on a 320 screen — and
     "Topic 3 — Economic Issues" is cut before it says which topic.
     Two lines beats an ellipsis on the word that identifies it. */
  .standrow .nm{white-space:normal}
}

/* ------------------------------------------------------------- stats */
.stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:18px}
.stat{padding:22px 24px;border-radius:var(--r-card);background:var(--surface);box-shadow:var(--shadow);
  display:flex;flex-direction:column;gap:5px}
.stat .metric{font-size:2rem}
.stat.dark{background:var(--night);box-shadow:none}
.stat.dark .eyebrow{color:var(--night-2)}
.stat.dark .metric{color:#fff}
.stat.dark .sm{color:var(--night-2)}

/* -------------------------------------------------------- focus mode */
.focus{min-height:100vh;display:flex;flex-direction:column;background:var(--ground)}
.focusbar{position:sticky;top:0;z-index:40;display:flex;align-items:center;gap:14px;height:64px;
  padding:0 22px;background:var(--surface)}
.focusbar b{font-family:var(--display);font-size:1.02rem;letter-spacing:-.02em}
.focusbody{width:100%;max-width:1180px;margin:0 auto;padding:26px 24px 80px}
.timer{display:inline-flex;align-items:center;gap:9px;height:40px;padding:0 18px;border-radius:var(--r-pill);
  background:var(--accent-soft);color:var(--accent);font-family:var(--display);font-size:1.15rem;font-weight:700}

/* ------------------------------------------------------ sitting a paper
   Question left, answer right, a strip of where you are along the bottom.
   Nothing else is on the screen, because nothing else is the job. */
.runbar{display:flex;align-items:center;gap:14px;margin-bottom:20px}
.runbar b{font-family:var(--display);font-size:1.05rem;letter-spacing:-.02em}
.runcols{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:20px;align-items:start}
.qtext{font-size:1.05rem;line-height:1.65}
.source{margin-top:16px;padding:18px 20px;border-radius:var(--r-row);background:var(--sunk)}
.source p{margin-top:8px;font-size:.94rem;line-height:1.65;color:var(--ink2)}
.answer textarea{width:100%;min-height:320px;margin-top:12px;padding:18px 20px;resize:vertical;
  border:1px solid var(--line2);border-radius:var(--r-row);font-family:var(--f);
  font-size:1rem;line-height:1.8}
.answer textarea:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
.runfoot{display:flex;align-items:center;gap:12px;margin-top:14px}
.qstrip{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:22px;
  padding:16px 20px;border-radius:var(--r-card);background:var(--surface);box-shadow:var(--shadow)}
.qstrip button{width:42px;height:42px;border-radius:var(--r-tile);background:var(--sunk);
  font-size:.92rem;font-weight:700;color:var(--muted)}
.qstrip button.done{background:var(--good-bg);color:var(--good)}
.qstrip button.here{background:var(--accent);color:#fff}
@media (max-width:900px){.runcols{grid-template-columns:minmax(0,1fr)}
  .answer textarea{min-height:220px}}

/* ------------------------------------------------------- the card run */
.cardface{min-height:320px;padding:44px;border-radius:var(--r-card);background:var(--surface);
  box-shadow:var(--shadow);display:flex;flex-direction:column;justify-content:center;
  align-items:center;text-align:center;gap:26px}
.cardface .front{font-size:1.5rem;font-weight:700;line-height:1.45;max-width:36ch}
.cardface .back{font-size:1.1rem;line-height:1.7;color:var(--ink2);max-width:46ch;
  border-top:1px solid var(--line);padding-top:26px;white-space:pre-wrap}
.runactions{display:flex;gap:12px;justify-content:center;margin-top:20px}
.runactions .btn{min-width:120px}
.btn.big{height:52px;padding:0 34px;font-size:1rem}
.btn.grade-g1{background:var(--g1);border-color:var(--g1);color:#fff}
.btn.grade-g2{background:var(--g2);border-color:var(--g2);color:#fff}
.btn.grade-g4{background:var(--g4);border-color:var(--g4);color:#fff}
.btn.grade-g5{background:var(--g5);border-color:var(--g5);color:#fff}
.runend{text-align:center;padding:52px}

/* ------------------------------------------------------ the phone bar */
.tabbar{display:none}
@media (max-width:960px){
  .shell{grid-template-columns:minmax(0,1fr)}
  .rail{position:fixed;inset:0 auto 0 0;width:270px;z-index:60;transform:translateX(-100%);
    transition:transform .16s ease;box-shadow:var(--shadow-lift)}
  .rail.open{transform:none}
  .scrim{position:fixed;inset:0;background:rgba(20,22,30,.4);z-index:55}
  .page{padding:20px 16px 108px}
  h1{font-size:1.7rem}
  .withmargin{gap:18px}
  .tabbar{display:flex;position:fixed;left:0;right:0;bottom:0;z-index:60;background:var(--surface);
    border-top:1px solid var(--line);padding:6px 6px 18px}
  .tabbar button{flex:1;min-height:52px;display:flex;flex-direction:column;align-items:center;
    justify-content:center;gap:3px;border-radius:14px;color:var(--muted);font-size:.7rem;font-weight:600;position:relative}
  .tabbar button.on{background:var(--accent-soft);color:var(--accent-hi);font-weight:700}
  .tabbar .pip{position:absolute;top:4px;right:26%;min-width:18px;height:18px;padding:0 5px;
    border-radius:var(--r-pill);background:var(--accent);color:#fff;font-size:.72rem;font-weight:700;
    display:flex;align-items:center;justify-content:center}
  /* nothing tappable under 44px on a phone */
  .btn,.btn.small,.chip,.markscale button,.qstrip button{min-height:44px}
  .grade button{height:34px;width:34px}
  .planrow .when{height:44px}
}

/* ------------------------------------------------------------- forms */
.stackform,.signform{display:flex;flex-direction:column;gap:14px}
.stackform label,.signform label{display:flex;flex-direction:column;gap:6px;
  font-size:.82rem;font-weight:700;color:var(--ink)}
.stackform input,.stackform select,.signform input{height:44px;padding:0 14px;font-size:.94rem;
  border:1px solid var(--line2);border-radius:var(--r-tile);background:var(--surface);font-weight:400}
.stackform input:focus,.stackform select:focus,.signform input:focus{outline:none;
  border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
.signform{margin-top:16px}
.lbl{display:block;font-size:.82rem;font-weight:700;margin-bottom:8px}
.swatches{display:flex;gap:8px;flex-wrap:wrap}
.sw{width:30px;height:30px;border-radius:9px}
.sw.on{outline:2px solid var(--accent);outline-offset:2px}

/* ----------------------------------------------- the list on the plan
   Write it down first; give it a day when you know one. */
.planrow{display:flex;align-items:center;gap:14px;padding:13px 16px;border-top:1px solid var(--line)}
.planrow:first-of-type{border-top:0}
.planrow .tick{width:22px;height:22px;flex:0 0 auto;border-radius:7px;border:1.8px solid var(--line2);
  display:flex;align-items:center;justify-content:center;color:transparent;background:var(--surface)}
.planrow .tick:hover{border-color:var(--accent)}
.planrow.done{opacity:.55}
.planrow.done .t{text-decoration:line-through}
.planrow.done .tick{background:var(--accent);border-color:var(--accent);color:#fff}
.planrow .t{display:block;font-size:.96rem;font-weight:700;line-height:1.35}
.planrow .m{display:flex;align-items:center;gap:7px;margin-top:3px;font-size:.8rem;color:var(--muted)}
.planrow .when{height:34px;border:1px solid var(--line2);border-radius:10px;padding:0 10px;
  font-size:.8rem;background:var(--surface);max-width:130px}
.planrow .when:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
.planrow .drop{width:30px;height:30px;border-radius:999px;color:var(--faint);font-size:.8rem}
.planrow .drop:hover{background:var(--bad-bg);color:var(--bad)}
.cardhead .chips{margin-left:auto;display:flex;align-items:center}
.dayadd select{height:32px;border:1px solid var(--line2);border-radius:10px;padding:0 8px;
  font-size:.74rem;background:var(--surface);width:100%}

/* --------------------------------------------------------- past papers
   A paper is a thing you have or have not sat, so the row leads with the
   year and ends with what you did about it. */
/* Wraps, because a row of filters that cannot wrap spills off the
   side of a 320px phone and takes the whole page with it. */
.filters{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:18px}
.filters .chip{cursor:pointer}
.paperrow{display:flex;align-items:center;gap:16px;padding:14px 16px;border-top:1px solid var(--line)}
.paperrow:first-of-type{border-top:0}
.paperrow .yr{width:52px;flex:0 0 auto;font-family:var(--display);font-size:1.05rem;font-weight:700;
  color:var(--muted)}
.paperrow .t{display:block;font-size:.96rem;font-weight:700;line-height:1.35}
.paperrow .m{display:block;margin-top:3px;font-size:.8rem;color:var(--muted)}
.paperrow .acts{display:flex;gap:8px;flex:0 0 auto}
.answerrow .acts{display:flex;gap:8px;flex:0 0 auto}
@media (max-width:820px){
  .paperrow{flex-wrap:wrap}
  .paperrow .acts{width:100%}
}

/* ------------------------------------------------- the coverage map
   Every point at once, coloured by how well it is known. The colour is
   the reading: a wall of rust is where the term goes. */
.covgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(170px,1fr));gap:8px}
.cov{min-height:62px;padding:10px 12px;border-radius:var(--r-tile);background:#EFF0F4;
  text-align:left;font-size:.78rem;font-weight:600;line-height:1.35;color:var(--muted);
  display:flex;align-items:flex-start}
.cov span{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.cov:hover{outline:2px solid var(--accent);outline-offset:1px}
.cov.g1{background:var(--g1);color:#fff} .cov.g2{background:var(--g2);color:#fff}
.cov.g3{background:var(--g3);color:#fff} .cov.g4{background:var(--g4);color:#fff}
.cov.g5{background:var(--g5);color:#fff}

/* ------------------------------------------------- answers and marks */
.answerrow{display:flex;align-items:center;gap:14px;width:100%;padding:14px 16px;
  border-radius:var(--r-row);text-align:left}
.answerrow+.answerrow{border-top:1px solid var(--line);border-radius:0}
.answerrow:hover{background:var(--sunk)}
.answerrow .t{display:block;font-size:.96rem;font-weight:700;line-height:1.35}
.answerrow .m{display:flex;align-items:center;gap:7px;margin-top:3px;font-size:.8rem;color:var(--muted)}
.written{margin-top:12px;font-size:1rem;line-height:1.9;white-space:pre-wrap}
.markscale{display:flex;gap:6px;flex-wrap:wrap;margin-top:6px}
.markscale button{min-width:42px;height:42px;border-radius:var(--r-tile);background:var(--sunk);
  font-size:.94rem;font-weight:700;color:var(--ink2)}
.markscale button:hover{outline:2px solid var(--accent);outline-offset:1px}
.markscale button.on{background:var(--accent);color:#fff}
.criteria{margin-top:16px;padding:16px 18px;border-radius:var(--r-row);background:var(--sunk)}

/* ------------------------------------------------------------ search */
.searchwrap{max-width:760px;margin:0 auto}
.searchwrap input{width:100%;height:60px;padding:0 22px;font-size:1.1rem;
  border:1px solid var(--line2);border-radius:var(--r-card);background:var(--surface)}
.searchwrap input:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 4px var(--accent-soft)}
.searchwrap .results{margin-top:18px;background:var(--surface);border-radius:var(--r-card);
  box-shadow:var(--shadow);overflow:hidden}
.searchwrap .results:empty{display:none}

/* ---------------------------------------------------------- sign in */
.signin{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:24px}
.signcard{width:100%;max-width:380px;background:var(--surface);border-radius:var(--r-card);
  box-shadow:var(--shadow);padding:30px}
.who{display:flex;align-items:center;gap:12px;width:100%;padding:12px;border-radius:var(--r-row);
  border:1px solid var(--line);background:var(--surface);text-align:left;margin-top:10px}
.who:hover{border-color:var(--accent);background:var(--accent-soft)}
.toast{position:fixed;left:50%;bottom:26px;transform:translateX(-50%);z-index:90;
  background:var(--night);color:#fff;padding:12px 18px;border-radius:var(--r-pill);
  font-size:.88rem;font-weight:600;box-shadow:var(--shadow-lift)}

/* ------------------------------------------- ticking a paper off
   Sitting a paper on paper still counts, so the mark is asked for at
   the moment it is ticked rather than on another screen later. */
.wentform{display:flex;align-items:center;gap:10px;flex-wrap:wrap;width:100%}
.wentform input[type=number]{width:84px}
.wentform input{height:38px;border:1px solid var(--line2);border-radius:10px;padding:0 10px;
  font-size:.86rem;background:var(--surface)}
.wentform input:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
.wentwrap{padding:12px 16px;border-top:1px solid var(--line);background:var(--sunk)}
.wentrow{background:var(--sunk);border-style:dashed}
.paperrow .tick{width:26px;height:26px;flex:0 0 auto;border-radius:8px;border:1.8px solid var(--line2);
  display:flex;align-items:center;justify-content:center;color:transparent;background:var(--surface)}
.paperrow .tick:hover{border-color:var(--accent)}
.paperrow .tick.on{background:var(--good);border-color:var(--good);color:#fff}

/* ---------------------------------------------- multiple choice
   Four rows you can hit without aiming. Once one is picked they all
   go quiet except the right one. */
.mcq{display:flex;flex-direction:column;gap:10px}
.mcq .opt{display:flex;align-items:flex-start;gap:12px;padding:14px 16px;text-align:left;
  border:1px solid var(--line2);border-radius:var(--r-row);background:var(--surface);width:100%}
.mcq .opt:hover{border-color:var(--accent);background:var(--accent-soft)}
.mcq .opt .k{width:26px;height:26px;flex:0 0 auto;border-radius:8px;background:var(--sunk);
  color:var(--muted);font-size:.8rem;font-weight:700;display:flex;align-items:center;justify-content:center}
.mcq .opt .v{font-size:.95rem;line-height:1.5}
.mcq .opt.done{pointer-events:none;opacity:.55}
.mcq .opt.right{opacity:1;border-color:var(--good);background:var(--good-bg)}
.mcq .opt.right .k{background:var(--good);color:#fff}
.mcq .opt.wrong{opacity:1;border-color:var(--bad);background:var(--bad-bg)}
.mcq .opt.wrong .k{background:var(--bad);color:#fff}
.qimg{display:block;width:100%;margin-top:16px;border-radius:var(--r-tile);border:1px solid var(--line)}
.runfoot .good{color:var(--good);font-weight:700}
.runfoot .bad{color:var(--bad);font-weight:700}
.runend .faint{color:var(--faint)}

/* ----------------------------------------------- asking one question
   A date, a choice — anything that needs the page to wait. */
.sheet{position:fixed;inset:0;z-index:60;background:rgba(42,43,51,.32);
  display:flex;align-items:center;justify-content:center;padding:24px}
.sheetcard{width:min(380px,100%);display:flex;flex-direction:column;gap:14px;box-shadow:var(--shadow-lift)}
.sheetcard input{height:44px;border:1px solid var(--line2);border-radius:12px;padding:0 12px;background:var(--surface)}
.sheetfoot{display:flex;gap:10px;justify-content:flex-end}

/* ------------------------------------------------------- exam dates */
.ledger .acts{display:flex;gap:10px;align-items:baseline;margin-left:10px}
.lnk{font-size:.76rem;font-weight:700;color:var(--faint)}
.lnk:hover{color:var(--accent)}
.line.next .lnk{color:var(--muted)}
.examform{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:14px 0 4px;
  border-top:1px solid var(--line)}
.examform input,.examform select{height:38px;border:1px solid var(--line2);border-radius:10px;
  padding:0 10px;font-size:.86rem;background:var(--surface)}
.examform input[name=label]{flex:1;min-width:180px}
.examform input:focus,.examform select:focus{outline:none;border-color:var(--accent);
  box-shadow:0 0 0 3px var(--accent-soft)}

/* ------------------------------------------------- writing a note
   The box is the page: a title, where it belongs, and room to write. */
.notewrite{display:flex;flex-direction:column;gap:14px}
.notewrite input[name=title]{height:48px;border:0;border-bottom:1px solid var(--line);
  font-family:var(--display);font-size:1.35rem;font-weight:700;letter-spacing:-.02em;padding:0 0 6px}
.notewrite input[name=title]:focus{outline:none;border-color:var(--accent)}
.notewrite select{align-self:flex-start;height:36px;border:1px solid var(--line2);
  border-radius:var(--r-pill);padding:0 12px;font-size:.84rem;background:var(--surface)}
.notewrite textarea{min-height:46vh;border:0;resize:vertical;font-size:1rem;line-height:1.75}
.notewrite textarea:focus{outline:none}
.notefoot{display:flex;align-items:center;gap:12px;border-top:1px solid var(--line);padding-top:16px}

/* ------------------------------------------------- numbers in a row
   Four facts, no sentences: the number loud, the label under it. */
.markstats{display:flex;flex-wrap:wrap;gap:26px;margin-top:6px}
.markstats span{display:flex;flex-direction:column;font-size:.76rem;color:var(--muted)}
.markstats b{font-family:var(--display);font-size:1.5rem;font-weight:700;letter-spacing:-.02em;
  line-height:1.15;color:var(--ink)}
.markstats span.over b{color:var(--bad)}
p.bad{color:var(--bad)}

/* ------------------------------------------------------- the shape
   Twelve marks at most, the target dashed across them. */
.spark{margin:16px 0 6px}
/* height:auto, or the viewBox is squashed and every dot on it
   becomes an ellipse. */
.spark svg{display:block;width:100%;height:auto;max-height:120px;overflow:visible}
.sparkfoot{display:flex;align-items:baseline;gap:8px;margin-top:6px;font-size:.76rem;color:var(--faint)}
.sparkfoot b{font-size:.9rem;color:var(--ink)}

/* --------------------------------------------------------- a goal */
.goalform{display:flex;flex-wrap:wrap;align-items:flex-end;gap:14px;margin-top:18px;
  border-top:1px solid var(--line);padding-top:18px}
.goalform label{display:flex;flex-direction:column;gap:6px;font-size:.76rem;font-weight:700;
  color:var(--muted);position:relative}
.goalform label.wide{flex:1;min-width:240px}
.goalform input{height:42px;border:1px solid var(--line2);border-radius:12px;padding:0 12px;
  font-size:.92rem;background:var(--surface);width:130px}
.goalform label.wide input{width:100%}
.goalform input:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
.goalform .unit{position:absolute;right:12px;bottom:11px;font-size:.78rem;color:var(--faint)}
.goalform label:not(.wide) input{padding-right:42px}

/* removing a row you logged yourself */
.answerrow .drop{width:30px;height:30px;flex:0 0 auto;border-radius:999px;color:transparent;font-size:.8rem}
.answerrow:hover .drop{color:var(--faint)}
.answerrow .drop:hover{background:var(--bad-bg);color:var(--bad)}

/* --------------------------------------------- saying it out loud
   Every word is there and none of them are readable until you say it. */
.sayboard{display:flex;flex-direction:column;gap:18px;max-width:780px;margin:0 auto}
.saidtext{font-size:1.06rem;line-height:2.1;padding:28px 30px}
.saidtext .w{border-radius:4px;color:transparent;background:var(--line);
  box-shadow:0 0 0 2px var(--line);transition:background .12s,color .12s}
.saidtext .w.got{color:var(--ink);background:transparent;box-shadow:none}
.saidtext .w.waved{color:var(--faint);background:transparent;box-shadow:none}
.saymeter{display:flex;align-items:center;gap:14px}
.saymeter .bar{flex:1;height:8px;border-radius:var(--r-pill);background:#F0F1F5;overflow:hidden}
.saymeter .bar i{display:block;height:100%;background:var(--accent);transition:width .2s}
.saymeter .pct{font-family:var(--display);font-size:1.1rem;font-weight:700;min-width:48px;text-align:right}

/* ----------------------------------------------------- making a card
   Two sides, or one side with words taken out of it. */
.cardmaker{display:flex;flex-direction:column;gap:14px}
.cardmaker textarea{width:100%;border:1px solid var(--line2);border-radius:var(--r-tile);
  padding:12px 14px;font-size:.95rem;line-height:1.6;resize:vertical;background:var(--surface)}
.cardmaker textarea:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
.cardmaker .chips{display:flex;gap:8px}
.cardmaker .chip{cursor:pointer}
.cardmaker .hidebar{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.cardmaker select{height:38px;border:1px solid var(--line2);border-radius:var(--r-pill);
  padding:0 12px;font-size:.84rem;background:var(--surface)}
.sheetcard.wide{width:min(620px,100%)}

/* a word taken out of a card */
.clz{padding:1px 8px;border-radius:6px;background:var(--accent-soft);color:var(--accent-hi);font-weight:700}
.clz.on{background:var(--good-bg);color:var(--good)}

/* finding one card in a deck of hundreds */
.minisearch{height:34px;margin-left:auto;margin-right:12px;width:180px;border:1px solid var(--line2);
  border-radius:var(--r-pill);padding:0 14px;font-size:.84rem;background:var(--surface)}
.minisearch:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}

/* ------------------------------------------------- every day at once
   Twenty weeks of squares: the only picture of effort in the app. */
.heat{display:flex;gap:4px;margin-top:6px;width:100%;max-width:100%;overflow-x:auto;padding-bottom:4px}
.hcol{display:flex;flex-direction:column;gap:4px}
.hc{width:13px;height:13px;border-radius:4px;background:#EDEEF2;display:block}
.hc.l1{background:#DCDBFA} .hc.l2{background:#BDBAF5} .hc.l3{background:#9A95EF}
.hc.l4{background:#6E67F2} .hc.l5{background:var(--accent-hi)}
.hc.fut{background:transparent;box-shadow:inset 0 0 0 1px var(--line)}
/* --- a strip that answers when it is asked ---
   A heat cell or a year cell carries its meaning in a title, which is a
   hover, which a phone does not have. The cell takes a tap and this
   line says what it is. It is not there until then: the words rule is
   about what is always on screen. */
.stripsay{margin:8px 0 0;font-size:.76rem;font-weight:600;color:var(--muted)}
.stripsay:empty{display:none}
[role="button"].hc,.ystrip i[role="button"]{cursor:pointer}
/* The ring is inset. These cells sit in a strip that scrolls, and an
   outer ring would be clipped by its own container. */
.hc.told{box-shadow:inset 0 0 0 1.5px var(--surface),inset 0 0 0 3px var(--accent-hi)}
.ystrip i.told{box-shadow:inset 0 0 0 2px var(--accent-hi)}
.heatkey{display:flex;align-items:center;gap:5px;margin-top:12px;font-size:.72rem;color:var(--faint)}
.heatkey i{width:12px;height:12px;border-radius:4px;background:#EDEEF2}

/* ------------------------------------------------- making it yours
   A subject you added: its colour, its topics, what it shows. */
.swatches{display:flex;gap:10px;flex-wrap:wrap}
.sw{width:30px;height:30px;border-radius:10px;box-shadow:inset 0 0 0 1px rgba(0,0,0,.06)}
.sw.on{box-shadow:0 0 0 2px var(--surface),0 0 0 4px var(--ink)}
.topicedit{display:flex;flex-direction:column;gap:12px;padding:14px 0 18px;
  border-bottom:1px solid var(--line)}
.topicedit input{height:42px;border:1px solid var(--line2);border-radius:12px;padding:0 12px;
  font-weight:700;background:var(--surface)}
.topicedit textarea{border:1px solid var(--line2);border-radius:var(--r-tile);padding:12px 14px;
  font-size:.92rem;line-height:1.7;resize:vertical;background:var(--surface)}
.topicedit input:focus,.topicedit textarea:focus{outline:none;border-color:var(--accent);
  box-shadow:0 0 0 3px var(--accent-soft)}
.railfoot .lnk{font-size:.72rem}

/* --------------------------------------------------------- on a phone
   A row with three labels on it is a desktop row. Here the subject name
   goes, because the dot already says which subject it is. */
@media (max-width:820px){
  .point{min-width:0}
  .point .note{display:none}
  .markstats{gap:18px}
  .goalform label:not(.wide){flex:1 1 40%}
  .goalform input{width:100%}
  .examform input[name=label]{flex:1 1 100%}
  .saidtext{padding:20px 18px;font-size:1rem}
  .minisearch{width:100%;margin:8px 0 0;order:3}
  .answerrow .drop{color:var(--faint)}

  /* a flex child will happily grow past the screen unless told not to */
  .stack>*,.page>*{min-width:0;max-width:100%}
  .card{overflow-wrap:anywhere}
}

/* ------------------------------------------------- on a wide screen
   The page is centred in whatever the rail leaves, and gets a little
   more room before it stops growing — a week of columns is worth the
   width, a row of text is not. */
@media (min-width:1600px){
  .page{max-width:1420px;padding:48px 48px 96px}
  .day{min-height:260px}
}
@media (min-width:2100px){
  .page{max-width:1560px}
}

/* ------------------------------------------- a day in the week strip
   One line a task. The tint is the subject, so the name is not said
   twice, and the minutes sit at the end without shouting. */
.slot{padding:0;gap:0;background:transparent}
.slot .grab{display:flex;flex-direction:row;align-items:center;gap:8px;width:100%;padding:7px 10px;
  border-radius:10px;background:color-mix(in srgb, var(--sub) 13%, #fff);text-align:left}
.slot .grab:hover{background:color-mix(in srgb, var(--sub) 22%, #fff)}
.slot .at{flex:0 0 auto;font-size:.64rem;font-weight:700;letter-spacing:.04em;
  color:color-mix(in srgb, var(--sub) 70%, #33353F);opacity:.9}
.slot b{flex:1;min-width:0;font-size:.76rem;font-weight:700;line-height:1.35;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  color:color-mix(in srgb, var(--sub) 78%, #24252B)}
.slot .mins{flex:0 0 auto;font-size:.66rem;font-weight:700;opacity:.55}
.slot.done .grab{background:var(--sunk)}
.slot.done b{text-decoration:line-through;color:var(--faint)}
@supports not (color: color-mix(in srgb, red 50%, blue)){
  .slot .grab{background:var(--sunk)}
  .slot b{color:var(--ink)}
}
.day{min-height:220px}
.day .slots{max-height:52vh}

/* -------------------------------------------- what the exam asks
   Marks a paper, how often, and the pattern by year. */
.seg{display:flex;gap:8px;flex-wrap:wrap;margin-top:18px}
.seg button{display:flex;flex-direction:column;gap:2px;padding:10px 16px;border-radius:var(--r-tile);
  border:1px solid var(--line2);background:var(--surface);font-size:.86rem;font-weight:700;text-align:left}
.seg button .n{font-size:.7rem;font-weight:600;color:var(--faint)}
.seg button:hover{border-color:var(--accent)}
.seg button.on{background:var(--accent-soft);border-color:var(--accent-soft);color:var(--accent-hi)}
.seg button.on .n{color:var(--accent-hi);opacity:.75}

.freqrow{display:flex;flex-wrap:wrap;align-items:center;gap:14px;width:100%;padding:12px 0;
  border-top:1px solid var(--line)}
.freqrow .nm{flex:1;min-width:0;font-size:.92rem;font-weight:600;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.freqrow .yield{display:flex;align-items:baseline;gap:3px;width:52px;justify-content:flex-end}
.freqrow .yield b{font-family:var(--display);font-size:1.1rem;font-weight:700}
.freqrow .yield i{font-style:normal;font-size:.8rem;font-weight:700}
.freqrow .yield i.up{color:var(--good)} .freqrow .yield i.down{color:var(--bad)}
.ystrip{display:flex;gap:2px;flex:0 0 auto}
.ystrip i{width:7px;height:20px;border-radius:2px;background:#EDEEF2;display:block}
.ystrip i.l1{background:#DCDBFA} .ystrip i.l2{background:#BDBAF5}
.ystrip i.l3{background:#8A84F0} .ystrip i.l4{background:var(--accent)}
.freqrow .stripsay{flex:1 1 100%;order:6;margin:2px 0 0}
@media (max-width:820px){
  .freqrow{gap:8px}
  /* It already has the whole line; nowrap was cutting it anyway.
     "Topic 2 — Australia in the Global Economy" is what the row is
     about, on the page whose job is saying which areas pay. */
  .freqrow .nm{flex:1 1 100%;white-space:normal}
  /* 7px is a colour, not a target. Given its own line the cells grow
     to something a thumb can hit, and the years stay in order. */
  .ystrip{order:5;flex:1 1 100%;gap:4px}
  .ystrip i{flex:1 1 auto;width:auto;max-width:44px;height:26px;border-radius:5px}
}

/* ------------------------------------------------------ the marks
   A table, because a year of results is something you read down. */
table.marks{width:100%;border-collapse:collapse;margin-top:16px}
table.marks th{text-align:left;font-size:.7rem;font-weight:700;letter-spacing:.08em;
  text-transform:uppercase;color:var(--faint);padding:0 10px 10px;white-space:nowrap}
table.marks th.n,table.marks td.n{text-align:right}
table.marks td{padding:11px 10px;border-top:1px solid var(--line);font-size:.9rem;vertical-align:middle}
table.marks tr:hover td{background:var(--sunk)}
table.marks .what .t{display:block;font-weight:700;line-height:1.35}
table.marks .sub{white-space:nowrap;color:var(--muted)}
table.marks .sub .dot{display:inline-block;vertical-align:-1px;margin-right:7px}
table.marks td.n{font-variant-numeric:tabular-nums;font-weight:700;white-space:nowrap}
table.marks .faint{font-weight:600;color:var(--faint)}
table.marks .pct{display:inline-block;min-width:52px;padding:3px 9px;border-radius:var(--r-pill);
  font-size:.8rem;font-weight:700;text-align:center}
table.marks .pct.good{background:var(--good-bg);color:var(--good)}
table.marks .pct.warn{background:var(--warn-bg);color:var(--warn)}
table.marks .pct.bad{background:var(--bad-bg);color:var(--bad)}
table.marks .when{font-size:.82rem;color:var(--muted);white-space:nowrap}
table.marks .x{width:34px}
table.marks .drop{width:28px;height:28px;border-radius:999px;color:transparent;font-size:.78rem}
table.marks tr:hover .drop{color:var(--faint)}
table.marks .drop:hover{background:var(--bad-bg);color:var(--bad)}
@media (max-width:820px){
  /* The same column goes from the head AND the body, or the headings
     stop describing what is under them. This hid the band cells by
     class and two headers by position, and the positions were not the
     band's — so "Grade" ended up printed above a percentage. */
  table.marks th:nth-child(2),table.marks td:nth-child(2),
  table.marks th:nth-child(4),table.marks td:nth-child(4){display:none}
  table.marks .sub{display:none}
  table.marks{table-layout:fixed}
  table.marks td,table.marks th{padding:10px 4px}
  /* What it was takes whatever is left. An equal sixth of a phone is
     49px, which is about six characters of the only thing that says
     which result this is. */
  /* Percentages, not auto: the first row of this table is a group
     heading spanning all six columns, so a fixed layout has nothing
     to size the columns from and auto keeps the name at a sixth. */
  table.marks th:nth-child(1),table.marks td:nth-child(1){width:48%}
  table.marks th:nth-child(3),table.marks td:nth-child(3){width:22%}
  table.marks th:nth-child(5),table.marks td:nth-child(5){width:21%}
  table.marks th:nth-child(6),table.marks td:nth-child(6){width:9%}
  table.marks .x{width:26px}
  table.marks .when{font-size:.74rem}
}

/* =====================================================================
   THE WEEK, as drawn on the E-Plan artboard.
   A day is a tall white column. A piece of work is a pastel block in
   its subject's colour: what it is, then how long it takes. The state
   of the day sits at the foot of the column, said once.
   ===================================================================== */
.week{display:flex;gap:12px;align-items:stretch}
.day{flex:1 1 0;min-width:0;min-height:540px;padding:16px 14px;border-radius:20px;
  background:var(--surface);box-shadow:var(--shadow);
  display:flex;flex-direction:column;gap:10px;outline:0}
.day.today{padding:14px 12px;border:2px solid var(--accent);outline:0}
.day .dhead{display:flex;align-items:flex-start;justify-content:space-between;gap:6px}
.day .dnum{font-family:var(--display);font-size:1.25rem;font-weight:700;line-height:1.1}
.day.today .dnum,.day.today .eyebrow{color:var(--accent)}
.day .dhead .chip{height:22px;padding:0 9px;font-size:.68rem}
.day .slots{display:flex;flex-direction:column;gap:10px;overflow-y:auto;flex:0 1 auto;
  margin:0 -2px;padding:0 2px;scrollbar-width:thin;max-height:none}

.slot{display:flex;flex-direction:column;gap:3px;width:100%;text-align:left;
  padding:10px 12px;border-radius:14px;
  background:color-mix(in srgb, var(--sub) 20%, #fff)}
.slot:hover{background:color-mix(in srgb, var(--sub) 30%, #fff)}
.slot .t{font-size:.78rem;font-weight:700;line-height:1.35;
  color:color-mix(in srgb, var(--sub) 64%, #2A2B33);
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.slot .m{font-size:.71rem;font-weight:600;opacity:.8;
  color:color-mix(in srgb, var(--sub) 58%, #2A2B33)}
.slot.done{background:var(--sunk)}
.slot.done .t{text-decoration:line-through;color:var(--faint)}
.slot.done .m{color:var(--faint)}
@supports not (color: color-mix(in srgb, red 50%, blue)){
  .slot{background:var(--sunk)} .slot .t,.slot .m{color:var(--ink)}
}

.dfoot{margin-top:auto;display:flex;align-items:center;gap:6px;
  font-size:.72rem;font-weight:700;padding-top:4px}
.dfoot .good{display:flex;align-items:center;gap:6px;color:var(--good)}
.dfoot .bad{color:var(--bad)}
.dfoot .muted{color:var(--faint);font-weight:600}
.dayplus{height:34px;border:1px dashed var(--line2);border-radius:12px;background:transparent;
  color:var(--muted);font-size:.76rem;font-weight:700}
.dayplus:hover{border-color:var(--accent);color:var(--accent)}

.weekbar{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin:4px 0 18px}
.weekbar b{font-family:var(--display);font-size:1.25rem;font-weight:700;letter-spacing:-.02em}
.weekbar .arrow{width:36px;height:36px;border-radius:var(--r-pill);background:var(--surface);
  box-shadow:var(--shadow);display:inline-flex;align-items:center;justify-content:center;
  font-size:1.1rem;line-height:1;color:var(--ink)}
.weekbar .arrow:hover{color:var(--accent)}
.weekbar .key{margin-left:auto;display:flex;align-items:center;gap:16px;
  font-size:.74rem;color:var(--muted)}
.weekbar .key i{display:inline-block;width:10px;height:10px;border-radius:3px;
  margin-right:6px;vertical-align:-1px}
@media (max-width:1100px){
  .week{flex-wrap:wrap}
  .day{flex:1 1 30%;min-height:300px}
  .weekbar .key{display:none}
}

/* -------------------------------------------- fixing a syllabus point */
.point .fix{width:26px;height:26px;flex:0 0 auto;border-radius:8px;color:transparent;
  font-size:.78rem;line-height:1}
.point:hover .fix{color:var(--faint);background:var(--sunk)}
.point .fix:hover{color:var(--accent);background:var(--accent-soft)}
.pointfix{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:12px 0 14px;
  border-top:1px solid var(--line)}
.pointfix input{flex:1;min-width:220px;height:40px;border:1px solid var(--line2);
  border-radius:10px;padding:0 12px;font-size:.9rem;background:var(--surface)}
.pointfix input:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}

/* ------------------------------------------------ clearing the plan */
.sheetopts{display:flex;flex-direction:column;gap:10px}
.sheetopts .btn{height:auto;justify-content:flex-start;flex-direction:column;align-items:flex-start;
  gap:3px;padding:14px 16px;border-radius:var(--r-tile);text-align:left;white-space:normal}
.sheetopts .btn span{font-size:.76rem;font-weight:600;color:var(--muted)}
.sheetopts .btn:hover{border-color:var(--accent);background:var(--accent-soft)}

/* ------------------------------------------- an essay, filled in live */
.saytabs{display:flex;align-items:center;gap:8px}
.saytabs button{height:34px;padding:0 14px;border-radius:var(--r-pill);font-size:.82rem;
  font-weight:700;color:var(--muted)}
.saytabs button.on{background:var(--accent-soft);color:var(--accent-hi)}
.saytabs button[disabled]{opacity:.4}
@media (max-width:820px){
  /* Five buttons in a row that does not wrap is 356px of controls in
     a 327px column, and the whole page slides sideways. */
  .saytabs{flex-wrap:wrap;gap:6px}
  /* These choose between writing it, saying it, and how much to show.
     They are the screen, and they were under the tap floor. */
  .saytabs button{height:44px;padding:0 16px}
}
.saytype{width:100%;min-height:150px;border:1px solid var(--line2);border-radius:var(--r-tile);
  padding:14px 16px;font-size:1rem;line-height:1.8;resize:vertical;background:var(--surface)}
.saytype:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
.saidtext.peek .w{color:var(--faint);background:transparent;box-shadow:none}
.saidtext.peek .w.got{color:var(--ink)}

/* --------------------------------------------- every subject, one chart */
.bigchart{margin:18px 0 4px}
.bigchart svg{display:block;width:100%;height:260px}
.chartkey{display:flex;flex-wrap:wrap;gap:8px 20px;padding-top:12px;border-top:1px solid var(--line);
  font-size:.78rem;color:var(--muted)}
.chartkey i{display:inline-block;width:10px;height:10px;border-radius:3px;margin-right:7px;vertical-align:-1px}
.chartkey b{margin-left:6px;color:var(--ink)}

/* ------------------------------------------- a field that says its unit */
.unitbox{position:relative;display:inline-flex;align-items:center}
.unitbox input{padding-right:38px;width:104px}
.unitbox.at input{width:126px;padding-right:44px}
.unitbox span{position:absolute;right:11px;font-size:.7rem;font-weight:700;color:var(--faint);
  pointer-events:none}

/* ------------------------------------------------ the list, in bands
   Overdue, today, this week, later, no day yet. A heading you can find
   with your eye, and the count and the time it will take beside it. */
.listband{display:flex;align-items:baseline;gap:10px;margin:22px 0 8px;
  padding-bottom:7px;border-bottom:1px solid var(--line)}
.listband:first-of-type{margin-top:16px}
.listband .nm{font-size:.72rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--faint)}
.listband .n{margin-left:auto;font-size:.74rem;font-weight:600;color:var(--faint)}
.listband.late .nm{color:var(--bad)}
.listband.now .nm{color:var(--accent)}
.bandmore{padding:8px 2px 0;font-size:.76rem;color:var(--faint)}
.planrow .t .tag{display:inline-block;margin-right:8px;padding:2px 7px;border-radius:6px;
  background:var(--sunk);color:var(--muted);font-size:.68rem;font-weight:700;
  letter-spacing:.02em;vertical-align:1px}

/* The composer has seven fields in it. Below a real desktop they wrap
   rather than each shrinking to nothing. */
@media (max-width:1180px){
  .addrow{flex-wrap:wrap}
  .addrow input[name=title],.addrow input[name=name]{flex:1 1 100%}
  .addrow select,.addrow input,.addrow .unitbox{min-width:104px}
}

/* the marks table, grouped by subject */
table.marks tr.subhead td{padding:22px 10px 8px;border-top:0}
table.marks tbody tr.subhead:first-child td{padding-top:8px}
table.marks tr.subhead b{font-family:var(--display);font-size:1rem;font-weight:700;margin-left:9px}
table.marks tr.subhead .dot{display:inline-block;vertical-align:0}
table.marks tr.subhead .s{margin-left:10px;font-size:.76rem;color:var(--faint);font-weight:600}
table.marks tr.subhead+tr td{border-top:1px solid var(--line2)}
table.marks .bnd{font-size:.82rem;color:var(--muted);white-space:nowrap}

/* the chart scales without squashing its dots */
.bigchart svg{display:block;width:100%;height:auto;max-height:340px}
.chartkey em{margin-left:6px;font-style:normal;font-weight:700}
.chartkey em.up{color:var(--good)} .chartkey em.down{color:var(--bad)}

/* ------------------------------------------- writing it out, live
   The box says whether the words just typed are in the paragraph. */
.saystate{display:flex;align-items:center;gap:10px;margin-top:8px;font-size:.78rem;color:var(--muted)}
.saystate .verdict{font-weight:700}
.saystate .verdict.ok{color:var(--good)}
.saystate .verdict.no{color:var(--bad)}
.saytype.hit{border-color:var(--good);box-shadow:0 0 0 3px var(--good-bg)}
.saytype.miss{border-color:var(--bad);box-shadow:0 0 0 3px var(--bad-bg)}

/* ------------------------------------------------ how that went
   The paragraph with the holes still in it, then the holes listed. */
.resulthead{text-align:center;padding:26px 24px}
.saidtext.result .w{color:var(--ink);background:transparent;box-shadow:none}
.saidtext.result .w.missed{color:var(--bad);background:var(--bad-bg);
  box-shadow:0 0 0 2px var(--bad-bg);border-radius:4px}
.gapline{font-size:.95rem;line-height:1.6;padding:9px 0;border-top:1px solid var(--line)}
.gapline:first-of-type{border-top:0}

/* ------------------------------------- changing a topic, and undoing it */
.topic .th .fix{width:26px;height:26px;border-radius:8px;color:transparent;font-size:.78rem;line-height:1}
.topic:hover .th .fix{color:var(--faint);background:var(--sunk)}
.topic .th .fix:hover{color:var(--accent);background:var(--accent-soft)}
.topicfix{border-top:0;padding-top:0}
.hiddenbits:empty{display:none}

/* ------------------------------------------------------ the ATAR
   A number to aim at, and what each subject's target is worth once it
   has been scaled. A guide, and it says so. */
.atarwrap{display:grid;grid-template-columns:minmax(220px,.85fr) minmax(0,1.7fr);gap:18px;margin-bottom:24px}
.atartarget{background:var(--night);color:#fff;display:flex;flex-direction:column;justify-content:center}
.atartarget .eyebrow{color:var(--night-2)}
.atartarget input{width:100%;margin:10px 0 4px;background:transparent;border:0;border-bottom:1px solid rgba(255,255,255,.25);
  color:#fff;font-family:var(--display);font-size:2.6rem;font-weight:700;letter-spacing:-.03em;padding:0 0 6px}
.atartarget input:focus{outline:none;border-color:#fff}
.atartarget .sm{color:var(--night-2);margin-top:8px}
.scaledrow{display:flex;align-items:center;gap:14px;padding:11px 0;border-top:1px solid var(--line)}
.scaledrow:first-of-type{border-top:0}
.scaledrow .nm{flex:0 0 40%;min-width:0;font-size:.9rem;font-weight:600;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.scaledrow .track{flex:1;height:8px;border-radius:var(--r-pill);background:#F0F1F5;overflow:hidden}
.scaledrow .track i{display:block;height:100%;border-radius:var(--r-pill);background:var(--sub,var(--accent))}
.scaledrow .val{width:74px;text-align:right;font-family:var(--display);font-size:1rem;font-weight:700}
.scaledrow .val .faint{font-family:var(--f);font-size:.76rem;font-weight:600;color:var(--faint)}
.scaledtotal{display:flex;align-items:baseline;gap:12px;margin-top:14px;padding-top:12px;
  border-top:1px solid var(--line2);font-size:.86rem;font-weight:700}
.scaledtotal b{margin-left:auto;font-family:var(--display);font-size:1.5rem}
.method{margin-top:14px;font-size:.78rem;line-height:1.6;color:var(--muted)}
@media (max-width:900px){ .atarwrap{grid-template-columns:1fr} }

/* the week you are on, and the dates it covers, always both */
.weekbar .when{display:flex;flex-direction:column;line-height:1.15;min-width:150px}
.weekbar .when .range{font-size:.76rem;font-weight:600;color:var(--faint)}
.weekbar .arrow{width:40px;height:40px;font-size:1.2rem}

/* ------------------------------------------------- a goal, as a sum
   An HSC mark is half the school assessment and half the exam. Showing
   it as three numbers that add up is the whole point. */
.goalcard{margin-bottom:18px}
.gsum{display:flex;align-items:stretch;gap:14px;margin:18px 0 4px;flex-wrap:wrap}
.gcell{flex:1 1 180px;min-width:0;display:flex;flex-direction:column;gap:2px;
  padding:14px 16px;border-radius:var(--r-tile);background:var(--sunk)}
.gcell .gl{font-size:.7rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--faint)}
.gcell .gv{font-family:var(--display);font-size:1.7rem;font-weight:700;letter-spacing:-.02em;line-height:1.15}
.gcell .gn{font-size:.74rem;color:var(--muted)}
.gcell.out{background:var(--accent-soft)}
.gcell.out .gv,.gcell.out .gl{color:var(--accent-hi)}
.gcell.bad{background:var(--bad-bg)}
.gcell.bad .gv,.gcell.bad .gl{color:var(--bad)}
.gop{align-self:center;font-family:var(--display);font-size:1.3rem;font-weight:700;color:var(--faint)}
.needline{margin-top:12px;font-size:.84rem;line-height:1.55;padding:10px 14px;border-radius:var(--r-tile)}
.needline.ok{background:var(--good-bg);color:var(--good)}
.needline.warn{background:var(--warn-bg);color:var(--warn)}
.needline.bad{background:var(--bad-bg);color:var(--bad)}
@media (max-width:820px){ .gop{display:none} .gcell{flex:1 1 100%} }

/* --------------------------------------------------------- waiting
   Signing in takes a round trip and a load. Say so. */
.signcard.waiting{display:flex;flex-direction:column;gap:16px}
.loadrow{display:flex;align-items:center;gap:12px}
.spinner{width:18px;height:18px;flex:0 0 auto;border-radius:50%;
  border:2px solid var(--line2);border-top-color:var(--accent);
  animation:spin .7s linear infinite}
.spinner.light{border-color:rgba(255,255,255,.35);border-top-color:#fff;margin-right:9px}
@keyframes spin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){ .spinner{animation-duration:2.4s} }
.btn[disabled]{opacity:.75;pointer-events:none}

/* ------------------------------------------- where the marks are going
   Marks a paper you are not getting, worst first. */
.leakrow{display:flex;align-items:center;gap:14px;width:100%;padding:13px 0;
  border-top:1px solid var(--line);text-align:left}
.leakrow:hover{background:var(--sunk)}
.leakrow .nm{flex:1;min-width:0;font-size:.92rem;font-weight:600;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.leakrow .sub{flex:0 0 auto;font-size:.74rem;color:var(--faint)}
.leakrow .lost{flex:0 0 auto;width:48px;text-align:right;
  font-family:var(--display);font-size:1.15rem;font-weight:700;color:var(--bad)}
.leakrow .note{flex:0 0 auto;width:150px;text-align:right;font-size:.74rem;color:var(--muted)}

.wheremarks{margin-top:18px;padding-top:16px;border-top:1px solid var(--line)}
.leakline{display:flex;align-items:baseline;gap:12px;padding:8px 0}
.leakline .nm{flex:1;min-width:0;font-size:.88rem;font-weight:600;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.leakline .lost{font-family:var(--display);font-size:1rem;font-weight:700;color:var(--bad)}
.leakline .note{flex:0 0 auto;font-size:.74rem;color:var(--faint)}

/* the standing row now says where its number came from */
.standrow .nm .src{display:block;font-size:.72rem;font-weight:500;color:var(--faint);margin-top:2px}
.standrow .av i{font-style:normal;font-size:.76rem;font-weight:700;margin-left:5px}
.standrow .av i.up{color:var(--good)} .standrow .av i.down{color:var(--bad)}
.markstats span.up b{color:var(--good)} .markstats span.down b{color:var(--bad)}
@media (max-width:820px){
  .leakrow .note,.leakrow .sub{display:none}
  /* 150px on a 320 screen, and "Topic 3 — Economic Issues" is cut
     before it says which topic. Two lines beats an ellipsis on the
     words that identify the row. */
  .leakrow .nm{white-space:normal}
}

/* ------------------------------------------ pasting in a syllabus
   Paste it however it came out of the PDF; the preview says what was
   understood before anything is saved. */
.pastewrap{display:flex;align-items:center;gap:12px;margin:4px 0 10px}
.pastecard{display:flex;flex-direction:column;gap:14px;width:100%}
.pastecard textarea{min-height:200px;border:1px solid var(--line2);border-radius:var(--r-tile);
  padding:14px 16px;font-size:.92rem;line-height:1.7;resize:vertical;background:var(--surface)}
.pastecard textarea:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
.pastepreview{display:flex;flex-direction:column;gap:14px;max-height:320px;overflow-y:auto}
.pastepreview:empty{display:none}
.pastetopic{padding:12px 14px;border-radius:var(--r-tile);background:var(--sunk)}
.pastetopic b{display:block;font-size:.9rem}
.pastetopic .n{font-size:.72rem;color:var(--faint);font-weight:600}
.pastepoint{font-size:.82rem;color:var(--muted);padding:3px 0 0 14px;position:relative;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pastepoint::before{content:'·';position:absolute;left:4px;color:var(--faint)}
.pastepoint.faint{color:var(--faint);font-style:italic}

/* -------------------------------------------- putting them in order
   Drag with a mouse, arrows with a thumb. */
.nav.child{position:relative}
.nav.child .nm{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.nav.child .move{display:none;gap:1px;margin-left:auto;flex:0 0 auto}
.nav.child:hover .move,.nav.child:focus-within .move{display:flex}
.nav.child .move i{font-style:normal;font-size:.56rem;line-height:1;padding:4px 3px;
  border-radius:5px;color:var(--faint);cursor:pointer}
.nav.child .move i:hover{background:var(--accent-soft);color:var(--accent)}
.nav.child.dragging{opacity:.45}
.nav.child.over{box-shadow:inset 0 2px 0 var(--accent)}
@media (max-width:960px){ .nav.child .move{display:flex} }

/* =====================================================================
   GOALS THAT FOLLOW THE YEAR
   Where a subject is, what is left, and what the rest has to average.
   ===================================================================== */
.g-hd{color:#17694B} .g-d{color:#3E8A57} .g-c{color:#7A5600}
.g-pm{color:#A65A1E} .g-p{color:#6B6E7C}

.track{margin:18px 0 6px}
.trackline{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap}
.trackline .now{font-family:var(--display);font-size:1.9rem;font-weight:700;letter-spacing:-.02em}
.trackbar{display:flex;height:10px;border-radius:var(--r-pill);overflow:hidden;
  background:#F0F1F5;margin-top:10px}
.trackbar i{display:block;height:100%}
.trackbar .done{background:var(--accent)}
.trackbar .left{background:var(--accent-soft)}

.sched{margin-top:22px}
.schedhead{display:flex;align-items:baseline;gap:12px;margin-bottom:6px}
.schedhead .sm{margin-left:auto}
.schedrow{display:flex;align-items:center;gap:12px;padding:11px 0;border-top:1px solid var(--line)}
.schedrow .nm{flex:1;min-width:0;font-size:.9rem;font-weight:600;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.schedrow .wt{width:48px;text-align:right;font-size:.8rem;color:var(--muted);font-weight:700}
.schedrow .got{width:84px;text-align:right;font-size:.84rem;font-variant-numeric:tabular-nums}
.schedrow .pc{width:78px;text-align:right;font-size:.84rem;font-weight:700}
.schedrow .gr{width:52px;text-align:right;font-size:.82rem;font-weight:700;white-space:nowrap}
.schedrow.todo .nm,.schedrow.todo .got{color:var(--faint)}
.schedrow.todo .pc{color:var(--accent)}
.schedrow .drop{width:28px;height:28px;border-radius:999px;color:transparent;font-size:.76rem}
.schedrow:hover .drop{color:var(--faint)}
.schedrow .drop:hover{background:var(--bad-bg);color:var(--bad)}
.sched-add{margin-top:14px}

/* every subject on one line */
.overall{margin-bottom:24px}
.overrow{display:flex;align-items:center;gap:14px;width:100%;padding:12px 0;
  border-top:1px solid var(--line);text-align:left}
.overrow:hover{background:var(--sunk)}
.overrow .nm{flex:1;min-width:0;font-size:.94rem;font-weight:600;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.overrow .now{width:96px;text-align:right;font-family:var(--display);font-size:1.05rem;font-weight:700}
.overrow .now i{font-style:normal;font-size:.74rem;margin-left:6px}
.overrow .bar{display:flex;width:120px;height:8px;border-radius:var(--r-pill);
  overflow:hidden;background:#F0F1F5;flex:0 0 auto}
.overrow .bar .done{background:var(--sub,var(--accent))}
.overrow .bar .left{background:color-mix(in srgb, var(--sub) 22%, #fff)}
.overrow .need{width:120px;text-align:right;font-size:.82rem;color:var(--muted)}
.overrow .need .bad{color:var(--bad);font-weight:700}
.overrow .need .ok{color:var(--good);font-weight:700}
.overrow .aim{width:34px;text-align:right;font-size:.8rem;font-weight:700;color:var(--faint)}
.overrow.risk .need b{color:var(--warn)}
.overrow.gone{opacity:.8}

/* the school's grades, set once */
.gradeset{display:flex;flex-direction:column}
.graderow{display:flex;align-items:center;gap:14px;padding:10px 0;border-top:1px solid var(--line)}
.graderow .k{width:38px;font-family:var(--display);font-size:1.05rem;font-weight:700}
.graderow .nm{flex:1;font-size:.9rem}
.graderow input{width:92px;height:40px;border:1px solid var(--line2);border-radius:10px;
  padding:0 12px;font-size:.92rem;background:var(--surface)}
.graderow input:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}

@media (max-width:820px){
  .overrow .bar,.overrow .aim{display:none}
  .schedrow .gr{display:none}
}

/* aiming at a specific task */
.aimbox{position:relative;display:inline-flex;align-items:center;width:74px;flex:0 0 auto}
.aimbox input{width:100%;height:32px;border:1px dashed var(--line2);border-radius:9px;
  padding:0 20px 0 8px;font-size:.8rem;background:transparent;text-align:right}
.aimbox input:focus{outline:none;border-style:solid;border-color:var(--accent);
  box-shadow:0 0 0 3px var(--accent-soft);background:var(--surface)}
.aimbox span{position:absolute;right:7px;font-size:.66rem;font-weight:700;color:var(--faint);pointer-events:none}
.pastepreview .schedrow{border-top:1px solid var(--line)}
.pastepreview .schedrow:first-child{border-top:0}
@media (max-width:820px){ .aimbox{display:none} }

@media (max-width:820px){
  /* Save · Make cards · Delete do not fit on one line on a phone. */
  .notefoot{flex-wrap:wrap;gap:10px}
  .notefoot .grow{display:none}
  .notefoot .btn{flex:1 1 auto}
}

/* ------------------------------------------------- the day, by the hour
   A calendar you can point at: the hour you click is the hour it goes in. */
.hourgrid{display:flex;flex-direction:column;margin-top:6px}
.hour{display:flex;align-items:stretch;gap:6px;min-height:34px;border-top:1px dashed var(--line)}
.hour:first-child{border-top:0}
.hour .hl{flex:0 0 30px;padding-top:4px;font-size:.6rem;font-weight:700;color:var(--faint);
  letter-spacing:.02em}
.hour .hbody{flex:1;min-width:0;display:flex;flex-direction:column;gap:4px;padding:2px 0}
.hour .put{width:100%;flex:1;min-height:26px;border-radius:8px;border:1px dashed transparent}
.hour .put:hover{border-color:var(--accent);background:var(--accent-soft)}
.hour.taken{border-top-style:solid}
.hour .slot .m{font-size:.66rem}
.asking{border-color:var(--bad)!important;box-shadow:0 0 0 3px var(--bad-bg)!important}
.hours .mins span{font-size:.78rem;color:var(--faint);margin:0 4px}
.hours .mins input[type=number]{width:58px}
@media (max-width:1100px){ .hour .hl{flex:0 0 26px;font-size:.56rem} }

/* the card you just asked for, briefly */
.goalcard.landed{box-shadow:0 0 0 2px var(--accent), var(--shadow);
  transition:box-shadow .2s}

/* ------------------------------------------------- goals, tightened
   The table is the page; one subject opens under it. */
.overrow .nm .src{display:block;font-size:.72rem;font-weight:500;color:var(--faint);margin-top:2px}
.overrow .aim{width:58px;white-space:nowrap}
.overrow .chev{width:18px;text-align:right;color:var(--faint);font-size:.9rem;flex:0 0 auto}
.overrow.open{background:var(--accent-soft)}
.overrow.open .chev{color:var(--accent-hi)}
.goalcard.open{box-shadow:0 0 0 1px var(--accent-soft), var(--shadow)}
.goalcard .cardhead .lnk{margin-left:14px}

/* A number field with native arrows: unreadable white blocks on the
   dark ATAR card, and clutter everywhere else. */
input[type=number]{-moz-appearance:textfield;appearance:textfield}
input[type=number]::-webkit-outer-spin-button,
input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}

/* The ATAR card holds a label, a number and a line — it should not
   stretch to the height of the list beside it. */
.atarwrap{align-items:start}
.atartarget{padding:22px 24px}
.scaledrow .val{white-space:nowrap}
.scaledrow .val .faint{white-space:nowrap}

/* An ATAR is reported in steps of 0.05, so the card carries its own
   steppers — the native arrows are hidden, and unreadable here anyway. */
.atarset{display:flex;align-items:center;gap:10px;margin:10px 0 4px}
.atartarget .atarset input{margin:0;text-align:center;min-width:0}
.atartarget .step{flex:none;width:36px;height:36px;border-radius:var(--r-pill);
  border:1px solid rgba(255,255,255,.28);background:transparent;color:#fff;
  font-size:1.05rem;font-weight:700;line-height:1;cursor:pointer}
.atartarget .step:hover{background:rgba(255,255,255,.14)}
.atartarget .step:focus-visible{outline:2px solid #fff;outline-offset:2px}

/* The year table's column header — "worth" means nothing unlabelled. */
.overhead{display:flex;align-items:center;gap:14px;width:100%;padding:0 0 4px;
  font-size:.62rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:#B4B7C2}
.overhead .dot{width:10px;height:10px;flex:0 0 auto;background:none}
.overhead .nm{flex:1;min-width:0}
.overhead .now{width:96px;text-align:right}
.overhead .bar{width:120px;flex:0 0 auto}
.overhead .need{width:120px;text-align:right}
.overhead .aim{width:58px;text-align:right}
.overhead .worth{width:52px;text-align:right}
.overhead .chev{width:18px;flex:0 0 auto}
.overrow .worth{width:52px;text-align:right;font-size:.84rem;font-weight:700}
.overrow .worth .faint{font-weight:400}

/* A subject opens under its own row, not at the foot of the table. */
.opened{margin:0 0 6px;border-radius:0 0 var(--r-card) var(--r-card);
  background:color-mix(in srgb, var(--accent) 4%, #fff);
  box-shadow:inset 0 0 0 1px var(--accent-soft)}
.opened .goalcard{margin:0;box-shadow:none;background:transparent;border-radius:0}

/* The ATAR as a distance: solid where the targets reach, hatched for
   what the units without one would add, and 500 at the end. */
.atarcard .cardhead .atarset{margin-left:auto}
.atarset{display:flex;align-items:center;gap:8px}
.atarset input{width:112px;text-align:center;border:0;border-bottom:1px solid var(--line2);
  background:transparent;color:var(--accent-hi);font-family:var(--display);
  font-size:1.5rem;font-weight:700;letter-spacing:-.03em;padding:0 0 2px}
.atarset input:focus{outline:none;border-color:var(--accent)}
.atarset .step{flex:none;width:28px;height:28px;border-radius:var(--r-pill);
  border:1px solid var(--line2);background:#fff;color:var(--muted);
  font-size:.86rem;font-weight:700;line-height:1;cursor:pointer}
.atarset .step:hover{background:var(--sunk);color:var(--ink)}
.atarset .step:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.gapbar{display:flex;height:14px;margin-top:18px;border-radius:var(--r-pill);
  background:#F0F1F5;overflow:hidden}
.gapbar i{display:block;height:100%}
.gapbar .got{background:var(--accent)}
.gapbar .maybe{background:repeating-linear-gradient(45deg,
  #E3C77A,#E3C77A 5px,#F4E7C2 5px,#F4E7C2 10px)}
.gapkeys{display:flex;flex-wrap:wrap;align-items:center;gap:6px 20px;margin-top:10px;
  font-size:.78rem;color:var(--muted)}
.gapkeys span{display:inline-flex;align-items:center;gap:7px}
.gapkeys b{color:var(--ink);font-family:var(--display);font-size:.94rem}
.gapkeys i{display:block;width:12px;height:12px;border-radius:4px;flex:none}
.gapkeys .got{background:var(--accent)}
.gapkeys .maybe{background:repeating-linear-gradient(45deg,
  #E3C77A,#E3C77A 4px,#F4E7C2 4px,#F4E7C2 8px)}
.gapkeys .end{margin-left:auto;font-weight:700;color:var(--faint)}
@media (max-width:760px){
  .overhead .worth,.overrow .worth{display:none}
  .atarcard .cardhead .atarset{margin-left:0;width:100%}
}

/* The header borrowed .bar's grey fill and wore it behind the word. */
.overhead .bar{background:none;border-radius:0;overflow:visible;
  text-align:left;line-height:1}

/* Seven columns and a name: the name is the one that has to survive, so
   the numbers give ground first and the name never drops below a
   readable width. */
.overrow .nm,.overhead .nm{min-width:132px}
.overrow .now,.overhead .now{width:82px}
.overrow .need,.overhead .need{width:100px}
.overrow .aim,.overhead .aim{width:52px}
.overrow .worth,.overhead .worth{width:46px}
@media (max-width:1180px){
  .overrow .worth,.overhead .worth{display:none}
}
@media (max-width:1040px){
  .overrow .aim,.overhead .aim,.overrow .bar,.overhead .bar{display:none}
}
@media (max-width:820px){
  .overrow .need,.overhead .need{width:78px}
}

/* "65% Band 3" is one thing and must not break across two lines. */
.overrow .now,.overrow .worth,.overrow .aim{white-space:nowrap}
.overrow .now,.overhead .now{width:96px}
@media (max-width:820px){ .overrow .now,.overhead .now{width:82px} }

/* ====================================================== MOTION
   Operate mode: feedback and state, fast; one authored moment.

   --ease is an exponential decay — it leaves quickly and arrives
   without overshoot, which is what a confident interface does. Nothing
   here animates a layout-driving property except the one unfold, which
   uses grid-template-rows so the page below moves with it. */
:root{
  --ease:cubic-bezier(.16,1,.3,1);
  --ease-out:cubic-bezier(.4,0,.2,1);
  --t-tap:.12s;
  --t-state:.2s;
  --t-move:.3s;
}

/* --- arriving somewhere. Once per view, never per card. --- */
.arrive{animation:arrive .26s var(--ease) both}
@keyframes arrive{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}

/* --- THE AUTHORED MOMENT: a row unfolds into its card ---
   The panel opens from the row's own bottom edge and the page below
   moves with it, so the card is visibly part of the line you clicked
   rather than a thing that appeared somewhere. */
.opened{display:grid;grid-template-rows:1fr;animation:unfold .36s var(--ease)}
.openedin{overflow:hidden;min-height:0}
@keyframes unfold{from{grid-template-rows:0fr;opacity:.5}to{grid-template-rows:1fr;opacity:1}}
.opened .goalcard{animation:settle .44s .05s var(--ease) both}
@keyframes settle{from{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:none}}
.overrow .chev{transition:transform var(--t-state) var(--ease),color var(--t-state)}
.overrow.open .chev{transform:rotate(90deg)}

/* --- a row answers the pointer, and the subject's colour answers with it --- */
.overrow,.task,.slot,.standrow,.leakrow,.scaledrow,.up{
  transition:background var(--t-state) var(--ease-out)}
.overrow .dot,.task .dot,.standrow .dot{transition:transform var(--t-state) var(--ease)}
.overrow:hover .dot,.standrow:hover .dot{transform:scale(1.35)}

/* --- ticking something off ---
   The tick fills, the row dims, and only then does the page redraw. */
.task .tick{transition:background var(--t-state),color var(--t-state),
  border-color var(--t-state),transform var(--t-tap) var(--ease)}
.task .tick:active{transform:scale(.9)}
.task.ticking{animation:ticked .19s var(--ease-out) both}
.task.ticking .tick{animation:tickpop .19s var(--ease) both}
@keyframes ticked{to{opacity:.45}}
@keyframes tickpop{40%{transform:scale(1.18)}to{transform:scale(1)}}

/* --- pressing things --- */
.btn,.pill,.chip,.step,.nav,.put,.dayplus{transition:background var(--t-state) var(--ease-out),
  color var(--t-state),border-color var(--t-state),box-shadow var(--t-state),
  transform var(--t-tap) var(--ease)}
.btn:active,.pill:active,.step:active,.put:active,.dayplus:active{transform:scale(.97)}

/* --- a card lifts only where lifting means something: it is draggable --- */
.slot{transition:background var(--t-state) var(--ease-out),
  box-shadow var(--t-move) var(--ease),transform var(--t-move) var(--ease)}

/* --- the confirmation --- */
.toast{animation:toastin .28s var(--ease) both}
@keyframes toastin{from{opacity:0;transform:translate(-50%,14px)}
  to{opacity:1;transform:translate(-50%,0)}}
.toast.out{animation:toastout .2s var(--ease-out) both}
@keyframes toastout{to{opacity:0;transform:translate(-50%,8px)}}

/* ============================================== BROWSER SURFACES
   Selection, caret and scrollbars ship with defaults that belong to no
   design system. They are part of the page. */
::selection{background:var(--accent-soft);color:var(--accent-hi)}
input,textarea{caret-color:var(--accent)}
*{scrollbar-width:thin;scrollbar-color:#D3D6E0 transparent}
*::-webkit-scrollbar{width:10px;height:10px}
*::-webkit-scrollbar-track{background:transparent}
*::-webkit-scrollbar-thumb{background:#D3D6E0;border-radius:999px;
  border:3px solid var(--ground);transition:background var(--t-state)}
*::-webkit-scrollbar-thumb:hover{background:#B9BDCB}

/* A width on a flex item is only a starting size: it shrinks. The name
   is the one thing that can ellipsis, so it gives ground and the
   numbers never do — that is what was crushing "out of reach" into a
   column one letter wide. */
.overrow .now,.overrow .need,.overrow .aim,.overrow .worth,.overrow .chev,.overrow .bar,
.overhead .now,.overhead .need,.overhead .aim,.overhead .worth,.overhead .chev,.overhead .bar{flex:none}
.overrow .need{white-space:nowrap}

/* Narrow: the row stops pretending to be a table. Name and standing on
   one line, what it needs underneath. */
@media (max-width:760px){
  .overhead{display:none}
  .overrow{flex-wrap:wrap;row-gap:3px;gap:10px}
  .overrow .nm{flex:1 1 auto}
  .overrow .now{margin-left:auto}
  .overrow .need{flex:1 0 100%;width:auto;text-align:left;padding-left:24px;order:9}
  .overrow .bar,.overrow .aim,.overrow .worth{display:none}
}

/* The same applies to a card head carrying five things. */
@media (max-width:900px){
  .goalcard .cardhead{flex-wrap:wrap;row-gap:6px}
  .goalcard .cardhead .sm.muted{margin-left:0;flex:1 0 100%;order:9}
  .schedrow{flex-wrap:wrap;row-gap:4px}
  .schedrow .nm{flex:1 0 100%}
  .schedrow .wt{margin-left:0}
}

/* =================================================== THE CALENDAR
   One time spine on the left, seven columns pinned to it, so an hour
   is the same height on every day of the week. */
.calbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:16px;
  padding:10px 14px;background:var(--surface);border-radius:16px;box-shadow:var(--shadow)}
.calbar .rnd{width:30px;height:30px;flex:none;border-radius:var(--r-pill);border:1px solid var(--line2);
  color:var(--muted);font-size:.86rem;line-height:1}
.calbar .rnd:hover{background:var(--sunk);color:var(--ink)}
.calwhen{font-family:var(--display);font-size:1.05rem;font-weight:700;letter-spacing:-.02em;margin:0 6px}
.calsep{width:1px;height:22px;background:var(--line);margin:0 4px}
.calbar .filt{display:inline-flex;align-items:center;gap:7px;height:30px;padding:0 13px;
  border-radius:var(--r-pill);background:var(--sunk);font-size:.78rem;font-weight:700;color:var(--muted)}
.calbar .filt i{width:8px;height:8px;border-radius:3px;background:var(--sub);flex:none}
.calbar .filt:hover{color:var(--ink)}
.calbar .filt.on{background:var(--night);color:#fff}

/* Renamed off .seg, which another component already owned — its
   margin-top:18px was what pushed this 18px below the buttons beside
   it. 36px to match .btn.small exactly. */
.viewseg{display:inline-flex;flex:none;flex-wrap:nowrap;align-items:center;
  height:36px;padding:3px;border-radius:var(--r-pill);background:#EDEEF2}
.viewseg button{height:30px;padding:0 15px;border-radius:var(--r-pill);
  font-size:.8rem;font-weight:700;color:var(--muted)}
.viewseg button.on{background:#fff;color:var(--ink);box-shadow:0 1px 3px rgba(0,0,0,.08)}

.cal{background:var(--surface);border-radius:var(--r-card);box-shadow:var(--shadow);overflow:hidden}
.calrow{display:flex}
.calgut{width:60px;flex:none}
.caldcol{flex:1;min-width:0;border-left:1px solid #F2F3F6}
.calhead{border-bottom:1px solid var(--line);padding-bottom:6px}
.calhead .dh{position:relative;margin:8px 6px 0;padding:7px 0 6px;border-radius:10px;text-align:center}
.calhead .dw{font-size:.7rem;font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--faint)}
/* ------------------------------------------ work with nowhere to be
   The tray the drag code has been stepping around since it was
   written: calDrag ignores presses on .calput, which until now was a
   class no element had. */
/* ------------------------------------------ the pasted-in planner
   One block per subject heading found, so what is about to happen is
   visible before it happens: what it was called, how much of it there
   is, and which subject it will land in. */
.planimp{display:flex;align-items:center;flex-wrap:wrap;gap:10px;
  padding:12px 0 6px;border-top:1px solid var(--line)}
.planimp:first-child{border-top:0}
.planimp .nm{font-size:.86rem;font-weight:700}
.planimp select{margin-left:auto;height:36px;padding:0 8px;border-radius:10px;
  border:1px solid var(--line2);background:var(--surface);font-size:.82rem;max-width:100%}
.planimpitems{display:flex;flex-wrap:wrap;gap:6px;padding-bottom:10px}
.planimpitems .chip{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
@media (max-width:820px){
  /* The dropdown is the decision on this screen; it gets the line. */
  .planimp select{margin-left:0;flex:1 1 100%;height:44px}
}
.calput{display:flex;align-items:center;flex-wrap:wrap;gap:8px;
  padding:10px 12px;background:var(--sunk);border-bottom:1px solid var(--line2)}
/* The tray is always on screen now, so its heading is read. */
.calput .nm{font-size:.7rem;font-weight:700;letter-spacing:.08em;
  text-transform:uppercase;color:var(--faint);flex:none}
.calput .chips{display:flex;flex-wrap:wrap;gap:6px;min-width:0}
.calput .sm.faint{margin-left:auto;flex:none}
.putchip{display:inline-flex;align-items:center;gap:7px;max-width:260px;
  padding:7px 11px;border-radius:var(--r-pill);background:var(--surface);
  border:1px solid var(--line2);font-size:.8rem;font-weight:600;
  text-align:left;cursor:grab}
.putchip .dot{width:8px;height:8px;border-radius:3px;background:var(--sub);flex:none}
.putchip .t{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.putchip .mn{color:var(--faint);font-weight:700;font-size:.72rem;flex:none}
.putchip:hover{border-color:var(--accent);color:var(--accent-hi)}
.putchip.lifted{opacity:.45;cursor:grabbing}
/* A paper reads as a paper, not as another job to write. */
.putchip.paper{background:var(--warn-bg);border-color:#EBD9A8}
/* Adding is a chip too, because it belongs to the tray now. */
.putchip.add{border-style:dashed;color:var(--muted);font-weight:700}
.putchip.add:hover{border-style:solid;border-color:var(--accent);color:var(--accent-hi)}

/* ------------------------------------------------- the one editor
   Opened from a tray chip, a block or the add button, and the same
   either way. */
.workedit{display:flex;flex-direction:column;gap:12px;margin-top:14px;
  padding:16px;border-radius:var(--r-card);background:var(--surface);
  box-shadow:var(--shadow-lift)}
.workedit input[name=title]{height:44px;padding:0 12px;border-radius:12px;
  border:1px solid var(--line2);font-size:1rem;font-weight:600}
.workedit input[name=title]:focus{border-color:var(--accent);outline:none;
  box-shadow:0 0 0 3px var(--accent-soft)}
.workedit .when2{display:flex;gap:10px;flex-wrap:wrap}
.workedit .fld{display:flex;flex-direction:column;gap:4px;flex:1 1 140px;min-width:0}
/* .7rem, not .62 — these name the three things the editor is for. */
.workedit .fld span{font-size:.7rem;font-weight:700;letter-spacing:.08em;
  text-transform:uppercase;color:var(--faint)}
/* .dayin, not .day: `.day` is the week view column and carries a
   min-height of 300px, which the date box inherited. */
.workedit .fld input,.workedit .dayin{height:44px;min-height:0;padding:0 10px;border-radius:12px;
  border:1px solid var(--line2);font-size:.9rem;width:100%}
.workedit .foot{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
/* Editing a card, in the row it belongs to. */
.cardedit{display:flex;flex-direction:column;gap:10px;margin:2px 0 14px;
  padding:14px;border-radius:var(--r-row);background:var(--sunk)}
.cardedit textarea{width:100%;padding:10px;border-radius:12px;
  border:1px solid var(--line2);font:inherit;resize:vertical}
.cardedit .foot{display:flex;gap:10px;flex-wrap:wrap}
/* .cardq went with the duplicate browser it was for. */
/* What an empty box will mean, before it is saved rather than after. */
.workedit #says{margin:0;min-height:1.1rem}

/* The two things that are no longer cards on the page. */
.plantools{display:flex;gap:10px;flex-wrap:wrap;margin-top:16px}
@media (max-width:820px){
  /* Three fields side by side on a phone is three fields you cannot
     read; the day gets its own line and the two times share one. */
  .workedit .fld{flex:1 1 100%}
  .workedit .fld.half{flex:1 1 calc(50% - 5px)}
  .plantools .btn{flex:1 1 calc(50% - 5px)}
}
.putchip.paper:hover{border-color:#7A5600;color:#7A5600}
/* A dot instead of a length means nobody said how long it takes. */
.putchip .mn{color:var(--faint);font-weight:700;font-size:.72rem;flex:none}
/* Dropping into the all-day row is "this day, no particular time". */
.calallday .caldcol.over{background:var(--accent-soft);
  box-shadow:inset 0 0 0 2px var(--accent)}
/* The ghost is the block it is about to become, not a copy of the
   chip — what you are being shown is where it will land. */
.putghost{pointer-events:none}
@media (max-width:820px){
  /* Nothing tappable under 44px, and a chip is how you place work. */
  .putchip{min-height:44px;max-width:100%}
  .calput{padding:10px}
  .calput .sm.faint{margin-left:0;flex:1 1 100%}
}
.calhead .dn{margin-top:1px;font-family:var(--display);font-size:1.15rem;font-weight:700;letter-spacing:-.02em}
/* today is the whole head, not a dot on it */
.calhead .dh.today{background:var(--night)}
.calhead .dh.today .dw{color:var(--night-2)}
.calhead .dh.today .dn{color:#fff}
.calhead .dplus{position:absolute;top:4px;right:4px;width:22px;height:22px;border-radius:var(--r-pill);
  color:var(--faint);font-size:.9rem;line-height:1;opacity:0}
.calhead .dh:hover .dplus,.calhead .dplus:focus-visible{opacity:1;background:var(--accent-soft);color:var(--accent)}
.calhead .dh.today .dplus{color:var(--night-2)}

.calallday{min-height:42px;border-bottom:1px solid var(--line2);background:#FBFBFD}
.calallday .calgut{display:flex;align-items:center;justify-content:flex-end;padding-right:10px;
  font-size:.56rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:#B4B7C2}
.calallday .caldcol{padding:6px 5px;display:flex;flex-direction:column;gap:4px}
.calexam{display:block;padding:4px 8px;border-radius:7px;background:var(--night);color:#fff;
  font-size:.72rem;font-weight:700;line-height:1.25;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.caltag{display:block;width:100%;padding:4px 8px;border-radius:7px;text-align:left;
  background:color-mix(in srgb, var(--sub) 16%, #fff);color:color-mix(in srgb, var(--sub) 72%, #000);
  font-size:.72rem;font-weight:700;line-height:1.25;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.caltag.done{opacity:.5;text-decoration:line-through}

.calbody .calgut{position:relative}
.calspine .hl{position:absolute;right:11px;transform:translateY(-7px);
  font-size:.68rem;font-weight:600;color:var(--faint)}
.calcol{flex:1;min-width:0;position:relative;border-left:1px solid #F2F3F6;
  background:repeating-linear-gradient(to bottom,var(--line) 0 1px,transparent 1px 52px)}
.calcol.today{background:linear-gradient(#FAF9FF,#FAF9FF),
  repeating-linear-gradient(to bottom,var(--line) 0 1px,transparent 1px 52px)}

.calblk{position:absolute;border-radius:9px;padding:5px 8px;overflow:hidden;text-align:left;
  background:color-mix(in srgb, var(--sub) 17%, #fff);
  color:color-mix(in srgb, var(--sub) 74%, #000);
  cursor:grab;touch-action:pan-y;
  transition:box-shadow var(--t-move) var(--ease),opacity var(--t-state)}
.calblk b{display:block;font-size:.72rem;font-weight:700;line-height:1.3;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.calblk i{display:block;font-style:normal;font-size:.66rem;font-weight:600;opacity:.75;line-height:1.3}
.calblk:hover{box-shadow:0 6px 18px -8px color-mix(in srgb, var(--sub) 70%, #000)}
.calblk.done{opacity:.5}
.calblk.done b{text-decoration:line-through}
.calblk.dragging{cursor:grabbing;box-shadow:var(--shadow-lift);z-index:6}
.calblk .grip{position:absolute;left:0;right:0;bottom:0;height:8px;cursor:ns-resize}
.calblk .grip:after{content:"";position:absolute;left:50%;bottom:2px;transform:translateX(-50%);
  width:24px;height:3px;border-radius:var(--r-pill);background:currentColor;opacity:0}
.calblk:hover .grip:after{opacity:.4}
.calblk.ghost{left:3px;right:3px;background:var(--accent-soft);color:var(--accent-hi);
  border:2px dashed #A9A4F5;z-index:7;pointer-events:none}
.calblk.ghost i{font-style:normal;font-size:.68rem;font-weight:700;opacity:1}

.calnow{position:absolute;left:0;right:0;height:2px;background:#E0483C;z-index:5;pointer-events:none}
.calnowt{position:absolute;right:6px;transform:translateY(-50%);padding:2px 6px;z-index:5;
  border-radius:var(--r-pill);background:var(--night);color:#fff;
  font-size:.6rem;font-weight:700;pointer-events:none}

/* the editor, where it was drawn */
.caledit{position:absolute;left:3px;right:3px;z-index:9;background:var(--surface);
  border-radius:12px;padding:10px 11px;display:flex;flex-direction:column;gap:8px;
  box-shadow:0 0 0 2px var(--accent),0 12px 30px rgba(74,67,201,.18)}
.caledit input[name=title]{height:32px;border:1px solid var(--accent);border-radius:8px;
  padding:0 9px;font-size:.8rem;background:#fff}
.caledit input[name=title]:focus{outline:none;box-shadow:0 0 0 2px var(--accent-soft)}
.caledit input.asking{border-color:var(--bad)}
.caledit .swatches{display:flex;gap:6px;flex-wrap:wrap}
.caledit .sw{width:20px;height:20px;flex:none;border-radius:6px;background:var(--sub);opacity:.4;
  transition:opacity var(--t-state),box-shadow var(--t-state),transform var(--t-tap) var(--ease)}
.caledit .sw:hover{opacity:.75}
.caledit .sw.on{opacity:1;box-shadow:0 0 0 2px #fff,0 0 0 4px var(--sub)}
.caledit .foot{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.caledit .when{font-size:.68rem;font-weight:700;color:var(--muted);flex:1 0 100%}
.caledit .btn{height:30px;padding:0 13px;font-size:.74rem}
.calhint{margin-top:12px;font-size:.78rem;color:var(--faint)}

/* ------------------------------------------------------ the month */
.calmonth{padding:18px 16px 16px}
.mhead{display:grid;grid-template-columns:repeat(7,1fr);padding:0 2px 8px}
.mhead span{text-align:center;font-size:.62rem;font-weight:700;letter-spacing:.09em;
  text-transform:uppercase;color:var(--faint)}
.mgrid{display:grid;grid-template-columns:repeat(7,1fr);grid-auto-rows:116px;
  border-top:1px solid var(--line);border-left:1px solid var(--line)}
.mcell{position:relative;border-right:1px solid var(--line);border-bottom:1px solid var(--line);
  padding:7px 7px 8px;min-width:0;display:flex;flex-direction:column;gap:3px;align-items:stretch;
  text-align:left;overflow:hidden;transition:background var(--t-state) var(--ease-out)}
.mcell:hover{background:var(--sunk)}
.mcell.out{background:#FAFAFC}
.mcell.out .n{color:#C3C5CE}
.mcell .n{font-size:.76rem;font-weight:700;color:var(--muted)}
.mcell.today .n{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;
  border-radius:var(--r-pill);background:var(--night);color:#fff;margin:-2px 0 1px -2px}
.mev{display:flex;align-items:center;gap:5px;padding:2px 5px;border-radius:5px;
  background:color-mix(in srgb, var(--sub) 15%, #fff);color:color-mix(in srgb, var(--sub) 72%, #000);
  font-size:.64rem;font-weight:600;line-height:1.5;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mev i{width:6px;height:6px;border-radius:2px;background:var(--sub);flex:none}
.mev.done{opacity:.5;text-decoration:line-through}
.mexam{display:block;padding:3px 6px;border-radius:5px;background:var(--night);color:#fff;
  font-size:.64rem;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mmore{font-size:.6rem;font-weight:700;color:var(--faint);padding-left:5px}
/* how full a day is, as the cell's own bottom edge */
.mload{position:absolute;left:0;bottom:0;height:3px;background:var(--accent)}
.mload.over{background:var(--bad)}

.uprow{display:flex;align-items:center;gap:11px;width:100%;padding:10px 0;
  border-top:1px solid var(--line);font-size:.86rem;text-align:left}
.uprow:first-of-type{border-top:0}
.uprow .dot{width:10px;height:10px;border-radius:3px;background:var(--sub);flex:none}
.uprow .nm{flex:1;min-width:0;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.uprow .dt{width:80px;text-align:right;color:var(--muted);font-size:.78rem;flex:none}
.uprow .dd{width:66px;text-align:right;font-family:var(--display);font-size:.98rem;font-weight:700;flex:none}
.uprow .dd.soon{color:var(--bad)}

@media (max-width:900px){
  .calgut{width:44px}
  /* This used to shrink them to .6rem. A 44px gutter holds "12pm" at
     11.2px with room to spare — the spine of the week was being made
     harder to read for space that was never needed. */
  .calspine .hl{right:6px;font-size:.7rem}
  .calhead .dn{font-size:1rem}
  .mgrid{grid-auto-rows:92px}
  .mev,.mexam{font-size:.58rem}
}

/* The all-day band holds three and counts the rest. */
.calmore,.calless{display:block;width:100%;padding:2px 6px;text-align:left;
  font-size:.62rem;font-weight:700;color:var(--faint)}
.calmore:hover,.calless:hover{color:var(--accent)}
.calallday .calgut{flex-direction:column;align-items:flex-end;justify-content:center;gap:2px}
.calless{text-align:right;padding:0;font-size:.56rem}

/* The day head is a real button now, so it has to look like the div it
   replaced. */
.calhead .dh{display:block;width:100%;text-align:center}
.calhead .dh .dw,.calhead .dh .dn{display:block}

/* ------------------------------------------- narrower than a desktop
   Seven columns in 375px is 45px a day. At 768 it is 96px, which sounds
   survivable until two blocks overlap. Either way the dates become a
   picker and the body shows the chosen day — a seven-day timetable on a
   portrait tablet is seven columns of nothing. */
@media (max-width:900px){
  .calbody .calcol{display:none}
  .calbody .calcol.pick{display:block}
  .calallday .caldcol{display:none}
  .calallday .caldcol.pick{display:block}
  .calhead .caldcol{border-left:0}
  .calhead .dh{margin:6px 2px 0;padding:6px 0}
  .calhead .dh.today{background:none}
  .calhead .dh.today .dn{color:var(--accent-hi)}
  .calhead .caldcol.pick .dh{background:var(--night)}
  .calhead .caldcol.pick .dw{color:var(--night-2)}
  .calhead .caldcol.pick .dn{color:#fff}
  .calhead .dplus{display:none}
  .calhead .caldcol.pick .dplus{display:block;opacity:1;background:none;color:var(--night-2)}
  .calblk b{font-size:.78rem}
  .calblk i{font-size:.7rem}
  .caltag,.calexam{font-size:.76rem}

  /* the page head stops fighting its own buttons */
  .phead{flex-wrap:wrap;row-gap:12px}
  .phead .actions{width:100%;flex-wrap:wrap}
  .calhint{font-size:.74rem}
}

/* ============================ THE CALENDAR, TIDIED
   Black belongs to the ATAR card. On this page "chosen" is violet and
   everything else is its subject's own colour. */

/* the selected filter is chosen, not heavy */
.calbar .filt.on{background:var(--accent-soft);color:var(--accent-hi)}

/* today, in the week heads and in the narrow day picker */
.calhead .dh.today{background:var(--accent)}
.calhead .dh.today .dw{color:#C9C6F6}
.calhead .dh.today .dn{color:#fff}
.calhead .dh.today .dplus{color:#C9C6F6}
@media (max-width:760px){
  .calhead .caldcol.pick .dh{background:var(--accent)}
  .calhead .caldcol.pick .dw{color:#C9C6F6}
  .calhead .caldcol.pick .dplus{color:#C9C6F6}
}

/* the now badge belongs to the now line, so it is the same red */
.calnowt{background:#E0483C}

/* an exam is the subject it is in */
.calexam,.mexam{background:var(--sub,#4A4C58);color:#fff}

/* ---- the month: headings and cells share one grid ---- */
.mgrid{grid-template-rows:auto repeat(6,116px);border-top:0}
.mdow{padding:0 9px 8px;font-size:.62rem;font-weight:700;letter-spacing:.09em;
  text-transform:uppercase;color:var(--faint);text-align:left}
.mcell{border-top:1px solid var(--line)}
.mcell.today .n{background:var(--accent)}
@media (max-width:900px){ .mgrid{grid-template-rows:auto repeat(6,92px)} }

/* ===================================== ADDING, AND MOVING

   The subject a block belongs to, named once beside the swatches. */
.pickrow{display:flex;align-items:center;gap:10px}
.pickrow .swatches{flex:1 1 auto}
/* It names the subject the work will be filed under: worth reading. */
.pickname{display:inline-flex;align-items:center;gap:6px;flex:none;
  font-size:.78rem;font-weight:700;color:var(--sub);white-space:nowrap}
.pickname:before{content:"";width:8px;height:8px;border-radius:3px;background:var(--sub)}
.pickname.none{color:var(--faint)}
.pickname.none:before{background:none;box-shadow:inset 0 0 0 1.5px var(--faint)}

/* At rest a block should look liftable: the grip shows, and it rises
   just enough to say it is not painted on. */
.calblk{transition:box-shadow var(--t-move) var(--ease),
  transform var(--t-state) var(--ease),opacity var(--t-state)}
.calblk:hover{transform:translateY(-1px)}
.calblk:hover .grip:after{opacity:.55}
.calblk:active{transform:scale(.995)}

/* While it moves: off the page, and following the pointer. */
.calblk.dragging{transform:scale(1.025);z-index:8;cursor:grabbing;
  box-shadow:0 18px 34px -14px rgba(13,27,42,.45);transition:none}
.calblk.dragging .grip:after{opacity:0}
body.grabbing,body.grabbing *{cursor:grabbing!important;user-select:none}

/* Where it came from, for as long as it is in the air. */
.calhole{position:absolute;border-radius:9px;z-index:1;pointer-events:none;
  border:1.5px dashed var(--line2);background:color-mix(in srgb, var(--line) 55%, #fff)}

/* What it says while moving: the time it would land on. */
.dragtime{position:absolute;left:0;transform:translate(-100%,-50%);z-index:9;
  padding:2px 7px;border-radius:var(--r-pill);background:var(--accent);color:#fff;
  font-size:.6rem;font-weight:700;white-space:nowrap;pointer-events:none}

/* The day it would land on. */
.calcol.over{background:linear-gradient(var(--accent-soft),var(--accent-soft)),
  repeating-linear-gradient(to bottom,var(--line) 0 1px,transparent 1px 52px)}

@media (prefers-reduced-motion:reduce){
  .calblk:hover,.calblk:active{transform:none}
  .calblk.dragging{transform:none}
}

/* ============================== THE DAY, AT FULL LENGTH
   Eighteen hours of grid inside a frame the viewport decides. The day
   heads and the all-day band sit outside it and never move, so the
   thing that scrolls is only ever the hours. */
.calbody{max-height:min(62vh,760px);overflow-y:auto;overscroll-behavior:contain}
.calbody .calgut{position:sticky;left:0;z-index:4;background:var(--surface)}
@media (max-width:900px){
  /* One column and a page that already scrolls: a second scroller
     inside it would just fight the first. */
  .calbody{max-height:none;overflow:visible}
}

/* An exam is filled solid in its subject's colour. Work in the same
   subject is a tint of that colour, so the two never read alike. */
.calexam,.mexam{background:var(--sub,#4A4C58);color:#fff;
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.08)}
.calexam.past,.mexam.past{opacity:.42}

/* What the microphone is catching, while it catches it. */
.saystate.heard{min-height:22px}
.saystate.heard .said.live{color:var(--accent-hi);font-style:normal}
.saystate.heard .said.live:after{content:"";display:inline-block;width:6px;height:6px;
  margin-left:7px;border-radius:999px;background:#E0483C;vertical-align:middle;
  animation:hearing 1.4s var(--ease-out) infinite}
@keyframes hearing{0%,100%{opacity:.25}50%{opacity:1}}
@media (prefers-reduced-motion:reduce){ .saystate.heard .said.live:after{animation:none;opacity:.9} }

/* Changing a block. The dots are quiet until wanted, and always there
   on a screen that has no hover to reveal them. */
.calblk .more{position:absolute;top:1px;right:2px;width:18px;height:16px;
  display:flex;align-items:center;justify-content:center;
  color:currentColor;opacity:0;font-size:.8rem;line-height:1;border-radius:5px;
  transition:opacity var(--t-state),background var(--t-state)}
.calblk:hover .more,.calblk .more:focus-visible{opacity:.65}
.calblk .more:hover{opacity:1;background:rgba(255,255,255,.55)}
.calblk b{padding-right:18px}
@media (hover:none){ .calblk .more{opacity:.6} }

.caledit .foot .drop{margin-right:auto;font-size:.72rem;color:var(--bad)}
.caledit .foot .drop:hover{text-decoration:underline}
.caledit.editing{box-shadow:0 0 0 2px var(--accent),0 14px 34px rgba(74,67,201,.2)}

/* ============================ REACHABLE ON A PHONE

   Two of the most-used controls on the densest screen in the app were
   revealed by :hover and sized for a mouse. A phone has neither, so the
   pencil that edits a syllabus point was not merely small — it was
   transparent, permanently, on every touch screen. A control nobody can
   see is a control that does not exist.

   The pointer rules come first and the touch rules override them, which
   is the order that works — the other way round the desktop sizes win
   and the phone keeps the targets it cannot hit. */
.grade button{height:28px}
.point .fix,.topic .th .fix{width:30px;height:30px}

@media (hover:none){
  .point .fix,.topic .th .fix{color:var(--faint);background:var(--sunk);
    width:40px;height:40px;font-size:.95rem}
  .grade{gap:5px}
  .grade button{width:44px;height:44px;font-size:.9rem;border-radius:10px}
}

/* ================== NOTHING HIDES BEHIND A HOVER

   Revealing a control on :hover keeps a list calm on a desktop, and
   removes the control entirely on a phone. Said once here rather than
   patched per component, because it was patched per component three
   times and missed twice. */
@media (hover:none){
  table.marks .drop,.schedrow .drop,.answerrow .drop,.planrow .drop,
  .point .fix,.topic .th .fix{color:var(--faint)}
  /* and big enough to mean it */
  table.marks .drop,.schedrow .drop,.answerrow .drop,.planrow .drop{
    width:38px;height:38px}
}

/* ===================== TODAY, AND THE RIGHT-CLICK

   Today is a circle on the date, the same mark the month view uses —
   not a violet block the size of the whole head, and not a wash down
   the column, which reads as "unavailable" rather than "now". */
.calhead .dh.today{background:none}
.calhead .dh.today .dw{color:var(--accent-hi)}
.calhead .dh.today .dn{display:inline-flex;align-items:center;justify-content:center;
  width:30px;height:30px;margin:0 auto;border-radius:var(--r-pill);
  background:var(--accent);color:#fff;font-size:1rem}
.calcol.today{background:repeating-linear-gradient(to bottom,var(--line) 0 1px,transparent 1px 52px)}

/* The menu under the right button. */
.ctx{position:fixed;z-index:60;min-width:168px;padding:6px;
  background:var(--surface);border-radius:14px;
  box-shadow:0 0 0 1px var(--line),0 18px 40px -12px rgba(13,27,42,.3);
  animation:ctxin .14s var(--ease) both}
@keyframes ctxin{from{opacity:0;transform:translateY(-4px) scale(.98)}to{opacity:1;transform:none}}
.ctxrow{display:flex;align-items:center;width:100%;height:36px;padding:0 12px;
  border-radius:9px;font-size:.86rem;font-weight:600;text-align:left}
.ctxrow:hover{background:var(--sunk)}
.ctxrow.bad{color:var(--bad)}
.ctxrow.bad:hover{background:var(--bad-bg)}
.ctxsw{display:flex;flex-wrap:wrap;gap:6px;padding:8px 10px 4px;margin-top:4px;
  border-top:1px solid var(--line)}
.ctxsw .sw{width:22px;height:22px;flex:none;border-radius:7px;background:var(--sub);opacity:.45;
  transition:opacity var(--t-state),box-shadow var(--t-state)}
.ctxsw .sw:hover{opacity:.85}
.ctxsw .sw.on{opacity:1;box-shadow:0 0 0 2px #fff,0 0 0 4px var(--sub)}
@media (prefers-reduced-motion:reduce){ .ctx{animation:none} }

/* ===================== THE MEMORISER'S THREE RUNGS

   Read it, then first letters, then nothing. Every rung keeps each
   word's real width, so the shape of the sentence stays legible even
   when the words are not — "the" and "consequently" should never look
   the same. */
.lvl{display:inline-flex;padding:3px;border-radius:var(--r-pill);background:#EDEEF2}
.lvl button{height:28px;padding:0 12px;border-radius:var(--r-pill);
  font-size:.76rem;font-weight:700;color:var(--muted);white-space:nowrap}
.lvl button.on{background:#fff;color:var(--ink);box-shadow:0 1px 3px rgba(0,0,0,.08)}
@media (max-width:820px){
  /* These choose how much of the paragraph to show. Same specificity
     as the rule above, so they have to come after it to win. */
  .lvl{padding:2px;max-width:100%;flex-wrap:wrap}
  .lvl button{height:40px;padding:0 14px}
}

/* read: the whole thing, quietly */
.saidtext.read .w{color:var(--ink);background:transparent;box-shadow:none}

/* first letters: the letter, and the length */
.saidtext.hint .w{position:relative;color:transparent}
.saidtext.hint .w:before{content:attr(data-f);position:absolute;left:6px;top:0;
  color:var(--muted);font-weight:600}
.saidtext.hint .w.got,.saidtext.hint .w.waved{color:var(--ink);background:transparent;box-shadow:none}
.saidtext.hint .w.got:before,.saidtext.hint .w.waved:before{content:none}

/* a word that was given rather than remembered */
.saidtext .w.waved{color:var(--muted);background:transparent;box-shadow:inset 0 -1px 0 var(--line2)}

/* The key that does this, on the button that does this. Small enough to
   ignore once it is known. */
.runactions .btn .key{display:inline-flex;align-items:center;justify-content:center;
  width:17px;height:17px;margin-left:8px;border-radius:5px;
  background:rgba(0,0,0,.07);color:inherit;opacity:.55;
  font-style:normal;font-size:.66rem;font-weight:700;line-height:1}
@media (hover:none){ .runactions .btn .key{display:none} }

/* Out of the way until a keyboard asks for it, then unmissable. The
   rail is thirteen tab stops; nobody should walk it twice. */
/* Fixed, not absolute: .shell is statically positioned, so an
   absolute skip link anchors to the document and lands off-screen
   above once a student has scrolled — which is exactly when they are
   most likely to be tabbing. */
.skip{position:fixed;left:12px;top:-60px;z-index:80;
  padding:10px 16px;border-radius:var(--r-pill);
  background:var(--accent);color:#fff;font-size:.86rem;font-weight:700;
  box-shadow:var(--shadow-lift);transition:top var(--t-state) var(--ease)}
.skip:focus{top:12px;color:#fff}
.page:focus{outline:none}
.page:focus-visible{outline:2px solid var(--accent);outline-offset:-4px;border-radius:var(--r-card)}

/* After a paper: rows, one open. The form sits between two rows, so the
   row below it needs the separator the adjacent-row rule would have
   given it, and the open row needs to look open. */
.stackform + .answerrow{border-top:1px solid var(--line);border-radius:0}
.answerrow[aria-expanded="true"]{background:var(--sunk)}

/* The coverage key. Five colours meant five things and the page never
   said which — the words were in a tooltip, and a phone has no hover. */
.covkey{display:flex;flex-wrap:wrap;gap:12px;margin:0 0 16px;padding:0 2px}
.covkey span{display:inline-flex;align-items:center;gap:7px;font-size:.78rem;color:var(--muted)}
.covkey i{width:12px;height:12px;border-radius:4px;background:#EFF0F4;flex:0 0 auto;position:relative}
.covkey i.g1{background:var(--g1)} .covkey i.g2{background:var(--g2)}
.covkey i.g3{background:var(--g3)} .covkey i.g4{background:var(--g4)}
.covkey i.g5{background:var(--g5)}
.covkey i.gapkey{background:#EFF0F4}
.covkey i.gapkey::after{content:"";position:absolute;top:2px;right:2px;width:5px;height:5px;
  border-radius:50%;background:var(--ink2)}

/* Weak or unrated, and nothing written down: the point to start on.
   The dot takes the cell's own ink, so it reads on the dark tiles and
   on the pale one without needing a colour of its own. */
.cov{position:relative}
.cov.gap{padding-right:22px}
.cov.gap::after{content:"";position:absolute;top:8px;right:8px;width:6px;height:6px;
  border-radius:50%;background:currentColor;opacity:.85}

/* What each card will look like. The braces are Anki's syntax, not a
   student's idea of a flashcard, so the maker shows the card. */
.clozepv{padding:14px 16px;border-radius:var(--r-tile);background:var(--sunk);
  display:flex;flex-direction:column;gap:10px}
.clozepv .pvcard{font-size:.92rem;line-height:1.75;color:var(--ink2)}
.clozepv .pvcard + .pvcard{padding-top:10px;border-top:1px solid var(--line)}

/* Narrow phones. The rating buttons are 44px because nothing tappable
   goes under 44 on a phone, which makes the row 240px wide — wider than
   what is left beside a point label on a 320px screen. So the row wraps
   and the rating drops to its own line, rather than the page scrolling
   sideways. A select sizes itself to its longest option, which on the
   note page is a topic name, so it is held to its container. */
.point{flex-wrap:wrap}
select{max-width:100%}

/* "Turn off" and "Delete" sat on one unbreakable line and pushed the
   flashcards page past the edge of a 320px screen. Third row this
   week to need it, after .filters and .point. */
.acts{flex-wrap:wrap}

/* Grading a card is four buttons — Again, Hard, Good, Easy — each held
   to min-width:120px. With gaps that row needs 516px, so on every
   phone ever made the last button sat off the side of the screen. It
   went unseen because the audit could not render a run in progress.
   On a narrow screen they share the row instead. */
@media (max-width:560px){
  /* Two by two: Again and Hard, then Good and Easy. Sharing one row
     left the last button alone on a line of its own. */
  .runactions{flex-wrap:wrap;gap:8px}
  .runactions .btn{min-width:0;flex:1 1 calc(50% - 4px)}

  /* The bar above a paper carries its title and the button that
     submits it; the row under a question carries "Something is wrong
     with it" and the criteria note. Neither fits on one line on a
     phone, and neither could wrap. */
  .runbar{flex-wrap:wrap;row-gap:8px}
  .row{flex-wrap:wrap}
  /* Previous, where you are, and the button that submits — the last
     row on a question, and the last one that could not wrap. */
  .runfoot{flex-wrap:wrap;row-gap:8px}
  /* .acts learned to wrap, but it sits inside .answerrow, which did
     not — so the whole block was pushed off the edge instead. Eighth
     row this week; on a phone these all wrap. */
  .answerrow{flex-wrap:wrap;row-gap:8px}
  /* The text column is flex:1 1 0%, so when the buttons beside it are
     wide it shrinks instead of making the row wrap — flexbox only
     wraps when the bases overflow, and a base of 0 never does. On the
     essays list that left the title 9px wide, spelling itself down
     the screen one character per line. A floor makes the row wrap and
     the buttons drop underneath, which is what was wanted. */
  .answerrow .grow{min-width:55%}

  /* A syllabus point is cut with an ellipsis and, when it runs over
     62 characters, can be tapped open. At this width the column is
     about thirty characters, so a shorter label is cut too — and a
     tap on it goes to the point rather than opening it, because it is
     not "long". The tooltip needs a hover a phone does not have. So
     it wraps here instead of being cut with no way to read it. */
  .point .lbl{white-space:normal}
}

/* The time and the length, in the block editor. A drag is quicker on
   a desktop and impossible on a phone, so these are the way the time
   gets changed at all on the device most of this is used on. */
.caledit .foot input.at,.caledit .foot input.mins{height:30px;padding:0 6px;
  border:1px solid var(--line2);border-radius:8px;background:var(--surface);
  font-family:var(--f);font-size:.78rem;color:var(--ink2);flex:0 0 auto}
.caledit .foot input.at{width:92px}
.caledit .foot input.mins{width:58px}
.caledit .foot input.at:focus,.caledit .foot input.mins:focus{outline:none;
  border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}

/* The things on a day in the month grid. A column of titles where
   there is room for titles. */
.mevs{display:flex;flex-direction:column;gap:3px;min-width:0}

@media (max-width:560px){
  /* Seven columns of a 375px screen is a 44px cell, and a title in
     one of those is four characters and an ellipsis. Dots instead:
     how many things and which subjects, with the day one tap from
     the week view where the words are. */
  .mevs{flex-direction:row;flex-wrap:wrap;gap:4px;align-items:center}
  .mcell .mev{width:7px;height:7px;min-width:0;padding:0;gap:0;border-radius:50%;
    background:var(--sub);font-size:0;line-height:0;overflow:hidden;flex:none}
  .mcell .mev i{display:none}
  .mcell .mev.done{opacity:.35;text-decoration:none}
  /* An exam is not one of several things that day. */
  .mcell .mexam{height:4px;padding:0;font-size:0;line-height:0;border-radius:2px}
  .mcell .mmore{font-size:.55rem;padding-left:0}
}

/* ---------- how much of a day is spoken for ----------
   Appended at the end deliberately. .mload and the calendar head live
   four hundred lines apart, and the last time I put a rule for one of
   these beside its sibling rather than after the base rule it lost to
   a later declaration of the same specificity and nothing moved. */
.calhead .caldcol{position:relative}
.dload{display:block;height:3px;margin:4px 6px 0;border-radius:2px;
  background:var(--line);overflow:hidden}
.dload i{display:block;height:100%;background:var(--accent);border-radius:2px}
.dload.over i{background:var(--bad)}
/* A day off has no bar to fill, so the track itself says so. An empty
   track and a day with nothing on it would otherwise look identical. */
.dload.off{background:repeating-linear-gradient(90deg,
  var(--line2) 0 3px,transparent 3px 6px)}
/* .6rem here was 9.6px — under the eleven-pixel floor that the rest of
   this app is held to, and I only missed it because the phone sweep
   never sees this rule: it is hidden below the breakpoint. */
.droom{display:block;margin:3px 4px 0;font-size:.7rem;line-height:1.3;
  text-align:center;color:var(--faint);white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis}
.caldcol.off .droom{color:var(--accent)}
.dayline{margin:10px 0 0;font-size:.82rem;color:var(--muted)}
@media (max-width:1180px){
  /* Seven heads share the width left after the rail, so even at a
     smallish laptop each is about ninety pixels — and "1h 45m of
     1h 30m" measures ninety-three. At 1100 it fitted to the pixel with
     nothing to spare, which is not fitting, it is luck with a font.
     .dayline under the calendar carries the same facts in a sentence
     at every width, so nothing is lost by showing this only where it
     genuinely reads. */
  .droom{display:none}
}

/* ---------- days that are not like the others ---------- */
.dayex{flex:0 0 100%;border-top:1px solid var(--line);margin-top:6px;padding-top:12px}
.dayex .eyebrow{display:block;margin-bottom:8px}
.exrow{display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  padding:7px 0;border-bottom:1px solid var(--line)}
.exrow:last-child{border-bottom:0}
.exwhat{flex:1 1 220px;min-width:0;font-size:.84rem}
.exwhat .sm{display:block;color:var(--faint);font-size:.74rem}
.exacts{display:flex;gap:6px;flex-wrap:wrap}
.exadd{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:10px}
.exadd input{height:36px;border:1px solid var(--line2);border-radius:10px;
  padding:0 9px;font:inherit;font-size:.82rem;background:var(--surface);color:var(--ink)}
.exadd .exd{width:150px}
.exadd .exn{flex:1 1 150px;min-width:130px}
.exfor{display:flex;align-items:center;gap:6px;font-size:.8rem;color:var(--faint)}
.exfor input{width:56px;text-align:center}
@media (max-width:560px){
  .exadd .exd,.exadd .exn{flex:1 1 100%;width:auto}
  /* "for N days" took the rest of its line and left the two buttons
     split across two more — the one that acts and the one that acts
     differently belong beside each other. */
  .exadd .exfor{flex:1 1 100%}
  .exadd .btn{flex:1 1 calc(50% - 4px)}
  .exacts{width:100%}
}

/* ---------- the subject list, where two subjects looked the same ----------
   "Mathematics Extension 1" and "Mathematics Extension 2" both came out
   as "Mathematics Extens…". The character that tells them apart is the
   last one, and the last one is what an ellipsis eats — so the rail
   showed a student sitting both of them two identical rows.

   The name wraps now. This file already does exactly that for .ledger,
   .standrow, .freqrow and .leakrow at narrow widths, so it is this
   app's own answer to this problem rather than a new one. */
.nav.child{height:auto;min-height:38px}
.nav.child .nm{white-space:normal;overflow:visible;text-overflow:clip;
  overflow-wrap:break-word;line-height:1.25;padding:7px 0}

/* The arrows hold their place whether or not they are showing, so the
   name is the same width when you point at a subject as when you do
   not. Appearing on hover took 39px off the name — truncating it at
   the moment you reached for it. */
.nav.child .move{display:flex;visibility:hidden}
.nav.child:hover .move,.nav.child:focus-within .move{visibility:visible}

@media (max-width:960px){
  .nav.child{min-height:44px}
  .nav.child .move{visibility:visible}
  /* Below 960 there is no hover, so these arrows are the only way to
     reorder without dragging — and they were a 14x17 tap target at 9px.
     44 is what the rest of this app gives a thumb. */
  .nav.child .move i{min-width:30px;height:44px;padding:0;font-size:.7rem;
    display:flex;align-items:center;justify-content:center}
}

/* ---------- two labels the last readability pass missed ----------
   That pass raised the hour labels off .6rem and wrote down why: the
   spine of the week was being made harder to read for space that was
   never needed. It did not reach the band's own label or the now
   pill, which stayed at 8.96px and 9.6px.

   "ALL DAY" at 11.2px does not fit a 44px gutter on one line, so it
   wraps to two — which is what the column direction below the
   breakpoint was already set up for. */
.calallday .calgut{font-size:.7rem;line-height:1.15;white-space:normal;
  text-align:right;word-spacing:normal}
.calnowt{font-size:.7rem}
